From 770ab29653fffc5cdf51eede2dc7263c0f7edf5c Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Fri, 3 Oct 2025 02:02:20 +0200 Subject: [PATCH] compilable --- Makefile | 6 +- asm/macros/battle_script.inc | 1216 ++-- charmap.txt | 6 +- data/battle_scripts_1.s | 2244 +++---- data/battle_scripts_2.s | 4 +- data/scripts/debug.inc | 98 + data/specials.inc | 1 + include/battle.h | 153 +- include/battle_ai_field_statuses.h | 18 + include/battle_ai_main.h | 18 +- include/battle_ai_switch_items.h | 2 +- include/battle_ai_util.h | 188 +- include/battle_anim.h | 10 + include/battle_controllers.h | 55 +- include/battle_dynamax.h | 3 - include/battle_gfx_sfx_util.h | 3 +- include/battle_interface.h | 2 +- include/battle_main.h | 16 +- include/battle_message.h | 10 +- include/battle_script_commands.h | 20 +- include/battle_scripts.h | 85 +- include/battle_terastal.h | 2 +- include/battle_util.h | 151 +- include/config/ai.h | 58 +- include/config/battle.h | 50 +- include/config/general.h | 1 - include/constants/abilities.h | 661 +- include/constants/battle.h | 293 +- include/constants/battle_ai.h | 75 +- include/constants/battle_anim.h | 19 +- include/constants/battle_move_effects.h | 12 +- include/constants/battle_script_commands.h | 144 +- include/constants/battle_string_ids.h | 79 +- include/constants/generational_changes.h | 21 + include/constants/hold_effects.h | 3 +- include/constants/item_effects.h | 12 +- include/constants/items.h | 3 - include/constants/pokemon.h | 3 + include/data.h | 8 +- include/follower_npc.h | 8 +- include/gba/defines.h | 2 + include/generational_changes.h | 21 + include/item.h | 171 +- include/math_util.h | 5 +- include/metaprogram.h | 132 +- include/move.h | 26 +- include/pokemon.h | 44 +- include/random.h | 17 + include/sprite.h | 1 + include/strings.h | 1 + include/trainer_pokemon_sprites.h | 2 + include/trainer_pools.h | 10 +- src/battle_ai_field_statuses.c | 498 ++ src/battle_ai_main.c | 2501 ++++--- src/battle_ai_switch_items.c | 520 +- src/battle_ai_util.c | 2329 +++++-- src/battle_anim_effects_1.c | 77 +- src/battle_anim_effects_3.c | 62 +- src/battle_anim_electric.c | 106 +- src/battle_anim_ground.c | 9 +- src/battle_anim_ice.c | 171 +- src/battle_anim_new.c | 339 +- src/battle_anim_rock.c | 135 +- src/battle_controller_oak_old_man.c | 2 +- src/battle_controller_opponent.c | 29 +- src/battle_controller_player.c | 17 +- src/battle_controllers.c | 110 +- src/battle_debug.c | 1183 ++-- src/battle_dynamax.c | 21 +- src/battle_end_turn.c | 235 +- src/battle_gfx_sfx_util.c | 73 +- src/battle_interface.c | 590 +- src/battle_main.c | 379 +- src/battle_message.c | 241 +- src/battle_script_commands.c | 7062 +++++++++----------- src/battle_terastal.c | 25 +- src/battle_util.c | 3467 ++++++---- src/battle_z_move.c | 21 +- src/data/abilities.h | 2 +- src/data/battle_move_effects.h | 70 +- src/data/battle_partners.h | 60 +- src/data/battle_partners.party | 7 +- src/data/debug_trainers.h | 136 + src/data/debug_trainers.party | 68 + src/data/graphics/trainers.h | 90 +- src/data/items.h | 2731 ++++---- src/data/moves_info.h | 3865 ++++++----- src/data/trainers.h | 1490 ++++- src/debug.c | 2041 ++---- src/field_specials.c | 7 + src/field_weather.c | 30 + src/item.c | 62 +- src/item_icon.c | 2 +- src/item_use.c | 59 +- src/math_util.c | 8 + src/overworld.c | 3 +- src/party_menu.c | 21 +- src/pokemon.c | 800 ++- src/pokemon_animation.c | 5 + src/recorded_battle.c | 57 +- src/reshow_battle_screen.c | 10 +- src/sprite.c | 1 - src/strings.c | 1 + src/teachy_tv.c | 2 +- src/trainer_pokemon_sprites.c | 22 +- src/trainer_pools.c | 9 +- test/battle/trainer_control.h | 30 +- tools/preproc/asm_file.cpp | 58 +- tools/preproc/c_file.cpp | 2 +- tools/preproc/preproc.cpp | 10 + tools/scaninc/c_file.cpp | 2 +- tools/trainerproc/main.c | 102 +- trainer_rules.mk | 10 + 113 files changed, 21184 insertions(+), 17084 deletions(-) create mode 100644 include/battle_ai_field_statuses.h create mode 100644 src/battle_ai_field_statuses.c create mode 100644 src/data/debug_trainers.h create mode 100644 src/data/debug_trainers.party create mode 100644 trainer_rules.mk diff --git a/Makefile b/Makefile index 6fb45f7d4..389b1bdf0 100644 --- a/Makefile +++ b/Makefile @@ -365,6 +365,7 @@ include tileset_rules.mk include spritesheet_rules.mk include json_data_rules.mk include audio_rules.mk +include trainer_rules.mk # NOTE: Tools must have been built prior (FIXME) # so you can't really call this rule directly @@ -394,11 +395,6 @@ clean-generated: @rm -f $(ALL_LEARNABLES_JSON) @echo "rm -f " -COMPETITIVE_PARTY_SYNTAX := $(shell PATH="$(PATH)"; echo 'COMPETITIVE_PARTY_SYNTAX' | $(CPP) $(CPPFLAGS) -imacros include/gba/defines.h -imacros include/config/general.h | tail -n1) -ifeq ($(COMPETITIVE_PARTY_SYNTAX),1) -%.h: %.party ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< - -endif - $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast $(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member $(C_BUILDDIR)/agb_flash.o: override CFLAGS += -fno-toplevel-reorder diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 0ba834610..b2a579fdc 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -9,11 +9,11 @@ .2byte \move .endm - .macro attackstring + .macro printattackstring .byte 0x2 .endm - .macro ppreduce + .macro unused0x3 .byte 0x3 .endm @@ -187,12 +187,8 @@ .4byte \jumpInstr .endm - .macro jumpifstatus3condition battler:req, flags:req, jumpIfTrue:req, jumpInstr:req + .macro unused_0x21 .byte 0x21 - .byte \battler - .4byte \flags - .byte \jumpIfTrue - .4byte \jumpInstr .endm .macro jumpbasedontype battler:req, type:req, jumpIfType:req, jumpInstr:req @@ -416,8 +412,11 @@ .4byte \argPtr .endm - .macro unused_0x47 + .macro jumpfifsemiinvulnerable battler:req, state:req, jumpInstr:req .byte 0x47 + .byte \battler + .byte \state + .4byte \jumpInstr .endm .macro unused_0x48 @@ -596,27 +595,15 @@ .byte \notChosenMove .endm - .macro statusanimation battler:req + .macro statusanimation battler:req, status=0, isVolatile=FALSE .byte 0x64 .byte \battler - .endm - - .macro status2animation battler:req, status2:req - .byte 0x65 - .byte \battler - .4byte \status2 - .endm - - .macro setmoveeffect effect:req - sethword sMOVE_EFFECT, \effect - sethword sSAVED_MOVE_EFFECT, \effect - .endm - - .macro chosenstatusanimation battler:req, isStatus2:req, status:req - .byte 0x66 - .byte \battler - .byte \isStatus2 .4byte \status + .byte \isVolatile + .endm + + .macro volatileanimation battler:req, volatile:req + statusanimation \battler, \volatile, TRUE .endm .macro yesnobox @@ -709,10 +696,10 @@ .4byte \jumpInstr .endm - .macro tryhealhalfhealth failInstr:req, battler:req + .macro tryhealhalfhealth battler:req, failInstr:req .byte 0x7b - .4byte \failInstr .byte \battler + .4byte \failInstr .endm .macro trymirrormove @@ -737,19 +724,16 @@ .byte \mode .endm - .macro trysetrest failInstr:req + .macro trysetrest .byte 0x81 - .4byte \failInstr .endm - .macro jumpifnotfirstturn jumpInstr:req + .macro unused_0x82 .byte 0x82 - .4byte \jumpInstr .endm - .macro setmiracleeye failInstr:req + .macro unused_0x83 .byte 0x83 - .4byte \failInstr .endm .macro jumpifuproarwakes jumpInstr:req @@ -762,9 +746,8 @@ .byte \id .endm - .macro stockpiletobasedamage failInstr:req + .macro stockpiletobasedamage .byte 0x86 - .4byte \failInstr .endm .macro stockpiletohpheal failInstr:req @@ -844,16 +827,19 @@ .4byte \failInstr .endm - .macro setstatuswithability + .macro checknonvolatiletrigger nonVolatile:req, failInstr:req .byte 0x94 + .2byte \nonVolatile + .4byte \failInstr .endm .macro copybidedmg .byte 0x95 .endm - .macro unused_96 + .macro animatewildpokemonafterfailedpokeball battler:req .byte 0x96 + .byte \battler .endm .macro tryinfatuating failInstr:req @@ -888,7 +874,7 @@ .4byte \failInstr .endm - .macro metronome + .macro setcalledmove .byte 0x9e .endm @@ -977,8 +963,11 @@ .4byte \failInstr .endm - .macro setforesight + .macro setvolatile battler:req, volatile:req, value=TRUE .byte 0xb1 + .byte \battler + .byte \volatile + .byte \value .endm .macro trysetperishsong failInstr:req @@ -1022,8 +1011,9 @@ .4byte \jumpInstr .endm - .macro tryrestorehpberry + .macro tryrestorehpberry battler:req .byte 0xbb + .byte \battler .endm .macro halvehp failInstr:req @@ -1031,19 +1021,14 @@ .4byte \failInstr .endm - .macro copyfoestats unused:req + .macro copyfoestats .byte 0xbd - .4byte \unused .endm .macro rapidspinfree .byte 0xbe .endm - .macro setdefensecurlbit - .byte 0xbf - .endm - .macro recoverbasedonsunlight failInstr:req .byte 0xc0 .4byte \failInstr @@ -1058,12 +1043,11 @@ .byte 0xc2 .endm - .macro trysetfutureattack failInstr:req + .macro setfutureattack .byte 0xc3 - .4byte \failInstr .endm - .macro trydobeatup endInstr, failInstr + .macro trydobeatup endInstr:req, failInstr:req .byte 0xc4 .4byte \endInstr .4byte \failInstr @@ -1093,7 +1077,7 @@ tryfiretwoturnmovenowbyeffect \battler, FALSE, \jumpInstr .endm - .macro setminimize + .macro unused_0xC7 .byte 0xc7 .endm @@ -1199,9 +1183,10 @@ .4byte \failInstr .endm - .macro setuserstatus3 flags:req, failInstr:req + .macro trysetvolatile battler:req, _volatile:req, failInstr:req .byte 0xdd - .4byte \flags + .byte \battler + .byte \_volatile .4byte \failInstr .endm @@ -1236,10 +1221,8 @@ .4byte \jumpInstr .endm - .macro jumpifnotcurrentmoveargtype battler:req, failInstr:req + .macro unused_0xE4 .byte 0xe4 - .byte \battler - .4byte \failInstr .endm .macro pickup @@ -1390,17 +1373,6 @@ .4byte \failInstr .endm - .macro jumpifcantfling battler:req, jumpInstr:req - callnative BS_JumpIfCantFling - .byte \battler - .4byte \jumpInstr - .endm - - .macro itemstatchangeeffects battler:req - callnative BS_RunStatChangeItems - .byte \battler - .endm - .macro allyswitchswapbattlers callnative BS_AllySwitchSwapBattler .endm @@ -1445,32 +1417,22 @@ callnative BS_TryRevertWeatherForm .endm - .macro trysetoctolock battler:req, failInstr:req + .macro trysetoctolock failInstr:req callnative BS_TrySetOctolock - .byte \battler .4byte \failInstr .endm - .macro setglaiverush - callnative BS_SetGlaiveRush - .endm - .macro setpledge jumpInstr:req callnative BS_SetPledge .4byte \jumpInstr .endm - .macro setpledgestatus battler:req sidestatus:req + .macro setpledgestatus battler:req, sidestatus:req callnative BS_SetPledgeStatus .byte \battler .4byte \sidestatus .endm - .macro trycopycat failInstr:req - callnative BS_TryCopycat - .4byte \failInstr - .endm - .macro setzeffect callnative BS_SetZEffect .endm @@ -1530,14 +1492,8 @@ .4byte \jumpInstr .endm - .macro jumpifmovepropertyargument argument:req, jumpInstr:req - callnative BS_JumpIfMovePropertyArgument - .byte \argument - .4byte \jumpInstr - .endm - - .macro setremoveterrain failInstr:req - callnative BS_SetRemoveTerrain + .macro setterrain failInstr:req + callnative BS_SetTerrain .4byte \failInstr .endm @@ -1741,6 +1697,10 @@ .byte \battler .endm + .macro resetterrainabilityflags + callnative BS_ResetTerrainAbilityFlags + .endm + @ Stores Healing Wish effect. .macro storehealingwish battler:req callnative BS_StoreHealingWish @@ -1824,503 +1784,6 @@ .4byte \jumpInstr .endm -@ various command changed to more readable macros - .macro cancelmultiturnmoves battler:req - various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES - .endm - - .macro getifcantrunfrombattle battler:req - various \battler, VARIOUS_IS_RUNNING_IMPOSSIBLE - .endm - - .macro getmovetarget battler:req - various \battler, VARIOUS_GET_MOVE_TARGET - .endm - - .macro getbattlerfainted battler:req - various \battler, VARIOUS_GET_BATTLER_FAINTED - .endm - - .macro resetswitchinabilitybits battler:req - various \battler, VARIOUS_RESET_SWITCH_IN_ABILITY_BITS - .endm - - .macro updatechoicemoveonlvlup battler:req - various \battler, VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP - .endm - - .macro resetplayerfainted - various BS_ATTACKER, VARIOUS_RESET_PLAYER_FAINTED - .endm - - .macro palaceflavortext battler:req - various \battler, VARIOUS_PALACE_FLAVOR_TEXT - .endm - - .macro arenajudgmentwindow - various BS_ATTACKER, VARIOUS_ARENA_JUDGMENT_WINDOW - .endm - - .macro arenaopponentmonlost - various BS_ATTACKER, VARIOUS_ARENA_OPPONENT_MON_LOST - .endm - - .macro arenaplayermonlost - various BS_ATTACKER, VARIOUS_ARENA_PLAYER_MON_LOST - .endm - - .macro arenabothmonlost - various BS_ATTACKER, VARIOUS_ARENA_BOTH_MONS_LOST - .endm - - .macro forfeityesnobox battler:req - various \battler, VARIOUS_EMIT_YESNOBOX - .endm - - .macro arenadrawreftextbox - various BS_ATTACKER, VARIOUS_DRAW_ARENA_REF_TEXT_BOX - .endm - - .macro arenaerasereftextbox - various BS_ATTACKER, VARIOUS_ERASE_ARENA_REF_TEXT_BOX - .endm - - .macro arenajudgmentstring id:req - various \id, VARIOUS_ARENA_JUDGMENT_STRING - .endm - - .macro arenawaitmessage id:req - various \id, VARIOUS_ARENA_WAIT_STRING - .endm - - .macro waitcry battler:req - various \battler, VARIOUS_WAIT_CRY - .endm - - .macro returnopponentmon1toball battler:req - various \battler, VARIOUS_RETURN_OPPONENT_MON1 - .endm - - .macro returnopponentmon2toball battler:req - various \battler, VARIOUS_RETURN_OPPONENT_MON2 - .endm - - .macro volumedown - various BS_ATTACKER, VARIOUS_VOLUME_DOWN - .endm - - .macro volumeup - various BS_ATTACKER, VARIOUS_VOLUME_UP - .endm - - .macro setalreadystatusedmoveattempt battler:req - various \battler, VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT - .endm - - .macro palacetryescapestatus battler:req - various \battler, VARIOUS_PALACE_TRY_ESCAPE_STATUS - .endm - - .macro setoutcomeonteleport battler:req - various \battler, VARIOUS_SET_TELEPORT_OUTCOME - .endm - - .macro playtrainerdefeatbgm battler:req - various \battler, VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC - .endm - - .macro stattextbuffer battler:req - various \battler, VARIOUS_STAT_TEXT_BUFFER - .endm - - .macro switchinabilities battler:req - various \battler, VARIOUS_SWITCHIN_ABILITIES - .endm - - .macro instanthpdrop battler:req - various \battler, VARIOUS_INSTANT_HP_DROP - .endm - - .macro clearstatus battler:req - various \battler, VARIOUS_CLEAR_STATUS - .endm - - .macro restorepp battler:req - various \battler, VARIOUS_RESTORE_PP - .endm - - .macro tryactivatereceiver battler:req - various \battler, VARIOUS_TRY_ACTIVATE_RECEIVER - .endm - - .macro tryactivatesoulheart - various BS_ATTACKER, VARIOUS_TRY_ACTIVATE_SOULHEART - .endm - - .macro playmoveanimation battler:req, move:req - various \battler, VARIOUS_PLAY_MOVE_ANIMATION - .2byte \move - .endm - - .macro setluckychant battler:req, failInstr:req - various \battler VARIOUS_SET_LUCKY_CHANT - .4byte \failInstr - .endm - - .macro suckerpunchcheck failInstr:req - various BS_ATTACKER, VARIOUS_SUCKER_PUNCH_CHECK - .4byte \failInstr - .endm - - .macro setabilitysimple battler:req, failInstr:req - various \battler VARIOUS_SET_SIMPLE_BEAM - .4byte \failInstr - .endm - - .macro tryentrainment failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ENTRAINMENT - .4byte \failInstr - .endm - - .macro setlastusedability battler:req - various \battler, VARIOUS_SET_LAST_USED_ABILITY - .endm - - .macro tryafteryou failInstr:req - various BS_ATTACKER, VARIOUS_AFTER_YOU - .4byte \failInstr - .endm - - .macro trybestow failInstr:req - various BS_ATTACKER, VARIOUS_BESTOW - .4byte \failInstr - .endm - - .macro invertstatstages battler:req - various \battler, VARIOUS_INVERT_STAT_STAGES - .endm - - .macro trymefirst failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ME_FIRST - .4byte \failInstr - .endm - - .macro jumpifbattleend jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_BATTLE_END - .4byte \jumpInstr - .endm - - .macro tryelectrify failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ELECTRIFY - .4byte \failInstr - .endm - - .macro trysoak failInstr:req - various BS_ATTACKER, VARIOUS_TRY_SOAK - .4byte \failInstr - .endm - - .macro handleformchange battler:req, case:req - various \battler, VARIOUS_HANDLE_FORM_CHANGE - .byte \case - .endm - - .macro jumpifcantuselastresort battler:req, jumpInstr:req - various \battler, VARIOUS_TRY_LAST_RESORT - .4byte \jumpInstr - .endm - - .macro tryautotomize battler:req, failInstr:req - various \battler, VARIOUS_TRY_AUTOTOMIZE - .4byte \failInstr - .endm - - .macro jumpifcantusesynchronoise jumpInstr:req - various BS_ATTACKER, VARIOUS_TRY_SYNCHRONOISE - .4byte \jumpInstr - .endm - - .macro showabilitypopup battler:req - various \battler, VARIOUS_ABILITY_POPUP - .endm - - .macro updateabilitypopup battler:req - various \battler, VARIOUS_UPDATE_ABILITY_POPUP - .endm - - .macro jumpiftargetally jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_TARGET_ALLY - .4byte \jumpInstr - .endm - - .macro trypsychoshift failInstr:req sleepClauseFailInstr:req - various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT - .4byte \failInstr - .4byte \sleepClauseFailInstr - .endm - - .macro curestatus battler:req - various \battler, VARIOUS_CURE_STATUS - .endm - - .macro powertrick battler:req - various \battler, VARIOUS_POWER_TRICK - .endm - - .macro jumpifnotgrounded battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_GROUNDED - .4byte \jumpInstr - .endm - - .macro handletrainerslidemsg battler:req, case:req - various \battler, VARIOUS_HANDLE_TRAINER_SLIDE_MSG - .byte \case - .endm - - .macro trytrainerslidefirstdownmsg battler:req - various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF - .endm - - .macro trytrainerslidelastonmsg battler:req - various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON - .endm - - .macro setauroraveil battler:req - various \battler, VARIOUS_SET_AURORA_VEIL - .endm - - .macro trysetthirdtype battler:req, failInstr:req - various \battler, VARIOUS_TRY_THIRD_TYPE - .4byte \failInstr - .endm - - .macro tryaccupressure battler:req, failInstr:req - various \battler, VARIOUS_ACUPRESSURE - .4byte \failInstr - .endm - - .macro setpowder battler:req - various \battler, VARIOUS_SET_POWDER - .endm - - .macro bringdownairbornebattler battler:req - various \battler, VARIOUS_GRAVITY_ON_AIRBORNE_MONS - .endm - - .macro checkgrassyterrainheal battler:req, failInstr:req - various \battler, VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS - .4byte \failInstr - .endm - - .macro jumpifnotberry battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_BERRY - .4byte \jumpInstr - .endm - - .macro jumpifroarfails jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_ROAR_FAILS - .4byte \jumpInstr - .endm - - .macro tryinstruct failInstr:req - various BS_ATTACKER, VARIOUS_TRY_INSTRUCT - .4byte \failInstr - .endm - - .macro settracedability battler:req - various \battler, VARIOUS_TRACE_ABILITY - .endm - - .macro updatenick battler:req - various \battler, VARIOUS_UPDATE_NICK - .endm - - .macro tryillusionoff battler:req - various \battler, VARIOUS_TRY_ILLUSION_OFF - .endm - - .macro spriteignore0hp value:req - various BS_ATTACKER, VARIOUS_SET_SPRITEIGNORE0HP - .byte \value - .endm - - .macro getstatvalue battler:req, stat:req - various \battler, VARIOUS_GET_STAT_VALUE - .byte \stat - .endm - - .macro jumpiffullhp battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_FULL_HP - .4byte \jumpInstr - .endm - - .macro losetype battler:req, type:req - various \battler, VARIOUS_LOSE_TYPE - .byte \type - .endm - - .macro tryfriskmsg battler:req - various \battler, VARIOUS_TRY_FRISK - .endm - - .macro jumpifshieldsdown battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED - .4byte \jumpInstr - .endm - - .macro trysetfairylock failInstr:req - various BS_ATTACKER, VARIOUS_TRY_FAIRY_LOCK - .4byte \failInstr - .endm - - .macro jumpifnoally battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NO_ALLY - .4byte \jumpInstr - .endm - - .macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req, equal=TRUE - various \battler, VARIOUS_JUMP_IF_HOLD_EFFECT - .byte \holdEffect - .4byte \jumpInstr - .byte \equal - .endm - - .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req - jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE - .endm - - .macro infatuatewithbattler battler:req, infatuateWith:req - various \battler, VARIOUS_INFATUATE_WITH_BATTLER - .byte \infatuateWith - .endm - - .macro setlastuseditem battler:req - various \battler, VARIOUS_SET_LAST_USED_ITEM - .endm - - .macro jumpifabsent battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_ABSENT - .4byte \jumpInstr - .endm - - .macro destroyabilitypopup - various BS_ABILITY_BATTLER, VARIOUS_DESTROY_ABILITY_POPUP - .endm - - .macro gettotemboost jumpInstr:req - various BS_ATTACKER, VARIOUS_TOTEM_BOOST - .4byte \jumpInstr - .endm - - .macro consumeberry battler:req, fromBattler:req - various \battler, VARIOUS_CONSUME_BERRY - .byte \fromBattler - .endm - - .macro activateitemeffects battler:req - various \battler, VARIOUS_MOVEEND_ITEM_EFFECTS - .endm - - .macro pickpocketsteal - various 0, VARIOUS_PICKPOCKET - .endm - - .macro doterrainseed battler:req, failInstr:req - various \battler, VARIOUS_TERRAIN_SEED - .4byte \failInstr - .endm - - .macro makeinvisible battler:req - various \battler, VARIOUS_MAKE_INVISIBLE - .endm - - .macro tryroomservice battler:req, failInstr:req - various \battler, VARIOUS_ROOM_SERVICE - .4byte \failInstr - .endm - - .macro jumpifpranksterblocked battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED - .4byte \jumpInstr - .endm - - .macro jumpifteamhealthy battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_TEAM_HEALTHY - .4byte \jumpInstr - .endm - - .macro tryhealquarterhealth battler:req, failInstr:req - various \battler, VARIOUS_TRY_HEAL_QUARTER_HP - .4byte \failInstr - .endm - - .macro trytoclearprimalweather - various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER - .endm - - .macro setattackertostickywebuser - various BS_TARGET, VARIOUS_SET_ATTACKER_STICKY_WEB_USER - .endm - - .macro getrototillertargets failInstr:req - various BS_ATTACKER, VARIOUS_GET_ROTOTILLER_TARGETS - .4byte \failInstr - .endm - - .macro jumpifnotrototilleraffected battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED - .4byte \jumpInstr - .endm - - .macro jumpifcantreverttoprimal jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL - .4byte \jumpInstr - .endm - - .macro jumpifweatheraffected battler:req, flags:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_WEATHER_AFFECTED - .4byte \flags - .4byte \jumpInstr - .endm - - .macro jumpifspecies battler:req, species:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_SPECIES - .2byte \species - .4byte \jumpInstr - .endm - - .macro tryendneutralizinggas battler:req - various \battler, VARIOUS_TRY_END_NEUTRALIZING_GAS - .endm - - .macro trynoretreat battler:req, failInstr:req - various \battler, VARIOUS_TRY_NO_RETREAT - .4byte \failInstr - .endm - - .macro checkpoltergeist battler:req, failInstr:req - various \battler, VARIOUS_CHECK_POLTERGEIST - .4byte \failInstr - .endm - - .macro cutonethirdhpraisestats failInstr:req - various BS_ATTACKER, VARIOUS_CUT_1_3_HP_RAISE_STATS - .4byte \failInstr - .endm - - .macro curecertainstatuses battler:req - various \battler, VARIOUS_CURE_CERTAIN_STATUSES - .endm - - .macro tryresetnegativestatstages battler:req - various \battler, VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES - .endm - - .macro jumpiflastuseditemberry jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY - .4byte \jumpInstr - .endm - .macro jumpiflastuseditemholdeffect holdEffect:req, secondaryId:req, jumpInstr:req callnative BS_JumpIfLastUsedItemHoldEffect .byte \holdEffect @@ -2328,23 +1791,6 @@ .4byte \jumpInstr .endm - .macro savebattleritem battler:req - various \battler, VARIOUS_SAVE_BATTLER_ITEM - .endm - - .macro restorebattleritem battler:req - various \battler, VARIOUS_RESTORE_BATTLER_ITEM - .endm - - .macro battleritemtolastuseditem battler:req - various \battler, VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM - .endm - -@ various remaining from pokefirered - .macro getbattlersforrecall - various BS_ATTACKER, VARIOUS_GET_BATTLERS_FOR_RECALL - .endm - .macro swapsidestatuses callnative BS_CourtChangeSwapSideStatuses .endm @@ -2363,12 +1809,9 @@ setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7 .endm - .macro chosenstatus1animation battler:req, status:req - chosenstatusanimation \battler, 0x0, \status - .endm - - .macro chosenstatus2animation battler:req, status:req - chosenstatusanimation \battler, 0x1, \status + .macro setmoveeffect effect:req + sethword sMOVE_EFFECT, \effect + sethword sSAVED_MOVE_EFFECT, \effect .endm .macro sethword dst:req, value:req @@ -2415,14 +1858,6 @@ jumpifhalfword CMP_NOT_EQUAL, gChosenMove, \move, \jumpInstr .endm - .macro jumpifstatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, FALSE, \jumpInstr - .endm - - .macro jumpifnostatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, TRUE, \jumpInstr - .endm - .macro jumpifmovehadnoeffect jumpInstr:req jumpifmoveresultflags MOVE_RESULT_NO_EFFECT, \jumpInstr .endm @@ -2471,6 +1906,516 @@ .byte \battler .endm + .macro trysynchronoise jumpInstr:req + callnative BS_TrySynchronoise + .4byte \jumpInstr + .endm + + .macro jumpifroarfails jumpInstr:req + callnative BS_JumpIfRoarFails + .4byte \jumpInstr + .endm + + .macro jumpifabsent battler:req, jumpInstr:req + callnative BS_JumpIfAbsent + .byte \battler + .4byte \jumpInstr + .endm + + .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req + jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE + .endm + + .macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req, equal:req + callnative BS_JumpIfHoldEffect + .byte \battler + .byte \holdEffect + .4byte \jumpInstr + .byte \equal + .endm + + .macro jumpifnoally battler:req, jumpInstr:req + callnative BS_JumpIfNoAlly + .byte \battler + .4byte \jumpInstr + .endm + + .macro infatuatewithbattler battler:req, infatuateWith:req + callnative BS_InfatuateWithBattler + .byte \battler + .byte \infatuateWith + .endm + + .macro setlastuseditem battler:req + callnative BS_SetLastUsedItem + .byte \battler + .endm + + .macro trysetfairylock failInstr:req + callnative BS_TrySetFairyLock + .4byte \failInstr + .endm + + .macro getstatvalue stat:req + callnative BS_GetStatValue + .byte \stat + .endm + + .macro jumpiffullhp battler:req, jumpInstr:req + callnative BS_JumpIfFullHp + .byte \battler + .4byte \jumpInstr + .endm + + .macro tryfriskmessage + callnative BS_TryFriskMessage + .endm + + .macro settracedability battler:req + callnative BS_SetTracedAbility + .byte \battler + .endm + + .macro tryillusionoff battler:req + callnative BS_TryIllusionOff + .byte \battler + .endm + + .macro setspriteignore0hp ignore0HP:req + callnative BS_SetSpriteIgnore0Hp + .byte \ignore0HP + .endm + + .macro updatenick + callnative BS_UpdateNick + .endm + + .macro jumpifnotberry battler:req, jumpInstr:req + callnative BS_JumpIfNotBerry + .byte \battler + .4byte \jumpInstr + .endm + + .macro gravityonairbornemons + callnative BS_GravityOnAirborneMons + .endm + + .macro tryacupressure failInstr:req + callnative BS_TryAcupressure + .4byte \failInstr + .endm + + .macro cancelmultiturnmoves + callnative BS_CancelMultiTurnMoves + .endm + + .macro isrunningimpossible + callnative BS_IsRunningImpossible + .endm + + .macro getmovetarget + callnative BS_GetMoveTarget + .endm + + @ Will jump to script pointer if the specified battler has or has not fainted. + .macro jumpiffainted battler:req, value:req, ptr:req + getbattlerfainted \battler + jumpifbyte CMP_EQUAL, gBattleCommunication, \value, \ptr + .endm + + .macro getbattlerfainted battler:req + callnative BS_GetBattlerFainted + .byte \battler + .endm + + .macro resetswitchinabilitybits + callnative BS_ResetSwitchInAbilityBits + .endm + + .macro updatechoicemoveonlvlup + callnative BS_UpdateChoiceMoveOnLvlUp + .endm + + .macro resetplayerfainted + callnative BS_ResetPlayerFainted + .endm + + .macro palaceflavortext + callnative BS_PalaceFlavorText + .endm + + .macro arenajudgmentwindow + callnative BS_ArenaJudgmentWindow + .endm + + .macro arenaopponentmonlost + callnative BS_ArenaOpponentMonLost + .endm + + .macro arenaplayermonlost + callnative BS_ArenaPlayerMonLost + .endm + + .macro arenabothmonslost + callnative BS_ArenaBothMonsLost + .endm + + .macro forfeityesnobox + callnative BS_ForfeitYesNoBox + .endm + + .macro drawarenareftextbox + callnative BS_DrawArenaRefTextBox + .endm + + .macro erasearenareftextbox + callnative BS_EraseArenaRefTextBox + .endm + + .macro arenajudgmentstring id:req + callnative BS_ArenaJudgmentString + .byte \id + .endm + + .macro arenawaitmessage id:req + callnative BS_ArenaWaitMessage + .byte \id + .endm + + .macro waitcry + callnative BS_WaitCry + .endm + + .macro returnopponentmon1toball + callnative BS_ReturnOpponentMon1ToBall + .endm + + .macro returnopponentmon2toball + callnative BS_ReturnOpponentMon2ToBall + .endm + + .macro volumedown + callnative BS_VolumeDown + .endm + + .macro volumeup + callnative BS_VolumeUp + .endm + + .macro setalreadystatusedmoveattempt + callnative BS_SetAlreadyStatusedMoveAttempt + .endm + + .macro palacetryescapestatus + callnative BS_PalaceTryEscapeStatus + .endm + + .macro setteleportoutcome battler:req + callnative BS_SetTeleportOutcome + .byte \battler + .endm + + .macro playtrainerdefeatedmusic + callnative BS_PlayTrainerDefeatedMusic + .endm + + .macro stattextbuffer + callnative BS_StatTextBuffer + .endm + + .macro switchinabilities battler:req + callnative BS_SwitchinAbilities + .byte \battler + .endm + + .macro instanthpdrop + callnative BS_InstantHpDrop + .endm + + .macro clearstatus + callnative BS_ClearStatus + .endm + + .macro restoremovepp + callnative BS_RestoreMovePp + .endm + + .macro tryactivatereceiver battler:req + callnative BS_TryActivateReceiver + .byte \battler + .endm + + .macro tryactivatesoulheart + callnative BS_TryActivateSoulheart + .endm + + .macro playmoveanimation move:req + callnative BS_PlayMoveAnimation + .2byte \move + .endm + + .macro setluckychant failInstr:req + callnative BS_SetLuckyChant + .4byte \failInstr + .endm + + .macro setsimplebeam failInstr:req + callnative BS_SetSimpleBeam + .4byte \failInstr + .endm + + .macro tryentrainment failInstr:req + callnative BS_TryEntrainment + .4byte \failInstr + .endm + + .macro setlastusedability + callnative BS_SetLastUsedAbility + .endm + + .macro invertstatstages + callnative BS_InvertStatStages + .endm + + .macro tryelectrify failInstr:req + callnative BS_TryElectrify + .4byte \failInstr + .endm + + .macro trysoak failInstr:req + callnative BS_TrySoak + .4byte \failInstr + .endm + + .macro handleformchange battler:req, case_:req + callnative BS_HandleFormChange + .byte \battler + .byte \case_ + .endm + + .macro tryautotomize failInstr:req + callnative BS_TryAutotomize + .4byte \failInstr + .endm + + .macro tryinstruct failInstr:req + callnative BS_TryInstruct + .4byte \failInstr + .endm + + .macro showabilitypopup + callnative BS_ShowAbilityPopup + .endm + + .macro updateabilitypopup + callnative BS_UpdateAbilityPopup + .endm + + .macro jumpiftargetally jumpInstr:req + callnative BS_JumpIfTargetAlly + .4byte \jumpInstr + .endm + + .macro trypsychoshift failInstr:req sleepClauseFailInstr:req + callnative BS_TryPsychoShift + .4byte \failInstr + .4byte \sleepClauseFailInstr + .endm + + .macro curestatus battler:req + callnative BS_CureStatus + .byte \battler + .endm + + .macro powertrick + callnative BS_PowerTrick + .endm + + .macro tryafteryou failInstr:req + callnative BS_TryAfterYou + .4byte \failInstr + .endm + + .macro trybestow failInstr:req + callnative BS_TryBestow + .4byte \failInstr + .endm + + .macro handletrainerslidemsg battler:req, case_:req + callnative BS_HandleTrainerSlideMsg + .byte \battler + .byte \case_ + .endm + + .macro trytrainerslidemsgfirstoff battler:req + callnative BS_TryTrainerSlideMsgFirstOff + .byte \battler + .endm + + .macro trytrainerslidemsglaston battler:req + callnative BS_TryTrainerSlideMsgLastOn + .byte \battler + .endm + + .macro setauroraveil + callnative BS_SetAuroraVeil + .endm + + .macro trythirdtype failInstr:req + callnative BS_TryThirdType + .4byte \failInstr + .endm + + .macro destroyabilitypopup + callnative BS_DestroyAbilityPopup + .endm + + .macro gettotemboost jumpInstr:req + callnative BS_GetTotemBoost + .4byte \jumpInstr + .endm + + .macro activateitemeffects + callnative BS_ActivateItemEffects + .endm + + .macro tryroomservice battler:req, failInstr:req + callnative BS_TryRoomService + .byte \battler + .4byte \failInstr + .endm + + .macro tryterrainseed battler:req, failInstr:req + callnative BS_TryTerrainSeed + .byte \battler + .4byte \failInstr + .endm + + .macro makeinvisible battler:req + callnative BS_MakeInvisible + .byte \battler + .endm + + .macro jumpifteamhealthy jumpInstr:req + callnative BS_JumpIfTeamHealthy + .4byte \jumpInstr + .endm + + .macro tryhealquarterhealth battler:req, failInstr:req + callnative BS_TryHealQuarterHealth + .byte \battler + .4byte \failInstr + .endm + + .macro jumpifunder200 jumpInstr:req + callnative BS_JumpIfUnder200 + .4byte \jumpInstr + .endm + + .macro setskydrop + callnative BS_SetSkyDrop + .endm + + .macro clearskydrop failInstr:req + callnative BS_ClearSkyDrop + .4byte \failInstr + .endm + + .macro skydropyawn + callnative BS_SkyDropYawn + .endm + + .macro jumpifpranksterblocked jumpInstr:req + callnative BS_JumpIfPranksterBlocked + .4byte \jumpInstr + .endm + + .macro trytoclearprimalweather + callnative BS_TryToClearPrimalWeather + .endm + + .macro tryendneutralizinggas + callnative BS_TryEndNeutralizingGas + .endm + + .macro getrototillertargets failInstr:req + callnative BS_GetRototillerTargets + .4byte \failInstr + .endm + + .macro jumpifnotrototilleraffected jumpInstr:req + callnative BS_JumpIfNotRototillerAffected + .4byte \jumpInstr + .endm + + .macro consumeberry battler:req, fromBattler:req + callnative BS_ConsumeBerry + .byte \battler + .byte \fromBattler + .endm + + .macro jumpifweatheraffected flags:req, jumpInstr:req + callnative BS_JumpIfWeatherAffected + .2byte \flags + .4byte \jumpInstr + .endm + + .macro jumpifspecies species:req, jumpInstr:req + callnative BS_JumpIfSpecies + .2byte \species + .4byte \jumpInstr + .endm + + .macro jumpifleafguardprotected battler:req, jumpInstr:req + callnative BS_JumpIfLeafGuardProtected + .byte \battler + .4byte \jumpInstr + .endm + + .macro setattackertostickywebuser + callnative BS_SetAttackerToStickyWebUser + .endm + + .macro cutonethirdhpandraisestats failInstr:req + callnative BS_CutOneThirdHpAndRaiseStats + .4byte \failInstr + .endm + + .macro setpoltergeistmessage failInstr:req + callnative BS_SetPoltergeistMessage + .4byte \failInstr + .endm + + .macro curecertainstatuses + callnative BS_CureCertainStatuses + .endm + + .macro tryresetnegativestatstages + callnative BS_TryResetNegativeStatStages + .endm + + .macro jumpiflastuseditemberry jumpInstr:req + callnative BS_JumpIfLastUsedItemBerry + .4byte \jumpInstr + .endm + + .macro savebattleritem + callnative BS_SaveBattlerItem + .endm + + .macro restorebattleritem + callnative BS_RestoreBattlerItem + .endm + + .macro battleritemtolastuseditem + callnative BS_BattlerItemToLastUsedItem + .endm + +@ various remaining from pokefirered + .macro getbattlersforrecall + callnative BS_GetBattlersForRecall + .endm + .macro setallytonexttarget jumpInstr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 @@ -2489,40 +2434,12 @@ goto \jumpInstr .endm - .macro jumpifleafguardprotected battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED - .4byte \jumpInstr - .endm - .macro jumpifsafeguard jumpInstr:req jumpifability BS_ATTACKER, ABILITY_INFILTRATOR, 1f jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, \jumpInstr 1: .endm - @ Will jump to script pointer if the target weighs less than 200 kg, or 441 lbs. - .macro jumpifunder200 battler:req, failInstr:req - various \battler, VARIOUS_JUMP_IF_UNDER_200 - .4byte \failInstr - .endm - - @ Sets the sky drop status and does all other necessary operations - .macro setskydrop - various 0, VARIOUS_SET_SKY_DROP - .endm - - @ Clears the sky drop status and does all other necessary operations. - @ If the target fainted in before this script is called, it goes to the given script. - .macro clearskydrop failInstr:req - various 0, VARIOUS_CLEAR_SKY_DROP - .4byte \failInstr - .endm - - @ Accounts for if the target of Sky Drop was in confuse_lock when the attacker falls asleep due to Yawn. - .macro skydropyawn - various 0, VARIOUS_SKY_DROP_YAWN - .endm - @ Tries to increase or decrease a battler's stat's stat stage by a specified amount. If impossible, jumps to \script. .macro modifybattlerstatstage battler:req, stat:req, mode:req, amount:req, script:req, animation:req, customString @@ -2553,12 +2470,6 @@ waitmessage B_WAIT_TIME_LONG .endm - @ Will jump to script pointer if the specified battler has or has not fainted. - .macro jumpiffainted battler:req, value:req, ptr:req - getbattlerfainted \battler - jumpifbyte CMP_EQUAL, gBattleCommunication, \value, \ptr - .endm - .macro flushtextbox printstring STRINGID_EMPTYSTRING3 waitmessage 1 @@ -2573,3 +2484,10 @@ callnative BS_TryBoosterEnergy .byte \onFieldStatus .endm + + .macro jumpifgenconfiglowerthan tag:req, gen:req, jumpInstr:req + callnative BS_JumpIfGenConfigLowerThan + .2byte \tag + .byte \gen + .4byte \jumpInstr + .endm diff --git a/charmap.txt b/charmap.txt index 7856eee85..1db0a9c41 100644 --- a/charmap.txt +++ b/charmap.txt @@ -385,7 +385,7 @@ B_LAST_ITEM = FD 16 B_LAST_ABILITY = FD 17 B_ATK_ABILITY = FD 18 B_DEF_ABILITY = FD 19 -B_SCR_ACTIVE_ABILITY = FD 1A +B_SCR_ABILITY = FD 1A B_EFF_ABILITY = FD 1B B_TRAINER1_CLASS = FD 1C B_TRAINER1_NAME = FD 1D @@ -431,8 +431,8 @@ B_TRAINER1_NAME_WITH_CLASS = FD 42 B_TRAINER2_NAME_WITH_CLASS = FD 43 B_PARTNER_NAME_WITH_CLASS = FD 44 B_ATK_TRAINER_NAME_WITH_CLASS = FD 45 -B_SCR_TEAM1 = FD 46 -B_SCR_TEAM2 = FD 47 +B_EFF_TEAM1 = FD 46 +B_EFF_TEAM2 = FD 47 @ indicates the end of a town/city name (before " TOWN" or " CITY") NAME_END = FC 00 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index ac30b7ed5..75fb05788 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -14,33 +14,21 @@ #include "constants/game_stat.h" #include "constants/trainers.h" #include "constants/species.h" +#include "constants/generational_changes.h" .include "asm/macros.inc" .include "asm/macros/battle_script.inc" .include "constants/constants.inc" .section script_data, "aw", %progbits -BattleScript_RivalBattleLost:: - jumpifhasnohp BS_ATTACKER, BattleScript_RivalBattleLostSkipMonRecall - printstring STRINGID_TRAINER1MON1COMEBACK - waitmessage B_WAIT_TIME_LONG - returnatktoball - waitstate -BattleScript_RivalBattleLostSkipMonRecall:: - trainerslidein BS_ATTACKER - waitstate - printstring STRINGID_TRAINER1WINTEXT - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 2, BattleScript_LocalBattleLostPrintWhiteOut - end2 - BattleScript_BattleTowerLost:: getbattlersforrecall jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0, BattleScript_BattleTowerLostLostSkipMonRecall printfromtable gDoubleBattleRecallStrings waitmessage B_WAIT_TIME_LONG - returnopponentmon1toball BS_ATTACKER + returnopponentmon1toball waitstate - returnopponentmon2toball BS_ATTACKER + returnopponentmon2toball waitstate BattleScript_BattleTowerLostLostSkipMonRecall:: trainerslidein BS_ATTACKER @@ -99,8 +87,6 @@ BattleScript_SilphScopeUnveiled:: BattleScript_EffectFickleBeam:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE ficklebeamdamagecalculation goto BattleScript_HitFromCritCalc @@ -157,19 +143,14 @@ BattleScript_LowerAtkSpAtkEnd: BattleScript_EffectSpicyExtract:: attackcanceler jumpifsubstituteblocks BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_SpicyExtract_CheckShouldSkipAttackAnim jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_SpicyExtract_CheckShouldSkipAttackAnim goto BattleScript_ButItFailed BattleScript_SpicyExtract_CheckShouldSkipAttackAnim: jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0, BattleScript_SpicyExtract_RaiseAtk - attackstring - ppreduce - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT goto BattleScript_SpicyExtract_SkipAttackAnim BattleScript_SpicyExtract_RaiseAtk: - attackstring - ppreduce attackanimation waitanimation BattleScript_SpicyExtract_SkipAttackAnim: @@ -187,9 +168,7 @@ BattleScript_EffectSpicyExtract_End: BattleScript_EffectTidyUp:: attackcanceler - attackstring pause B_WAIT_TIME_MED - ppreduce waitstate saveattacker savetarget @@ -210,20 +189,18 @@ BattleScript_EffectTidyUpDoMoveAnimation:: BattleScript_EffectUpperHand:: attackcanceler - tryupperhand BattleScript_FailedFromAtkString + tryupperhand BattleScript_ButItFailed goto BattleScript_HitFromAccCheck BattleScript_EffectShedTail:: attackcanceler - attackstring - ppreduce waitstate jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_AlreadyHasSubstitute jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString - orword gHitMarker, HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -241,14 +218,12 @@ BattleScript_EffectPsychicNoise:: BattleScript_EffectFilletAway:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ButItFailed BattleScript_FilletAwayTryAttack:: halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation setstatchanger STAT_ATK, 2, FALSE @@ -273,34 +248,33 @@ BattleScript_FilletAwayEnd:: BattleScript_EffectDoodle:: attackcanceler - attackstring - ppreduce trycopyability BS_ATTACKER, BattleScript_ButItFailed + saveattacker attackanimation waitanimation setbyte gBattleCommunication, 0 goto BattleScript_EffectDoodle_AfterCopy BattleScript_EffectDoodle_CopyAbility: - trycopyability BS_ATTACKER, BattleScript_MoveEnd + trycopyability BS_ATTACKER, BattleScript_EffectDoodleMoveEnd BattleScript_EffectDoodle_AfterCopy: -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd addbyte gBattleCommunication, 1 - jumpifnoally BS_ATTACKER, BattleScript_MoveEnd + jumpifnoally BS_ATTACKER, BattleScript_EffectDoodleMoveEnd setallytonextattacker BattleScript_EffectDoodle_CopyAbility +BattleScript_EffectDoodleMoveEnd: + restoreattacker goto BattleScript_MoveEnd BattleScript_EffectGlaiveRush:: call BattleScript_EffectHit_Ret jumpifmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_TryFaintMon - setglaiverush + setvolatile BS_ATTACKER, VOLATILE_GLAIVE_RUSH, 2 goto BattleScript_TryFaintMon BattleScript_SyrupBombActivates:: @@ -322,7 +296,6 @@ BattleScript_EffectChillyReception:: printstring STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE waitmessage B_WAIT_TIME_LONG attackcanceler - ppreduce jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_SUN_PRIMAL, BattleScript_EffectChillyReceptionBlockedByPrimalSun jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_EffectChillyReceptionBlockedByPrimalRain jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_EffectChillyReceptionBlockedByStrongWinds @@ -335,7 +308,6 @@ BattleScript_EffectChillyReception:: call BattleScript_MoveWeatherChangeRet goto BattleScript_MoveSwitch BattleScript_EffectChillyReceptionPlayAnimation: - attackstring attackanimation waitanimation return @@ -352,8 +324,8 @@ BattleScript_EffectChillyReceptionBlockedByStrongWinds: call BattleScript_MysteriousAirCurrentBlowsOnRet goto BattleScript_MoveSwitch BattleScript_EffectChillyReceptionTrySwitchWeatherFailed: - jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_FailedFromAtkString - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_FailedFromAtkString + jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed call BattleScript_EffectChillyReceptionPlayAnimation return @@ -402,9 +374,7 @@ BattleScript_MoveSwitchEnd: BattleScript_EffectPledge:: attackcanceler setpledge BattleScript_HitFromAccCheck - attackstring pause B_WAIT_TIME_MED - ppreduce printstring STRINGID_WAITINGFORPARTNERSMOVE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -475,23 +445,23 @@ BattleScript_MoveEffectSaltCure:: BattleScript_SaltCureExtraDamage:: playanimation BS_ATTACKER, B_ANIM_SALT_CURE_DAMAGE, NULL waitanimation - call BattleScript_HurtTarget_NoString + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER printstring STRINGID_TARGETISHURTBYSALTCURE waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER end2 BattleScript_HurtTarget_NoString: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET return BattleScript_EffectCorrosiveGas:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifsubstituteblocks BattleScript_CorrosiveGasFail jumpifcantloseitem BS_TARGET, BattleScript_CorrosiveGasFail attackanimation @@ -512,8 +482,6 @@ BattleScript_CorrosiveGasFail: BattleScript_EffectTakeHeart:: attackcanceler - attackstring - ppreduce curestatuswithmove BattleScript_CalmMindTryToRaiseStats attackanimation waitanimation @@ -526,8 +494,6 @@ BattleScript_EffectTakeHeart:: BattleScript_EffectRevivalBlessing:: attackcanceler - attackstring - ppreduce tryrevivalblessing BattleScript_ButItFailed attackanimation waitanimation @@ -560,8 +526,6 @@ BattleScript_SpikesActivates:: BattleScript_EffectAttackUpUserAlly:: jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_EffectAttackUpUserAlly_Works jumpifstat BS_ATTACKER_PARTNER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed BattleScript_EffectAttackUpUserAlly_Works: @@ -579,7 +543,7 @@ BattleScript_EffectAttackUpUserAlly_TryAlly_: jumpifblockedbysoundproof BS_ATTACKER_PARTNER, BattleScript_EffectAttackUpUserAlly_TryAllyBlocked setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectAttackUpUserAlly_End - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectAttackUpUserAlly_AllyString + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectAttackUpUserAlly_AllyString pause B_WAIT_TIME_SHORTEST printstring STRINGID_TARGETSTATWONTGOHIGHER waitmessage B_WAIT_TIME_LONG @@ -598,8 +562,6 @@ BattleScript_EffectAttackUpUserAlly_TryAllyBlocked: BattleScript_EffectTeatime:: attackcanceler - attackstring - ppreduce jumpifteanoberry BattleScript_ButItFailed @ at least one battler is affected attackanimation @@ -698,7 +660,7 @@ BattleScript_AffectionBasedStatus_HealFrostbiteString: printstring STRINGID_ATTACKERHEALEDITSFROSTBITE BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER + clearstatus waitstate updatestatusicon BS_ATTACKER waitstate @@ -714,17 +676,13 @@ BattleScript_ShellTrapSetUp:: BattleScript_EffectShellTrap:: attackcanceler jumpifshelltrap BS_ATTACKER, BattleScript_HitFromAccCheck - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT, BattleScript_MoveEnd - ppreduce printstring STRINGID_SHELLTRAPDIDNTWORK waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectCourtChange:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE swapsidestatuses attackanimation waitanimation @@ -749,12 +707,10 @@ BattleScript_BeakBlastBurn:: BattleScript_EffectSkyDrop:: attackcanceler jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_SkyDropTurn2 - ppreduce - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifsubstituteblocks BattleScript_ButItFailed jumpiftargetally BattleScript_ButItFailed - jumpifunder200 BS_TARGET, BattleScript_SkyDropWork + jumpifunder200 BattleScript_SkyDropWork pause B_WAIT_TIME_SHORT printstring STRINGID_TARGETTOOHEAVY waitmessage B_WAIT_TIME_LONG @@ -766,7 +722,6 @@ BattleScript_SkyDropWork: goto BattleScript_MoveEnd BattleScript_SkyDropTurn2: call BattleScript_TwoTurnMovesSecondTurnRet - attackstring clearskydrop BattleScript_SkyDropChangedTarget jumpiftype BS_TARGET, TYPE_FLYING, BattleScript_SkyDropFlyingType goto BattleScript_HitFromCritCalc @@ -796,14 +751,11 @@ BattleScript_SkyDropFlyingAlreadyConfused: BattleScript_EffectFling:: attackcanceler - jumpifcantfling BS_ATTACKER, BattleScript_FailedFromAtkString setlastuseditem BS_ATTACKER accuracycheck BattleScript_FlingMissed, ACC_CURR_MOVE - attackstring pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNFLUNG waitmessage B_WAIT_TIME_SHORT - ppreduce critcalc damagecalc adjustdamage @@ -830,14 +782,14 @@ BattleScript_EffectFling:: jumpiflastuseditemholdeffect HOLD_EFFECT_WHITE_HERB, 0, BattleScript_FlingWhiteHerb goto BattleScript_FlingEnd BattleScript_EffectFlingConsumeBerry: - savebattleritem BS_TARGET - battleritemtolastuseditem BS_TARGET + savebattleritem + battleritemtolastuseditem setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries orword gHitMarker, HITMARKER_DISABLE_ANIMATION consumeberry BS_TARGET, TRUE bicword gHitMarker, HITMARKER_DISABLE_ANIMATION setbyte sBERRY_OVERRIDE, 0 - restorebattleritem BS_TARGET + restorebattleritem BattleScript_FlingEnd: tryfaintmon BS_TARGET trysymbiosis BS_ATTACKER @@ -845,7 +797,7 @@ BattleScript_FlingEnd: BattleScript_FlingFailConsumeItem:: removeitem BS_ATTACKER - goto BattleScript_FailedFromAtkString + goto BattleScript_ButItFailed BattleScript_FlingBlockedByShieldDust:: printstring STRINGID_ITEMWASUSEDUP @@ -862,7 +814,7 @@ BattleScript_FlingLightBall: seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_PARALYSIS goto BattleScript_FlingEnd BattleScript_FlingMentalHerb: - curecertainstatuses BS_TARGET + curecertainstatuses savetarget copybyte gBattlerAttacker, gBattlerTarget playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL @@ -878,7 +830,7 @@ BattleScript_FlingToxicOrb: seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_TOXIC goto BattleScript_FlingEnd BattleScript_FlingWhiteHerb: - tryresetnegativestatstages BS_TARGET + tryresetnegativestatstages swapattackerwithtarget printstring STRINGID_PKMNSTATUSNORMAL waitmessage B_WAIT_TIME_MED @@ -887,21 +839,12 @@ BattleScript_FlingWhiteHerb: BattleScript_FlingMissed: removeitem BS_ATTACKER - attackstring - ppreduce goto BattleScript_MoveMissedPause -BattleScript_EffectAuraWheel:: @ Aura Wheel can only be used by Morpeko - jumpifspecies BS_ATTACKER, SPECIES_MORPEKO_FULL_BELLY, BattleScript_EffectHit - jumpifspecies BS_ATTACKER, SPECIES_MORPEKO_HANGRY, BattleScript_EffectHit - goto BattleScript_PokemonCantUseTheMove - BattleScript_EffectClangorousSoul:: attackcanceler - attackstring - ppreduce - cutonethirdhpraisestats BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_BIDE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE + cutonethirdhpandraisestats BattleScript_ButItFailed + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_BIDE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -911,11 +854,9 @@ BattleScript_EffectClangorousSoul:: BattleScript_EffectOctolock:: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - trysetoctolock BS_TARGET, BattleScript_ButItFailed + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + trysetoctolock BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE @@ -937,21 +878,17 @@ BattleScript_OctlockTurnDmgEnd: BattleScript_EffectPoltergeist:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - checkpoltergeist BS_TARGET, BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + setpoltergeistmessage BattleScript_ButItFailed printstring STRINGID_ABOUTTOUSEPOLTERGEIST waitmessage B_WAIT_TIME_LONG goto BattleScript_HitFromCritCalc BattleScript_EffectTarShot:: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - cantarshotwork BattleScript_FailedFromAtkString - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + cantarshotwork BattleScript_ButItFailed setstatchanger STAT_SPEED, 1, TRUE attackanimation waitanimation @@ -966,10 +903,9 @@ BattleScript_TryTarShot: BattleScript_EffectNoRetreat:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - trynoretreat BS_TARGET, BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + jumpifvolatile BS_TARGET, VOLATILE_NO_RETREAT, BattleScript_ButItFailed + setvolatile BS_TARGET, VOLATILE_NO_RETREAT attackanimation waitanimation call BattleScript_AllStatsUp @@ -985,8 +921,8 @@ BattleScript_BothCanNoLongerEscape:: return BattleScript_EffectHyperspaceFury:: - jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit - jumpifspecies BS_ATTACKER, SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt + jumpifspecies SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit + jumpifspecies SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt goto BattleScript_PokemonCantUseTheMove BattleScript_ButHoopaCantUseIt: @@ -1026,9 +962,6 @@ BattleScript_MoveEffectLightScreen:: BattleScript_EffectStuffCheeks:: attackcanceler - attackstring - ppreduce - jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation setbyte sBERRY_OVERRIDE, 1 @@ -1046,9 +979,7 @@ BattleScript_StuffCheeksEnd: BattleScript_EffectDecorate:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost goto BattleScript_ButItFailed @@ -1070,8 +1001,6 @@ BattleScript_DecorateBoostSpAtk: BattleScript_EffectCoaching:: attackcanceler - attackstring - ppreduce jumpifnoally BS_ATTACKER, BattleScript_ButItFailed copybyte gBattlerTarget, gBattlerAttacker setallytonexttarget EffectCoaching_CheckAllyStats @@ -1099,9 +1028,7 @@ BattleScript_CoachingBoostDef: BattleScript_EffectJungleHealing:: attackcanceler - attackstring - ppreduce - jumpifteamhealthy BS_ATTACKER, BattleScript_ButItFailed + jumpifteamhealthy BattleScript_ButItFailed attackanimation waitanimation copybyte gBattlerTarget, gBattlerAttacker @@ -1115,7 +1042,6 @@ JungleHealing_RestoreTargetHealth: printstring STRINGID_PKMNREGAINEDHEALTH waitmessage B_WAIT_TIME_LONG BattleScript_JungleHealing_TryCureStatus: - jumpifmove MOVE_LIFE_DEW, BattleScript_JungleHealingTryRestoreAlly @ life dew only heals jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_JungleHealingCureStatus goto BattleScript_JungleHealingTryRestoreAlly BattleScript_JungleHealingCureStatus: @@ -1130,11 +1056,40 @@ BattleScript_JungleHealingTryRestoreAlly: setallytonexttarget JungleHealing_RestoreTargetHealth goto BattleScript_MoveEnd +BattleScript_EffectLifeDew:: + attackcanceler + jumpiffullhp BS_ATTACKER, BattleScript_EffectLifeDewCheckPartner + copybyte gBattlerTarget, gBattlerAttacker + attackanimation + waitanimation + call BattleScript_EffectLifeDewHealing + jumpifabsent BS_ATTACKER_PARTNER, BattleScript_EffectLifeDewEnd + jumpiffullhp BS_ATTACKER_PARTNER, BattleScript_EffectLifeDewEnd + setallytonexttarget BattleScript_EffectLifeDewNextTarget +BattleScript_EffectLifeDewNextTarget: + call BattleScript_EffectLifeDewHealing +BattleScript_EffectLifeDewEnd: + goto BattleScript_MoveEnd + +BattleScript_EffectLifeDewCheckPartner: + jumpifabsent BS_ATTACKER_PARTNER, BattleScript_ButItFailed + jumpiffullhp BS_ATTACKER_PARTNER, BattleScript_ButItFailed + attackanimation + waitanimation + setallytonexttarget BattleScript_EffectLifeDewNextTarget + +BattleScript_EffectLifeDewHealing: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + tryhealquarterhealth BS_TARGET, BattleScript_EffectLifeDewEnd + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + printstring STRINGID_PKMNREGAINEDHEALTH + waitmessage B_WAIT_TIME_LONG + return + BattleScript_EffectAllySwitch:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryallyswitch BattleScript_ButItFailed attackanimation waitanimation @@ -1146,9 +1101,7 @@ BattleScript_EffectAllySwitch:: BattleScript_EffectFairyLock:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE trysetfairylock BattleScript_ButItFailed attackanimation waitanimation @@ -1156,14 +1109,6 @@ BattleScript_EffectFairyLock:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_FailIfNotArgType:: - attackcanceler - attackstring - ppreduce - jumpifnotcurrentmoveargtype BS_ATTACKER, BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromCritCalc - BattleScript_RemoveFireType:: printstring STRINGID_ATTACKERLOSTFIRETYPE waitmessage B_WAIT_TIME_LONG @@ -1186,8 +1131,6 @@ BattleScript_DefDown_Ret: BattleScript_EffectPurify:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_PurifyWorks goto BattleScript_ButItFailed @@ -1198,16 +1141,14 @@ BattleScript_PurifyWorks: updatestatusicon BS_TARGET printstring STRINGID_ATTACKERCUREDTARGETSTATUS waitmessage B_WAIT_TIME_LONG - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_ATTACKER + tryhealhalfhealth BS_ATTACKER, BattleScript_AlreadyAtFullHp goto BattleScript_RestoreHp BattleScript_EffectStrengthSap:: setstatchanger STAT_ATK, 1, TRUE attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, MIN_STAT_STAGE, BattleScript_StrengthSapTryLower pause B_WAIT_TIME_SHORT statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd @@ -1215,19 +1156,19 @@ BattleScript_EffectStrengthSap:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_StrengthSapTryLower: - getstatvalue BS_TARGET, STAT_ATK + getstatvalue STAT_ATK jumpiffullhp BS_ATTACKER, BattleScript_StrengthSapMustLower BattleScript_StrengthSapAnimation: attackanimation waitanimation statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_StrengthSapHp - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StrengthSapHp + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StrengthSapHp printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG @ Drain HP without lowering a stat BattleScript_StrengthSapHp: jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_StrengthSapManipulateDmg - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_MoveEnd + jumpifvolatile BS_ATTACKER, VOLATILE_HEAL_BLOCK, BattleScript_MoveEnd jumpiffullhp BS_ATTACKER, BattleScript_MoveEnd BattleScript_StrengthSapManipulateDmg: manipulatedamage DMG_BIG_ROOT @@ -1250,7 +1191,7 @@ BattleScript_StrengthSapLiquidOoze: goto BattleScript_MoveEnd BattleScript_StrengthSapMustLower: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_MoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_MoveEnd goto BattleScript_StrengthSapAnimation BattleScript_MoveEffectIncinerate:: @@ -1283,9 +1224,7 @@ BattleScript_CoreEnforcerRet: BattleScript_EffectLaserFocus:: attackcanceler - attackstring - ppreduce - setuserstatus3 STATUS3_LASER_FOCUS, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_LASER_FOCUS, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_LASERFOCUS @@ -1299,19 +1238,19 @@ BattleScript_VCreateStatLoss:: BattleScript_VCreateStatAnim: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateTrySpDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateTrySpDef: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateTrySpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateTrySpeed: setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_VCreateStatLossRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VCreateStatLossRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VCreateStatLossRet printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VCreateStatLossRet: @@ -1319,7 +1258,7 @@ BattleScript_VCreateStatLossRet: BattleScript_SpectralThiefSteal:: setbyte sB_ANIM_TURN, 1 - playmoveanimation BS_ATTACKER, MOVE_SPECTRAL_THIEF + playmoveanimation MOVE_SPECTRAL_THIEF waitanimation setbyte sB_ANIM_TURN, 0 printstring STRINGID_SPECTRALTHIEFSTEAL @@ -1331,9 +1270,7 @@ BattleScript_SpectralThiefSteal:: BattleScript_EffectSpectralThief:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc tryspectralthiefsteal BattleScript_SpectralThiefSteal BattleScript_EffectSpectralThiefFromDamage: @@ -1347,12 +1284,10 @@ BattleScript_EffectSpectralThiefFromDamage: BattleScript_EffectPartingShot:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_EffectPartingShotTryAtk jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_EffectPartingShotTryAtk: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE attackanimation waitanimation setstatchanger STAT_ATK, 1, TRUE @@ -1370,11 +1305,9 @@ BattleScript_EffectPartingShotSwitch: BattleScript_EffectPowder:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_POWDER, BattleScript_ButItFailed - setpowder BS_TARGET + setvolatile BS_TARGET, VOLATILE_POWDER attackanimation waitanimation printstring STRINGID_COVEREDINPOWDER @@ -1383,8 +1316,6 @@ BattleScript_EffectPowder:: BattleScript_EffectAromaticMist:: attackcanceler - attackstring - ppreduce jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed jumpiftargetally BattleScript_EffectAromaticMistWorks goto BattleScript_ButItFailed @@ -1406,8 +1337,6 @@ BattleScript_EffectAromaticMistWontGoHigher: BattleScript_EffectMagneticFlux:: attackcanceler - attackstring - ppreduce setbyte gBattleCommunication, 0 BattleScript_EffectMagneticFluxStart: jumpifability BS_TARGET, ABILITY_MINUS, BattleScript_EffectMagneticFluxCheckStats @@ -1423,14 +1352,14 @@ BattleScript_EffectMagneticFluxTryDef: BattleScript_EffectMagneticFluxSkipAnim: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMagneticFluxTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectMagneticFluxTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectMagneticFluxTrySpDef addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMagneticFluxTrySpDef: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMagneticFluxLoop - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectMagneticFluxLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectMagneticFluxLoop addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG @@ -1443,8 +1372,6 @@ BattleScript_EffectMagneticFluxEnd: BattleScript_EffectGearUp:: attackcanceler - attackstring - ppreduce setbyte gBattleCommunication, 0 BattleScript_EffectGearUpStart: jumpifability BS_TARGET, ABILITY_MINUS, BattleScript_EffectGearUpCheckStats @@ -1460,14 +1387,14 @@ BattleScript_EffectGearUpTryAtk: BattleScript_EffectGearUpSkipAnim: setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectGearUpTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectGearUpTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectGearUpTrySpAtk addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectGearUpTrySpAtk: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectGearUpLoop - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectGearUpLoop + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectGearUpLoop addbyte gBattleCommunication, 1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG @@ -1481,11 +1408,9 @@ BattleScript_EffectGearUpEnd: BattleScript_EffectAcupressure:: attackcanceler jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_EffectAcupressureTry - jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_PrintMoveMissed + jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_MoveMissedPause BattleScript_EffectAcupressureTry: - attackstring - ppreduce - tryaccupressure BS_TARGET, BattleScript_ButItFailed + tryacupressure BattleScript_ButItFailed attackanimation waitanimation statbuffchange BS_TARGET, STAT_CHANGE_CERTAIN, BattleScript_MoveEnd @@ -1500,10 +1425,8 @@ BattleScript_MoveEffectFeint:: BattleScript_EffectThirdType:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - trysetthirdtype BS_TARGET, BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + trythirdtype BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_THIRDTYPEADDED @@ -1512,24 +1435,26 @@ BattleScript_EffectThirdType:: BattleScript_EffectFlowerShield:: attackcanceler - attackstring - ppreduce + savetarget selectfirstvalidtarget -BattleScript_FlowerShieldIsAnyGrass: +BattleScript_FlowerShieldIsAnyValidTarget: + jumpifvolatile BS_TARGET, VOLATILE_SEMI_INVULNERABLE, BattleScript_FlowerShieldCheckNextTarget jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_FlowerShieldLoopStart - jumpifnexttargetvalid BattleScript_FlowerShieldIsAnyGrass - goto BattleScript_ButItFailed +BattleScript_FlowerShieldCheckNextTarget: + jumpifnexttargetvalid BattleScript_FlowerShieldIsAnyValidTarget + goto BattleScript_RestoreTargetButItFailed BattleScript_FlowerShieldLoopStart: selectfirstvalidtarget BattleScript_FlowerShieldLoop: movevaluescleanup + jumpifvolatile BS_TARGET, VOLATILE_SEMI_INVULNERABLE, BattleScript_FlowerShieldMoveTargetEnd jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_FlowerShieldLoop2 goto BattleScript_FlowerShieldMoveTargetEnd BattleScript_FlowerShieldLoop2: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_FlowerShieldMoveTargetEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_FlowerShieldDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_EMPTY, BattleScript_FlowerShieldMoveTargetEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_FlowerShieldDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_FlowerShieldMoveTargetEnd pause 21 goto BattleScript_FlowerShieldString BattleScript_FlowerShieldDoAnim: @@ -1542,12 +1467,12 @@ BattleScript_FlowerShieldString: BattleScript_FlowerShieldMoveTargetEnd: moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_FlowerShieldLoop + restoretarget + moveendfrom MOVEEND_ITEM_EFFECTS_ATTACKER end BattleScript_EffectRototiller:: attackcanceler - attackstring - ppreduce getrototillertargets BattleScript_ButItFailed @ at least one battler is affected attackanimation @@ -1559,16 +1484,16 @@ BattleScript_RototillerLoop: jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_RototillerCheckAffected jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_RototillerCantRaiseMultipleStats BattleScript_RototillerCheckAffected: - jumpifnotrototilleraffected BS_TARGET, BattleScript_RototillerNoEffect + jumpifnotrototilleraffected BattleScript_RototillerNoEffect setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RototillerTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RototillerTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RototillerTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RototillerTrySpAtk:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RototillerMoveTargetEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RototillerMoveTargetEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RototillerMoveTargetEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RototillerMoveTargetEnd: @@ -1592,9 +1517,7 @@ BattleScript_RototillerNoEffect: BattleScript_EffectBestow:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON jumpifsubstituteblocks BattleScript_ButItFailed trybestow BattleScript_ButItFailed attackanimation @@ -1606,9 +1529,7 @@ BattleScript_EffectBestow:: BattleScript_EffectAfterYou:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryafteryou BattleScript_ButItFailed attackanimation waitanimation @@ -1617,25 +1538,18 @@ BattleScript_EffectAfterYou:: goto BattleScript_MoveEnd BattleScript_MoveEffectFlameBurst:: - tryfaintmon BS_TARGET - copybyte sBATTLER, sSAVED_BATTLER printstring STRINGID_BURSTINGFLAMESHIT waitmessage B_WAIT_TIME_LONG - savetarget - copybyte gBattlerTarget, sSAVED_BATTLER - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - tryfaintmon BS_TARGET - restoretarget - goto BattleScript_MoveEnd + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + tryfaintmon BS_SCRIPTING + return BattleScript_EffectPowerTrick:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - powertrick BS_ATTACKER + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + powertrick attackanimation waitanimation printstring STRINGID_PKMNSWITCHEDATKANDDEF @@ -1644,9 +1558,7 @@ BattleScript_EffectPowerTrick:: BattleScript_EffectPsychoShift:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifstatus BS_ATTACKER, STATUS1_ANY, BattleScript_EffectPsychoShiftCanWork goto BattleScript_ButItFailed BattleScript_EffectPsychoShiftCanWork: @@ -1668,43 +1580,19 @@ BattleScript_EffectPsychoShiftCanWork: BattleScript_EffectSynchronoise:: attackcanceler - attackstring - ppreduce - selectfirstvalidtarget -BattleScript_SynchronoiseLoop: - movevaluescleanup - jumpifcantusesynchronoise BattleScript_SynchronoiseNoEffect - accuracycheck BattleScript_SynchronoiseMissed, ACC_CURR_MOVE - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + pause B_WAIT_TIME_MED + trysynchronoise BattleScript_MoveEnd + accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc + +BattleScript_ItDoesntAffectFoe:: + savetarget + copybyte gBattlerTarget, sBATTLER + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_SHORT flushtextbox - tryfaintmon BS_TARGET -BattleScript_SynchronoiseMoveTargetEnd: - moveendto MOVEEND_NEXT_TARGET - jumpifnexttargetvalid BattleScript_SynchronoiseLoop - end -BattleScript_SynchronoiseMissed: - pause B_WAIT_TIME_SHORT - resultmessage - waitmessage B_WAIT_TIME_LONG - goto BattleScript_SynchronoiseMoveTargetEnd -BattleScript_SynchronoiseNoEffect: - pause B_WAIT_TIME_SHORT - printstring STRINGID_NOEFFECTONTARGET - waitmessage B_WAIT_TIME_LONG - goto BattleScript_SynchronoiseMoveTargetEnd + restoretarget + return BattleScript_MoveEffectSmackDown:: printstring STRINGID_FELLSTRAIGHTDOWN @@ -1721,14 +1609,12 @@ BattleScript_EffectDefog:: jumpifsubstituteblocks BattleScript_DefogIfCanClearHazards jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_EVASION, MIN_STAT_STAGE, BattleScript_DefogWorks BattleScript_DefogIfCanClearHazards: - trydefog FALSE, BattleScript_FailedFromAtkString + trydefog FALSE, BattleScript_ButItFailed BattleScript_DefogWorks: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefogTryHazardsWithAnim - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefogDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_DefogTryHazardsWithAnim + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefogDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_DefogTryHazardsWithAnim pause B_WAIT_TIME_SHORT goto BattleScript_DefogPrintString BattleScript_DefogDoAnim:: @@ -1738,7 +1624,7 @@ BattleScript_DefogDoAnim:: BattleScript_DefogPrintString:: printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG -BattleScript_DefogTryHazards:: +BattleScript_DefogTryHazards: copybyte gEffectBattler, gBattlerAttacker trydefog TRUE, NULL copybyte gBattlerAttacker, gEffectBattler @@ -1748,23 +1634,15 @@ BattleScript_DefogTryHazardsWithAnim: waitanimation goto BattleScript_DefogTryHazards -BattleScript_EffectCopycat:: - attackcanceler - attackstring - pause 5 - trycopycat BattleScript_CopycatFail - attackanimation - waitanimation - jumptocalledmove TRUE -BattleScript_CopycatFail: - ppreduce - goto BattleScript_ButItFailed +BattleScript_MoveEffectDefog:: + saveattacker + trydefog TRUE, NULL + restoreattacker + return BattleScript_EffectInstruct:: attackcanceler - attackstring - ppreduce - pause 5 + pause B_WAIT_TIME_SHORT tryinstruct BattleScript_ButItFailed attackanimation waitanimation @@ -1777,10 +1655,8 @@ BattleScript_EffectInstruct:: BattleScript_EffectAutotomize:: setstatchanger STAT_SPEED, 2, FALSE attackcanceler - attackstring - ppreduce statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_AutotomizeWeightLoss - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AutotomizeAttackAnim + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AutotomizeAttackAnim pause B_WAIT_TIME_SHORT goto BattleScript_AutotomizePrintString BattleScript_AutotomizeAttackAnim:: @@ -1792,7 +1668,7 @@ BattleScript_AutotomizePrintString:: waitmessage B_WAIT_TIME_LONG BattleScript_AutotomizeWeightLoss:: jumpifmovehadnoeffect BattleScript_MoveEnd - tryautotomize BS_ATTACKER, BattleScript_MoveEnd + tryautotomize BattleScript_MoveEnd printstring STRINGID_BECAMENIMBLE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -1818,21 +1694,18 @@ BattleScript_HitSwitchTargetForceRandomSwitchFailed: BattleScript_EffectToxicThread:: setstatchanger STAT_SPEED, 1, TRUE attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_ToxicThreadWorks - jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_FailedFromAtkString -BattleScript_ToxicThreadWorks: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + checknonvolatiletrigger MOVE_EFFECT_POISON, BattleScript_EffectStatDownFromAccCheck + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + attackanimation + waitanimation + setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ToxicThreadTryPsn - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_ToxicThreadDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_ToxicThreadTryPsn + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ToxicThreadDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_ToxicThreadTryPsn pause B_WAIT_TIME_SHORT goto BattleScript_ToxicThreadPrintString BattleScript_ToxicThreadDoAnim:: - attackanimation - waitanimation statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_ToxicThreadTryPsn BattleScript_ToxicThreadPrintString:: printfromtable gStatDownStringIds @@ -1843,8 +1716,6 @@ BattleScript_ToxicThreadTryPsn:: BattleScript_EffectVenomDrench:: attackcanceler - attackstring - ppreduce jumpifstatus BS_TARGET, STATUS1_PSN_ANY, BattleScript_EffectVenomDrenchCanBeUsed goto BattleScript_ButItFailed BattleScript_EffectVenomDrenchCanBeUsed: @@ -1857,19 +1728,19 @@ BattleScript_VenomDrenchDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchTryLowerSpAtk, BIT_SPATK | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchTryLowerSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchTryLowerSpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchTryLowerSpAtk:: setstatchanger STAT_SPATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchTryLowerSpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchTryLowerSpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchTryLowerSpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchTryLowerSpeed:: setstatchanger STAT_SPEED, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_VenomDrenchEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_VenomDrenchEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VenomDrenchEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VenomDrenchEnd:: @@ -1877,8 +1748,6 @@ BattleScript_VenomDrenchEnd:: BattleScript_EffectNobleRoar:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_NobleRoarDoMoveAnim jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_NobleRoarDoMoveAnim:: @@ -1887,13 +1756,13 @@ BattleScript_NobleRoarDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_NobleRoarTryLowerSpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_NobleRoarTryLowerSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_NobleRoarTryLowerSpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_NobleRoarTryLowerSpAtk:: setstatchanger STAT_SPATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_NobleRoarEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_NobleRoarEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_NobleRoarEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_NobleRoarEnd:: @@ -1901,8 +1770,6 @@ BattleScript_NobleRoarEnd:: BattleScript_EffectShellSmash:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ShellSmashTryDef @@ -1913,72 +1780,62 @@ BattleScript_ShellSmashTryDef:: waitanimation setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_ShellSmashTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpDef: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_ShellSmashTryAttack - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTryAttack + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTryAttack printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTryAttack: setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashTrySpAtk, BIT_SPATK | BIT_SPEED, - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpAtk: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashTrySpeed: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShellSmashEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShellSmashEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShellSmashEnd: goto BattleScript_MoveEnd -BattleScript_EffectLastResort:: - attackcanceler - attackstring - ppreduce - jumpifcantuselastresort BS_ATTACKER, BattleScript_ButItFailed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromCritCalc - BattleScript_EffectGrowth:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_GrowthDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_GrowthDoMoveAnim:: attackanimation waitanimation - jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthAtk2 + jumpifweatheraffected B_WEATHER_SUN, BattleScript_GrowthAtk2 setstatchanger STAT_ATK, 1, FALSE goto BattleScript_GrowthAtk BattleScript_GrowthAtk2: setstatchanger STAT_ATK, 2, FALSE BattleScript_GrowthAtk: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GrowthTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GrowthTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GrowthTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GrowthTrySpAtk:: - jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthSpAtk2 + jumpifweatheraffected B_WEATHER_SUN, BattleScript_GrowthSpAtk2 setstatchanger STAT_SPATK, 1, FALSE goto BattleScript_GrowthSpAtk BattleScript_GrowthSpAtk2: setstatchanger STAT_SPATK, 2, FALSE BattleScript_GrowthSpAtk: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GrowthEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GrowthEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GrowthEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GrowthEnd: @@ -1986,9 +1843,7 @@ BattleScript_GrowthEnd: BattleScript_EffectSoak:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET, ABILITY_MULTITYPE, BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_RKS_SYSTEM, BattleScript_ButItFailed jumpifsubstituteblocks BattleScript_ButItFailed @@ -2001,9 +1856,7 @@ BattleScript_EffectSoak:: BattleScript_EffectReflectType:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryreflecttype BattleScript_ButItFailed attackanimation waitanimation @@ -2013,9 +1866,7 @@ BattleScript_EffectReflectType:: BattleScript_EffectElectrify:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryelectrify BattleScript_ButItFailed attackanimation waitanimation @@ -2025,8 +1876,6 @@ BattleScript_EffectElectrify:: BattleScript_EffectShiftGear:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ShiftGearDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_ShiftGearDoMoveAnim: @@ -2039,13 +1888,13 @@ BattleScript_ShiftGearSpeedBy1: setstatchanger STAT_SPEED, 1, FALSE BattleScript_ShiftGearDoSpeed: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShiftGearTryAtk, BIT_ATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShiftGearTryAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShiftGearTryAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShiftGearTryAtk: setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_ShiftGearEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShiftGearEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_ShiftGearEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_ShiftGearEnd: @@ -2053,8 +1902,6 @@ BattleScript_ShiftGearEnd: BattleScript_EffectCoil:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_CoilDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_CoilDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ACC, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2063,19 +1910,19 @@ BattleScript_CoilDoMoveAnim: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilTryDef, BIT_DEF | BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilTryDef: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilTryAcc, BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilTryAcc + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilTryAcc printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilTryAcc: setstatchanger STAT_ACC, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CoilEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CoilEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CoilEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CoilEnd: @@ -2083,8 +1930,6 @@ BattleScript_CoilEnd: BattleScript_EffectQuiverDance:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_QuiverDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_QuiverDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2093,19 +1938,19 @@ BattleScript_QuiverDanceDoMoveAnim:: waitanimation setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_QuiverDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_QuiverDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_QuiverDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_QuiverDanceEnd:: @@ -2113,8 +1958,6 @@ BattleScript_QuiverDanceEnd:: BattleScript_EffectVictoryDance:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_VictoryDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_VictoryDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -2123,36 +1966,26 @@ BattleScript_VictoryDanceDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceTryDef, BIT_DEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceTryDef:: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_VictoryDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_VictoryDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_VictoryDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_VictoryDanceEnd:: goto BattleScript_MoveEnd -BattleScript_EffectMeFirst:: - attackcanceler - attackstring - trymefirst BattleScript_FailedFromPpReduce - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectAttackSpAttackUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AttackSpAttackUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_AttackSpAttackUpDoMoveAnim:: @@ -2160,13 +1993,13 @@ BattleScript_AttackSpAttackUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackSpAttackUpTrySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackSpAttackUpTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackSpAttackUpTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackSpAttackUpTrySpAtk:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackSpAttackUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackSpAttackUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackSpAttackUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackSpAttackUpEnd: @@ -2174,8 +2007,6 @@ BattleScript_AttackSpAttackUpEnd: BattleScript_EffectAttackAccUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AttackAccUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ACC, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_AttackAccUpDoMoveAnim:: @@ -2183,13 +2014,13 @@ BattleScript_AttackAccUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackAccUpTryAcc, BIT_ACC - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackAccUpTryAcc + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackAccUpTryAcc printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackAccUpTryAcc:: setstatchanger STAT_ACC, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackAccUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackAccUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackAccUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AttackAccUpEnd: @@ -2200,9 +2031,7 @@ BattleScript_EffectGrassyTerrain:: BattleScript_EffectElectricTerrain:: BattleScript_EffectPsychicTerrain:: attackcanceler - attackstring - ppreduce - setremoveterrain BattleScript_ButItFailed + setterrain BattleScript_ButItFailed attackanimation waitanimation printfromtable gTerrainStringIds @@ -2213,8 +2042,6 @@ BattleScript_EffectPsychicTerrain:: BattleScript_EffectTopsyTurvy:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 6, BattleScript_EffectTopsyTurvyWorks jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 6, BattleScript_EffectTopsyTurvyWorks @@ -2226,16 +2053,14 @@ BattleScript_EffectTopsyTurvy:: BattleScript_EffectTopsyTurvyWorks: attackanimation waitanimation - invertstatstages BS_TARGET + invertstatstages printstring STRINGID_TOPSYTURVYSWITCHEDSTATS waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectIonDeluge:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE orword gFieldStatuses, STATUS_FIELD_ION_DELUGE attackanimation waitanimation @@ -2245,9 +2070,7 @@ BattleScript_EffectIonDeluge:: BattleScript_EffectQuash:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryquash BattleScript_ButItFailed attackanimation waitanimation @@ -2257,10 +2080,8 @@ BattleScript_EffectQuash:: BattleScript_EffectHealPulse:: attackcanceler - attackstring - ppreduce - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents @ stops pollen puff - jumpifstatus3 BS_TARGET, STATUS3_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents + jumpifvolatile BS_ATTACKER, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents @ stops pollen puff + jumpifvolatile BS_TARGET, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifsubstituteblocks BattleScript_ButItFailed tryhealpulse BattleScript_AlreadyAtFullHp @@ -2274,49 +2095,39 @@ BattleScript_EffectHealPulse:: BattleScript_EffectEntrainment:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryentrainment BattleScript_ButItFailed attackanimation waitanimation - setlastusedability BS_TARGET + switchinabilities BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG + trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectSimpleBeam:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - setabilitysimple BS_TARGET, BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + setsimplebeam BattleScript_ButItFailed attackanimation waitanimation -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET printstring STRINGID_PKMNACQUIREDSIMPLE waitmessage B_WAIT_TIME_LONG trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd -BattleScript_EffectSuckerPunch:: - attackcanceler - suckerpunchcheck BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - goto BattleScript_HitFromAtkString - BattleScript_EffectLuckyChant:: attackcanceler - attackstring - ppreduce - setluckychant BS_ATTACKER, BattleScript_ButItFailed + setluckychant BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_SHIELDEDFROMCRITICALHITS @@ -2325,10 +2136,8 @@ BattleScript_EffectLuckyChant:: BattleScript_EffectMetalBurst:: attackcanceler - metalburstdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + metalburstdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -2336,16 +2145,18 @@ BattleScript_EffectMetalBurst:: BattleScript_EffectHealingWish:: attackcanceler - jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_FailedFromAtkString - attackstring - ppreduce + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation - instanthpdrop BS_ATTACKER + instanthpdrop setatkhptozero tryfaintmon BS_ATTACKER storehealingwish BS_ATTACKER -.if B_HEALING_WISH_SWITCH <= GEN_4 + jumpifgenconfiglowerthan GEN_CONFIG_HEALING_WISH_SWITCH, GEN_5, BattleScript_EffectHealingWishGen4 +BattleScript_EffectHealingWishEnd: + moveendall + end +BattleScript_EffectHealingWishGen4: openpartyscreen BS_ATTACKER, BattleScript_EffectHealingWishEnd waitstate switchhandleorder BS_ATTACKER, 2 @@ -2354,22 +2165,22 @@ BattleScript_EffectHealingWish:: switchindataupdate BS_ATTACKER hpthresholds BS_ATTACKER trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas flushtextbox printstring STRINGID_SWITCHINMON switchinanim BS_ATTACKER, FALSE, TRUE waitstate switchineffects BS_ATTACKER -.endif -BattleScript_EffectHealingWishEnd: - moveendall - end + goto BattleScript_EffectHealingWishEnd BattleScript_HealingWishActivates:: setbyte cMULTISTRING_CHOOSER, 0 goto BattleScript_EffectHealingWishRestore BattleScript_LunarDanceActivates:: setbyte cMULTISTRING_CHOOSER, 1 - restorepp BS_ATTACKER + restoremovepp BattleScript_EffectHealingWishRestore: printfromtable gHealingWishStringIds waitmessage B_WAIT_TIME_LONG @@ -2379,7 +2190,7 @@ BattleScript_EffectHealingWishRestore: manipulatedamage DMG_CHANGE_SIGN healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - clearstatus BS_ATTACKER + clearstatus waitstate updatestatusicon BS_ATTACKER waitstate @@ -2389,29 +2200,23 @@ BattleScript_EffectHealingWishRestore: BattleScript_EffectWorrySeed:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE tryworryseed BattleScript_ButItFailed attackanimation waitanimation -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectPowerSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON averagestats STAT_ATK averagestats STAT_SPATK @@ -2423,8 +2228,6 @@ BattleScript_EffectPowerSplit:: BattleScript_EffectGuardSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON averagestats STAT_DEF averagestats STAT_SPDEF @@ -2436,8 +2239,6 @@ BattleScript_EffectGuardSplit:: BattleScript_EffectHeartSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_ATK swapstatstages STAT_DEF @@ -2454,8 +2255,6 @@ BattleScript_EffectHeartSwap:: BattleScript_EffectPowerSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_ATK swapstatstages STAT_SPATK @@ -2467,8 +2266,6 @@ BattleScript_EffectPowerSwap:: BattleScript_EffectGuardSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstatstages STAT_DEF swapstatstages STAT_SPDEF @@ -2480,8 +2277,6 @@ BattleScript_EffectGuardSwap:: BattleScript_EffectSpeedSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON swapstats STAT_SPEED attackanimation @@ -2492,9 +2287,7 @@ BattleScript_EffectSpeedSwap:: BattleScript_EffectTelekinesis:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, NO_ACC_CALC_CHECK_LOCK_ON settelekinesis BattleScript_ButItFailed attackanimation waitanimation @@ -2504,8 +2297,6 @@ BattleScript_EffectTelekinesis:: BattleScript_EffectStealthRock:: attackcanceler - attackstring - ppreduce setstealthrock BattleScript_ButItFailed attackanimation waitanimation @@ -2515,8 +2306,6 @@ BattleScript_EffectStealthRock:: BattleScript_EffectStickyWeb:: attackcanceler - attackstring - ppreduce setstickyweb BattleScript_ButItFailed attackanimation waitanimation @@ -2526,9 +2315,8 @@ BattleScript_EffectStickyWeb:: BattleScript_EffectGastroAcid:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + jumpifvolatile BS_TARGET, VOLATILE_GASTRO_ACID, BattleScript_ButItFailed setgastroacid BattleScript_ButItFailed attackanimation waitanimation @@ -2537,13 +2325,11 @@ BattleScript_EffectGastroAcid:: trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectToxicSpikes:: attackcanceler - attackstring - ppreduce settoxicspikes BattleScript_ButItFailed attackanimation waitanimation @@ -2553,9 +2339,9 @@ BattleScript_EffectToxicSpikes:: BattleScript_EffectMagnetRise:: attackcanceler - attackstring - ppreduce - setuserstatus3 STATUS3_MAGNET_RISE, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_SMACK_DOWN, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_MAGNET_RISE, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNLEVITATEDONELECTROMAGNETISM @@ -2564,8 +2350,6 @@ BattleScript_EffectMagnetRise:: BattleScript_EffectTrickRoom:: attackcanceler - attackstring - ppreduce setroom attackanimation waitanimation @@ -2590,8 +2374,6 @@ BattleScript_RoomServiceLoop_NextBattler: BattleScript_EffectWonderRoom:: BattleScript_EffectMagicRoom:: attackcanceler - attackstring - ppreduce setroom attackanimation waitanimation @@ -2601,9 +2383,7 @@ BattleScript_EffectMagicRoom:: BattleScript_EffectAquaRing:: attackcanceler - attackstring - ppreduce - setuserstatus3 STATUS3_AQUA_RING, BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_AQUA_RING attackanimation waitanimation printstring STRINGID_PKMNSURROUNDEDWITHVEILOFWATER @@ -2612,9 +2392,7 @@ BattleScript_EffectAquaRing:: BattleScript_EffectEmbargo:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE setembargo BattleScript_ButItFailed attackanimation waitanimation @@ -2624,8 +2402,6 @@ BattleScript_EffectEmbargo:: BattleScript_EffectTailwind:: attackcanceler - attackstring - ppreduce settailwind BattleScript_ButItFailed attackanimation waitanimation @@ -2661,16 +2437,15 @@ BattleScript_TryTailwindAbilitiesLoop_WindPower: BattleScript_EffectMiracleEye:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - setmiracleeye BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE + setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE goto BattleScript_IdentifiedFoe - BattleScript_EffectGravity:: + call BattleScript_EffectGravityInternal + goto BattleScript_MoveEnd + +BattleScript_EffectGravityInternal: attackcanceler - attackstring - ppreduce setgravity BattleScript_ButItFailed attackanimation waitanimation @@ -2681,43 +2456,39 @@ BattleScript_EffectGravitySuccess:: selectfirstvalidtarget BattleScript_GravityLoop: movevaluescleanup - jumpifstatus3 BS_TARGET, STATUS3_ON_AIR | STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop + jumpfifsemiinvulnerable BS_TARGET, STATE_ON_AIR, BattleScript_GravityLoopDrop + jumpifvolatile BS_TARGET, VOLATILE_MAGNET_RISE, BattleScript_GravityLoopDrop + jumpifvolatile BS_TARGET, VOLATILE_TELEKINESIS, BattleScript_GravityLoopDrop goto BattleScript_GravityLoopEnd BattleScript_GravityLoopDrop: - bringdownairbornebattler BS_TARGET + gravityonairbornemons printstring STRINGID_GRAVITYGROUNDING waitmessage B_WAIT_TIME_LONG BattleScript_GravityLoopEnd: moveendcase MOVEEND_TARGET_VISIBLE jumpifnexttargetvalid BattleScript_GravityLoop restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRoost:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_TARGET + tryhealhalfhealth BS_TARGET, BattleScript_AlreadyAtFullHp setroost goto BattleScript_PresentHealTarget BattleScript_EffectCaptivate:: setstatchanger STAT_SPATK, 2, TRUE attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed jumpifcaptivateaffected BattleScript_CaptivateCheckAcc goto BattleScript_ButItFailed BattleScript_CaptivateCheckAcc: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE - goto BattleScript_StatDownFromAttackString + goto BattleScript_EffectStatDownFromStatBuffChange BattleScript_EffectHealBlock:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects sethealblock BattleScript_ButItFailed attackanimation @@ -2736,8 +2507,6 @@ BattleScript_HitEscapeSwitch: BattleScript_EffectPlaceholder:: attackcanceler - attackstring - ppreduce pause 5 printstring STRINGID_NOTDONEYET goto BattleScript_MoveEnd @@ -2745,10 +2514,8 @@ BattleScript_EffectPlaceholder:: BattleScript_EffectHit:: attackcanceler BattleScript_HitFromAccCheck:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_HitFromAtkString:: - attackstring - ppreduce BattleScript_HitFromCritCalc:: critcalc damagecalc @@ -2764,9 +2531,7 @@ BattleScript_MoveEnd:: BattleScript_EffectHit_Ret:: attackcanceler BattleScript_EffectHit_RetFromAccCheck:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_EffectHit_RetFromCritCalc:: critcalc damagecalc @@ -2788,26 +2553,15 @@ BattleScript_Hit_RetFromAtkAnimation:: BattleScript_EffectNaturalGift:: attackcanceler - attackstring - ppreduce jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MAGIC_ROOM, BattleScript_ButItFailed jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailed - jumpifstatus3 BS_ATTACKER, STATUS3_EMBARGO, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_EMBARGO, BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE - call BattleScript_EffectHit_RetFromCritCalc - jumpifmovehadnoeffect BattleScript_EffectNaturalGiftEnd - checkparentalbondcounter 2, BattleScript_EffectNaturalGiftEnd - removeitem BS_ATTACKER -BattleScript_EffectNaturalGiftEnd: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + call BattleScript_HitFromCritCalc BattleScript_MakeMoveMissed:: setmoveresultflags MOVE_RESULT_MISSED -BattleScript_PrintMoveMissed:: - attackstring - ppreduce BattleScript_MoveMissedPause:: pause B_WAIT_TIME_SHORT BattleScript_MoveMissed:: @@ -2816,18 +2570,19 @@ BattleScript_MoveMissed:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectDarkVoid:: -.if B_DARK_VOID_FAIL >= GEN_7 - jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus - goto BattleScript_PokemonCantUseTheMove -.endif - BattleScript_TerrainPreventsEnd2:: pause B_WAIT_TIME_SHORT printfromtable gTerrainPreventsStringIds waitmessage B_WAIT_TIME_LONG end2 +BattleScript_ImmunityProtectedEnd2:: + call BattleScript_AbilityPopUp + pause B_WAIT_TIME_SHORT + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_LONG + end2 + BattleScript_ElectricTerrainPrevents:: pause B_WAIT_TIME_SHORT printstring STRINGID_ELECTRICTERRAINPREVENTS @@ -2878,14 +2633,6 @@ BattleScript_AromaVeilProtects: setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_PastelVeilProtects: - pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp - printstring STRINGID_PASTELVEILPROTECTED - waitmessage B_WAIT_TIME_LONG - setmoveresultflags MOVE_RESULT_FAILED - goto BattleScript_MoveEnd - BattleScript_AbilityProtectsDoesntAffectRet:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -2898,7 +2645,7 @@ BattleScript_AbilityProtectsDoesntAffect:: setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_InsomniaProtects: +BattleScript_InsomniaProtects:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSTAYEDAWAKEUSING @@ -2907,20 +2654,13 @@ BattleScript_InsomniaProtects: goto BattleScript_MoveEnd BattleScript_AlreadyAsleep:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYASLEEP waitmessage B_WAIT_TIME_LONG setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_WasntAffected:: - pause B_WAIT_TIME_SHORT - printstring STRINGID_PKMNWASNTAFFECTED - waitmessage B_WAIT_TIME_LONG - setmoveresultflags MOVE_RESULT_FAILED - goto BattleScript_MoveEnd - BattleScript_CantMakeAsleep:: pause B_WAIT_TIME_SHORT printfromtable gUproarAwakeStringIds @@ -2938,18 +2678,16 @@ BattleScript_EffectAbsorb:: printfromtable gAbsorbDrainStringIds waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER - bicword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_PASSIVE_DAMAGE + bicword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_PASSIVE_HP_UPDATE return BattleScript_EffectExplosion:: attackcanceler - attackstring - ppreduce tryexplosion setatkhptozero waitstate jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_FaintAttackerForExplosion:: @@ -2957,7 +2695,7 @@ BattleScript_FaintAttackerForExplosion:: return BattleScript_MaxHp50Recoil:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER @@ -2965,55 +2703,10 @@ BattleScript_MaxHp50Recoil:: BattleScript_EffectDreamEater:: attackcanceler - jumpifsubstituteblocks BattleScript_DreamEaterNoEffect - jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_DreamEaterWorked - jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_DreamEaterWorked -BattleScript_DreamEaterNoEffect: - attackstring - ppreduce - waitmessage B_WAIT_TIME_LONG - goto BattleScript_WasntAffected -BattleScript_DreamEaterWorked: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_DreamEaterTryFaintEnd - setdrainedhp - manipulatedamage DMG_BIG_ROOT - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - jumpifmovehadnoeffect BattleScript_DreamEaterTryFaintEnd - printstring STRINGID_PKMNENERGYDRAINED - waitmessage B_WAIT_TIME_LONG -BattleScript_DreamEaterTryFaintEnd: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd - -BattleScript_EffectMirrorMove:: - attackcanceler - attackstring - pause B_WAIT_TIME_LONG - trymirrormove - ppreduce - setmoveresultflags MOVE_RESULT_FAILED - printstring STRINGID_MIRRORMOVEFAILED - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + jumpifsubstituteblocks BattleScript_DoesntAffectTargetAtkString + jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_HitFromAccCheck + jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_HitFromAccCheck + goto BattleScript_DoesntAffectTargetAtkString BattleScript_EffectAttackUp:: setstatchanger STAT_ATK, 1, FALSE @@ -3044,10 +2737,8 @@ BattleScript_EffectEvasionUp:: BattleScript_EffectStatUp:: attackcanceler BattleScript_EffectStatUpAfterAtkCanceler:: - attackstring - ppreduce statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_StatUpEnd - jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpAttackAnim + jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpAttackAnim pause B_WAIT_TIME_SHORT goto BattleScript_StatUpPrintString BattleScript_StatUpAttackAnim:: @@ -3094,15 +2785,13 @@ BattleScript_EffectEvasionDown:: setstatchanger STAT_EVASION, 1, TRUE BattleScript_EffectStatDown: attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -BattleScript_StatDownFromAttackString: - attackstring - ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed +BattleScript_EffectStatDownFromAccCheck: + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE BattleScript_EffectStatDownFromStatBuffChange: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_StatDownEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_StatDownDoAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StatDownEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatDownDoAnim + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StatDownEnd pause B_WAIT_TIME_SHORT goto BattleScript_StatDownPrintString BattleScript_StatDownDoAnim:: @@ -3122,7 +2811,7 @@ BattleScript_MirrorArmorReflect:: jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_MirrorArmorDoesntAffect BattleScript_MirrorArmorReflectStatLoss: statbuffchange BS_ATTACKER, STAT_CHANGE_MIRROR_ARMOR | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorArmorReflectEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_MirrorArmorReflectPrintString + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_MirrorArmorReflectPrintString goto BattleScript_MirrorArmorReflectWontFall BattleScript_MirrorArmorReflectPrintString: printfromtable gStatDownStringIds @@ -3156,8 +2845,6 @@ BattleScript_StatDown:: BattleScript_EffectHaze:: attackcanceler - attackstring - ppreduce attackanimation waitanimation normalisebuffs @@ -3167,8 +2854,6 @@ BattleScript_EffectHaze:: BattleScript_EffectBide:: attackcanceler - attackstring - ppreduce attackanimation waitanimation setbide @@ -3176,13 +2861,11 @@ BattleScript_EffectBide:: BattleScript_EffectRoar:: attackcanceler - attackstring - ppreduce jumpifroarfails BattleScript_ButItFailed jumpifcommanderactive BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut - jumpifstatus3 BS_TARGET, STATUS3_ROOTED, BattleScript_PrintMonIsRooted + jumpifvolatile BS_TARGET, VOLATILE_ROOT, BattleScript_PrintMonIsRooted jumpiftargetdynamaxed BattleScript_RoarBlockedByDynamax accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE @@ -3208,8 +2891,6 @@ BattleScript_ScaleShot:: BattleScript_EffectConversion:: attackcanceler - attackstring - ppreduce tryconversiontypechange BattleScript_ButItFailed attackanimation waitanimation @@ -3219,9 +2900,7 @@ BattleScript_EffectConversion:: BattleScript_EffectRestoreHp:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_ATTACKER + tryhealhalfhealth BS_ATTACKER, BattleScript_AlreadyAtFullHp attackanimation waitanimation BattleScript_RestoreHp: @@ -3233,7 +2912,7 @@ BattleScript_RestoreHp: goto BattleScript_MoveEnd BattleScript_AlreadyPoisoned:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_LONG printstring STRINGID_PKMNALREADYPOISONED waitmessage B_WAIT_TIME_LONG @@ -3241,39 +2920,24 @@ BattleScript_AlreadyPoisoned:: BattleScript_ImmunityProtected:: call BattleScript_AbilityPopUp - pause B_WAIT_TIME_SHORT - printfromtable gStatusPreventionStringIds - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + goto BattleScript_DoesntAffectTargetAtkString BattleScript_EffectAuroraVeil:: attackcanceler - attackstring - ppreduce - setauroraveil BS_ATTACKER + setauroraveil goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectLightScreen:: attackcanceler - attackstring - ppreduce setlightscreen goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectRest:: attackcanceler - attackstring - ppreduce - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_RestIsAlreadyAsleep - jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_RestIsAlreadyAsleep - jumpifuproarwakes BattleScript_RestCantSleep - jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_InsomniaProtects - jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_InsomniaProtects - jumpifability BS_ATTACKER, ABILITY_PURIFYING_SALT, BattleScript_InsomniaProtects .if B_LEAF_GUARD_PREVENTS_REST >= GEN_5 jumpifleafguardprotected BS_TARGET, BattleScript_LeafGuardPreventsRest .endif - trysetrest BattleScript_AlreadyAtFullHp + trysetrest pause B_WAIT_TIME_SHORT printfromtable gRestUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -3288,7 +2952,7 @@ BattleScript_RestCantSleep:: goto BattleScript_MoveEnd BattleScript_RestIsAlreadyAsleep:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYASLEEP2 waitmessage B_WAIT_TIME_LONG @@ -3302,9 +2966,6 @@ BattleScript_LeafGuardPreventsRest:: BattleScript_EffectOHKO:: attackcanceler - attackstring - ppreduce - accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE typecalc jumpifmovehadnoeffect BattleScript_HitFromAtkAnimation tryKO BattleScript_KOFail @@ -3320,7 +2981,7 @@ BattleScript_RecoilIfMiss:: printstring STRINGID_PKMNCRASHED waitmessage B_WAIT_TIME_LONG jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_RecoilEnd - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER @@ -3328,8 +2989,6 @@ BattleScript_RecoilIfMiss:: BattleScript_EffectMist:: attackcanceler - attackstring - ppreduce setmist attackanimation waitanimation @@ -3339,8 +2998,6 @@ BattleScript_EffectMist:: BattleScript_EffectFocusEnergy:: attackcanceler - attackstring - ppreduce jumpifvolatile BS_ATTACKER, VOLATILE_DRAGON_CHEER, BattleScript_ButItFailed jumpifvolatile BS_ATTACKER, VOLATILE_FOCUS_ENERGY, BattleScript_ButItFailed setfocusenergy BS_TARGET @@ -3352,8 +3009,6 @@ BattleScript_EffectFocusEnergy:: BattleScript_EffectConfuse:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents jumpifsubstituteblocks BattleScript_ButItFailed jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_AlreadyConfused @@ -3368,7 +3023,7 @@ BattleScript_EffectConfuse:: goto BattleScript_MoveEnd BattleScript_AlreadyConfused:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYCONFUSED waitmessage B_WAIT_TIME_LONG @@ -3412,9 +3067,10 @@ BattleScript_EffectEvasionUp2:: BattleScript_EffectTransform:: attackcanceler - attackstring - ppreduce trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas flushtextbox transformdataexecution attackanimation @@ -3453,24 +3109,26 @@ BattleScript_EffectEvasionDown2:: BattleScript_EffectReflect:: attackcanceler - attackstring - ppreduce setreflect BattleScript_PrintReflectLightScreenSafeguardString:: attackanimation waitanimation -BattleScript_EffectAuroraVeilSuccess:: printfromtable gReflectLightScreenSafeguardStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_MoveEffectAuroraVeil:: + printfromtable gReflectLightScreenSafeguardStringIds + waitmessage B_WAIT_TIME_LONG + return + BattleScript_VoltAbsorbHeal: copybyte gBattlerAbility, gBattlerTarget tryhealquarterhealth BS_TARGET, BattleScript_MonMadeMoveUseless @ Check if max hp goto BattleScript_MoveHPDrain BattleScript_AlreadyParalyzed:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNISALREADYPARALYZED waitmessage B_WAIT_TIME_LONG @@ -3485,16 +3143,15 @@ BattleScript_PowerHerbActivation: BattleScript_EffectTwoTurnsAttack:: jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn tryfiretwoturnmovewithoutcharging BS_ATTACKER, BattleScript_EffectHit @ e.g. Solar Beam + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_EffectHit @ if it's not the first hit call BattleScript_FirstChargingTurn tryfiretwoturnmoveaftercharging BS_ATTACKER, BattleScript_TwoTurnMovesSecondTurn @ e.g. Electro Shot - jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_TwoTurnMovesSecondPowerHerbActivates + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_TwoTurnMovesSecondPowerHerbActivates, TRUE goto BattleScript_MoveEnd BattleScript_EffectGeomancy:: jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_GeomancySecondTurn - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_GeomancySecondTurn call BattleScript_FirstChargingTurn jumpifnoholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_MoveEnd call BattleScript_PowerHerbActivation @@ -3502,8 +3159,6 @@ BattleScript_GeomancySecondTurn: attackcanceler setbyte sB_ANIM_TURN, 1 clearvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS - orword gHitMarker, HITMARKER_NO_PPDEDUCT - attackstring jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_GeomancyDoMoveAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_GeomancyDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -3512,19 +3167,19 @@ BattleScript_GeomancyDoMoveAnim:: waitanimation setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyTrySpDef, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyTrySpDef:: setstatchanger STAT_SPDEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyTrySpeed:: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_GeomancyEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_GeomancyEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_GeomancyEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GeomancyEnd:: @@ -3532,13 +3187,7 @@ BattleScript_GeomancyEnd:: BattleScript_FirstChargingTurn:: attackcanceler -@ before Gen 5, charge moves did not print an attack string on the charge turn -.if B_UPDATED_MOVE_DATA >= GEN_5 - flushtextbox - attackstring waitmessage B_WAIT_TIME_LONG -.endif - ppreduce BattleScript_FirstChargingTurnAfterAttackString: setsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP setchargingturn @@ -3551,17 +3200,12 @@ BattleScript_TwoTurnMovesSecondPowerHerbActivates: trygulpmissile @ Edge case for Cramorant ability Gulp Missile BattleScript_FromTwoTurnMovesSecondTurnRet: call BattleScript_TwoTurnMovesSecondTurnRet - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -@ before Gen 5, charge moves did not print an attack string on the charge turn -.if B_UPDATED_MOVE_DATA < GEN_5 - attackstring -.endif + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_TwoTurnMovesSecondTurn:: attackcanceler call BattleScript_TwoTurnMovesSecondTurnRet - orword gHitMarker, HITMARKER_NO_PPDEDUCT goto BattleScript_HitFromAccCheck BattleScript_TwoTurnMovesSecondTurnRet: @@ -3573,13 +3217,11 @@ BattleScript_TwoTurnMovesSecondTurnRet: BattleScript_EffectSubstitute:: attackcanceler - ppreduce - attackstring waitstate jumpifvolatile BS_ATTACKER, VOLATILE_SUBSTITUTE, BattleScript_AlreadyHasSubstitute setsubstitute jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_SUBSTITUTE_FAILED, BattleScript_SubstituteString - orword gHitMarker, HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -3590,7 +3232,7 @@ BattleScript_SubstituteString:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_AlreadyHasSubstitute:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNHASSUBSTITUTE waitmessage B_WAIT_TIME_LONG @@ -3608,12 +3250,10 @@ BattleScript_EffectRage:: goto BattleScript_HitFromAtkString BattleScript_RageMiss:: clearvolatile BS_ATTACKER, VOLATILE_RAGE - goto BattleScript_PrintMoveMissed + goto BattleScript_MoveMissedPause BattleScript_EffectMimic:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON mimicattackcopy BattleScript_ButItFailed @@ -3623,19 +3263,9 @@ BattleScript_EffectMimic:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectMetronome:: - attackcanceler - attackstring - pause B_WAIT_TIME_SHORT - attackanimation - waitanimation - metronome - BattleScript_EffectLeechSeed:: attackcanceler - attackstring pause B_WAIT_TIME_SHORT - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_DoLeechSeed, ACC_CURR_MOVE BattleScript_DoLeechSeed:: @@ -3648,8 +3278,6 @@ BattleScript_DoLeechSeed:: BattleScript_EffectDoNothing:: attackcanceler - attackstring - ppreduce attackanimation waitanimation incrementgamestat GAME_STAT_USED_SPLASH @@ -3659,8 +3287,6 @@ BattleScript_EffectDoNothing:: BattleScript_EffectHoldHands:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed attackanimation @@ -3669,8 +3295,6 @@ BattleScript_EffectHoldHands:: BattleScript_EffectCelebrate:: attackcanceler - attackstring - ppreduce attackanimation waitanimation printstring STRINGID_CELEBRATEMESSAGE @@ -3679,8 +3303,6 @@ BattleScript_EffectCelebrate:: BattleScript_EffectHappyHour:: attackcanceler - attackstring - ppreduce attackanimation waitanimation seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_HAPPY_HOUR @@ -3688,8 +3310,6 @@ BattleScript_EffectHappyHour:: BattleScript_EffectDisable:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE disablelastusedattack BattleScript_ButItFailed @@ -3701,10 +3321,8 @@ BattleScript_EffectDisable:: BattleScript_EffectCounter:: attackcanceler - counterdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + counterdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -3712,9 +3330,7 @@ BattleScript_EffectCounter:: BattleScript_EffectEncore:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects trysetencore BattleScript_ButItFailed attackanimation @@ -3725,8 +3341,6 @@ BattleScript_EffectEncore:: BattleScript_EffectPainSplit:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON painsplitdmgcalc BattleScript_ButItFailed attackanimation @@ -3742,26 +3356,16 @@ BattleScript_EffectPainSplit:: BattleScript_EffectSnore:: attackcanceler - jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_SnoreIsAsleep - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_SnoreIsAsleep - attackstring - ppreduce - goto BattleScript_ButItFailed -BattleScript_SnoreIsAsleep:: jumpifhalfword CMP_EQUAL, gChosenMove, MOVE_SLEEP_TALK, BattleScript_DoSnore printstring STRINGID_PKMNFASTASLEEP waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER BattleScript_DoSnore:: - attackstring - ppreduce accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_EffectConversion2:: attackcanceler - attackstring - ppreduce settypetorandomresistance BattleScript_ButItFailed attackanimation waitanimation @@ -3771,8 +3375,6 @@ BattleScript_EffectConversion2:: BattleScript_EffectLockOn:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE setalwayshitflag @@ -3784,8 +3386,6 @@ BattleScript_EffectLockOn:: BattleScript_EffectSketch:: attackcanceler - attackstring - ppreduce copymovepermanently BattleScript_ButItFailed attackanimation waitanimation @@ -3793,33 +3393,9 @@ BattleScript_EffectSketch:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectSleepTalk:: - attackcanceler - jumpifability BS_ATTACKER, ABILITY_COMATOSE, BattleScript_SleepTalkIsAsleep - jumpifstatus BS_ATTACKER, STATUS1_SLEEP, BattleScript_SleepTalkIsAsleep - attackstring - ppreduce - goto BattleScript_ButItFailed -BattleScript_SleepTalkIsAsleep:: - printstring STRINGID_PKMNFASTASLEEP - waitmessage B_WAIT_TIME_LONG - statusanimation BS_ATTACKER - attackstring - ppreduce - orword gHitMarker, HITMARKER_NO_PPDEDUCT - trychoosesleeptalkmove BattleScript_SleepTalkUsingMove - pause B_WAIT_TIME_LONG - goto BattleScript_ButItFailed -BattleScript_SleepTalkUsingMove:: - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectDestinyBond:: attackcanceler - attackstring - ppreduce - trysetdestinybond BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_DESTINY_BOND, 2 attackanimation waitanimation printstring STRINGID_PKMNTRYINGTOTAKEFOE @@ -3833,8 +3409,6 @@ BattleScript_MoveEffectEerieSpell:: BattleScript_EffectSpite:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE tryspiteppreduce BattleScript_ButItFailed attackanimation @@ -3843,13 +3417,11 @@ BattleScript_EffectSpite:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +@ TODO: Simplfy script BattleScript_EffectHealBell:: attackcanceler - attackstring - ppreduce attackanimation waitanimation -BattleScript_EffectHealBell_FromHeal:: healpartystatus waitstate printfromtable gPartyStatusHealStringIds @@ -3869,10 +3441,17 @@ BattleScript_PartyHealEnd:: waitstate goto BattleScript_MoveEnd +BattleScript_MoveEffectAromatherapy:: + healpartystatus + waitstate + printfromtable gPartyStatusHealStringIds + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_ATTACKER_WITH_PARTNER + waitstate + return + BattleScript_EffectMeanLook:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_ESCAPE_PREVENTION, BattleScript_ButItFailed jumpifsubstituteblocks BattleScript_ButItFailed @@ -3888,8 +3467,6 @@ BattleScript_EffectMeanLook:: BattleScript_EffectNightmare:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed jumpifvolatile BS_TARGET, VOLATILE_NIGHTMARE, BattleScript_ButItFailed jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_NightmareWorked @@ -3905,7 +3482,7 @@ BattleScript_NightmareWorked:: BattleScript_EffectMinimize:: attackcanceler - setminimize + setvolatile BS_ATTACKER, VOLATILE_MINIMIZE .if B_MINIMIZE_EVASION >= GEN_5 setstatchanger STAT_EVASION, 2, FALSE .else @@ -3917,8 +3494,6 @@ BattleScript_EffectCurse:: jumpiftype BS_ATTACKER, TYPE_GHOST, BattleScript_GhostCurse attackcanceler jumpiftype BS_ATTACKER, TYPE_GHOST, BattleScript_DoGhostCurse - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_GREATER_THAN, STAT_SPEED, MIN_STAT_STAGE, BattleScript_CurseTrySpeed jumpifstat BS_ATTACKER, CMP_NOT_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_CurseTrySpeed jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MAX_STAT_STAGE, BattleScript_ButItFailed @@ -3945,11 +3520,9 @@ BattleScript_CurseEnd:: goto BattleScript_MoveEnd BattleScript_GhostCurse:: jumpifbytenotequal gBattlerAttacker, gBattlerTarget, BattleScript_DoGhostCurse - getmovetarget BS_ATTACKER + getmovetarget BattleScript_DoGhostCurse:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON cursetarget BattleScript_ButItFailed orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE @@ -3963,17 +3536,9 @@ BattleScript_DoGhostCurse:: tryfaintmon BS_ATTACKER goto BattleScript_MoveEnd -BattleScript_EffectMatBlock:: - attackcanceler - jumpifnotfirstturn BattleScript_FailedFromAtkString - goto BattleScript_ProtectLikeAtkString - BattleScript_EffectProtect:: BattleScript_EffectEndure:: attackcanceler -BattleScript_ProtectLikeAtkString: - attackstring - ppreduce setprotectlike attackanimation waitanimation @@ -3983,9 +3548,7 @@ BattleScript_ProtectLikeAtkString: BattleScript_EffectSpikes:: attackcanceler - trysetspikes BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetspikes BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_SPIKESSCATTERED @@ -3994,11 +3557,9 @@ BattleScript_EffectSpikes:: BattleScript_EffectForesight:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_FORESIGHT, BattleScript_ButItFailed - setforesight + setvolatile BS_TARGET, VOLATILE_FORESIGHT BattleScript_IdentifiedFoe: attackanimation waitanimation @@ -4008,8 +3569,6 @@ BattleScript_IdentifiedFoe: BattleScript_EffectPerishSong:: attackcanceler - attackstring - ppreduce trysetperishsong BattleScript_ButItFailed savetarget attackanimation @@ -4019,7 +3578,7 @@ BattleScript_EffectPerishSong:: setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: jumpifblockedbysoundproof BS_TARGET, BattleScript_PerishSongBlocked - jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected + jumpifpranksterblocked BattleScript_PerishSongNotAffected BattleScript_PerishSongLoopIncrement:: addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop @@ -4039,17 +3598,13 @@ BattleScript_PerishSongNotAffected: BattleScript_EffectSandstorm:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SANDSTORM goto BattleScript_MoveWeatherChange BattleScript_EffectRollout:: attackcanceler - attackstring jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_RolloutCheckAccuracy - ppreduce BattleScript_RolloutCheckAccuracy:: accuracycheck BattleScript_RolloutHit, ACC_CURR_MOVE BattleScript_RolloutHit:: @@ -4060,15 +3615,13 @@ BattleScript_RolloutHit:: BattleScript_EffectSwagger:: attackcanceler jumpifsubstituteblocks BattleScript_MakeMoveMissed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifconfusedandstatmaxed STAT_ATK, BattleScript_ButItFailed attackanimation waitanimation setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_SwaggerTryConfuse - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_SwaggerTryConfuse + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_SwaggerTryConfuse printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_SwaggerTryConfuse: @@ -4079,8 +3632,6 @@ BattleScript_SwaggerTryConfuse: BattleScript_EffectFuryCutter:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_FuryCutterHit, ACC_CURR_MOVE BattleScript_FuryCutterHit: handlefurycutter @@ -4095,7 +3646,7 @@ BattleScript_TryDestinyKnotTarget: infatuatewithbattler BS_TARGET, BS_ATTACKER playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation - status2animation BS_TARGET, STATUS2_INFATUATION + volatileanimation BS_TARGET, VOLATILE_INFATUATION waitanimation printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG @@ -4107,7 +3658,7 @@ BattleScript_TryDestinyKnotAttacker: infatuatewithbattler BS_ATTACKER, BS_TARGET playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT waitanimation - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION waitanimation printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG @@ -4116,8 +3667,6 @@ BattleScript_TryDestinyKnotAttackerRet: BattleScript_EffectAttract:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects tryinfatuating BattleScript_ButItFailed @@ -4130,36 +3679,26 @@ BattleScript_EffectAttract:: BattleScript_EffectPresent:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc presentdamagecalculation BattleScript_EffectSafeguard:: attackcanceler - attackstring - ppreduce setsafeguard goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectMagnitude:: - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT, BattleScript_EffectMagnitudeTarget attackcanceler - attackstring - ppreduce magnitudedamagecalculation pause B_WAIT_TIME_SHORT printstring STRINGID_MAGNITUDESTRENGTH waitmessage B_WAIT_TIME_LONG -BattleScript_EffectMagnitudeTarget: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc BattleScript_EffectBatonPass:: attackcanceler - attackstring - ppreduce jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_ButItFailed attackanimation @@ -4185,15 +3724,11 @@ BattleScript_EffectSynthesis:: BattleScript_EffectMoonlight:: BattleScript_EffectShoreUp:: attackcanceler - attackstring - ppreduce recoverbasedonsunlight BattleScript_AlreadyAtFullHp goto BattleScript_PresentHealTarget BattleScript_EffectRainDance:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_RAIN BattleScript_MoveWeatherChange:: @@ -4210,8 +3745,6 @@ BattleScript_MoveWeatherChangeRet:: BattleScript_EffectSunnyDay:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SUN goto BattleScript_MoveWeatherChange @@ -4286,11 +3819,9 @@ BattleScript_BlockedByPrimalWeatherRet:: BattleScript_EffectBellyDrum:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed halvehp BattleScript_ButItFailed - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE attackanimation waitanimation healthbarupdate BS_ATTACKER @@ -4303,9 +3834,7 @@ BattleScript_EffectBellyDrum:: BattleScript_EffectPsychUp:: attackcanceler - attackstring - ppreduce - copyfoestats BattleScript_ButItFailed + copyfoestats attackanimation waitanimation printstring STRINGID_PKMNCOPIEDSTATCHANGES @@ -4314,10 +3843,8 @@ BattleScript_EffectPsychUp:: BattleScript_EffectMirrorCoat:: attackcanceler - mirrorcoatdamagecalculator BattleScript_FailedFromAtkString - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + mirrorcoatdamagecalculator BattleScript_ButItFailed + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE adjustdamage @@ -4325,9 +3852,7 @@ BattleScript_EffectMirrorCoat:: BattleScript_EffectFutureSight:: attackcanceler - attackstring - ppreduce - trysetfutureattack BattleScript_ButItFailed + setfutureattack attackanimation waitanimation printfromtable gFutureMoveUsedStringIds @@ -4335,40 +3860,28 @@ BattleScript_EffectFutureSight:: goto BattleScript_MoveEnd BattleScript_EffectTeleport:: -.if B_TELEPORT_BEHAVIOR >= GEN_8 + jumpifgenconfiglowerthan GEN_CONFIG_TELEPORT_BEHAVIOR, GEN_8, BattleScript_EffectTeleportGen7 jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass -.else + goto BattleScript_DoEffectTeleport +BattleScript_EffectTeleportGen7:: jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_FailedFromAtkCanceler -.endif +BattleScript_DoEffectTeleport:: attackcanceler - attackstring - ppreduce - getifcantrunfrombattle BS_ATTACKER + isrunningimpossible jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective attackanimation waitanimation printstring STRINGID_PKMNFLEDFROMBATTLE waitmessage B_WAIT_TIME_LONG - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER goto BattleScript_MoveEnd BattleScript_EffectBeatUp:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE -.if B_BEAT_UP >= GEN_5 - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - trydobeatup - goto BattleScript_HitFromAtkAnimation -.else - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE pause B_WAIT_TIME_SHORT - ppreduce setbyte gBattleCommunication, 0 BattleScript_BeatUpLoop:: movevaluescleanup @@ -4395,16 +3908,13 @@ BattleScript_BeatUpAttack:: goto BattleScript_BeatUpLoop BattleScript_BeatUpEnd:: end -.endif BattleScript_EffectDefenseCurl:: attackcanceler - attackstring - ppreduce - setdefensecurlbit + setvolatile BS_TARGET, VOLATILE_DEFENSE_CURL setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefenseCurlDoStatUpAnim - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpPrintString attackanimation waitanimation BattleScript_DefenseCurlDoStatUpAnim:: @@ -4412,9 +3922,7 @@ BattleScript_DefenseCurlDoStatUpAnim:: BattleScript_EffectSoftboiled:: attackcanceler - attackstring - ppreduce - tryhealhalfhealth BattleScript_AlreadyAtFullHp, BS_TARGET + tryhealhalfhealth BS_TARGET, BattleScript_AlreadyAtFullHp BattleScript_PresentHealTarget:: attackanimation waitanimation @@ -4431,17 +3939,8 @@ BattleScript_AlreadyAtFullHp:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectFirstTurnOnly:: - attackcanceler - jumpifnotfirstturn BattleScript_FailedFromAtkString - goto BattleScript_EffectHit - BattleScript_FailedFromAtkCanceler:: attackcanceler -BattleScript_FailedFromAtkString:: - attackstring -BattleScript_FailedFromPpReduce:: - ppreduce BattleScript_ButItFailed:: pause B_WAIT_TIME_SHORT setmoveresultflags MOVE_RESULT_FAILED @@ -4451,6 +3950,9 @@ BattleScript_ButItFailed:: BattleScript_RestoreAttackerButItFailed: restoreattacker goto BattleScript_ButItFailed +BattleScript_RestoreTargetButItFailed: + restoretarget + goto BattleScript_ButItFailed BattleScript_NotAffected:: pause B_WAIT_TIME_SHORT @@ -4467,23 +3969,12 @@ BattleScript_NotAffectedAbilityPopUp:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectUproar:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_UproarHit - ppreduce -BattleScript_UproarHit:: - goto BattleScript_HitFromCritCalc - BattleScript_EffectStockpile:: attackcanceler - attackstring - ppreduce stockpile 0 attackanimation waitanimation - printfromtable gStockpileUsedStringIds + printstring STRINGID_PKMNSTOCKPILED waitmessage B_WAIT_TIME_LONG .if B_STOCKPILE_RAISES_DEFS < GEN_4 goto BattleScript_EffectStockpileEnd @@ -4494,13 +3985,13 @@ BattleScript_EffectStockpile:: BattleScript_EffectStockpileDef: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileSpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectStockpileSpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectStockpileSpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectStockpileSpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectStockpileEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectStockpileEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectStockpileEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectStockpileEnd: @@ -4525,38 +4016,25 @@ BattleScript_StockpileStatChangeDown_Ret: BattleScript_EffectSpitUp:: attackcanceler jumpifbyte CMP_EQUAL, cMISS_TYPE, B_MSG_PROTECTED, BattleScript_SpitUpFailProtect - attackstring - ppreduce - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE damagecalc adjustdamage - stockpiletobasedamage BattleScript_SpitUpFail + stockpiletobasedamage call BattleScript_Hit_RetFromAtkAnimation tryfaintmon BS_TARGET removestockpilecounters - goto BattleScript_SpitUpEnd -BattleScript_SpitUpFail:: - checkparentalbondcounter 2, BattleScript_SpitUpEnd - pause B_WAIT_TIME_SHORT - printstring STRINGID_FAILEDTOSPITUP - waitmessage B_WAIT_TIME_LONG -BattleScript_SpitUpEnd: goto BattleScript_MoveEnd BattleScript_SpitUpFailProtect:: - attackstring - ppreduce pause B_WAIT_TIME_LONG - stockpiletobasedamage BattleScript_SpitUpFail + stockpiletobasedamage resultmessage waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectSwallow:: attackcanceler - attackstring - ppreduce - stockpiletohpheal BattleScript_SwallowFail + stockpiletohpheal BattleScript_ButItFailed attackanimation waitanimation orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE @@ -4567,25 +4045,14 @@ BattleScript_EffectSwallow:: removestockpilecounters goto BattleScript_MoveEnd - -BattleScript_SwallowFail:: - pause B_WAIT_TIME_SHORT - printfromtable gSwallowFailStringIds - waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd - BattleScript_EffectHail:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_HAIL goto BattleScript_MoveWeatherChange BattleScript_EffectTorment:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects settorment BattleScript_ButItFailed @@ -4598,15 +4065,13 @@ BattleScript_EffectTorment:: BattleScript_EffectFlatter:: attackcanceler jumpifsubstituteblocks BattleScript_MakeMoveMissed - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE jumpifconfusedandstatmaxed STAT_SPATK, BattleScript_ButItFailed attackanimation waitanimation setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_FlatterTryConfuse - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_FlatterTryConfuse + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_FlatterTryConfuse printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_FlatterTryConfuse:: @@ -4615,21 +4080,25 @@ BattleScript_FlatterTryConfuse:: seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_CONFUSION goto BattleScript_MoveEnd +BattleScript_EffectDarkVoid:: +.if B_DARK_VOID_FAIL >= GEN_7 + jumpifspecies SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus + goto BattleScript_PokemonCantUseTheMove +.endif BattleScript_EffectNonVolatileStatus:: attackcanceler - attackstring - ppreduce trynonvolatilestatus accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE attackanimation waitanimation setnonvolatilestatus TRIGGER_ON_MOVE + clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE resultmessage waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_AlreadyBurned:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYHASBURN waitmessage B_WAIT_TIME_LONG @@ -4638,8 +4107,6 @@ BattleScript_AlreadyBurned:: BattleScript_EffectMemento:: attackcanceler jumpifbyte CMP_EQUAL, cMISS_TYPE, B_MSG_PROTECTED, BattleScript_MementoTargetProtect - attackstring - ppreduce trymemento BattleScript_ButItFailed setatkhptozero attackanimation @@ -4647,15 +4114,15 @@ BattleScript_EffectMemento:: jumpifsubstituteblocks BattleScript_EffectMementoPrintNoEffect setstatchanger STAT_ATK, 2, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMementoTrySpAtk, BIT_SPATK -@ Greater than B_MSG_DEFENDER_STAT_FELL is checking if the stat cannot decrease - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_EffectMementoTrySpAtk +@ Greater than B_MSG_DEFENDER_STAT_CHANGED is checking if the stat cannot decrease + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_EffectMementoTrySpAtk printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMementoTrySpAtk: setstatchanger STAT_SPATK, 2, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectMementoTryFaint -@ Greater than B_MSG_DEFENDER_STAT_FELL is checking if the stat cannot decrease - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_EffectMementoTryFaint +@ Greater than B_MSG_DEFENDER_STAT_CHANGED is checking if the stat cannot decrease + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_EffectMementoTryFaint printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectMementoTryFaint: @@ -4667,8 +4134,6 @@ BattleScript_EffectMementoPrintNoEffect: goto BattleScript_EffectMementoTryFaint @ If the target is protected there's no need to check the target's stats or animate, the user will just faint BattleScript_MementoTargetProtect: - attackstring - ppreduce trymemento BattleScript_MementoTargetProtectEnd BattleScript_MementoTargetProtectEnd: setatkhptozero @@ -4682,18 +4147,12 @@ BattleScript_MementoTargetProtectEnd: BattleScript_EffectFocusPunch:: attackcanceler jumpifnodamage BattleScript_HitFromAccCheck - ppreduce printstring STRINGID_PKMNLOSTFOCUS waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_EffectFollowMe:: attackcanceler - attackstring - ppreduce - .if B_UPDATED_MOVE_DATA >= GEN_8 - jumpifnotbattletype BATTLE_TYPE_DOUBLE, BattleScript_ButItFailed - .endif setforcedtarget attackanimation waitanimation @@ -4701,26 +4160,15 @@ BattleScript_EffectFollowMe:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectNaturePower:: - attackcanceler - attackstring - pause B_WAIT_TIME_SHORT - callenvironmentattack - printstring STRINGID_NATUREPOWERTURNEDINTO - waitmessage B_WAIT_TIME_LONG - return - BattleScript_EffectCharge:: attackcanceler - attackstring - ppreduce setcharge BS_ATTACKER attackanimation waitanimation .if B_CHARGE_SPDEF_RAISE >= GEN_5 setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectChargeString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectChargeString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectChargeString printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectChargeString: @@ -4731,8 +4179,6 @@ BattleScript_EffectChargeString: BattleScript_EffectTaunt:: attackcanceler - attackstring - ppreduce jumpifability BS_TARGET_SIDE, ABILITY_AROMA_VEIL, BattleScript_AromaVeilProtects accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE settaunt BattleScript_ButItFailed @@ -4744,8 +4190,6 @@ BattleScript_EffectTaunt:: BattleScript_EffectHelpingHand:: attackcanceler - attackstring - ppreduce trysethelpinghand BattleScript_ButItFailed attackanimation waitanimation @@ -4755,8 +4199,6 @@ BattleScript_EffectHelpingHand:: BattleScript_EffectTrick:: attackcanceler - attackstring - ppreduce jumpifsubstituteblocks BattleScript_ButItFailed accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE tryswapitems BattleScript_ButItFailed @@ -4770,16 +4212,12 @@ BattleScript_EffectTrick:: BattleScript_EffectRolePlay:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON trycopyability BS_ATTACKER, BattleScript_ButItFailed attackanimation waitanimation -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_ATTACKER printstring STRINGID_PKMNCOPIEDFOE waitmessage B_WAIT_TIME_LONG @@ -4788,26 +4226,14 @@ BattleScript_EffectRolePlay:: BattleScript_EffectWish:: attackcanceler - attackstring - ppreduce trywish BattleScript_ButItFailed attackanimation waitanimation goto BattleScript_MoveEnd -BattleScript_EffectAssist:: - attackcanceler - attackstring - assistattackselect BattleScript_FailedFromPpReduce - attackanimation - waitanimation - jumptocalledmove TRUE - BattleScript_EffectIngrain:: attackcanceler - attackstring - ppreduce - setuserstatus3 STATUS3_ROOTED, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNPLANTEDROOTS @@ -4816,9 +4242,7 @@ BattleScript_EffectIngrain:: BattleScript_EffectMagicCoat:: attackcanceler - trysetmagiccoat BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetmagiccoat BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNSHROUDEDITSELF @@ -4827,8 +4251,6 @@ BattleScript_EffectMagicCoat:: BattleScript_EffectRecycle:: attackcanceler - attackstring - ppreduce tryrecycleitem BattleScript_ButItFailed attackanimation waitanimation @@ -4838,9 +4260,7 @@ BattleScript_EffectRecycle:: BattleScript_EffectBrickBreak:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc removescreens critcalc @@ -4865,24 +4285,26 @@ BattleScript_BrickBreakDoHit:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - setadditionaleffects tryfaintmon BS_TARGET + setadditionaleffects goto BattleScript_MoveEnd BattleScript_EffectYawn:: attackcanceler - attackstring - ppreduce trynonvolatilestatus accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON setyawn BattleScript_ButItFailed attackanimation waitanimation -BattleScript_EffectYawnSuccess:: printstring STRINGID_PKMNWASMADEDROWSY waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_MoveEffectYawnSide:: + printstring STRINGID_PKMNWASMADEDROWSY + waitmessage B_WAIT_TIME_LONG + return + BattleScript_PrintAbilityMadeIneffective:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -4892,8 +4314,6 @@ BattleScript_PrintAbilityMadeIneffective:: BattleScript_EffectEndeavor:: attackcanceler - attackstring - ppreduce setdamagetohealthdifference BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE typecalc @@ -4904,20 +4324,16 @@ BattleScript_EffectEndeavor:: BattleScript_EffectSkillSwap:: attackcanceler - attackstring - ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON tryswapabilities BattleScript_ButItFailed attackanimation waitanimation jumpiftargetally BattleScript_EffectSkillSwap_AfterAbilityPopUp -.if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUpOverwriteThenNormal copybyte gBattlerAbility, gBattlerTarget copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif BattleScript_EffectSkillSwap_AfterAbilityPopUp: recordability BS_ATTACKER recordability BS_TARGET @@ -4931,8 +4347,6 @@ BattleScript_EffectSkillSwap_AfterAbilityPopUp: BattleScript_EffectImprison:: attackcanceler - attackstring - ppreduce tryimprison BattleScript_ButItFailed attackanimation waitanimation @@ -4942,8 +4356,6 @@ BattleScript_EffectImprison:: BattleScript_EffectRefresh:: attackcanceler - attackstring - ppreduce curestatuswithmove BattleScript_ButItFailed attackanimation waitanimation @@ -4954,9 +4366,8 @@ BattleScript_EffectRefresh:: BattleScript_EffectGrudge:: attackcanceler - attackstring - ppreduce - setuserstatus3 STATUS3_GRUDGE, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_GRUDGE, BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_GRUDGE, 2 attackanimation waitanimation printstring STRINGID_PKMNWANTSGRUDGE @@ -4965,9 +4376,7 @@ BattleScript_EffectGrudge:: BattleScript_EffectSnatch:: attackcanceler - trysetsnatch BattleScript_FailedFromAtkString - attackstring - ppreduce + trysetsnatch BattleScript_ButItFailed attackanimation waitanimation pause B_WAIT_TIME_SHORT @@ -4983,8 +4392,6 @@ BattleScript_EffectStruggle:: BattleScript_EffectMudSport:: BattleScript_EffectWaterSport:: attackcanceler - attackstring - ppreduce settypebasedhalvers BattleScript_ButItFailed attackanimation waitanimation @@ -4994,8 +4401,6 @@ BattleScript_EffectWaterSport:: BattleScript_EffectTickle:: attackcanceler - attackstring - ppreduce jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_ATK, MIN_STAT_STAGE, BattleScript_TickleDoMoveAnim jumpifstat BS_TARGET, CMP_EQUAL, STAT_DEF, MIN_STAT_STAGE, BattleScript_CantLowerMultipleStats BattleScript_TickleDoMoveAnim:: @@ -5004,13 +4409,13 @@ BattleScript_TickleDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_TickleTryLowerDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_TickleTryLowerDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TickleTryLowerDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_TickleTryLowerDef:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_TickleEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_TickleEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TickleEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_TickleEnd:: @@ -5025,8 +4430,6 @@ BattleScript_CantLowerMultipleStats:: BattleScript_EffectCosmicPower:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_CosmicPowerDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_CosmicPowerDoMoveAnim:: @@ -5034,13 +4437,13 @@ BattleScript_CosmicPowerDoMoveAnim:: waitanimation setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CosmicPowerTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CosmicPowerTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CosmicPowerTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CosmicPowerTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CosmicPowerEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CosmicPowerEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CosmicPowerEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CosmicPowerEnd:: @@ -5048,8 +4451,6 @@ BattleScript_CosmicPowerEnd:: BattleScript_EffectBulkUp:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_BulkUpDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_DEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats BattleScript_BulkUpDoMoveAnim:: @@ -5057,13 +4458,13 @@ BattleScript_BulkUpDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_BulkUpTryDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_BulkUpTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_BulkUpTryDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_BulkUpTryDef:: setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_BulkUpEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_BulkUpEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_BulkUpEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_BulkUpEnd:: @@ -5071,8 +4472,6 @@ BattleScript_BulkUpEnd:: BattleScript_EffectCalmMind:: attackcanceler - attackstring - ppreduce BattleScript_CalmMindTryToRaiseStats:: jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_CalmMindDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPDEF, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -5082,13 +4481,13 @@ BattleScript_CalmMindDoMoveAnim:: BattleScript_CalmMindStatRaise:: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CalmMindTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CalmMindTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CalmMindTrySpDef printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CalmMindTrySpDef:: setstatchanger STAT_SPDEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CalmMindEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CalmMindEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CalmMindEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CalmMindEnd:: @@ -5103,8 +4502,6 @@ BattleScript_CantRaiseMultipleStats:: BattleScript_EffectDragonDance:: attackcanceler - attackstring - ppreduce BattleScript_EffectDragonDanceFromStatUp:: jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_DragonDanceDoMoveAnim jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_CantRaiseMultipleStats @@ -5113,13 +4510,13 @@ BattleScript_DragonDanceDoMoveAnim:: waitanimation setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_DragonDanceTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DragonDanceTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DragonDanceTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DragonDanceTrySpeed:: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_DragonDanceEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DragonDanceEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DragonDanceEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DragonDanceEnd:: @@ -5127,8 +4524,6 @@ BattleScript_DragonDanceEnd:: BattleScript_EffectCamouflage:: attackcanceler - attackstring - ppreduce settypetoenvironment BattleScript_ButItFailed attackanimation waitanimation @@ -5144,9 +4539,13 @@ BattleScript_FaintAttacker:: dofaintanimation BS_ATTACKER printstring STRINGID_ATTACKERFAINTED cleareffectsonfaint BS_ATTACKER + trytoclearprimalweather + tryrevertweatherform + flushtextbox + waitanimation tryactivatesoulheart tryactivatereceiver BS_ATTACKER - trytrainerslidefirstdownmsg BS_ATTACKER + trytrainerslidemsgfirstoff BS_ATTACKER return BattleScript_FaintTarget:: @@ -5158,9 +4557,13 @@ BattleScript_FaintTarget:: dofaintanimation BS_TARGET printstring STRINGID_TARGETFAINTED cleareffectsonfaint BS_TARGET + trytoclearprimalweather + tryrevertweatherform + flushtextbox + waitanimation tryactivatesoulheart tryactivatereceiver BS_TARGET - trytrainerslidefirstdownmsg BS_TARGET + trytrainerslidemsgfirstoff BS_TARGET return BattleScript_GiveExp:: @@ -5206,7 +4609,7 @@ BattleScript_FaintedMonTryChoose: jumpifbyte CMP_EQUAL, gBattleCommunication, PARTY_SIZE, BattleScript_FaintedMonSendOutNew @ Switch Pokémon before opponent atknameinbuff1 - resetswitchinabilitybits BS_ATTACKER + resetswitchinabilitybits hpthresholds2 BS_ATTACKER printstring STRINGID_RETURNMON switchoutabilities BS_ATTACKER @@ -5236,7 +4639,7 @@ BattleScript_FaintedMonSendOutNew: switchinanim BS_FAINTED, FALSE, FALSE waitstate resetplayerfainted - trytrainerslidelastonmsg BS_FAINTED + trytrainerslidemsglaston BS_FAINTED jumpifbytenotequal sSHIFT_SWITCHED, sZero, BattleScript_FaintedMonShiftSwitched BattleScript_FaintedMonSendOutNewEnd: switchineffects BS_FAINTED @@ -5300,13 +4703,26 @@ BattleScript_PayDayMoneyAndPickUpItems:: pickup end2 +BattleScript_RivalBattleLost:: + jumpifhasnohp BS_ATTACKER, BattleScript_RivalBattleLostSkipMonRecall + printstring STRINGID_TRAINER1MON1COMEBACK + waitmessage B_WAIT_TIME_LONG + returnatktoball + waitstate +BattleScript_RivalBattleLostSkipMonRecall:: + trainerslidein BS_ATTACKER + waitstate + printstring STRINGID_TRAINER1WINTEXT + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 2, BattleScript_LocalBattleLostPrintWhiteOut + end2 + BattleScript_LocalBattleLost:: - jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut jumpifbattletype BATTLE_TYPE_TRAINER_TOWER, BattleScript_BattleTowerLost jumpifbattletype BATTLE_TYPE_EREADER_TRAINER, BattleScript_LocalBattleLostEnd jumpifhalfword CMP_EQUAL, gTrainerBattleParameter + 2, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, 0, BattleScript_RivalBattleLost jumpifnowhiteout BattleScript_LocalBattleLostEnd_ + jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut BattleScript_LocalBattleLostPrintWhiteOut:: getmoneyreward printstring STRINGID_PLAYERWHITEOUT @@ -5335,9 +4751,9 @@ BattleScript_LocalBattleLostEnd:: @ jumpifbyte CMP_EQUAL, gBattleOutcome, B_OUTCOME_DREW, BattleScript_LocalBattleLostEnd_ @BattleScript_LocalBattleLostPrintTrainersWinText:: @ jumpifnotbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostPrintWhiteOut -@ returnopponentmon1toball BS_ATTACKER +@ returnopponentmon1toball @ waitstate -@ returnopponentmon2toball BS_ATTACKER +@ returnopponentmon2toball @ waitstate @ trainerslidein BS_OPPONENT1 @ waitstate @@ -5354,9 +4770,9 @@ BattleScript_LocalBattleLostEnd_:: end2 @BattleScript_FrontierLinkBattleLost:: -@ returnopponentmon1toball BS_ATTACKER +@ returnopponentmon1toball @ waitstate -@ returnopponentmon2toball BS_ATTACKER +@ returnopponentmon2toball @ waitstate @ trainerslidein BS_OPPONENT1 @ waitstate @@ -5383,7 +4799,7 @@ BattleScript_LocalBattleLostEnd_:: @ end2 @ @BattleScript_TowerLinkBattleWon:: -@ playtrainerdefeatbgm BS_ATTACKER +@ playtrainerdefeatedmusic @ printstring STRINGID_BATTLEEND @ waitmessage B_WAIT_TIME_LONG @ trainerslidein BS_OPPONENT1 @@ -5527,7 +4943,7 @@ BattleScript_LearnedNewMove:: fanfare MUS_LEVEL_UP printstring STRINGID_PKMNLEARNEDMOVE waitmessage B_WAIT_TIME_LONG - updatechoicemoveonlvlup BS_ATTACKER + updatechoicemoveonlvlup goto BattleScript_TryLearnMoveLoop BattleScript_LearnMoveReturn:: return @@ -5566,7 +4982,7 @@ BattleScript_IceBodyHeal:: datahpupdate BS_ATTACKER printstring STRINGID_ICEBODYHPGAIN waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_OverworldStatusStarts:: printfromtable gStartingStatusStringIds @@ -5630,7 +5046,7 @@ BattleScript_MagicRoomEnds:: setbyte gBattlerTarget, 0 BattleScript_MagicRoomHealingItemsLoop: copyarraywithindex gBattlerAttacker, gBattlerByTurnOrder, gBattlerTarget, 1 - tryrestorehpberry + tryrestorehpberry BS_ATTACKER addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MagicRoomHealingItemsLoop end2 @@ -5690,6 +5106,7 @@ BattleScript_LeechSeedTurnDrainHealBlock:: BattleScript_LeechSeedTurnDrainRecovery:: call BattleScript_LeechSeedTurnDrain BattleScript_LeechSeedTurnDrainGainHp: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET printfromtable gLeechSeedStringIds @@ -5762,7 +5179,7 @@ BattleScript_RoarSuccessSwitch_Ret: BattleScript_RoarSuccessEndBattle:: call BattleScript_RoarSuccessRet setbyte sSWITCH_CASE, B_SWITCH_NORMAL - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER finishaction BattleScript_RoarSuccessRet: @@ -5785,13 +5202,13 @@ BattleScript_WeaknessPolicyAtk: waitanimation setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeaknessPolicySpAtk, BIT_SPATK - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeaknessPolicySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeaknessPolicySpAtk printstring STRINGID_USINGITEMSTATOFPKMNROSE waitmessage B_WAIT_TIME_LONG BattleScript_WeaknessPolicySpAtk: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeaknessPolicyRemoveItem - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeaknessPolicyRemoveItem + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeaknessPolicyRemoveItem printstring STRINGID_USINGITEMSTATOFPKMNROSE waitmessage B_WAIT_TIME_LONG BattleScript_WeaknessPolicyRemoveItem: @@ -5802,7 +5219,7 @@ BattleScript_WeaknessPolicyEnd: BattleScript_TargetItemStatRaise:: copybyte sBATTLER, gBattlerTarget statbuffchange BS_TARGET, STAT_CHANGE_ONLY_CHECKING, BattleScript_TargetItemStatRaiseRemoveItemRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_TargetItemStatRaiseRemoveItemRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_TargetItemStatRaiseRemoveItemRet playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT waitanimation statbuffchange BS_TARGET, 0, BattleScript_TargetItemStatRaiseRemoveItemRet @@ -5815,7 +5232,7 @@ BattleScript_TargetItemStatRaiseRemoveItemRet: BattleScript_AttackerItemStatRaise:: copybyte sBATTLER, gBattlerAttacker statbuffchange BS_ATTACKER, STAT_CHANGE_ONLY_CHECKING, BattleScript_AttackerItemStatRaiseRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_AttackerItemStatRaiseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AttackerItemStatRaiseRet playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation statbuffchange BS_ATTACKER, 0, BattleScript_AttackerItemStatRaiseRet @@ -5874,14 +5291,14 @@ BattleScript_EncoredNoMore:: BattleScript_DestinyBondTakesLife:: printstring STRINGID_PKMNTOOKFOE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER return BattleScript_DmgHazardsOnAttacker:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER call BattleScript_PrintHurtByDmgHazards @@ -5896,7 +5313,7 @@ BattleScript_DmgHazardsOnAttackerFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnTarget:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET call BattleScript_PrintHurtByDmgHazards @@ -5911,7 +5328,7 @@ BattleScript_DmgHazardsOnTargetFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnBattlerScripting:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING call BattleScript_PrintHurtByDmgHazards @@ -5926,7 +5343,7 @@ BattleScript_DmgHazardsOnBattlerScriptingFainted:: goto BattleScript_HandleFaintedMon BattleScript_DmgHazardsOnFaintedBattler:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_FAINTED datahpupdate BS_FAINTED call BattleScript_PrintHurtByDmgHazards @@ -5975,7 +5392,7 @@ BattleScript_StickyWebOnSwitchIn:: waitmessage B_WAIT_TIME_LONG jumpifability BS_TARGET, ABILITY_MIRROR_ARMOR, BattleScript_MirrorArmorReflectStickyWeb statbuffchange BS_TARGET, STAT_CHANGE_CHECK_PREVENTION | STAT_CHANGE_ALLOW_PTR, BattleScript_StickyWebOnSwitchInEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_StickyWebOnSwitchInEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_StickyWebOnSwitchInEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_StickyWebOnSwitchInEnd: @@ -5987,7 +5404,7 @@ BattleScript_StickyWebOnSwitchInEnd: BattleScript_PerishSongTakesLife:: printstring STRINGID_PKMNPERISHCOUNTFELL waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER @@ -5997,14 +5414,14 @@ BattleScript_PerishBodyActivates:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSWILLPERISHIN3TURNS waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE return BattleScript_GulpMissileGorging:: call BattleScript_AbilityPopUp playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE effectivenesssound hitanimation BS_ATTACKER waitstate @@ -6031,7 +5448,7 @@ BattleScript_GulpMissileGulping:: call BattleScript_AbilityPopUp playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE waitanimation - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE effectivenesssound hitanimation BS_ATTACKER waitstate @@ -6067,27 +5484,36 @@ BattleScript_SeedSowerActivates:: call BattleScript_ActivateTerrainEffects return -BattleScript_AngerShellActivates:: +BattleScript_BerserkActivates:: saveattacker - copybyte gBattlerAttacker, gBattlerTarget + copybyte gBattlerAttacker, gEffectBattler call BattleScript_AbilityPopUp - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_AngerShellTryDef - jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed -BattleScript_AngerShellTryDef:: - modifybattlerstatstage BS_ATTACKER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON -BattleScript_AngerShellTrySpDef: - modifybattlerstatstage BS_ATTACKER, STAT_SPDEF, DECREASE, 1, BattleScript_AngerShellTryAttack, ANIM_ON -BattleScript_AngerShellTryAttack: - modifybattlerstatstage BS_ATTACKER, STAT_ATK, INCREASE, 1, BattleScript_AngerShellTrySpAtk, ANIM_ON -BattleScript_AngerShellTrySpAtk: - modifybattlerstatstage BS_ATTACKER, STAT_SPATK, INCREASE, 1, BattleScript_AngerShellTrySpeed, ANIM_ON -BattleScript_AngerShellTrySpeed: - modifybattlerstatstage BS_ATTACKER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON -BattleScript_AngerShellRet: + statbuffchange BS_EFFECT_BATTLER, STAT_CHANGE_CERTAIN, BattleScript_BerserkActivatesTryBerry + call BattleScript_StatUp +BattleScript_BerserkActivatesTryBerry: restoreattacker + tryrestorehpberry BS_EFFECT_BATTLER + return + +BattleScript_AngerShellActivates:: + call BattleScript_AbilityPopUp + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_GREATER_THAN, STAT_DEF, MIN_STAT_STAGE, BattleScript_AngerShellTryDef + jumpifstat BS_EFFECT_BATTLER, CMP_EQUAL, STAT_SPDEF, MIN_STAT_STAGE, BattleScript_RestoreAttackerButItFailed +BattleScript_AngerShellTryDef:: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_DEF, DECREASE, 1, BattleScript_AngerShellTrySpDef, ANIM_ON +BattleScript_AngerShellTrySpDef: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPDEF, DECREASE, 1, BattleScript_AngerShellTryAttack, ANIM_ON +BattleScript_AngerShellTryAttack: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_ATK, INCREASE, 1, BattleScript_AngerShellTrySpAtk, ANIM_ON +BattleScript_AngerShellTrySpAtk: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPATK, INCREASE, 1, BattleScript_AngerShellTrySpeed, ANIM_ON +BattleScript_AngerShellTrySpeed: + modifybattlerstatstage BS_EFFECT_BATTLER, STAT_SPEED, INCREASE, 1, BattleScript_AngerShellRet, ANIM_ON +BattleScript_AngerShellRet: + tryrestorehpberry BS_EFFECT_BATTLER return BattleScript_WindPowerActivates:: @@ -6113,7 +5539,7 @@ BattleScript_EarthEaterActivates:: call BattleScript_AbilityPopUp pause B_WAIT_TIME_LONG tryhealquarterhealth BS_TARGET, BattleScript_EarthEaterRet - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET printstring STRINGID_PKMNREGAINEDHEALTH @@ -6178,53 +5604,13 @@ BattleScript_LeechSeedFree:: waitmessage B_WAIT_TIME_LONG return -BattleScript_SpikesFree:: - printstring STRINGID_PKMNBLEWAWAYSPIKES +BattleScript_SpinHazardsAway:: + printfromtable gSpinHazardsStringIds waitmessage B_WAIT_TIME_LONG return -BattleScript_ToxicSpikesFree:: - printstring STRINGID_PKMNBLEWAWAYTOXICSPIKES - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StickyWebFree:: - printstring STRINGID_PKMNBLEWAWAYSTICKYWEB - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StealthRockFree:: - printstring STRINGID_PKMNBLEWAWAYSTEALTHROCK - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SteelsurgeFree:: - printstring STRINGID_PKMNBLEWAWAYSHARPSTEEL - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SpikesDefog:: - printstring STRINGID_SPIKESDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_ToxicSpikesDefog:: - printstring STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StickyWebDefog:: - printstring STRINGID_STICKYWEBDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StealthRockDefog:: - printstring STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SteelsurgeDefog:: - printstring STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM +BattleScript_DefogClearHazards:: + printfromtable gDefogHazardsStringIds waitmessage B_WAIT_TIME_LONG return @@ -6260,8 +5646,10 @@ BattleScript_DoFutureAttackResult: tryfaintmon BS_TARGET checkteamslost BattleScript_FutureAttackEnd BattleScript_FutureAttackEnd:: + moveendcase MOVEEND_SET_VALUES moveendcase MOVEEND_RAGE moveendcase MOVEEND_ABILITIES + moveendcase MOVEEND_COLOR_CHANGE moveendfromto MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_UPDATE_LAST_MOVES setmoveresultflags 0 end2 @@ -6282,7 +5670,7 @@ BattleScript_SelectingMoveWithNoPP:: endselectionscript BattleScript_NoPPForMove:: - attackstring + printattackstring pause B_WAIT_TIME_SHORT printstring STRINGID_BUTNOPPLEFT waitmessage B_WAIT_TIME_LONG @@ -6447,7 +5835,7 @@ BattleScript_PrintMonIsRootedRet:: BattleScript_AtkDefDown:: setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_AtkDefDownTryDef, BIT_DEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_AtkDefDownTryDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_AtkDefDownTryDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_AtkDefDownTryDef: @@ -6461,13 +5849,13 @@ BattleScript_AtkDefDownRet: BattleScript_DefSpDefDown:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownTrySpDef, BIT_SPDEF - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownTrySpDef + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefSpDefDownTrySpDef printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefSpDefDownTrySpDef:: setstatchanger STAT_SPDEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_ALLOW_PTR, BattleScript_DefSpDefDownRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_DefSpDefDownRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefSpDefDownRet printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefSpDefDownRet:: @@ -6479,13 +5867,13 @@ BattleScript_DefDownSpeedUp:: BattleScript_DefDownSpeedUpTryDef:: setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_DefDownSpeedUpTrySpeed - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefDownSpeedUpTrySpeed printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefDownSpeedUpTrySpeed: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_CERTAIN, BattleScript_DefDownSpeedUpRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_DefDownSpeedUpRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_DefDownSpeedUpRet printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_DefDownSpeedUpRet:: @@ -6516,31 +5904,21 @@ BattleScript_GrudgeTakesPp:: return BattleScript_MagicBounce:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNMOVEBOUNCEDABILITY waitmessage B_WAIT_TIME_LONG setmagiccoattarget - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING return BattleScript_MagicCoat:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT setmagiccoattarget printstring STRINGID_PKMNMOVEBOUNCED waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING return BattleScript_MagicCoatPrankster:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNMOVEBOUNCED waitmessage B_WAIT_TIME_LONG @@ -6550,13 +5928,10 @@ BattleScript_MagicCoatPrankster:: goto BattleScript_MoveEnd BattleScript_SnatchedMove:: - attackstring - ppreduce snatchsetbattlers playanimation BS_TARGET, B_ANIM_SNATCH_MOVE printstring STRINGID_PKMNSNATCHEDMOVE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP swapattackerwithtarget return @@ -6626,16 +6001,15 @@ BattleScript_PowerConstruct:: flushtextbox printstring STRINGID_POWERCONSTRUCTPRESENCEOFMANY waitmessage B_WAIT_TIME_SHORT - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp - handleformchange BS_ATTACKER, 0 - handleformchange BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_POWER_CONSTRUCT + call BattleScript_AbilityPopUpScripting + handleformchange BS_SCRIPTING, 0 + handleformchange BS_SCRIPTING, 1 + playanimation BS_SCRIPTING, B_ANIM_POWER_CONSTRUCT waitanimation - handleformchange BS_ATTACKER, 2 + handleformchange BS_SCRIPTING, 2 printstring STRINGID_POWERCONSTRUCTTRANSFORM waitmessage B_WAIT_TIME_SHORT - end3 + end2 BattleScript_UltraBurst:: flushtextbox @@ -6652,51 +6026,44 @@ BattleScript_UltraBurst:: end3 BattleScript_GulpMissileFormChange:: - call BattleScript_AttackerFormChange + call BattleScript_BattlerFormChange goto BattleScript_FromTwoTurnMovesSecondTurnRet -BattleScript_AttackerFormChange:: +BattleScript_BattlerFormChange:: pause 5 - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting flushtextbox -BattleScript_AttackerFormChangeNoPopup:: - handleformchange BS_ATTACKER, 0 - handleformchange BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE +BattleScript_BattlerFormChangeNoPopup: + handleformchange BS_SCRIPTING, 0 + handleformchange BS_SCRIPTING, 1 + playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - handleformchange BS_ATTACKER, 2 + handleformchange BS_SCRIPTING, 2 return -BattleScript_AttackerFormChangeEnd3:: - call BattleScript_AttackerFormChange +BattleScript_BattlerFormChangeEnd3:: + call BattleScript_BattlerFormChange end3 -BattleScript_AttackerFormChangeEnd3NoPopup:: - call BattleScript_AttackerFormChangeNoPopup - end3 +BattleScript_BattlerFormChangeEnd3NoPopup:: + call BattleScript_BattlerFormChangeNoPopup + end2 -BattleScript_AttackerFormChangeWithString:: +BattleScript_BattlerFormChangeEnd2:: + call BattleScript_BattlerFormChange + end2 + +BattleScript_BattlerFormChangeWithStringEnd3:: pause 5 - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting flushtextbox -BattleScript_AttackerFormChangeWithStringNoPopup:: - handleformchange BS_ATTACKER, 0 - handleformchange BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE + handleformchange BS_SCRIPTING, 0 + handleformchange BS_SCRIPTING, 1 + playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - handleformchange BS_ATTACKER, 2 + handleformchange BS_SCRIPTING, 2 printstring STRINGID_PKMNTRANSFORMED waitmessage B_WAIT_TIME_LONG - return - -BattleScript_AttackerFormChangeWithStringEnd3:: - call BattleScript_AttackerFormChangeWithString - end3 - -BattleScript_AttackerFormChangeWithStringEnd3NoPopup:: - call BattleScript_AttackerFormChangeWithStringNoPopup end3 BattleScript_AttackerFormChangeMoveEffect:: @@ -6715,7 +6082,7 @@ BattleScript_BallFetch:: call BattleScript_AbilityPopUp printstring STRINGID_FETCHEDPOKEBALL waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_CudChewActivates:: pause B_WAIT_TIME_SHORTEST @@ -6723,13 +6090,14 @@ BattleScript_CudChewActivates:: setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries consumeberry BS_ATTACKER, FALSE setbyte sBERRY_OVERRIDE, 0 - end3 + end2 BattleScript_ApplyDisguiseFormChangeHPLoss:: -.if B_DISGUISE_HP_LOSS >= GEN_8 + jumpifgenconfiglowerthan GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn + orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING -.endif +BattleScript_ApplyDisguiseFormChangeHPLossReturn: return BattleScript_TargetFormChangeNoPopup: @@ -6762,19 +6130,6 @@ BattleScript_TargetFormChangeWithStringNoPopup:: waitmessage B_WAIT_TIME_LONG return -BattleScript_BattlerFormChangeWithStringEnd3:: - pause 5 - call BattleScript_AbilityPopUpScripting - flushtextbox - handleformchange BS_SCRIPTING, 0 - handleformchange BS_SCRIPTING, 1 - playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE, NULL - waitanimation - handleformchange BS_SCRIPTING, 2 - printstring STRINGID_PKMNTRANSFORMED - waitmessage B_WAIT_TIME_LONG - end3 - BattleScript_IllusionOffAndTerastallization:: call BattleScript_IllusionOff goto BattleScript_Terastallization @@ -6784,12 +6139,12 @@ BattleScript_IllusionOffEnd3:: end3 BattleScript_IllusionOff:: - spriteignore0hp TRUE + setspriteignore0hp TRUE playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF waitanimation - updatenick BS_SCRIPTING + updatenick waitstate - spriteignore0hp FALSE + setspriteignore0hp FALSE printstring STRINGID_ILLUSIONWOREOFF waitmessage B_WAIT_TIME_LONG return @@ -6801,11 +6156,11 @@ BattleScript_CottonDownActivates:: swapattackerwithtarget setbyte gBattlerTarget, 0 BattleScript_CottonDownLoop: - jumpiffainted BS_TARGET, TRUE, BattleScript_CottonDownLoopIncrement + jumpifabsent BS_TARGET, BattleScript_CottonDownLoopIncrement setstatchanger STAT_SPEED, 1, TRUE jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_CottonDownLoopIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_CottonDownTargetSpeedCantGoLower + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CottonDownTargetSpeedCantGoLower printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_CottonDownLoopIncrement @@ -6830,7 +6185,7 @@ BattleScript_AftermathDmg:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpScripting jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_AftermathDmgRet - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_AFTERMATHDMG @@ -6864,7 +6219,7 @@ BattleScript_MoveUsedWokeUp:: BattleScript_MonWokeUpInUproar:: printstring STRINGID_PKMNWOKEUPINUPROAR waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER + updatestatusicon BS_EFFECT_BATTLER end2 BattleScript_PoisonTurnDmg:: @@ -6873,12 +6228,12 @@ BattleScript_PoisonTurnDmg:: BattleScript_DoStatusTurnDmg:: statusanimation BS_ATTACKER BattleScript_DoTurnDmg: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER checkteamslost BattleScript_DoTurnDmgEnd - tryrestorehpberry + tryrestorehpberry BS_ATTACKER BattleScript_DoTurnDmgEnd: end2 @@ -6888,7 +6243,7 @@ BattleScript_PoisonHealActivates:: printstring STRINGID_POISONHEALHPUP waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER end2 @@ -6937,12 +6292,10 @@ BattleScript_MoveUsedIsParalyzed:: printstring STRINGID_PKMNISPARALYZED waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves goto BattleScript_MoveEnd BattleScript_PowderMoveNoEffect:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_PowderMoveNoEffectPrint jumpifability BS_TARGET, ABILITY_OVERCOAT, BattleScript_PowderMoveNoEffectOvercoat @@ -6954,7 +6307,7 @@ BattleScript_PowderMoveNoEffectPrint: printstring STRINGID_ITDOESNTAFFECT BattleScript_PowderMoveNoEffectWaitMsg: waitmessage B_WAIT_TIME_LONG - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd @@ -6967,12 +6320,12 @@ BattleScript_MoveUsedFlinchedEnd: BattleScript_TryActivateSteadFast: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_MoveUsedFlinchedEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_MoveUsedFlinchedEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_MoveUsedFlinchedEnd copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUp statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveUsedFlinchedEnd setbyte gBattleCommunication STAT_SPEED - stattextbuffer BS_ATTACKER + stattextbuffer printstring STRINGID_ATTACKERABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveUsedFlinchedEnd @@ -6983,7 +6336,7 @@ BattleScript_PrintUproarOverTurns:: end2 BattleScript_ThrashConfuses:: - chosenstatus2animation BS_ATTACKER, STATUS2_CONFUSION + volatileanimation BS_ATTACKER, VOLATILE_CONFUSION printstring STRINGID_PKMNFATIGUECONFUSION waitmessage B_WAIT_TIME_LONG end2 @@ -6991,17 +6344,17 @@ BattleScript_ThrashConfuses:: BattleScript_MoveUsedIsConfused:: printstring STRINGID_PKMNISCONFUSED waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_CONFUSION + volatileanimation BS_ATTACKER, VOLATILE_CONFUSION jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, FALSE, BattleScript_MoveUsedIsConfusedRet BattleScript_DoSelfConfusionDmg:: - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves adjustdamage printstring STRINGID_ITHURTCONFUSION waitmessage B_WAIT_TIME_LONG effectivenesssound hitanimation BS_ATTACKER waitstate - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER resultmessage @@ -7012,17 +6365,14 @@ BattleScript_MoveUsedIsConfusedRet:: return BattleScript_MoveUsedPowder:: - bicword gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED - attackstring - ppreduce pause B_WAIT_TIME_SHORT - cancelmultiturnmoves BS_ATTACKER - status2animation BS_ATTACKER, STATUS2_POWDER + cancelmultiturnmoves + volatileanimation BS_ATTACKER, VOLATILE_POWDER waitanimation effectivenesssound hitanimation BS_ATTACKER waitstate - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_POWDEREXPLODES @@ -7055,7 +6405,7 @@ BattleScript_WrapEnds:: BattleScript_MoveUsedIsInLove:: printstring STRINGID_PKMNINLOVE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION return BattleScript_MoveUsedIsInLoveCantAttack:: @@ -7066,13 +6416,13 @@ BattleScript_MoveUsedIsInLoveCantAttack:: BattleScript_NightmareTurnDmg:: printstring STRINGID_PKMNLOCKEDINNIGHTMARE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_NIGHTMARE + volatileanimation BS_ATTACKER, VOLATILE_NIGHTMARE goto BattleScript_DoTurnDmg BattleScript_CurseTurnDmg:: printstring STRINGID_PKMNAFFLICTEDBYCURSE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_CURSED + volatileanimation BS_ATTACKER, VOLATILE_CURSED goto BattleScript_DoTurnDmg BattleScript_TargetPRLZHeal:: @@ -7110,13 +6460,13 @@ BattleScript_UpdateEffectStatusIconRet:: flushtextbox return -BattleScript_YawnMakesAsleep:: +BattleScript_YawnMakesAsleepEnd2:: statusanimation BS_EFFECT_BATTLER printstring STRINGID_PKMNFELLASLEEP waitmessage B_WAIT_TIME_LONG updatestatusicon BS_EFFECT_BATTLER waitstate - jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_SKY_DROPPED, BattleScript_YawnEnd + jumpfifsemiinvulnerable BS_EFFECT_BATTLER, STATE_SKY_DROP, BattleScript_YawnEnd makevisible BS_EFFECT_BATTLER skydropyawn BattleScript_YawnEnd: @@ -7125,7 +6475,7 @@ BattleScript_YawnEnd: BattleScript_EmbargoEndTurn:: printstring STRINGID_EMBARGOENDS waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryrestorehpberry BS_ATTACKER end2 BattleScript_TelekinesisEndTurn:: @@ -7202,7 +6552,7 @@ BattleScript_MoveEffectWrap:: return BattleScript_MoveEffectConfusion:: - chosenstatus2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_CONFUSION printstring STRINGID_PKMNWASCONFUSED waitmessage B_WAIT_TIME_LONG return @@ -7212,7 +6562,7 @@ BattleScript_MoveEffectRecoil:: jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_RecoilEnd BattleScript_DoRecoil:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_PKMNHITWITHRECOIL @@ -7268,10 +6618,8 @@ BattleScript_AbilityPopUpTarget:: copybyte gBattlerAbility, gBattlerTarget BattleScript_AbilityPopUp:: tryactivateabilityshield BS_ABILITY_BATTLER - .if B_ABILITY_POP_UP == TRUE - showabilitypopup BS_ABILITY_BATTLER - pause 40 - .endif + showabilitypopup + pause B_WAIT_TIME_SHORT recordability BS_ABILITY_BATTLER sethword sABILITY_OVERWRITE, 0 return @@ -7282,24 +6630,16 @@ BattleScript_AbilityPopUpScripting: BattleScript_AbilityPopUpOverwriteThenNormal: setbyte sFIXED_ABILITY_POPUP, TRUE - showabilitypopup BS_ABILITY_BATTLER - pause 60 + showabilitypopup + pause B_WAIT_TIME_SHORT sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_ABILITY_BATTLER - pause 20 + updateabilitypopup + pause B_WAIT_TIME_SHORT recordability BS_ABILITY_BATTLER destroyabilitypopup - pause 40 + setbyte sFIXED_ABILITY_POPUP, FALSE return -BattleScript_SpeedBoostActivates:: - call BattleScript_AbilityPopUp - statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_SpeedBoostActivatesEnd - printstring STRINGID_PKMNRAISEDSPEED - waitmessage B_WAIT_TIME_LONG -BattleScript_SpeedBoostActivatesEnd: - end3 - @ Can't compare directly to a value, have to compare to value at pointer sZero: .byte 0 @@ -7308,32 +6648,30 @@ BattleScript_MoodyActivates:: call BattleScript_AbilityPopUp jumpifbyteequal sSTATCHANGER, sZero, BattleScript_MoodyLower statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_MoodyLower - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_ROSE, BattleScript_MoodyLower + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_MoodyLower printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_MoodyLower: jumpifbyteequal sSAVED_STAT_CHANGER, sZero, BattleScript_MoodyEnd copybyte sSTATCHANGER, sSAVED_STAT_CHANGER statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_MoodyEnd - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_FELL, BattleScript_MoodyEnd + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_MoodyEnd printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_MoodyEnd: - end3 + end2 BattleScript_EmergencyExit:: - .if B_ABILITY_POP_UP == TRUE pause 5 call BattleScript_AbilityPopUpScripting pause B_WAIT_TIME_LONG - .endif playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation openpartyscreen BS_SCRIPTING, BattleScript_EmergencyExitRet switchoutabilities BS_SCRIPTING waitstate switchhandleorder BS_SCRIPTING, 2 - returntoball BS_TARGET, FALSE + returntoball BS_SCRIPTING, FALSE getswitchedmondata BS_SCRIPTING switchindataupdate BS_SCRIPTING hpthresholds BS_SCRIPTING @@ -7345,14 +6683,12 @@ BattleScript_EmergencyExitRet: return BattleScript_EmergencyExitWild:: - .if B_ABILITY_POP_UP == TRUE pause 5 call BattleScript_AbilityPopUpScripting pause B_WAIT_TIME_LONG - .endif playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation - setoutcomeonteleport BS_SCRIPTING + setteleportoutcome BS_SCRIPTING finishaction return @@ -7366,7 +6702,7 @@ BattleScript_EmergencyExitEnd2:: switchoutabilities BS_ATTACKER waitstate switchhandleorder BS_ATTACKER, 2 - returntoball BS_TARGET, FALSE + returntoball BS_ATTACKER, FALSE getswitchedmondata BS_ATTACKER switchindataupdate BS_ATTACKER hpthresholds BS_ATTACKER @@ -7383,7 +6719,7 @@ BattleScript_EmergencyExitWildEnd2:: pause B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_SLIDE_OFFSCREEN waitanimation - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER finishaction end2 @@ -7414,7 +6750,7 @@ BattleScript_AbilityHpHeal: BattleScript_RainDishActivates:: call BattleScript_AbilityHpHeal - end3 + end2 BattleScript_CheekPouchActivates:: copybyte sSAVED_BATTLER, gBattlerAttacker @@ -7429,9 +6765,9 @@ BattleScript_PickupActivates:: call BattleScript_AbilityPopUp printstring STRINGID_XFOUNDONEY waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryrestorehpberry BS_ATTACKER BattleScript_PickupActivatesEnd: - end3 + end2 BattleScript_HarvestActivates:: pause 5 @@ -7439,19 +6775,19 @@ BattleScript_HarvestActivates:: call BattleScript_AbilityPopUp printstring STRINGID_HARVESTBERRY waitmessage B_WAIT_TIME_LONG - tryrestorehpberry + tryrestorehpberry BS_ATTACKER BattleScript_HarvestActivatesEnd: - end3 + end2 BattleScript_SolarPowerActivates:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE call BattleScript_AbilityPopUp healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_SOLARPOWERHPDROP waitmessage B_WAIT_TIME_LONG tryfaintmon BS_ATTACKER - end3 + end2 BattleScript_HealerActivates:: call BattleScript_AbilityPopUp @@ -7459,7 +6795,7 @@ BattleScript_HealerActivates:: updatestatusicon BS_SCRIPTING printstring STRINGID_HEALERCURE waitmessage B_WAIT_TIME_LONG - end3 + end2 BattleScript_SandstreamActivates:: pause B_WAIT_TIME_SHORT @@ -7484,7 +6820,7 @@ BattleScript_ShedSkinActivates:: printstring STRINGID_PKMNSXCUREDYPROBLEM waitmessage B_WAIT_TIME_LONG updatestatusicon BS_ATTACKER - end3 + end2 BattleScript_ActivateWeatherAbilities: saveattacker @@ -7501,7 +6837,6 @@ BattleScript_ActivateWeatherAbilities_Loop: return BattleScript_TryIntimidateHoldEffects: - itemstatchangeeffects BS_TARGET jumpifnoholdeffect BS_TARGET, HOLD_EFFECT_ADRENALINE_ORB, BattleScript_TryIntimidateHoldEffectsRet jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_TryIntimidateHoldEffectsRet setstatchanger STAT_SPEED, 1, FALSE @@ -7518,7 +6853,6 @@ BattleScript_TryIntimidateHoldEffectsRet: BattleScript_IntimidateActivates:: savetarget call BattleScript_AbilityPopUp - destroyabilitypopup setbyte gBattlerTarget, 0 BattleScript_IntimidateLoop: jumpiftargetally BattleScript_IntimidateLoopIncrement @@ -7529,8 +6863,7 @@ BattleScript_IntimidateEffect: copybyte sBATTLER, gBattlerAttacker setstatchanger STAT_ATK, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_IntimidateLoopIncrement - jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_IntimidateContrary - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_IntimidateWontDecrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_IntimidateWontDecrease printstring STRINGID_PKMNCUTSATTACKWITH BattleScript_IntimidateEffect_WaitString: waitmessage B_WAIT_TIME_LONG @@ -7546,6 +6879,7 @@ BattleScript_IntimidateLoopIncrement: copybyte sBATTLER, gBattlerAttacker destroyabilitypopup restoretarget + restoreattacker pause B_WAIT_TIME_MED end3 @@ -7559,10 +6893,6 @@ BattleScript_IntimidateWontDecrease: printstring STRINGID_STATSWONTDECREASE goto BattleScript_IntimidateEffect_WaitString -BattleScript_IntimidateContrary: - printfromtable gStatUpStringIds - goto BattleScript_IntimidateEffect_WaitString - BattleScript_IntimidateInReverse:: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUpTarget @@ -7574,7 +6904,6 @@ BattleScript_IntimidateInReverse:: BattleScript_SupersweetSyrupActivates:: savetarget call BattleScript_AbilityPopUp - destroyabilitypopup printstring STRINGID_SUPERSWEETAROMAWAFTS waitmessage B_WAIT_TIME_LONG setbyte gBattlerTarget, 0 @@ -7586,8 +6915,7 @@ BattleScript_SupersweetSyrupEffect: copybyte sBATTLER, gBattlerAttacker setstatchanger STAT_EVASION, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_SupersweetSyrupLoopIncrement - jumpifability BS_TARGET, ABILITY_CONTRARY, BattleScript_SupersweetSyrupContrary - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_SupersweetSyrupWontDecrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_SupersweetSyrupWontDecrease printfromtable gStatDownStringIds BattleScript_SupersweetSyrupEffect_WaitString: waitmessage B_WAIT_TIME_LONG @@ -7603,6 +6931,7 @@ BattleScript_SupersweetSyrupLoopIncrement: copybyte sBATTLER, gBattlerAttacker destroyabilitypopup restoretarget + restoreattacker pause B_WAIT_TIME_MED end3 @@ -7610,10 +6939,6 @@ BattleScript_SupersweetSyrupWontDecrease: printstring STRINGID_STATSWONTDECREASE goto BattleScript_SupersweetSyrupEffect_WaitString -BattleScript_SupersweetSyrupContrary: - printfromtable gStatUpStringIds - goto BattleScript_SupersweetSyrupEffect_WaitString - BattleScript_DroughtActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -7633,11 +6958,7 @@ BattleScript_DesolateLandActivates:: end3 BattleScript_PrimalWeatherBlocksMove:: - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_MoveEnd @in case of multi-target moves, if move fails once, no point in printing the message twice - accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring pause B_WAIT_TIME_SHORT - ppreduce printfromtable gPrimalWeatherBlocksStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -7690,12 +7011,9 @@ BattleScript_SupremeOverlordActivates:: BattleScript_CostarActivates:: pause B_WAIT_TIME_SHORT - savetarget - copybyte gBattlerTarget, sBATTLER call BattleScript_AbilityPopUp printstring STRINGID_PKMNCOPIEDSTATCHANGES waitmessage B_WAIT_TIME_LONG - restoretarget end3 BattleScript_ZeroToHeroActivates:: @@ -7713,31 +7031,31 @@ BattleScript_CommanderActivates:: BattleScript_CommanderAtkIncrease: setstatchanger STAT_ATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderDefIncrease, BIT_DEF | BIT_SPATK | BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderDefIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderDefIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderDefIncrease: setstatchanger STAT_DEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpAtkIncrease, BIT_SPATK | BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpAtkIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpAtkIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpAtkIncrease: setstatchanger STAT_SPATK, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpDefIncrease, BIT_SPDEF | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpDefIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpDefIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpDefIncrease: setstatchanger STAT_SPDEF, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderSpeedIncrease, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderSpeedIncrease + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderSpeedIncrease printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderSpeedIncrease: setstatchanger STAT_SPEED, 2, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_CommanderEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_CommanderEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_CommanderEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_CommanderEnd: @@ -7750,8 +7068,9 @@ BattleScript_HospitalityActivates:: printstring STRINGID_HOSPITALITYRESTORATION waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + playanimation BS_EFFECT_BATTLER, B_ANIM_SIMPLE_HEAL + healthbarupdate BS_EFFECT_BATTLER + datahpupdate BS_EFFECT_BATTLER end3 BattleScript_AttackWeakenedByStrongWinds:: @@ -7789,10 +7108,11 @@ BattleScript_ActivateTerrainEffects: saveattacker savetarget tryboosterenergy ON_TERRAIN + resetterrainabilityflags setbyte gBattlerAttacker, 0 BattleScript_ActivateTerrainSeed: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 - doterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility + tryterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility removeitem BS_TARGET BattleScript_ActivateTerrainAbility: activateterrainchangeabilities BS_TARGET @@ -7852,7 +7172,7 @@ BattleScript_BadDreams_DmgAfterPopUp: printstring STRINGID_BADDREAMSDMG waitmessage B_WAIT_TIME_LONG dmg_1_8_targethp - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET jumpifhasnohp BS_TARGET, BattleScript_BadDreams_HidePopUp @@ -7863,7 +7183,7 @@ BattleScript_BadDreamsIncrement: destroyabilitypopup pause 15 BattleScript_BadDreamsEnd: - end3 + end2 BattleScript_BadDreams_ShowPopUp: copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUp @@ -7875,11 +7195,9 @@ BattleScript_BadDreams_HidePopUp: goto BattleScript_BadDreamsIncrement BattleScript_TookAttack:: - attackstring pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNSXTOOKATTACK waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED return BattleScript_SturdyPreventsOHKO:: @@ -7898,10 +7216,7 @@ BattleScript_DampStopsExplosion:: moveendcase MOVEEND_CLEAR_BITS end -BattleScript_MoveHPDrain_PPLoss:: - ppreduce BattleScript_MoveHPDrain:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE @@ -7912,10 +7227,7 @@ BattleScript_MoveHPDrain:: setmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE goto BattleScript_MoveEnd -BattleScript_MoveStatDrain_PPLoss:: - ppreduce BattleScript_MoveStatDrain:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveStatDrain_Cont @@ -7930,10 +7242,7 @@ BattleScript_MoveStatDrain_Cont: clearsemiinvulnerablebit goto BattleScript_MoveEnd -BattleScript_MonMadeMoveUseless_PPLoss:: - ppreduce BattleScript_MonMadeMoveUseless:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXMADEYUSELESS @@ -7941,10 +7250,7 @@ BattleScript_MonMadeMoveUseless:: setmoveresultflags MOVE_RESULT_DOESNT_AFFECT_FOE goto BattleScript_MoveEnd -BattleScript_FlashFireBoost_PPLoss:: - ppreduce BattleScript_FlashFireBoost:: - attackstring pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printfromtable gFlashFireStringIds @@ -7987,7 +7293,7 @@ BattleScript_FlinchPrevention:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXPREVENTSFLINCHING waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_OwnTempoPrevents:: pause B_WAIT_TIME_SHORT @@ -7997,8 +7303,6 @@ BattleScript_OwnTempoPrevents:: goto BattleScript_MoveEnd BattleScript_SoundproofProtected:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXBLOCKSY @@ -8011,8 +7315,6 @@ BattleScript_IceFaceNullsDamage:: return BattleScript_DazzlingProtected:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpScripting printstring STRINGID_POKEMONCANNOTUSEMOVE @@ -8020,17 +7322,19 @@ BattleScript_DazzlingProtected:: goto BattleScript_MoveEnd BattleScript_MoveUsedPsychicTerrainPrevents:: - printstring STRINGID_POKEMONCANNOTUSEMOVE + pause B_WAIT_TIME_SHORT + printstring STRINGID_PSYCHICTERRAINPREVENTS waitmessage B_WAIT_TIME_LONG + setmoveresultflags MOVE_RESULT_NO_EFFECT goto BattleScript_MoveEnd BattleScript_GrassyTerrainHeals:: printstring STRINGID_GRASSYTERRAINHEALS waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE end2 BattleScript_AbilityNoSpecificStatLoss:: @@ -8038,7 +7342,7 @@ BattleScript_AbilityNoSpecificStatLoss:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXPREVENTSYLOSS waitmessage B_WAIT_TIME_LONG - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY setmoveresultflags MOVE_RESULT_NO_EFFECT return @@ -8076,33 +7380,35 @@ BattleScript_TeraShellDistortingTypeMatchups:: BattleScript_CursedBodyActivates:: call BattleScript_AbilityPopUp - printstring STRINGID_CUSEDBODYDISABLED + printstring STRINGID_CURSEDBODYDISABLED waitmessage B_WAIT_TIME_LONG return BattleScript_MummyActivates:: -.if B_ABILITY_POP_UP == TRUE - call BattleScript_AbilityPopUpTarget setbyte sFIXED_ABILITY_POPUP, TRUE + call BattleScript_AbilityPopUpTarget copybyte gBattlerAbility, gBattlerAttacker copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET recordability BS_ATTACKER printstring STRINGID_ATTACKERACQUIREDABILITY waitmessage B_WAIT_TIME_LONG + trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas return BattleScript_WanderingSpiritActivates:: -.if B_ABILITY_POP_UP == TRUE + saveattacker + savetarget copybyte gBattlerAbility, gBattlerTarget sethword sABILITY_OVERWRITE, ABILITY_WANDERING_SPIRIT call BattleScript_AbilityPopUpOverwriteThenNormal copybyte gBattlerAbility, gBattlerAttacker copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal -.endif recordability BS_TARGET recordability BS_ATTACKER printstring STRINGID_SWAPPEDABILITIES @@ -8111,6 +7417,8 @@ BattleScript_WanderingSpiritActivates:: jumpiffainted BS_TARGET, TRUE, BattleScript_WanderingSpiritActivatesRet switchinabilities BS_TARGET BattleScript_WanderingSpiritActivatesRet: + restoreattacker + restoretarget return BattleScript_TargetsStatWasMaxedOut:: @@ -8122,14 +7430,12 @@ BattleScript_TargetsStatWasMaxedOutRet: return BattleScript_BattlerAbilityStatRaiseOnSwitchIn:: - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp - statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_BattlerAbilityStatRaiseOnSwitchInRet + call BattleScript_AbilityPopUpScripting + statbuffchange BS_SCRIPTING, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_CERTAIN, BattleScript_BattlerAbilityStatRaiseOnSwitchInRet waitanimation - printstring STRINGID_BATTLERABILITYRAISEDSTAT + printstring STRINGID_SCRIPTINGABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG BattleScript_BattlerAbilityStatRaiseOnSwitchInRet: - copybyte gBattlerAttacker, sSAVED_BATTLER end3 BattleScript_ScriptingAbilityStatRaise:: @@ -8148,8 +7454,8 @@ BattleScript_WeakArmorActivates:: call BattleScript_AbilityPopUp setstatchanger STAT_DEF, 1, TRUE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesSpeed - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_WeakArmorDefPrintString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_WeakArmorActivatesSpeed + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeakArmorDefPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_WeakArmorActivatesSpeed pause B_WAIT_TIME_SHORTEST printfromtable gStatDownStringIds clearmoveresultflags MOVE_RESULT_MISSED @ Set by statbuffchange when stat can't be decreased @@ -8159,14 +7465,15 @@ BattleScript_WeakArmorDefPrintString: printstring STRINGID_TARGETABILITYSTATLOWER waitmessage B_WAIT_TIME_LONG BattleScript_WeakArmorActivatesSpeed: -.if B_WEAK_ARMOR_SPEED >= GEN_7 + jumpifgenconfiglowerthan GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6 setstatchanger STAT_SPEED, 2, FALSE -.else + goto BattleScript_WeakArmorDoSpeed +BattleScript_WeakArmorSetSpeedGen6: setstatchanger STAT_SPEED, 1, FALSE -.endif +BattleScript_WeakArmorDoSpeed: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesEnd - jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeakArmorSpeedPrintString - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_EMPTY, BattleScript_WeakArmorActivatesEnd + jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeakArmorSpeedPrintString + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_WeakArmorActivatesEnd pause B_WAIT_TIME_SHORTEST printstring STRINGID_TARGETSTATWONTGOHIGHER clearmoveresultflags MOVE_RESULT_MISSED @@ -8189,10 +7496,9 @@ BattleScript_RaiseStatOnFaintingTarget_End: return BattleScript_AttackerAbilityStatRaise:: - statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_AttackerAbilityStatRaise_End - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp - statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackerAbilityStatRaise_End + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_AttackerAbilityStatRaise_End + call BattleScript_AbilityPopUpScripting + statbuffchange BS_SCRIPTING, STAT_CHANGE_ALLOW_PTR, BattleScript_AttackerAbilityStatRaise_End printstring STRINGID_ATTACKERABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG BattleScript_AttackerAbilityStatRaise_End: @@ -8200,7 +7506,7 @@ BattleScript_AttackerAbilityStatRaise_End: BattleScript_FellStingerRaisesStat:: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_FellStingerRaisesAtkEnd - jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_ROSE, BattleScript_FellStingerRaisesAtkEnd + jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, B_MSG_DEFENDER_STAT_CHANGED, BattleScript_FellStingerRaisesAtkEnd printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_FellStingerRaisesAtkEnd: @@ -8208,8 +7514,14 @@ BattleScript_FellStingerRaisesAtkEnd: BattleScript_AttackerAbilityStatRaiseEnd3:: call BattleScript_AttackerAbilityStatRaise + restoreattacker end3 +BattleScript_AttackerAbilityStatRaiseEnd2:: + call BattleScript_AttackerAbilityStatRaise + restoreattacker + end2 + BattleScript_SwitchInAbilityMsg:: call BattleScript_AbilityPopUp printfromtable gSwitchInAbilityStringIds @@ -8244,24 +7556,26 @@ BattleScript_FriskMsg:: BattleScript_FriskActivates:: saveattacker - savetarget + savetarget copybyte gBattlerAttacker, sBATTLER - tryfriskmsg BS_SCRIPTING + tryfriskmessage restoreattacker - restoretarget + restoretarget end3 BattleScript_ImposterActivates:: call BattleScript_AbilityPopUp transformdataexecution - playmoveanimation BS_ATTACKER, MOVE_TRANSFORM + playmoveanimation MOVE_TRANSFORM waitanimation printstring STRINGID_IMPOSTERTRANSFORM waitmessage B_WAIT_TIME_LONG + restoreattacker + restoretarget end3 BattleScript_HurtAttacker: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_PKMNHURTSWITH @@ -8285,7 +7599,7 @@ BattleScript_RockyHelmetActivatesDmg: BattleScript_SpikyShieldEffect:: jumpifabsent BS_ATTACKER, BattleScript_SpikyShieldRet - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER @@ -8297,7 +7611,7 @@ BattleScript_SpikyShieldRet:: return BattleScript_KingsShieldEffect:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_NONE copybyte sBATTLER, gBattlerTarget @@ -8307,7 +7621,7 @@ BattleScript_KingsShieldEffect:: return BattleScript_BanefulBunkerEffect:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE clearmoveresultflags MOVE_RESULT_NO_EFFECT setnonvolatilestatus TRIGGER_ON_PROTECT setmoveresultflags MOVE_RESULT_MISSED @@ -8315,7 +7629,7 @@ BattleScript_BanefulBunkerEffect:: BattleScript_CuteCharmActivates:: call BattleScript_AbilityPopUp - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION printstring STRINGID_PKMNSXINFATUATEDY waitmessage B_WAIT_TIME_LONG call BattleScript_TryDestinyKnotTarget @@ -8352,19 +7666,19 @@ BattleScript_EffectBattleBondStatIncrease:: call BattleScript_AbilityPopUp setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpAtk, BIT_SPATK | BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseTrySpAtk printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseTrySpAtk: setstatchanger STAT_SPATK, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpeed, BIT_SPEED - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseTrySpeed printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseTrySpeed: setstatchanger STAT_SPEED, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseRet - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_EffectBattleBondStatIncreaseRet printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_EffectBattleBondStatIncreaseRet: @@ -8373,7 +7687,6 @@ BattleScript_EffectBattleBondStatIncreaseRet: BattleScript_DancerActivates:: call BattleScript_AbilityPopUp waitmessage B_WAIT_TIME_SHORT - orword gHitMarker, HITMARKER_ALLOW_NO_PP jumptocalledmove TRUE BattleScript_SynchronizeActivates:: @@ -8416,15 +7729,14 @@ BattleScript_IgnoresWhileAsleep:: BattleScript_IgnoresAndUsesRandomMove:: printstring STRINGID_PKMNIGNOREDORDERS waitmessage B_WAIT_TIME_LONG - setbyte sMOVE_EFFECT, 0 - jumptocalledmove FALSE + return BattleScript_MoveUsedLoafingAround:: jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_LOAFING, BattleScript_MoveUsedLoafingAroundMsg @ Skip ahead if not the Battle Palace message jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_INCAPABLE_OF_POWER, BattleScript_MoveUsedLoafingAroundMsg setbyte gBattleCommunication, 0 - palacetryescapestatus BS_ATTACKER + palacetryescapestatus setbyte cMULTISTRING_CHOOSER, B_MSG_INCAPABLE_OF_POWER BattleScript_MoveUsedLoafingAroundMsg:: printfromtable gInobedientStringIds @@ -8432,6 +7744,7 @@ BattleScript_MoveUsedLoafingAroundMsg:: moveendto MOVEEND_NEXT_TARGET end BattleScript_TruantLoafingAround:: + flushtextbox call BattleScript_AbilityPopUp goto BattleScript_MoveUsedLoafingAroundMsg @@ -8598,7 +7911,7 @@ BattleScript_ItemHealHP_RemoveItemRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING removeitem BS_SCRIPTING @@ -8613,22 +7926,22 @@ BattleScript_ItemHealHP_RemoveItemEnd2_Anim: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER removeitem BS_ATTACKER end2 BattleScript_BerryPPHealRet:: - jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryPPHeal_AbilityPopup + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryPPHeal_AbilityPopup goto BattleScript_BerryPPHeal_Anim BattleScript_BerryPPHeal_AbilityPopup: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting BattleScript_BerryPPHeal_Anim: - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDPP waitmessage B_WAIT_TIME_LONG - removeitem BS_ATTACKER + removeitem BS_SCRIPTING return BattleScript_BerryPPHealEnd2:: @@ -8651,7 +7964,7 @@ BattleScript_AirBaloonMsgPop:: return BattleScript_ItemHurtRet:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_IGNORE_DISGUISE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_HURTBYITEM @@ -8669,7 +7982,7 @@ BattleScript_ItemHealHP_Ret:: playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHPALITTLE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER return @@ -8724,7 +8037,7 @@ BattleScript_BerryConfuseHealEnd2_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION @@ -8740,7 +8053,7 @@ BattleScript_BerryConfuseHealRet_Anim: playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION @@ -8765,7 +8078,7 @@ BattleScript_ConsumableStatRaiseRet_Anim: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_ConsumableStatRaiseRet_End playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_ConsumableStatRaiseRet_End - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGED_ITEM call BattleScript_StatUp removeitem BS_SCRIPTING BattleScript_ConsumableStatRaiseRet_End: @@ -8794,7 +8107,7 @@ BattleScript_FlushMessageBox:: @BattleScript_PalacePrintFlavorText:: @ setbyte gBattleCommunication + 1, 0 @BattleScript_PalaceTryBattlerFlavorText:: -@ palaceflavortext BS_ATTACKER @ BS_ATTACKER here overwritten by gBattleCommunication + 1 +@ palaceflavortext @ jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, TRUE, BattleScript_PalaceEndFlavorText @ printfromtable gBattlePalaceFlavorTextTable @ waitmessage B_WAIT_TIME_LONG @@ -8806,16 +8119,16 @@ BattleScript_FlushMessageBox:: @ end2 @ @BattleScript_ArenaTurnBeginning:: -@ waitcry BS_ATTACKER +@ waitcry @ volumedown @ playse SE_ARENA_TIMEUP1 @ pause 8 @ playse SE_ARENA_TIMEUP1 -@ arenadrawreftextbox +@ drawarenareftextbox @ arenajudgmentstring B_MSG_REF_COMMENCE_BATTLE @ arenawaitmessage B_MSG_REF_COMMENCE_BATTLE @ pause B_WAIT_TIME_LONG -@ arenaerasereftextbox +@ erasearenareftextbox @ volumeup @ end2 @ @@ -8829,7 +8142,7 @@ BattleScript_FlushMessageBox:: @ pause 8 @ playse SE_ARENA_TIMEUP1 @ pause B_WAIT_TIME_LONG -@ arenadrawreftextbox +@ drawarenareftextbox @ arenajudgmentstring B_MSG_REF_THATS_IT @ arenawaitmessage B_MSG_REF_THATS_IT @ pause B_WAIT_TIME_LONG @@ -8852,13 +8165,14 @@ BattleScript_FlushMessageBox:: @ arenajudgmentstring B_MSG_REF_PLAYER_WON @ arenawaitmessage B_MSG_REF_PLAYER_WON @ arenajudgmentwindow -@ arenaerasereftextbox +@ erasearenareftextbox @ printstring STRINGID_DEFEATEDOPPONENTBYREFEREE @ waitmessage B_WAIT_TIME_LONG @ playfaintcry BS_OPPONENT1 -@ waitcry BS_ATTACKER +@ waitcry @ dofaintanimation BS_OPPONENT1 @ cleareffectsonfaint BS_OPPONENT1 +@ waitanimation @ arenaopponentmonlost @ end2 @ @@ -8866,13 +8180,14 @@ BattleScript_FlushMessageBox:: @ arenajudgmentstring B_MSG_REF_OPPONENT_WON @ arenawaitmessage B_MSG_REF_OPPONENT_WON @ arenajudgmentwindow -@ arenaerasereftextbox +@ erasearenareftextbox @ printstring STRINGID_LOSTTOOPPONENTBYREFEREE @ waitmessage B_WAIT_TIME_LONG @ playfaintcry BS_PLAYER1 -@ waitcry BS_ATTACKER +@ waitcry @ dofaintanimation BS_PLAYER1 @ cleareffectsonfaint BS_PLAYER1 +@ waitanimation @ arenaplayermonlost @ end2 @ @@ -8880,23 +8195,25 @@ BattleScript_FlushMessageBox:: @ arenajudgmentstring B_MSG_REF_DRAW @ arenawaitmessage B_MSG_REF_DRAW @ arenajudgmentwindow -@ arenaerasereftextbox +@ erasearenareftextbox @ printstring STRINGID_TIEDOPPONENTBYREFEREE @ waitmessage B_WAIT_TIME_LONG @ playfaintcry BS_PLAYER1 -@ waitcry BS_ATTACKER +@ waitcry @ dofaintanimation BS_PLAYER1 @ cleareffectsonfaint BS_PLAYER1 +@ waitanimation @ playfaintcry BS_OPPONENT1 -@ waitcry BS_ATTACKER +@ waitcry @ dofaintanimation BS_OPPONENT1 @ cleareffectsonfaint BS_OPPONENT1 -@ arenabothmonlost +@ waitanimation +@ arenabothmonslost @ end2 BattleScript_AskIfWantsToForfeitMatch:: printselectionstring STRINGID_QUESTIONFORFEITMATCH - forfeityesnobox BS_ATTACKER + forfeityesnobox endselectionscript BattleScript_PrintPlayerForfeited:: @@ -8947,6 +8264,10 @@ BattleScript_OpportunistStartCopyStats: goto BattleScript_OpportunistStartCopyStats BattleScript_OpportunistCopyStatChangeEnd: setbyte sSTAT_ANIM_PLAYED, FALSE + return + +BattleScript_OpportunistCopyStatChangeEnd3:: + call BattleScript_OpportunistCopyStatChange end3 BattleScript_TotemVar:: @@ -9074,16 +8395,6 @@ BattleScript_ZMoveActivateStatus:: copybyte sSTATCHANGER, sSAVED_STAT_CHANGER return -BattleScript_ZMoveActivatePowder:: - flushtextbox - trytrainerslidezmovemsg - savetarget - printstring STRINGID_ZPOWERSURROUNDS - playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL - setzeffect - restoretarget - goto BattleScript_MoveUsedPowder - BattleScript_ZEffectPrintString:: printfromtable gZEffectStringIds waitmessage B_WAIT_TIME_LONG @@ -9098,7 +8409,7 @@ BattleScript_RecoverHPZMove:: BattleScript_StatUpZMove:: statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_StatUpZMoveEnd - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpZMoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_StatUpZMoveEnd printstring STRINGID_ZMOVESTATUP waitmessage B_WAIT_TIME_LONG printfromtable gStatUpStringIds @@ -9116,8 +8427,6 @@ BattleScript_HealReplacementZMove:: BattleScript_EffectExtremeEvoboost:: attackcanceler - attackstring - ppreduce jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_DEF, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ExtremeEvoboostAnim @@ -9154,12 +8463,9 @@ BattleScript_ExtremeEvoboostSpDef:: BattleScript_ExtremeEvoboostEnd:: goto BattleScript_MoveEnd -BattleScript_EffectHitSetRemoveTerrain:: +BattleScript_EffectHitSetTerrain:: attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - jumpifmovepropertyargument ARG_TRY_REMOVE_TERRAIN_FAIL, BattleScript_RemoveTerrain + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE critcalc damagecalc adjustdamage @@ -9174,7 +8480,7 @@ BattleScript_EffectHitSetRemoveTerrain:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - setremoveterrain BattleScript_TryFaint + setterrain BattleScript_TryFaint playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG @@ -9182,30 +8488,12 @@ BattleScript_TryFaint: tryfaintmon BS_TARGET goto BattleScript_MoveEnd -BattleScript_RemoveTerrain: - jumpifterrainaffected BS_TARGET, STATUS_FIELD_TERRAIN_ANY, BattleScript_RemoveTerrain_Cont - goto BattleScript_ButItFailed -BattleScript_RemoveTerrain_Cont: - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG +BattleScript_RemoveTerrain:: removeterrain playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + return BattleScript_Pickpocket:: call BattleScript_AbilityPopUp @@ -9213,7 +8501,7 @@ BattleScript_Pickpocket:: swapattackerwithtarget call BattleScript_ItemSteal swapattackerwithtarget - activateitemeffects BS_TARGET + activateitemeffects return BattleScript_PickpocketPrevented: @@ -9245,7 +8533,7 @@ BattleScript_RedCardActivates:: printstring STRINGID_REDCARDACTIVATE waitmessage B_WAIT_TIME_LONG swapattackerwithtarget - jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain + jumpifvolatile BS_EFFECT_BATTLER, VOLATILE_ROOT, BattleScript_RedCardIngrain jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups jumpiftargetdynamaxed BattleScript_RedCardDynamaxed removeitem BS_SCRIPTING @@ -9311,9 +8599,7 @@ BattleScript_EjectPackActivates:: jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd goto BattleScript_EjectPackActivate_Ret -BattleScript_DarkTypePreventsPrankster:: - attackstring - ppreduce +BattleScript_DoesntAffectTargetAtkString:: pause B_WAIT_TIME_SHORT printstring STRINGID_ITDOESNTAFFECT waitmessage B_WAIT_TIME_LONG @@ -9321,8 +8607,6 @@ BattleScript_DarkTypePreventsPrankster:: goto BattleScript_MoveEnd BattleScript_WellBakedBodyActivates:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpTarget setmoveresultflags MOVE_RESULT_NO_EFFECT @@ -9331,8 +8615,6 @@ BattleScript_WellBakedBodyEnd: goto BattleScript_MoveEnd BattleScript_WindRiderActivatesMoveEnd:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUpTarget setmoveresultflags MOVE_RESULT_NO_EFFECT @@ -9341,8 +8623,6 @@ BattleScript_WindRiderActivatesMoveEnd_End: goto BattleScript_MoveEnd BattleScript_GoodAsGoldActivates:: - attackstring - ppreduce call BattleScript_AbilityPopUpTarget pause B_WAIT_TIME_SHORT printstring STRINGID_ITDOESNTAFFECT @@ -9371,6 +8651,7 @@ BattleScript_PastelVeilLoopIncrement: setallytonexttarget BattleScript_PastelVeil_TryCurePoison goto BattleScript_PastelVeilEnd BattleScript_PastelVeilEnd: + restoretarget end3 BattleScript_NeutralizingGasExits:: @@ -9406,40 +8687,20 @@ BattleScript_SymbiosisActivates:: return BattleScript_TargetAbilityStatRaiseRet:: - copybyte sSAVED_BATTLER, gBattlerAttacker - copybyte gBattlerAbility, gEffectBattler - copybyte gBattlerAttacker, gBattlerTarget + saveattacker + copybyte gBattlerAttacker, gEffectBattler call BattleScript_AbilityPopUp statbuffchange BS_ATTACKER, STAT_CHANGE_CERTAIN, BattleScript_TargetAbilityStatRaiseRet_End call BattleScript_StatUp BattleScript_TargetAbilityStatRaiseRet_End: - copybyte gBattlerAttacker, sSAVED_BATTLER + restoreattacker return @@@ MAX MOVES @@@ BattleScript_EffectMaxMove:: attackcanceler accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - setadditionaleffects - moveendall - end + goto BattleScript_HitFromAtkString BattleScript_EffectRaiseStatAllies:: savetarget @@ -9447,7 +8708,7 @@ BattleScript_EffectRaiseStatAllies:: BattleScript_RaiseSideStatsLoop: jumpifabsent BS_TARGET, BattleScript_RaiseSideStatsIncrement statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RaiseSideStatsIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RaiseSideStatsIncrement + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_RaiseSideStatsIncrement printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RaiseSideStatsIncrement: @@ -9455,7 +8716,7 @@ BattleScript_RaiseSideStatsIncrement: setallytonexttarget BattleScript_RaiseSideStatsLoop BattleScript_RaiseSideStatsEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectLowerStatFoes:: savetarget @@ -9463,7 +8724,7 @@ BattleScript_EffectLowerStatFoes:: BattleScript_LowerSideStatsLoop: jumpifabsent BS_TARGET, BattleScript_LowerSideStatsIncrement statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_LowerSideStatsIncrement - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_LowerSideStatsIncrement + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_LowerSideStatsIncrement printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG BattleScript_LowerSideStatsIncrement: @@ -9471,26 +8732,26 @@ BattleScript_LowerSideStatsIncrement: setallytonexttarget BattleScript_LowerSideStatsLoop BattleScript_LowerSideStatsEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectSetWeather:: playanimation 0, B_ANIM_MAX_SET_WEATHER printfromtable gMoveWeatherChangeStringIds waitmessage B_WAIT_TIME_LONG call BattleScript_ActivateWeatherAbilities - goto BattleScript_MoveEnd + return BattleScript_EffectSetTerrain:: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG call BattleScript_ActivateTerrainEffects - goto BattleScript_MoveEnd + return BattleScript_DamageNonTypesStarts:: printfromtable gDamageNonTypesStartStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_DamageNonTypesContinues:: printfromtable gDamageNonTypesDmgStringIds @@ -9503,7 +8764,7 @@ BattleScript_EffectTryReducePP:: tryspiteppreduce BattleScript_MoveEnd printstring STRINGID_PKMNREDUCEDPP waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_EffectParalyzeSide:: savetarget @@ -9511,18 +8772,12 @@ BattleScript_EffectParalyzeSide:: BattleScript_ParalyzeSideLoop: jumpifabsent BS_TARGET, BattleScript_ParalyzeSideIncrement trysetparalysis BattleScript_ParalyzeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_ParalyzeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ParalyzeSideEnd setallytonexttarget BattleScript_ParalyzeSideLoop BattleScript_ParalyzeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectPoisonSide:: savetarget @@ -9530,18 +8785,12 @@ BattleScript_EffectPoisonSide:: BattleScript_PoisonSideLoop: jumpifabsent BS_TARGET, BattleScript_PoisonSideIncrement trysetpoison BattleScript_PoisonSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_PoisonSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonSideEnd setallytonexttarget BattleScript_PoisonSideLoop BattleScript_PoisonSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectPoisonParalyzeSide:: savetarget @@ -9549,18 +8798,12 @@ BattleScript_EffectPoisonParalyzeSide:: BattleScript_PoisonParalyzeSideLoop: jumpifabsent BS_TARGET, BattleScript_PoisonParalyzeSideIncrement trysetpoisonparalysis BattleScript_PoisonParalyzeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_PoisonParalyzeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonParalyzeSideEnd setallytonexttarget BattleScript_PoisonParalyzeSideLoop BattleScript_PoisonParalyzeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectEffectSporeSide:: savetarget @@ -9568,18 +8811,12 @@ BattleScript_EffectEffectSporeSide:: BattleScript_EffectSporeSideLoop: jumpifabsent BS_TARGET, BattleScript_EffectSporeSideIncrement tryseteffectspore BattleScript_EffectSporeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_EffectSporeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_EffectSporeSideEnd setallytonexttarget BattleScript_EffectSporeSideLoop BattleScript_EffectSporeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectConfuseSide:: savetarget @@ -9587,9 +8824,9 @@ BattleScript_EffectConfuseSide:: BattleScript_ConfuseSideLoop: jumpifabsent BS_TARGET, BattleScript_ConfuseSideIncrement trysetconfusion BattleScript_ConfuseSideIncrement - status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_CONFUSION BattleScript_ConfuseSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNWASCONFUSED waitmessage B_WAIT_TIME_LONG BattleScript_ConfuseSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ConfuseSideEnd @@ -9597,11 +8834,11 @@ BattleScript_ConfuseSideIncrement: BattleScript_ConfuseSideEnd: restoretarget jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush - goto BattleScript_MoveEnd + return BattleScript_PrintCoinsScattered: printstring STRINGID_COINSSCATTERED - goto BattleScript_MoveEnd + return BattleScript_EffectInfatuateSide:: savetarget @@ -9609,16 +8846,16 @@ BattleScript_EffectInfatuateSide:: BattleScript_InfatuateSideLoop: jumpifabsent BS_TARGET, BattleScript_InfatuateSideIncrement trysetinfatuation BattleScript_InfatuateSideIncrement - status2animation BS_EFFECT_BATTLER, STATUS2_INFATUATION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_INFATUATION BattleScript_InfatuateSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNFELLINLOVE waitmessage B_WAIT_TIME_LONG BattleScript_InfatuateSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_InfatuateSideEnd setallytonexttarget BattleScript_InfatuateSideLoop BattleScript_InfatuateSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectTormentSide:: savetarget @@ -9627,14 +8864,14 @@ BattleScript_TormentSideLoop: jumpifabsent BS_TARGET, BattleScript_TormentSideIncrement trysettorment BattleScript_TormentSideIncrement BattleScript_TormentSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNSUBJECTEDTOTORMENT waitmessage B_WAIT_TIME_LONG BattleScript_TormentSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_TormentSideEnd setallytonexttarget BattleScript_TormentSideLoop BattleScript_TormentSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_TormentEnds:: printstring STRINGID_TORMENTEDNOMORE @@ -9648,14 +8885,14 @@ BattleScript_MeanLookSideLoop: jumpifabsent BS_TARGET, BattleScript_MeanLookSideIncrement trysetescapeprevention BattleScript_MeanLookSideIncrement BattleScript_MeanLookSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_TARGETCANTESCAPENOW waitmessage B_WAIT_TIME_LONG BattleScript_MeanLookSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_MeanLookSideEnd setallytonexttarget BattleScript_MeanLookSideLoop BattleScript_MeanLookSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRaiseCritAlliesAnim:: savetarget @@ -9671,10 +8908,10 @@ BattleScript_RaiseCritAlliesIncrement: setallytonexttarget BattleScript_RaiseCritAlliesLoop BattleScript_RaiseCritAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectHealOneSixthAllies:: - jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd + jumpifteamhealthy BattleScript_MoveEnd savetarget copybyte gBattlerTarget, gBattlerAttacker BattleScript_HealOneSixthAlliesLoop: @@ -9690,7 +8927,7 @@ BattleScript_HealOneSixthAlliesIncrement: setallytonexttarget BattleScript_HealOneSixthAlliesLoop BattleScript_HealOneSixthAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRecycleBerriesAllies:: savetarget @@ -9707,13 +8944,13 @@ BattleScript_RecycleBerriesAlliesIncrement: setallytonexttarget BattleScript_RecycleBerriesAlliesLoop BattleScript_RecycleBerriesAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectSteelsurge:: setsteelsurge BattleScript_MoveEnd printfromtable gDmgHazardsStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return @@@ END MAX MOVES @@@ @@ -9755,19 +8992,17 @@ BattleScript_DynamaxEnds:: BattleScript_DynamaxEnds_Ret:: flushtextbox - spriteignore0hp TRUE + setspriteignore0hp TRUE updatedynamax playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - spriteignore0hp FALSE + setspriteignore0hp FALSE pause B_WAIT_TIME_SHORT return BattleScript_MoveBlockedByDynamax:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE pause B_WAIT_TIME_SHORT - ppreduce jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd printstring STRINGID_MOVEBLOCKEDBYDYNAMAX waitmessage B_WAIT_TIME_LONG @@ -9775,8 +9010,6 @@ BattleScript_MoveBlockedByDynamax:: goto BattleScript_MoveEnd BattleScript_PokemonCantUseTheMove:: - attackstring - ppreduce pause B_WAIT_TIME_SHORT printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE waitmessage B_WAIT_TIME_LONG @@ -9794,7 +9027,7 @@ BattleScript_BerserkGeneRet:: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_BerserkGeneRet_TryConfuse playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse - setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM + setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGED_ITEM call BattleScript_StatUp BattleScript_BerserkGeneRet_TryConfuse: jumpifability BS_ATTACKER, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents @@ -9837,8 +9070,6 @@ BattleScript_BoosterEnergyRet:: BattleScript_EffectSnow:: attackcanceler - attackstring - ppreduce call BattleScript_CheckPrimalWeather setfieldweather BATTLE_WEATHER_SNOW goto BattleScript_MoveWeatherChange @@ -9850,7 +9081,7 @@ BattleScript_SleepClauseBlocked:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_SleepClausePreventsEnd:: +BattleScript_SleepClausePreventsEnd2:: pause B_WAIT_TIME_SHORT printstring STRINGID_BLOCKEDBYSLEEPCLAUSE waitmessage B_WAIT_TIME_LONG @@ -9858,7 +9089,7 @@ BattleScript_SleepClausePreventsEnd:: BattleScript_QuestionForfeitBattle:: printselectionstring STRINGID_QUESTIONFORFEITBATTLE - forfeityesnobox BS_ATTACKER + forfeityesnobox endselectionscript BattleScript_ForfeitBattleGaveMoney:: @@ -9870,3 +9101,44 @@ BattleScript_ForfeitBattleGaveMoney:: .endif waitmessage B_WAIT_TIME_LONG end2 + +BattleScript_Attackstring:: + printattackstring + return + +BattleScript_SubmoveAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + attackanimation + waitanimation + setcalledmove + return + +BattleScript_SleepTalkAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + printstring STRINGID_PKMNFASTASLEEP + waitmessage B_WAIT_TIME_LONG + statusanimation BS_ATTACKER + attackanimation + waitanimation + setcalledmove + return + +BattleScript_MetronomeAttackstring:: + printattackstring + pause B_WAIT_TIME_LONG + attackanimation + waitanimation + setcalledmove + printstring STRINGID_WAGGLINGAFINGER + waitmessage B_WAIT_TIME_LONG + return + +BattleScript_NaturePowerAttackstring:: + printattackstring + pause B_WAIT_TIME_SHORT + printstring STRINGID_NATUREPOWERTURNEDINTO + waitmessage B_WAIT_TIME_LONG + setcalledmove + return diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 5cfaf1dee..8fec1d949 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -174,7 +174,7 @@ BattleScript_PokeFluteEnd:: BattleScript_ItemSetMist:: call BattleScript_UseItemMessage setmist - playmoveanimation BS_ATTACKER, MOVE_MIST + playmoveanimation MOVE_MIST waitanimation printfromtable gMistUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -185,7 +185,7 @@ BattleScript_ItemSetFocusEnergy:: jumpifvolatile BS_ATTACKER, VOLATILE_DRAGON_CHEER, BattleScript_ButItFailed jumpifvolatile BS_ATTACKER, VOLATILE_FOCUS_ENERGY, BattleScript_ButItFailed setfocusenergy BS_ATTACKER - playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY + playmoveanimation MOVE_FOCUS_ENERGY waitanimation copybyte sBATTLER, gBattlerAttacker printstring STRINGID_PKMNUSEDXTOGETPUMPED diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 355fe0ebb..7165ef921 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -83,6 +83,15 @@ Debug_FlagsNotSetBattleConfigMessage_Text: .string "Please define a usable flag in:\l" .string "'include/config/battle.h'!$" +Debug_VarsNotSetBattleConfigMessage:: + message Debug_VarsNotSetBattleConfigMessage_Text + goto Debug_MessageEnd + +Debug_VarsNotSetBattleConfigMessage_Text: + .string "Feature unavailable!\n" + .string "Please define a usable var in:\l" + .string "'include/config/battle.h'!$" + Debug_BoxFilledMessage:: message Debug_BoxFilledMessage_Text goto Debug_MessageEnd @@ -331,6 +340,44 @@ Debug_EventScript_InflictStatus1_Single: releaseall end +Debug_EventScript_SetHiddenNature:: + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_EventScript_InflictStatus1_Close + specialvar VAR_RESULT, ScriptGetPartyMonSpecies + goto_if_eq VAR_RESULT, SPECIES_EGG, Debug_EventScript_InflictStatus1_Close + dynmultipush Debug_EventScript_ChangeNature_Text_Hardy, 0 + dynmultipush Debug_EventScript_ChangeNature_Text_Lonely, 1 + dynmultipush Debug_EventScript_ChangeNature_Text_Brave, 2 + dynmultipush Debug_EventScript_ChangeNature_Text_Adamant, 3 + dynmultipush Debug_EventScript_ChangeNature_Text_Naughty, 4 + dynmultipush Debug_EventScript_ChangeNature_Text_Bold, 5 + dynmultipush Debug_EventScript_ChangeNature_Text_Docile, 6 + dynmultipush Debug_EventScript_ChangeNature_Text_Relaxed, 7 + dynmultipush Debug_EventScript_ChangeNature_Text_Impish, 8 + dynmultipush Debug_EventScript_ChangeNature_Text_Lax, 9 + dynmultipush Debug_EventScript_ChangeNature_Text_Timid, 10 + dynmultipush Debug_EventScript_ChangeNature_Text_Hasty, 11 + dynmultipush Debug_EventScript_ChangeNature_Text_Serious, 12 + dynmultipush Debug_EventScript_ChangeNature_Text_Jolly, 13 + dynmultipush Debug_EventScript_ChangeNature_Text_Naive, 14 + dynmultipush Debug_EventScript_ChangeNature_Text_Modest, 15 + dynmultipush Debug_EventScript_ChangeNature_Text_Mild, 16 + dynmultipush Debug_EventScript_ChangeNature_Text_Quiet, 17 + dynmultipush Debug_EventScript_ChangeNature_Text_Bashful, 18 + dynmultipush Debug_EventScript_ChangeNature_Text_Rash, 19 + dynmultipush Debug_EventScript_ChangeNature_Text_Calm, 20 + dynmultipush Debug_EventScript_ChangeNature_Text_Gentle, 21 + dynmultipush Debug_EventScript_ChangeNature_Text_Sassy, 22 + dynmultipush Debug_EventScript_ChangeNature_Text_Careful, 23 + dynmultipush Debug_EventScript_ChangeNature_Text_Quirky, 24 + dynmultistack 0, 0, TRUE, 7, FALSE, 0, NULL + switch VAR_RESULT + case MULTI_B_PRESSED, Debug_EventScript_InflictStatus1_Close + special SetHiddenNature + releaseall + end + Debug_EventScript_InflictStatus1_Single_Poison: setstatus1 STATUS1_POISON, VAR_0x8004 releaseall @@ -439,6 +486,57 @@ Debug_EventScript_InflictStatus1_Text_Freeze: Debug_EventScript_InflictStatus1_Text_Frostbite: .string "Frostbite$" +Debug_EventScript_ChangeNature_Text_Hardy: + .string "Hardy$" +Debug_EventScript_ChangeNature_Text_Lonely: + .string "Lonely$" +Debug_EventScript_ChangeNature_Text_Brave: + .string "Brave$" +Debug_EventScript_ChangeNature_Text_Adamant: + .string "Adamant$" +Debug_EventScript_ChangeNature_Text_Naughty: + .string "Naughty$" +Debug_EventScript_ChangeNature_Text_Bold: + .string "Bold$" +Debug_EventScript_ChangeNature_Text_Docile: + .string "Docile$" +Debug_EventScript_ChangeNature_Text_Relaxed: + .string "Relaxed$" +Debug_EventScript_ChangeNature_Text_Impish: + .string "Impish$" +Debug_EventScript_ChangeNature_Text_Lax: + .string "Lax$" +Debug_EventScript_ChangeNature_Text_Timid: + .string "Timid$" +Debug_EventScript_ChangeNature_Text_Hasty: + .string "Hasty$" +Debug_EventScript_ChangeNature_Text_Serious: + .string "Serious$" +Debug_EventScript_ChangeNature_Text_Jolly: + .string "Jolly$" +Debug_EventScript_ChangeNature_Text_Naive: + .string "Naive$" +Debug_EventScript_ChangeNature_Text_Modest: + .string "Modest$" +Debug_EventScript_ChangeNature_Text_Mild: + .string "Mild$" +Debug_EventScript_ChangeNature_Text_Quiet: + .string "Quiet$" +Debug_EventScript_ChangeNature_Text_Bashful: + .string "Bashful$" +Debug_EventScript_ChangeNature_Text_Rash: + .string "Rash$" +Debug_EventScript_ChangeNature_Text_Calm: + .string "Calm$" +Debug_EventScript_ChangeNature_Text_Gentle: + .string "Gentle$" +Debug_EventScript_ChangeNature_Text_Sassy: + .string "Sassy$" +Debug_EventScript_ChangeNature_Text_Careful: + .string "Careful$" +Debug_EventScript_ChangeNature_Text_Quirky: + .string "Quirky$" + Debug_EventScript_EWRAMCounters:: callnative CheckEWRAMCounters msgbox Debug_EventScript_EWRAMCounters_Text, MSGBOX_DEFAULT diff --git a/data/specials.inc b/data/specials.inc index 18a1cd850..3f2e7c9ad 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -464,4 +464,5 @@ gSpecials:: def_special GetLastUsedSprayType def_special TrySkyBattle def_special TryPrepareSecondApproachingTrainer + def_special SetHiddenNature gSpecialsEnd:: diff --git a/include/battle.h b/include/battle.h index b47273b74..d8a014e9c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -2,6 +2,7 @@ #define GUARD_BATTLE_H // should they be included here or included individually by every file? +#include "constants/abilities.h" #include "constants/battle.h" #include "constants/form_change_types.h" #include "battle_main.h" @@ -18,6 +19,7 @@ #include "battle_terastal.h" #include "battle_gimmick.h" #include "generational_changes.h" +#include "item.h" #include "move.h" #include "random.h" // for rng_value_t #include "trainer_slide.h" @@ -44,7 +46,7 @@ // Used to exclude moves learned temporarily by Transform or Mimic #define MOVE_IS_PERMANENT(battler, moveSlot) \ - (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) \ + (!(gBattleMons[battler].volatiles.transformed) \ && !(gDisableStructs[battler].mimickedMoves & (1u << moveSlot))) // Battle Actions @@ -113,37 +115,34 @@ struct DisableStruct u8 usedMoves:4; u8 truantCounter:1; u8 truantSwitchInHack:1; - u8 noRetreat:1; u8 tarShot:1; u8 octolock:1; u8 cudChew:1; - u8 spikesDone:1; - u8 toxicSpikesDone:1; - u8 stickyWebDone:1; - u8 stealthRockDone:1; u8 weatherAbilityDone:1; u8 terrainAbilityDone:1; u8 syrupBombIsShiny:1; - u8 steelSurgeDone:1; u8 usedProteanLibero:1; u8 flashFireBoosted:1; - u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 boosterEnergyActivated:1; + u8 padding1:1; + u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 roostActive:1; u8 unburdenActive:1; u8 neutralizingGas:1; u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in - u8 padding:3; + u8 hazardsDone:1; + u8 endured:1; + u8 tryEjectPack:1; + u8 octolockedBy:3; + u8 padding:5; }; // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects struct ProtectStruct { u32 protected:7; // 126 protect options - u32 endured:1; u32 noValidMoves:1; - u32 helpingHand:1; u32 bounceMove:1; u32 stealMove:1; u32 nonVolatileStatusImmobility:1; @@ -151,31 +150,31 @@ struct ProtectStruct u32 chargingTurn:1; u32 fleeType:2; // 0: Normal, 1: FLEE_ITEM, 2: FLEE_ABILITY u32 unableToUseMove:1; // Not to be confused with HITMARKER_UNABLE_TO_USE_MOVE (It is questionable though if there is a difference. Needs further research) - u32 notFirstStrike:1; + u32 laggingTail:1; u32 palaceUnableToUseMove:1; - u32 powderSelfDmg:1; u32 statRaised:1; u32 usedCustapBerry:1; // also quick claw u32 touchedProtectLike:1; - u32 unused:8; - // End of 32-bit bitfield - u16 disableEjectPack:1; - u16 tryEjectPack:1; - u16 pranksterElevated:1; - u16 quickDraw:1; - u16 beakBlastCharge:1; - u16 quash:1; - u16 shellTrap:1; - u16 eatMirrorHerb:1; - u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy + u32 disableEjectPack:1; + u32 pranksterElevated:1; + u32 quickDraw:1; + u32 beakBlastCharge:1; + u32 quash:1; + u32 shellTrap:1; + u32 eatMirrorHerb:1; + u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u16 usedAllySwitch:1; + // End of 32-bit bitfield + u16 helpingHand:3; u16 lashOutAffected:1; - u16 padding:4; + u16 assuranceDoubled:1; + u16 myceliumMight:1; + u16 padding:10; // End of 16-bit bitfield u16 physicalDmg; u16 specialDmg; - u8 physicalBattlerId; - u8 specialBattlerId; + u8 physicalBattlerId:4; + u8 specialBattlerId:4; }; // Cleared at the start of HandleAction_ActionFinished @@ -185,13 +184,13 @@ struct SpecialStatus s32 specialDmg; u8 changedStatsBattlerId; // Battler that was responsible for the latest stat change. Can be self. u8 statLowered:1; - u8 lightningRodRedirected:1; + u8 abilityRedirected:1; u8 restoredBattlerSprite: 1; u8 faintedHasReplacement:1; - u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects. u8 afterYou:1; u8 enduredDamage:1; - u8 stormDrainRedirected:1; + u8 dancerUsedMove:1; + u8 padding:1; // End of byte u8 switchInAbilityDone:1; u8 switchInItemDone:1; @@ -210,9 +209,8 @@ struct SpecialStatus u8 teraShellAbilityDone:1; u8 criticalHit:1; // End of byte - u8 dancerUsedMove:1; u8 dancerOriginalTarget:3; - u8 unused:4; + u8 unused:5; // End of byte }; @@ -222,21 +220,18 @@ struct SideTimer u16 lightscreenTimer; u16 mistTimer; u16 safeguardTimer; - u16 spikesAmount; // debug menu complains. might be better to solve there instead if possible - u16 toxicSpikesAmount; - u16 stealthRockAmount; - u16 stickyWebAmount; + u8 spikesAmount:4; + u8 toxicSpikesAmount:4; u8 stickyWebBattlerId; u8 stickyWebBattlerSide; // Used for Court Change u16 auroraVeilTimer; u16 tailwindTimer; u16 luckyChantTimer; - u16 steelsurgeAmount; // Timers below this point are not swapped by Court Change - u16 followmeTimer; + u8 followmeTimer:4; u8 followmeTarget:3; u8 followmePowder:1; // Rage powder, does not affect grass type pokemon. - u16 retaliateTimer; + u8 retaliateTimer; u16 damageNonTypesTimer; u8 damageNonTypesType; u16 rainbowTimer; @@ -270,7 +265,7 @@ struct WishFutureKnock struct AI_SavedBattleMon { - u16 ability; + enum Ability ability; u16 moves[MAX_MON_MOVES]; u16 heldItem; u16 species:15; @@ -283,7 +278,7 @@ struct AiPartyMon u16 species; u16 item; u16 heldEffect; - u16 ability; + enum Ability ability; u16 level; u16 moves[MAX_MON_MOVES]; u32 status; @@ -316,7 +311,7 @@ struct SimulatedDamage // Ai Data used when deciding which move to use, computed only once before each turn's start. struct AiLogicData { - u16 abilities[MAX_BATTLERS_COUNT]; + enum Ability abilities[MAX_BATTLERS_COUNT]; u16 items[MAX_BATTLERS_COUNT]; u16 holdEffects[MAX_BATTLERS_COUNT]; u8 holdEffectParams[MAX_BATTLERS_COUNT]; @@ -335,12 +330,12 @@ struct AiLogicData u8 ejectButtonSwitch:1; // Tracks whether current switch out was from Eject Button u8 ejectPackSwitch:1; // Tracks whether current switch out was from Eject Pack u8 predictingSwitch:1; // Determines whether AI will use switch predictions this turn or not - u8 predictingMove:1; // Determines whether AI will use move predictions this turn or not u8 aiPredictionInProgress:1; // Tracks whether the AI is in the middle of running prediction calculations - u8 padding:2; - u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out u8 aiCalcInProgress:1; - u8 battlerDoingPrediction; // Stores which battler is currently running its prediction calcs + u8 predictingMove:1; // Determines whether AI will use move predictions this turn or not + u8 padding1:1; + u8 shouldSwitch:4; // Stores result of ShouldSwitch, which decides whether a mon should be switched out + u8 padding2:4; u16 predictedMove[MAX_BATTLERS_COUNT]; }; @@ -350,7 +345,6 @@ struct AiThinkingStruct u8 movesetIndex; u16 moveConsidered; s32 score[MAX_MON_MOVES]; - u32 funcResult; u64 aiFlags[MAX_BATTLERS_COUNT]; u8 aiAction; u8 aiLogicId; @@ -361,7 +355,7 @@ struct AiThinkingStruct struct BattleHistory { - u16 abilities[MAX_BATTLERS_COUNT]; + enum Ability abilities[MAX_BATTLERS_COUNT]; u8 itemEffects[MAX_BATTLERS_COUNT]; u16 usedMoves[MAX_BATTLERS_COUNT][MAX_MON_MOVES]; u16 moveHistory[MAX_BATTLERS_COUNT][AI_MOVE_HISTORY_COUNT]; // 3 last used moves for each battler @@ -588,7 +582,10 @@ struct BattlerState u32 pursuitTarget:1; u32 stompingTantrumTimer:2; u32 canPickupItem:1; - u32 padding:17; + u32 itemCanBeKnockedOff:1; + u32 ateBoost:1; + u32 commanderSpecies:11; + u32 padding:4; // End of Word }; @@ -600,7 +597,9 @@ struct PartyState u32 battleBondBoost:1; u32 transformZeroToHero:1; u32 supersweetSyrup:1; - u32 padding:26; + u32 timesGotHit:5; + u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon. + u32 padding:10; }; // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. @@ -609,8 +608,9 @@ struct BattleStruct struct BattlerState battlerState[MAX_BATTLERS_COUNT]; struct PartyState partyState[NUM_BATTLE_SIDES][PARTY_SIZE]; u8 eventBlockCounter; - u8 turnEffectsBattlerId; u8 endTurnEventsCounter; + u8 turnEffectsBattlerId:4; + u8 moveEndBattlerId:4; u16 wrappedMove[MAX_BATTLERS_COUNT]; u16 moveTarget[MAX_BATTLERS_COUNT]; u32 expShareExpValue; @@ -662,7 +662,8 @@ struct BattleStruct u8 anyMonHasTransformed:1; // Only used in battle_tv.c u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; - u8 padding1:2; + u8 sleepClauseNotBlocked:1; + u8 isSkyBattle:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle @@ -681,11 +682,11 @@ struct BattleStruct u8 startingStatusDone:1; u8 terrainDone:1; u8 overworldWeatherDone:1; - u8 unused:3; - u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. + u8 battlerKOAnimsRunning:3; u8 friskedAbility:1; // If identifies two mons, show the ability pop-up only once. u8 fickleBeamBoosted:1; u8 poisonPuppeteerConfusion:1; + u8 toxicChainPriority:1; // If Toxic Chain will trigger on target, all other non volatiles will be blocked u16 startingStatusTimer; u8 atkCancellerTracker; // struct BattleTvMovePoints tvMovePoints; @@ -699,12 +700,10 @@ struct BattleStruct u8 debugBattler; u8 magnitudeBasePower; u8 presentBasePower; - u8 roostTypes[MAX_BATTLERS_COUNT][NUM_BATTLE_SIDES]; u8 savedBattlerTarget[5]; u8 savedBattlerAttacker[5]; u8 savedTargetCount:4; u8 savedAttackerCount:4; - bool8 ateBoost[MAX_BATTLERS_COUNT]; u8 abilityPopUpSpriteIds[MAX_BATTLERS_COUNT][NUM_BATTLE_SIDES]; // two per battler struct ZMoveData zmove; struct DynamaxData dynamax; @@ -713,13 +712,12 @@ struct BattleStruct enum BattleIntroStates introState:8; u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages u8 lastMoveTarget[MAX_BATTLERS_COUNT]; // The last target on which each mon used a move, for the sake of Instruct - u16 tracedAbility[MAX_BATTLERS_COUNT]; + enum Ability tracedAbility[MAX_BATTLERS_COUNT]; u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk and Anger Shell. struct Illusion illusion[MAX_BATTLERS_COUNT]; u8 soulheartBattlerId; u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles. u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. - u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; struct LostItem itemLost[NUM_BATTLE_SIDES][PARTY_SIZE]; // Pokemon that had items consumed or stolen (two bytes per party member per side) u8 blunderPolicy:1; // should blunder policy activate @@ -735,6 +733,7 @@ struct BattleStruct u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. + u16 beatUpSpecies[PARTY_SIZE]; u8 attackerBeforeBounce:2; u8 beatUpSlot:3; u8 pledgeMove:1; @@ -743,17 +742,14 @@ struct BattleStruct u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies. u8 itemPartyIndex[MAX_BATTLERS_COUNT]; u8 itemMoveIndex[MAX_BATTLERS_COUNT]; - u8 isSkyBattle:1; s32 aiDelayTimer; // Counts number of frames AI takes to choose an action. s32 aiDelayFrames; // Number of frames it took to choose an action. s32 aiDelayCycles; // Number of cycles it took to choose an action. - u8 timesGotHit[NUM_BATTLE_SIDES][PARTY_SIZE]; u8 stickySyrupdBy[MAX_BATTLERS_COUNT]; u8 supremeOverlordCounter[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. enum DamageCategory categoryOverride:8; // for Z-Moves and Max Moves - u16 commanderActive[MAX_BATTLERS_COUNT]; u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party u16 opponentMonCanTera:6; @@ -766,7 +762,7 @@ struct BattleStruct s16 critChance[MAX_BATTLERS_COUNT]; u16 moveResultFlags[MAX_BATTLERS_COUNT]; u8 missStringId[MAX_BATTLERS_COUNT]; - u8 noResultString[MAX_BATTLERS_COUNT]; + enum CalcDamageState noResultString[MAX_BATTLERS_COUNT]; u8 doneDoublesSpreadHit:1; u8 calculatedDamageDone:1; u8 calculatedSpreadMoveAccuracy:1; @@ -777,7 +773,11 @@ struct BattleStruct s16 savedcheekPouchDamage; // Cheek Pouch can happen in the middle of an attack execution so we need to store the current dmg struct MessageStatus slideMessageStatus; u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT]; - + u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT]; + u8 numHazards[NUM_BATTLE_SIDES]; + u8 hazardsCounter:4; // Counter for applying hazard on switch in + enum SubmoveState submoveAnnouncement:2; + u8 padding2:2; // pokefirered u8 field_DA; // battle tower related u8 lastAttackerToFaintOpponent; @@ -867,8 +867,6 @@ static inline bool32 IsBattleMoveStatus(u32 move) #define SET_STATCHANGER(statId, stage, goesDown) (gBattleScripting.statChanger = (statId) + ((stage) << 3) + (goesDown << 7)) #define SET_STATCHANGER2(dst, statId, stage, goesDown)(dst = (statId) + ((stage) << 3) + (goesDown << 7)) -#define DO_ACCURACY_CHECK 2 // Don't skip the accuracy check before the move might be absorbed - // NOTE: The members of this struct have hard-coded offsets // in include/constants/battle_script_commands.h struct BattleScripting @@ -904,7 +902,7 @@ struct BattleScripting s32 savedDmg; u16 savedMoveEffect; // For moves hitting multiple targets. u16 moveEffect; - u16 multihitMoveEffect; + u16 unused_0x30; u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. bool8 fixedPopup; // Force ability popup to stick until manually called back u16 abilityPopupOverwrite; @@ -1060,7 +1058,7 @@ extern u16 gChosenMove; extern u16 gCalledMove; extern s32 gBideDmg[MAX_BATTLERS_COUNT]; extern u16 gLastUsedItem; -extern u16 gLastUsedAbility; +extern enum Ability gLastUsedAbility; extern u8 gBattlerAttacker; extern u8 gBattlerTarget; extern u8 gBattlerFainted; @@ -1086,8 +1084,6 @@ extern u32 gHitMarker; extern u8 gBideTarget[MAX_BATTLERS_COUNT]; extern u32 gSideStatuses[NUM_BATTLE_SIDES]; extern struct SideTimer gSideTimers[NUM_BATTLE_SIDES]; -extern u32 gStatuses3[MAX_BATTLERS_COUNT]; -extern u32 gStatuses4[MAX_BATTLERS_COUNT]; extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT]; extern u16 gPauseCounterBattle; extern u16 gPaydayMoney; @@ -1136,7 +1132,7 @@ extern u8 gHealthboxSpriteIds[MAX_BATTLERS_COUNT]; extern u8 gMultiUsePlayerCursor; extern u8 gNumberOfMovesToChoose; extern bool8 gHasFetchedBall; -extern u8 gLastUsedBall; +extern u16 gLastUsedBall; extern u16 gLastThrownBall; extern u16 gBallToDisplay; extern bool8 gLastUsedBallMenuPresent; @@ -1230,6 +1226,11 @@ static inline struct Pokemon *GetBattlerParty(u32 battler) return GetSideParty(GetBattlerSide(battler)); } +static inline struct PartyState *GetBattlerPartyState(u32 battler) +{ + return &gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]]; +} + static inline bool32 IsDoubleBattle(void) { return gBattleTypeFlags & BATTLE_TYPE_DOUBLE; @@ -1243,7 +1244,7 @@ static inline bool32 IsSpreadMove(u32 moveTarget) static inline bool32 IsDoubleSpreadMove(void) { return gBattleStruct->numSpreadTargets > 1 - && !(gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_UNABLE_TO_USE_MOVE)) + && !(gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_UNABLE_TO_USE_MOVE)) && IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove)); } @@ -1254,4 +1255,14 @@ static inline bool32 IsBattlerInvalidForSpreadMove(u32 battlerAtk, u32 battlerDe || (battlerDef == BATTLE_PARTNER(battlerAtk) && (moveTarget == MOVE_TARGET_BOTH)); } +static inline u32 GetChosenMoveFromPosition(u32 battler) +{ + return gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; +} + +static inline bool32 IsGhostBattleWithoutScope() +{ + return (gBattleTypeFlags & BATTLE_TYPE_GHOST) && !CheckBagHasItem(ITEM_SILPH_SCOPE, 1); +} + #endif // GUARD_BATTLE_H diff --git a/include/battle_ai_field_statuses.h b/include/battle_ai_field_statuses.h new file mode 100644 index 000000000..64608f637 --- /dev/null +++ b/include/battle_ai_field_statuses.h @@ -0,0 +1,18 @@ +#ifndef GUARD_BATTLE_AI_FIELD_STATUSES_H +#define GUARD_BATTLE_AI_FIELD_STATUSES_H + +#include "battle_ai_main.h" +#include "battle_ai_util.h" + +enum FieldEffectOutcome +{ + FIELD_EFFECT_POSITIVE, + FIELD_EFFECT_NEUTRAL, + FIELD_EFFECT_NEGATIVE, + FIELD_EFFECT_BLOCKED, +}; + +bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredResult); +bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome desiredResult); + +#endif //GUARD_BATTLE_AI_FIELD_STATUSES_H diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 31d6437b9..4330f9d2b 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -23,6 +23,11 @@ enum StatChange STAT_CHANGE_SPEED_2, STAT_CHANGE_SPATK_2, STAT_CHANGE_SPDEF_2, + STAT_CHANGE_ATK_3, + STAT_CHANGE_DEF_3, + STAT_CHANGE_SPEED_3, + STAT_CHANGE_SPATK_3, + STAT_CHANGE_SPDEF_3, STAT_CHANGE_ACC, STAT_CHANGE_EVASION }; @@ -38,7 +43,18 @@ enum AIScore WEAK_EFFECT = 1, DECENT_EFFECT = 2, GOOD_EFFECT = 3, - BEST_EFFECT = 4 + BEST_EFFECT = 4, + PERFECT_EFFECT = 10, + BAD_EFFECT = -1, + AWFUL_EFFECT = -3, + WORST_EFFECT = -10 +}; + +enum MoveComparisonResult +{ + MOVE_NEUTRAL_COMPARISON, + MOVE_WON_COMPARISON, + MOVE_LOST_COMPARISON, }; // AI_TryToFaint diff --git a/include/battle_ai_switch_items.h b/include/battle_ai_switch_items.h index b91d45209..8fcd7ba35 100644 --- a/include/battle_ai_switch_items.h +++ b/include/battle_ai_switch_items.h @@ -45,7 +45,7 @@ void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId); void AI_TrySwitchOrUseItem(u32 battler); u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType); bool32 ShouldSwitch(u32 battler); -bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2); +bool32 IsMonGrounded(u16 heldItemEffect, enum Ability ability, u8 type1, u8 type2); void ModifySwitchAfterMoveScoring(u32 battler); #endif // GUARD_BATTLE_AI_SWITCH_ITEMS_H diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 2144056cd..415c4fb93 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -2,8 +2,12 @@ #define GUARD_BATTLE_AI_UTIL_H #include "battle_ai_main.h" +#include "battle_ai_field_statuses.h" -#define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) +// Left and right are determined by how they're referred to in tests and everywhere else. +// Left is battlers 0 and 1, right 2 and 3; if you assume the battler referencing them is south, left is to the northeast and right to the northwest. +#define LEFT_FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) +#define RIGHT_FOE(battler) (((BATTLE_OPPOSITE(battler)) & BIT_SIDE) | BIT_FLANK) // Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt. #define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI @@ -23,6 +27,17 @@ enum DamageCalcContext AI_ATTACKING, }; +// Higher priority at the bottom; note that these are used in the formula MAX_MON_MOVES ^ AiCompareMovesPriority, which must fit within a u32. +// In expansion where MAX_MON_MOVES is 4, this means that AiCompareMovesPriority can range from 0 - 15 inclusive. +enum AiCompareMovesPriority +{ + PRIORITY_EFFECT, + PRIORITY_GUARANTEE, + PRIORITY_ACCURACY, + PRIORITY_NOT_CHARGING, + PRIORITY_SPEED, +}; + enum AIPivot { DONT_PIVOT, @@ -44,6 +59,12 @@ enum AIConsiderGimmick USE_GIMMICK, }; +enum ConsiderPriority +{ + DONT_CONSIDER_PRIORITY, + CONSIDER_PRIORITY, +}; + static inline bool32 IsMoveUnusable(u32 moveIndex, u32 move, u32 moveLimitations) { return move == MOVE_NONE @@ -53,18 +74,25 @@ static inline bool32 IsMoveUnusable(u32 moveIndex, u32 move, u32 moveLimitations typedef bool32 (*MoveFlag)(u32 move); -bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move); -bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move); +bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsPartyMonFaster(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsPartyMonSlower(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); bool32 AI_RandLessThan(u32 val); +bool32 AI_IsBattlerGrounded(u32 battler); u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData); bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); +bool32 CanAiPredictMove(void); +bool32 IsAiBattlerAssumingStab(void); +bool32 IsAiBattlerAssumingStatusMoves(void); +bool32 ShouldRecordStatusMove(u32 move); void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordAllMoves(u32 battler); void RecordKnownMove(u32 battlerId, u32 move); -void RecordAbilityBattle(u32 battlerId, u32 abilityId); +void RecordAbilityBattle(u32 battlerId, enum Ability abilityId); void ClearBattlerAbilityHistory(u32 battlerId); void RecordItemEffectBattle(u32 battlerId, u32 itemEffect); void ClearBattlerItemEffectHistory(u32 battlerId); @@ -79,146 +107,164 @@ bool32 AI_BattlerAtMaxHp(u32 battler); u32 GetHealthPercentage(u32 battler); bool32 AI_CanBattlerEscape(u32 battler); bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef); -s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority); bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk); -u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk); +u32 NoOfHitsForTargetToFaintBattler(u32 battlerDef, u32 battlerAtk); u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); u32 GetBestDmgFromBattler(u32 battler, u32 battlerTarget, enum DamageCalcContext calcContext); bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits); bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dmgMod); -s32 AI_DecideKnownAbilityForTurn(u32 battlerId); +enum Ability AI_DecideKnownAbilityForTurn(u32 battlerId); enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId); -bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move); +bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, enum Ability atkAbility, u32 move); u32 AI_GetWeather(void); +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon); enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, enum DamageCalcContext calcContext); -bool32 CanIndexMoveGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index); -bool32 HasDamagingMove(u32 battlerId); -bool32 HasDamagingMoveOfType(u32 battlerId, u32 type); +bool32 HasDamagingMove(u32 battler); +bool32 HasDamagingMoveOfType(u32 battler, u32 type); u32 GetBattlerSecondaryDamage(u32 battlerId); -bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability); -bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability); -bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move); +bool32 BattlerWillFaintFromWeather(u32 battler, enum Ability ability); +bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, enum Ability ability); +bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move); bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex); -u32 GetBattlerSideSpeedAverage(u32 battler); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage); -bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent, enum DamageCalcContext calcContext); +bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect); -enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex); +enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 moveIndex); bool32 IsRecycleEncouragedItem(u32 item); bool32 ShouldRestoreHpBerry(u32 battlerAtk, u32 item); bool32 IsStatBoostingBerry(u32 item); bool32 CanKnockOffItem(u32 battler, u32 item); -bool32 IsAbilityOfRating(u32 ability, s8 rating); -bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability); -bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move); +bool32 IsAbilityOfRating(enum Ability ability, s8 rating); +bool32 AI_IsAbilityOnSide(u32 battlerId, enum Ability ability); +bool32 AI_MoveMakesContact(enum Ability ability, enum ItemHoldEffect holdEffect, u32 move); +bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move); bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove); void SetAIUsingGimmick(u32 battler, enum AIConsiderGimmick use); bool32 IsAIUsingGimmick(u32 battler); void DecideTerastal(u32 battler); +bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move); // stat stage checks bool32 AnyStatIsRaised(u32 battlerId); -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat); -bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat); +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat); +bool32 BattlerStatCanRise(u32 battler, enum Ability battlerAbility, u32 stat); bool32 AreBattlersStatsMaxed(u32 battler); u32 CountPositiveStatStages(u32 battlerId); u32 CountNegativeStatStages(u32 battlerId); // move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); +bool32 Ai_IsPriorityBlocked(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); +bool32 IsAffectedByPowder(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category); -s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); +enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef); struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef, u32 weather); bool32 AI_IsDamagedByRecoil(u32 battler); u32 GetNoOfHitsToKO(u32 dmg, s32 hp); u32 GetNoOfHitsToKOBattlerDmg(u32 dmg, u32 battlerDef); u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext); +u32 GetBestNoOfHitsToKO(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); u16 *GetMovesArray(u32 battler); bool32 IsConfusionMoveEffect(enum BattleMoveEffects moveEffect); bool32 HasMove(u32 battlerId, u32 move); +u32 GetIndexInMoveArray(u32 battler, u32 move); bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive); bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category); bool32 HasMoveWithType(u32 battler, u32 type); -bool32 HasMoveWithEffect(u32 battlerId, enum BattleMoveEffects moveEffect); +bool32 HasMoveWithEffect(u32 battler, enum BattleMoveEffects moveEffect); +bool32 HasMoveWithAIEffect(u32 battler, u32 aiEffect); bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect); +bool32 HasBattlerSideMoveWithAIEffect(u32 battler, u32 effect); +bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect); bool32 HasNonVolatileMoveEffect(u32 battlerId, u32 effect); bool32 IsPowerBasedOnStatus(u32 battlerId, enum BattleMoveEffects effect, u32 argument); bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect); +bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect); bool32 HasMoveWithCriticalHitChance(u32 battlerId); bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, enum BattleMoveEffects exception); bool32 HasMoveThatLowersOwnStats(u32 battlerId); -bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus); bool32 HasAnyKnownMove(u32 battlerId); bool32 IsAromaVeilProtectedEffect(enum BattleMoveEffects moveEffect); bool32 IsNonVolatileStatusMove(u32 moveEffect); -bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility); -bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move); +bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, enum Ability atkAbility); bool32 IsHazardMove(u32 move); bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move); bool32 IsBattlerDamagedByStatus(u32 battler); s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove); -bool32 ShouldSetSandstorm(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetHail(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetRain(u32 battlerAtk, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect); +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef); +bool32 ShouldSetWeather(u32 battler, u32 weather); +bool32 ShouldClearWeather(u32 battler, u32 weather); +bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus); +bool32 ShouldClearFieldStatus(u32 battler, u32 fieldStatus); bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef); bool32 IsHealingMove(u32 move); bool32 HasHealingEffect(u32 battler); bool32 IsTrappingMove(u32 move); bool32 HasTrappingMoveEffect(u32 battler); -bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move); +bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move); +bool32 HasChoiceEffect(u32 battler); bool32 HasThawingMove(u32 battler); bool32 IsStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsStatLoweringEffect(enum BattleMoveEffects effect); -bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect); +bool32 IsSelfStatLoweringEffect(enum MoveEffect effect); +bool32 IsSelfStatRaisingEffect(enum MoveEffect effect); bool32 IsSwitchOutEffect(enum BattleMoveEffects effect); bool32 IsChaseEffect(enum BattleMoveEffects effect); bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect); bool32 IsUngroundingEffect(enum BattleMoveEffects effect); -bool32 IsSemiInvulnerable(u32 battlerDef, u32 move); bool32 HasMoveWithFlag(u32 battler, MoveFlag getFlag); bool32 IsHazardClearingMove(u32 move); bool32 IsSubstituteEffect(enum BattleMoveEffects effect); // status checks -bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability); -bool32 IsBattlerIncapacitated(u32 battler, u32 ability); -bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); +bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability ability); +bool32 IsBattlerIncapacitated(u32 battler, enum Ability ability); +bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef); -bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); -bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove); -bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); -bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility); +bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); +bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove); +bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove); +bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, enum Ability defAbility); bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof); -u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move); +u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move); bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsWakeupTurn(u32 battler); bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId); // ability logic -bool32 IsMoxieTypeAbility(u32 ability); -bool32 ShouldTriggerAbility(u32 battler, u32 ability); +bool32 IsMoxieTypeAbility(enum Ability ability); +bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability); +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability); +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData); +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData); +s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData); // partner logic -#define IS_TARGETING_PARTNER(battlerAtk, battlerDef)((battlerAtk) == (battlerDef ^ BIT_FLANK)) +bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef); +// IsTargetingPartner includes a check to make sure the adjacent pokemon is truly a partner. u32 GetAllyChosenMove(u32 battlerId); -bool32 IsValidDoubleBattle(u32 battlerAtk); +bool32 IsBattle1v1(); +// IsBattle1v1 is distinct from !IsDoubleBattle. If the player is fighting Maxie and Tabitha, with Steven as their partner, and both Tabitha and Steven have run out of Pokemon, the battle is 1v1, even though mechanically it is a Double Battle for how battlers and flags are set. +// Most AI checks should be using IsBattle1v1; most engine checks should be using !IsDoubleBattle +bool32 HasTwoOpponents(u32 battler); +// HasTwoOpponents checks if the opposing side has two pokemon. Partner state is irrelevant. e.g., Dragon Darts hits one time with two opponents and twice with one opponent. +bool32 HasPartner(u32 battler); +bool32 HasPartnerIgnoreFlags(u32 battler); +// HasPartner respects the Attacks Partner AI flag; HasPartnerIgnoreFlags checks only if a live pokemon is adjacent. +bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 partnerMove); bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); -bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove); bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove); -bool32 IsMoveEffectWeather(u32 move); -bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove); bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMoveEffects effectCheck); bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck); bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); @@ -247,19 +293,37 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); -s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext); -u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 moveConsidered); +s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext); +u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle); bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData); u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsBattlerItemEnabled(u32 battler); bool32 IsBattlerPredictedToSwitch(u32 battler); u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); -bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); -bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); -u32 GetThinkingBattler(u32 battler); +u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); +bool32 HasBattlerSideAbility(u32 battlerDef, enum Ability ability, struct AiLogicData *aiData); +bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); + +// These are for the purpose of not doubling up on moves during double battles. +// Used in GetAIEffectGroup for move effects and GetAIEffectGroupFromMove for additional effects +#define AI_EFFECT_NONE 0 +#define AI_EFFECT_WEATHER (1 << 0) +#define AI_EFFECT_TERRAIN (1 << 1) +#define AI_EFFECT_CLEAR_HAZARDS (1 << 2) +#define AI_EFFECT_BREAK_SCREENS (1 << 3) +#define AI_EFFECT_RESET_STATS (1 << 4) +#define AI_EFFECT_FORCE_SWITCH (1 << 5) +#define AI_EFFECT_TORMENT (1 << 6) +#define AI_EFFECT_LIGHT_SCREEN (1 << 7) +#define AI_EFFECT_REFLECT (1 << 8) +#define AI_EFFECT_GRAVITY (1 << 9) +#define AI_EFFECT_CHANGE_ABILITY (1 << 10) + +// As Aurora Veil should almost never be used alongside the other screens, we save the bit. +#define AI_EFFECT_AURORA_VEIL (AI_EFFECT_LIGHT_SCREEN | AI_EFFECT_REFLECT) #endif //GUARD_BATTLE_AI_UTIL_H diff --git a/include/battle_anim.h b/include/battle_anim.h index fea12c5d7..ca7326a96 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -121,6 +121,8 @@ void AnimMudSportDirt(struct Sprite *sprite); void AnimDirtScatter(struct Sprite *sprite); void AnimMudSportDirtRising(struct Sprite *sprite); void AnimDirtPlumeParticle(struct Sprite *); +void AnimBoneHitProjectile(struct Sprite *sprite); +extern const union AnimCmd *const sAnims_MudSlapMud[]; extern const union AffineAnimCmd *const gAffineAnims_SpinningBone[]; // battle_anim_throw.c @@ -153,6 +155,7 @@ void AnimTranslateLinearSingleSineWave(struct Sprite *sprite); void AnimTeraStarstormStars(struct Sprite *sprite); void AnimGrantingStars(struct Sprite *sprite); void AnimFollowMeFinger(struct Sprite *sprite); +void AnimPoisonJabProjectile(struct Sprite *sprite); extern const union AnimCmd *const gRazorLeafParticleAnimTable[]; extern const union AnimCmd *const gPowerAbsorptionOrbAnimTable[]; extern const union AffineAnimCmd *const gPowerAbsorptionOrbAffineAnimTable[]; @@ -380,6 +383,7 @@ void AnimElectricity(struct Sprite *); void AnimTask_VoltSwitch(struct Sprite* sprite); extern const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb[]; extern const union AffineAnimCmd *const gAffineAnims_FlashingSpark[]; +extern const union AnimCmd *const sAnims_CirclingElectricShock[]; extern const union AnimCmd *const gAnims_ThunderboltOrb[]; extern const union AnimCmd *const gAnims_ElectricPuff[]; extern const union AnimCmd *const gAnims_ElectricChargingParticles[]; @@ -403,6 +407,9 @@ extern const union AnimCmd *const gAnims_RevengeBigScratch[]; extern const union AnimCmd *const gAnims_FlyingRock[]; extern const union AffineAnimCmd *const gAffineAnims_Whirlpool[]; extern const union AffineAnimCmd *const gAffineAnims_BasicRock[]; +extern const union AnimCmd *const gAnims_FlyingRock[]; +extern const union AnimCmd *const sAnims_BasicRock[]; +void AnimRockTomb(struct Sprite *sprite); void AnimParticleInVortex(struct Sprite *sprite); void AnimFallingRock(struct Sprite *sprite); void AnimRaiseSprite(struct Sprite *sprite); @@ -598,6 +605,9 @@ void ClearBattleAnimBg(u32 bgId); void AnimLoadCompressedBgTilemapHandleContest(struct BattleAnimBgData *, const void *, bool32); bool32 InitSpritePosToAnimBattler(u32 animBattlerId, struct Sprite *sprite, bool8 respectMonPicOffsets); +// battle_anim_ice.c +void AnimIceBeamParticle(struct Sprite *sprite); + // battle_anim_bug.c void AnimTranslateStinger(struct Sprite *sprite); diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 5f66831f0..71799e16e 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -280,6 +280,7 @@ void InitBattleControllers(void); bool32 IsValidForBattle(struct Pokemon *mon); void TryReceiveLinkBattleData(void); void PrepareBufferDataTransferLink(u32 battler, u32 bufferId, u16 size, u8 *data); +void UpdateFriendshipFromXItem(u32 battler); // emitters void BtlController_EmitGetMonData(u32 battler, u32 bufferId, u8 requestId, u8 monToCheck); @@ -302,8 +303,8 @@ void BtlController_EmitChooseItem(u32 battler, u32 bufferId, u8 *battlePartyOrde void BtlController_EmitChoosePokemon(u32 battler, u32 bufferId, u8 caseId, u8 slotId, u16 abilityId, u8 battlerPreventingSwitchout, u8 *data); void BtlController_EmitHealthBarUpdate(u32 battler, u32 bufferId, u16 hpValue); void BtlController_EmitExpUpdate(u32 battler, u32 bufferId, u8 partyId, s32 expPoints); -void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status1, u32 status2); -void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 status2, u32 status); +void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status); +void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 isVolatile, u32 status); void BtlController_EmitDataTransfer(u32 battler, u32 bufferId, u16 size, void *data); void BtlController_EmitTwoReturnValues(u32 battler, u32 bufferId, u8 ret8, u32 ret32); void BtlController_EmitChosenMonReturnValue(u32 battler, u32 bufferId, u8 partyId, u8 *battlePartyOrder); @@ -421,11 +422,50 @@ void LinkOpponentBufferExecCompleted(u32 battler); void SetControllerToLinkPartner(u32 battler); void LinkPartnerBufferExecCompleted(u32 battler); +void TrySetBattlerShadowSpriteCallback(u32 battler); + +void AnimateMonAfterPokeBallFail(u32 battler); +void TryShinyAnimAfterMonAnim(u32 battler); +void WaitForMonAnimAfterLoad(u32 battler); +void BtlController_HandleSwitchInWaitAndEnd(u32 battler); +void BtlController_Intro_DelayAndEnd(u32 battler); +void BtlController_HandleSwitchInShowHealthbox(u32 battler); +void BtlController_HandleSwitchInTryShinyAnim(u32 battler); +void BtlController_HandleSwitchInSoundAndEnd(u32 battler); +void BtlController_HandleSwitchInShowSubstitute(u32 battler); + +// oak and old man controller +void SetControllerToOakOrOldMan(u32 battler); +void OakOldManBufferExecCompleted(u32 battler); + // pokedude controller void SetControllerToPokedude(u32 battler); void InitPokedudePartyAndOpponent(void); void PokedudeBufferExecCompleted(u32 battler); +// These flags are set to signal that the indicated message +// was already emitted + +// Inflicting damage is key +#define FIRST_BATTLE_MSG_FLAG_INFLICT_DMG 0x1 +// Lowering stats is advantageous +#define FIRST_BATTLE_MSG_FLAG_STAT_CHG 0x2 +// Keep an eye on your HP +#define FIRST_BATTLE_MSG_FLAG_HP_RESTORE 0x4 +// +#define FIRST_BATTLE_MSG_FLAG_PARTY_MENU 0x8 + +bool8 BtlCtrl_OakOldMan_TestState2Flag(u8 mask); +void BtlCtrl_OakOldMan_SetState2Flag(u8 mask); +void PrintOakText_InflictingDamageIsKey(u32 battler); +void PrintOakText_HowDisappointing(u32 battler); +void PrintOakText_OakNoRunningFromATrainer(u32 battler); +void OakOldManHandleInputChooseMove(u32 battler); +void BtlCtrl_DrawVoiceoverMessageFrame(void); +void BtlCtrl_RemoveVoiceoverMessageFrame(void); + +bool32 ShouldBattleRestrictionsApply(u32 battler); + // oak and old man controller void SetControllerToOakOrOldMan(u32 battler); void OakOldManBufferExecCompleted(u32 battler); @@ -451,15 +491,4 @@ void OakOldManHandleInputChooseMove(u32 battler); void BtlCtrl_DrawVoiceoverMessageFrame(void); void BtlCtrl_RemoveVoiceoverMessageFrame(void); -void TrySetBattlerShadowSpriteCallback(u32 battler); - -void TryShinyAnimAfterMonAnim(u32 battler); -void WaitForMonAnimAfterLoad(u32 battler); -void BtlController_HandleSwitchInWaitAndEnd(u32 battler); -void BtlController_Intro_DelayAndEnd(u32 battler); -void BtlController_HandleSwitchInShowHealthbox(u32 battler); -void BtlController_HandleSwitchInTryShinyAnim(u32 battler); -void BtlController_HandleSwitchInSoundAndEnd(u32 battler); -void BtlController_HandleSwitchInShowSubstitute(u32 battler); - #endif // GUARD_BATTLE_CONTROLLERS_H diff --git a/include/battle_dynamax.h b/include/battle_dynamax.h index 0762601c8..03dfef96a 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -11,7 +11,6 @@ u16 GetNonDynamaxHP(u32 battler); u16 GetNonDynamaxMaxHP(u32 battler); void UndoDynamax(u32 battler); bool32 IsMoveBlockedByMaxGuard(u32 move); -bool32 IsMoveBlockedByDynamax(u32 move); u16 GetMaxMove(u32 battler, u32 baseMove); u32 GetMaxMovePower(u32 move); @@ -20,8 +19,6 @@ void ChooseDamageNonTypesString(u8 type); void BS_UpdateDynamax(void); void BS_SetSteelsurge(void); -void BS_TrySetStatus1(void); -void BS_TrySetStatus2(void); void BS_HealOneSixth(void); void BS_TryRecycleBerry(void); void BS_JumpIfDynamaxed(void); diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index 9be635fb7..9b9c72d94 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -11,10 +11,9 @@ bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattler, u8 atkBattler, u8 de void InitAndLaunchSpecialAnimation(u8 activeBattler, u8 atkBattler, u8 defBattler, u8 tableId); bool8 IsBattleSEPlaying(u8 battlerId); void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId); -void DecompressGhostFrontPic(struct Pokemon *unused, u8 battlerId); +void DecompressGhostFrontPic(u32 battlerId); void DecompressTrainerFrontPic(u16 frontPicId, u8 battlerId); void DecompressTrainerBackPic(u16 backPicId, u8 battler); -void DecompressTrainerBackPalette(u16 a1, u8 a2); void BattleGfxSfxDummy2(u16 species); void FreeTrainerFrontPicPalette(u16 frontPicId); bool8 BattleLoadAllHealthBoxesGfx(u8 state); diff --git a/include/battle_interface.h b/include/battle_interface.h index 3627e18e4..de91849db 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -125,7 +125,7 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem s32 MoveBattleBar(u8 battler, u8 healthboxSpriteId, u8 whichBar, u8 unused); u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); u8 GetHPBarLevel(s16 hp, s16 maxhp); -void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle); +void CreateAbilityPopUp(u8 battlerId, enum Ability ability, bool32 isDoubleBattle); void DestroyAbilityPopUp(u8 battlerId); bool32 CanThrowLastUsedBall(void); void TryHideLastUsedBall(void); diff --git a/include/battle_main.h b/include/battle_main.h index a25dd68ff..94c8ad971 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -57,9 +57,10 @@ enum FirstTurnEventsStates FIRST_TURN_EVENTS_TOTEM_BOOST, FIRST_TURN_EVENTS_NEUTRALIZING_GAS, FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES, - FIRST_TURN_EVENTS_OPPORTUNIST_1, FIRST_TURN_EVENTS_ITEM_EFFECTS, - FIRST_TURN_EVENTS_OPPORTUNIST_2, + FIRST_TURN_EVENTS_WHITE_HERB, + FIRST_TURN_EVENTS_OPPORTUNIST, + FIRST_TURN_EVENTS_MIRROR_HERB, FIRST_TURN_EVENTS_EJECT_PACK, FIRST_TURN_EVENTS_END, }; @@ -90,18 +91,18 @@ void SpriteCB_TrainerThrowObject(struct Sprite *sprite); void AnimSetCenterToCornerVecX(struct Sprite *sprite); void BeginBattleIntroDummy(void); void BeginBattleIntro(void); -void SwitchInClearSetData(u32 battler); +void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy); const u8* FaintClearSetData(u32 battler); void BattleTurnPassed(void); u8 IsRunningFromBattleImpossible(u32 battler); void SwitchTwoBattlersInParty(u32 battler, u32 battler2); void SwitchPartyOrder(u32 battler); void SwapTurnOrder(u8 id1, u8 id2); -u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); +u32 GetBattlerTotalSpeedStatArgs(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect); u32 GetBattlerTotalSpeedStat(u32 battler); -s32 GetChosenMovePriority(u32 battler, u32 ability); -s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move); -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, +s32 GetChosenMovePriority(u32 battler, enum Ability ability); +s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move); +s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, enum Ability ability1, enum Ability ability2, enum ItemHoldEffect holdEffectBattler1, enum ItemHoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2); s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves); @@ -117,6 +118,7 @@ u32 GeneratePersonalityForGender(u32 gender, u32 species); void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry); bool32 CanPlayerForfeitNormalTrainerBattle(void); bool32 DidPlayerForfeitNormalTrainerBattle(void); +void BattleDebug_WonBattle(void); extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; diff --git a/include/battle_message.h b/include/battle_message.h index 0713882c5..e9f4f625d 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -2,6 +2,7 @@ #define GUARD_BATTLE_MESSAGE_H #include "constants/battle.h" +#include "constants/battle_string_ids.h" // This buffer can hold many different things. Some of the things it can hold // that have explicit sizes are listed below to ensure it can contain them. @@ -83,8 +84,8 @@ #define B_TXT_TRAINER2_NAME_WITH_CLASS 0x43 #define B_TXT_PARTNER_NAME_WITH_CLASS 0x44 #define B_TXT_ATK_TRAINER_NAME_WITH_CLASS 0x45 -#define B_TXT_SCR_TEAM1 0x46 -#define B_TXT_SCR_TEAM2 0x47 +#define B_TXT_EFF_TEAM1 0x46 +#define B_TXT_EFF_TEAM2 0x47 // for B_TXT_BUFF1, B_TXT_BUFF2 and B_TXT_BUFF3 @@ -249,7 +250,7 @@ struct BattleMsgData u8 textBuffs[3][TEXT_BUFF_ARRAY_COUNT]; }; -void BufferStringBattle(u16 stringID, u32 battler); +void BufferStringBattle(enum StringID stringID, u32 battler); u32 BattleStringExpandPlaceholdersToDisplayedString(const u8 *src); u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize); void BattleHandleAddTextPrinter(const u8 *text, u8 arg1); @@ -299,4 +300,7 @@ extern const u8 gText_Win[]; extern const u8 gText_Loss[]; extern const u8 gText_Draw[]; +extern const u16 gStatUpStringIds[]; +extern const u16 gStatDownStringIds[]; + #endif // GUARD_BATTLE_MESSAGE_H diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index 5fb6bf974..10bc1219d 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -40,11 +40,12 @@ union TRANSPARENT StatChangeFlags }; }; -s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk); -s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk); +s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum ItemHoldEffect holdEffectAtk); +s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum ItemHoldEffect holdEffectAtk); s32 GetCritHitOdds(s32 critChanceIndex); -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); -u8 GetBattlerTurnOrderNum(u8 battler); +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 HasBattlerActedThisTurn(u32 battler); +u32 GetBattlerTurnOrderNum(u32 battler); bool32 NoAliveMonsForBattlerSide(u32 battler); bool32 NoAliveMonsForPlayer(void); bool32 NoAliveMonsForEitherParty(void); @@ -59,24 +60,23 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move); bool32 DoesDisguiseBlockMove(u32 battler, u32 move); bool32 CanUseLastResort(u8 battlerId); u32 IsFlowerVeilProtected(u32 battler); -u32 IsLeafGuardProtected(u32 battler, u32 ability); -bool32 IsShieldsDownProtected(u32 battler, u32 ability); -u32 IsAbilityStatusProtected(u32 battler, u32 ability); +u32 IsLeafGuardProtected(u32 battler, enum Ability ability); +bool32 IsShieldsDownProtected(u32 battler, enum Ability ability); +u32 IsAbilityStatusProtected(u32 battler, enum Ability ability); bool32 TryResetBattlerStatChanges(u8 battler); bool32 CanCamouflage(u8 battlerId); -u32 GetNaturePowerMove(u32 battler); void StealTargetItem(u8 battlerStealer, u8 battlerItem); u8 GetCatchingBattler(void); u32 GetHighestStatId(u32 battlerId); -bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType); +bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, u32 moveType); bool32 IsMoveNotAllowedInSkyBattles(u32 move); bool32 DoSwitchInAbilities(u32 battlerId); u8 GetFirstFaintedPartyIndex(u8 battlerId); bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler); void SaveBattlerTarget(u32 battler); void SaveBattlerAttacker(u32 battler); -bool32 IsMonGettingExpSentOut(void); bool32 CanBurnHitThaw(u16 move); +bool32 IsMonGettingExpSentOut(void); extern void (*const gBattleScriptingCommandsTable[])(void); extern const struct StatFractions gAccuracyStageRatios[]; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 88c8ac781..8fbf623ed 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -3,17 +3,17 @@ extern const u8 BattleScript_SupersweetSyrupActivates[]; extern const u8 BattleScript_OpportunistCopyStatChange[]; +extern const u8 BattleScript_OpportunistCopyStatChangeEnd3[]; extern const u8 BattleScript_MirrorHerbCopyStatChange[]; extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[]; extern const u8 BattleScript_NotAffected[]; extern const u8 BattleScript_HitFromCritCalc[]; extern const u8 BattleScript_MoveEnd[]; extern const u8 BattleScript_MakeMoveMissed[]; -extern const u8 BattleScript_PrintMoveMissed[]; +extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissed[]; extern const u8 BattleScript_FlingFailConsumeItem[]; -extern const u8 BattleScript_FailedFromAtkString[]; extern const u8 BattleScript_FailedFromAtkCanceler[]; extern const u8 BattleScript_ButItFailed[]; extern const u8 BattleScript_StatUp[]; @@ -92,7 +92,7 @@ extern const u8 BattleScript_AllStatsUp[]; extern const u8 BattleScript_RapidSpinAway[]; extern const u8 BattleScript_WrapFree[]; extern const u8 BattleScript_LeechSeedFree[]; -extern const u8 BattleScript_SpikesFree[]; +extern const u8 BattleScript_SpinHazardsAway[]; extern const u8 BattleScript_MonTookFutureAttack[]; extern const u8 BattleScript_NoMovesLeft[]; extern const u8 BattleScript_SelectingMoveWithNoPP[]; @@ -150,7 +150,7 @@ extern const u8 BattleScript_TargetWokeUp[]; extern const u8 BattleScript_TargetBurnHeal[]; extern const u8 BattleScript_TargetPoisonHealed[]; extern const u8 BattleScript_MoveEffectSleep[]; -extern const u8 BattleScript_YawnMakesAsleep[]; +extern const u8 BattleScript_YawnMakesAsleepEnd2[]; extern const u8 BattleScript_MoveEffectPoison[]; extern const u8 BattleScript_MoveEffectBurn[]; extern const u8 BattleScript_MoveEffectFrostbite[]; @@ -168,7 +168,6 @@ extern const u8 BattleScript_DoRecoil33[]; extern const u8 BattleScript_Recoil33End[]; extern const u8 BattleScript_ItemSteal[]; extern const u8 BattleScript_DrizzleActivates[]; -extern const u8 BattleScript_SpeedBoostActivates[]; extern const u8 BattleScript_TraceActivates[]; extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; @@ -180,11 +179,8 @@ extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; extern const u8 BattleScript_SturdyPreventsOHKO[]; extern const u8 BattleScript_DampStopsExplosion[]; -extern const u8 BattleScript_MoveHPDrain_PPLoss[]; extern const u8 BattleScript_MoveHPDrain[]; -extern const u8 BattleScript_MonMadeMoveUseless_PPLoss[]; extern const u8 BattleScript_MonMadeMoveUseless[]; -extern const u8 BattleScript_FlashFireBoost_PPLoss[]; extern const u8 BattleScript_FlashFireBoost[]; extern const u8 BattleScript_AbilityNoStatLoss[]; extern const u8 BattleScript_ItemNoStatLoss[]; @@ -279,10 +275,10 @@ extern const u8 BattleScript_WaterSportEnds[]; extern const u8 BattleScript_SturdiedMsg[]; extern const u8 BattleScript_GravityEnds[]; extern const u8 BattleScript_MoveStatDrain[]; -extern const u8 BattleScript_MoveStatDrain_PPLoss[]; extern const u8 BattleScript_TargetsStatWasMaxedOut[]; extern const u8 BattleScript_AttackerAbilityStatRaise[]; extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[]; +extern const u8 BattleScript_AttackerAbilityStatRaiseEnd2[]; extern const u8 BattleScript_PoisonHealActivates[]; extern const u8 BattleScript_BadDreamsActivates[]; extern const u8 BattleScript_SwitchInAbilityMsg[]; @@ -296,6 +292,7 @@ extern const u8 BattleScript_CursedBodyActivates[]; extern const u8 BattleScript_MummyActivates[]; extern const u8 BattleScript_WeakArmorActivates[]; extern const u8 BattleScript_FellStingerRaisesStat[]; +extern const u8 BattleScript_RemoveTerrain[]; extern const u8 BattleScript_SnowWarningActivatesHail[]; extern const u8 BattleScript_SnowWarningActivatesSnow[]; extern const u8 BattleScript_PickupActivates[]; @@ -311,13 +308,7 @@ extern const u8 BattleScript_SelectingNotAllowedMoveGravityInPalace[]; extern const u8 BattleScript_SelectingNotAllowedMoveHealBlock[]; extern const u8 BattleScript_MoveUsedHealBlockPrevents[]; extern const u8 BattleScript_SelectingNotAllowedMoveHealBlockInPalace[]; -extern const u8 BattleScript_ToxicSpikesFree[]; -extern const u8 BattleScript_StickyWebFree[]; -extern const u8 BattleScript_StealthRockFree[]; -extern const u8 BattleScript_SpikesDefog[]; -extern const u8 BattleScript_ToxicSpikesDefog[]; -extern const u8 BattleScript_StickyWebDefog[]; -extern const u8 BattleScript_StealthRockDefog[]; +extern const u8 BattleScript_DefogClearHazards[]; extern const u8 BattleScript_MegaEvolution[]; extern const u8 BattleScript_WishMegaEvolution[]; extern const u8 BattleScript_MoveEffectClearSmog[]; @@ -333,7 +324,6 @@ extern const u8 BattleScript_ProteanActivates[]; extern const u8 BattleScript_DazzlingProtected[]; extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[]; extern const u8 BattleScript_MoveUsedPowder[]; -extern const u8 BattleScript_ZMoveActivatePowder[]; extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[]; extern const u8 BattleScript_SelectingNotAllowedStuffCheeksInPalace[]; extern const u8 BattleScript_SelectingNotAllowedBelch[]; @@ -343,6 +333,7 @@ extern const u8 BattleScript_GrassySurgeActivates[]; extern const u8 BattleScript_MistySurgeActivates[]; extern const u8 BattleScript_ElectricSurgeActivates[]; extern const u8 BattleScript_EffectSpectralThief[]; +extern const u8 BattleScript_EffectLifeDew[]; extern const u8 BattleScript_AbilityRaisesDefenderStat[]; extern const u8 BattleScript_PowderMoveNoEffect[]; extern const u8 BattleScript_GrassyTerrainHeals[]; @@ -375,10 +366,11 @@ extern const u8 BattleScript_IllusionOffEnd3[]; extern const u8 BattleScript_IllusionOffAndTerastallization[]; extern const u8 BattleScript_DancerActivates[]; extern const u8 BattleScript_AftermathDmg[]; -extern const u8 BattleScript_AttackerFormChange[]; -extern const u8 BattleScript_AttackerFormChangeEnd3[]; +extern const u8 BattleScript_BattlerFormChange[]; +extern const u8 BattleScript_BattlerFormChangeEnd2[]; +extern const u8 BattleScript_BattlerFormChangeEnd3[]; extern const u8 BattleScript_AttackerFormChangeWithString[]; -extern const u8 BattleScript_AttackerFormChangeWithStringEnd3[]; +extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[]; extern const u8 BattleScript_TargetFormChange[]; extern const u8 BattleScript_AnticipationActivates[]; extern const u8 BattleScript_SlowStartEnds[]; @@ -427,9 +419,10 @@ extern const u8 BattleScript_EjectPackActivates[]; extern const u8 BattleScript_MentalHerbCureRet[]; extern const u8 BattleScript_MentalHerbCureEnd2[]; extern const u8 BattleScript_TerrainPreventsEnd2[]; +extern const u8 BattleScript_ImmunityProtectedEnd2[]; extern const u8 BattleScript_MistyTerrainPrevents[]; extern const u8 BattleScript_ElectricTerrainPrevents[]; -extern const u8 BattleScript_DarkTypePreventsPrankster[]; +extern const u8 BattleScript_DoesntAffectTargetAtkString[]; extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; extern const u8 BattleScript_GulpMissileFormChange[]; @@ -451,8 +444,7 @@ extern const u8 BattleScript_WanderingSpiritActivates[]; extern const u8 BattleScript_MirrorArmorReflect[]; extern const u8 BattleScript_GooeyActivates[]; extern const u8 BattleScript_PastelVeilActivates[]; -extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[]; -extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[]; +extern const u8 BattleScript_BattlerFormChangeEnd3NoPopup[]; extern const u8 BattleScript_AttackerFormChangeMoveEffect[]; extern const u8 BattleScript_BothCanNoLongerEscape[]; extern const u8 BattleScript_OctolockEndTurn[]; @@ -470,6 +462,7 @@ extern const u8 BattleScript_RemoveFireType[]; extern const u8 BattleScript_TargetAbilityStatRaiseRet[]; extern const u8 BattleScript_RemoveElectricType[]; extern const u8 BattleScript_SeedSowerActivates[]; +extern const u8 BattleScript_BerserkActivates[]; extern const u8 BattleScript_AngerShellActivates[]; extern const u8 BattleScript_WellBakedBodyActivates[]; extern const u8 BattleScript_WindRiderActivatesMoveEnd[]; @@ -522,9 +515,8 @@ extern const u8 BattleScript_BoosterEnergyEnd2[]; extern const u8 BattleScript_BoosterEnergyRet[]; extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraFormChange[]; -extern const u8 BattleScript_SleepClausePreventsEnd[]; +extern const u8 BattleScript_SleepClausePreventsEnd2[]; extern const u8 BattleScript_PowerConstruct[]; - extern const u8 BattleScript_AbilityProtectsDoesntAffect[]; extern const u8 BattleScript_ImmunityProtected[]; extern const u8 BattleScript_SafeguardProtected[]; @@ -536,6 +528,7 @@ extern const u8 BattleScript_AlreadyPoisoned[]; extern const u8 BattleScript_AlreadyParalyzed[]; extern const u8 BattleScript_AlreadyBurned[]; extern const u8 BattleScript_PrintAbilityMadeIneffective[]; +extern const u8 BattleScript_ItDoesntAffectFoe[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; @@ -553,14 +546,12 @@ extern const u8 BattleScript_EffectSetWeather[]; extern const u8 BattleScript_EffectSetTerrain[]; extern const u8 BattleScript_EffectStonesurge[]; extern const u8 BattleScript_EffectSteelsurge[]; -extern const u8 BattleScript_SteelsurgeFree[]; -extern const u8 BattleScript_SteelsurgeDefog[]; extern const u8 BattleScript_DamageNonTypesStarts[]; extern const u8 BattleScript_DamageNonTypesContinues[]; -extern const u8 BattleScript_DefogTryHazards[]; -extern const u8 BattleScript_EffectAuroraVeilSuccess[]; +extern const u8 BattleScript_MoveEffectDefog[]; +extern const u8 BattleScript_MoveEffectAuroraVeil[]; extern const u8 BattleScript_EffectGravitySuccess[]; -extern const u8 BattleScript_EffectYawnSuccess[]; +extern const u8 BattleScript_MoveEffectYawnSide[]; extern const u8 BattleScript_EffectTryReducePP[]; extern const u8 BattleScript_EffectParalyzeSide[]; extern const u8 BattleScript_EffectPoisonSide[]; @@ -587,7 +578,6 @@ extern const u8 BattleScript_EffectAbsorb[]; extern const u8 BattleScript_EffectAbsorbLiquidOoze[]; extern const u8 BattleScript_EffectExplosion[]; extern const u8 BattleScript_EffectDreamEater[]; -extern const u8 BattleScript_EffectMirrorMove[]; extern const u8 BattleScript_EffectAttackUp[]; extern const u8 BattleScript_EffectDefenseUp[]; extern const u8 BattleScript_EffectSpeedUp[]; @@ -611,6 +601,8 @@ extern const u8 BattleScript_EffectConversion[]; extern const u8 BattleScript_EffectRestoreHp[]; extern const u8 BattleScript_EffectLightScreen[]; extern const u8 BattleScript_EffectRest[]; +extern const u8 BattleScript_RestIsAlreadyAsleep[]; +extern const u8 BattleScript_InsomniaProtects[]; extern const u8 BattleScript_EffectOHKO[]; extern const u8 BattleScript_EffectHealBlock[]; extern const u8 BattleScript_RecoilIfMiss[]; @@ -637,7 +629,6 @@ extern const u8 BattleScript_EffectTwoTurnsAttack[]; extern const u8 BattleScript_EffectSubstitute[]; extern const u8 BattleScript_EffectRage[]; extern const u8 BattleScript_EffectMimic[]; -extern const u8 BattleScript_EffectMetronome[]; extern const u8 BattleScript_EffectLeechSeed[]; extern const u8 BattleScript_EffectDoNothing[]; extern const u8 BattleScript_EffectHoldHands[]; @@ -651,11 +642,10 @@ extern const u8 BattleScript_EffectSnore[]; extern const u8 BattleScript_EffectConversion2[]; extern const u8 BattleScript_EffectLockOn[]; extern const u8 BattleScript_EffectSketch[]; -extern const u8 BattleScript_EffectSleepTalk[]; extern const u8 BattleScript_EffectDestinyBond[]; extern const u8 BattleScript_EffectSpite[]; extern const u8 BattleScript_EffectHealBell[]; -extern const u8 BattleScript_EffectHealBell_FromHeal[]; +extern const u8 BattleScript_MoveEffectAromatherapy[]; extern const u8 BattleScript_EffectMeanLook[]; extern const u8 BattleScript_EffectNightmare[]; extern const u8 BattleScript_EffectMinimize[]; @@ -693,8 +683,6 @@ extern const u8 BattleScript_EffectBeatUp[]; extern const u8 BattleScript_EffectSemiInvulnerable[]; extern const u8 BattleScript_EffectDefenseCurl[]; extern const u8 BattleScript_EffectSoftboiled[]; -extern const u8 BattleScript_EffectFirstTurnOnly[]; -extern const u8 BattleScript_EffectUproar[]; extern const u8 BattleScript_EffectStockpile[]; extern const u8 BattleScript_EffectSpitUp[]; extern const u8 BattleScript_EffectSwallow[]; @@ -706,14 +694,12 @@ extern const u8 BattleScript_EffectNonVolatileStatus[]; extern const u8 BattleScript_EffectMemento[]; extern const u8 BattleScript_EffectFocusPunch[]; extern const u8 BattleScript_EffectFollowMe[]; -extern const u8 BattleScript_EffectNaturePower[]; extern const u8 BattleScript_EffectCharge[]; extern const u8 BattleScript_EffectTaunt[]; extern const u8 BattleScript_EffectHelpingHand[]; extern const u8 BattleScript_EffectTrick[]; extern const u8 BattleScript_EffectRolePlay[]; extern const u8 BattleScript_EffectWish[]; -extern const u8 BattleScript_EffectAssist[]; extern const u8 BattleScript_EffectIngrain[]; extern const u8 BattleScript_EffectMagicCoat[]; extern const u8 BattleScript_EffectRecycle[]; @@ -761,7 +747,6 @@ extern const u8 BattleScript_EffectGuardSplit[]; extern const u8 BattleScript_EffectStickyWeb[]; extern const u8 BattleScript_EffectMetalBurst[]; extern const u8 BattleScript_EffectLuckyChant[]; -extern const u8 BattleScript_EffectSuckerPunch[]; extern const u8 BattleScript_EffectSimpleBeam[]; extern const u8 BattleScript_EffectEntrainment[]; extern const u8 BattleScript_EffectHealPulse[]; @@ -774,14 +759,12 @@ extern const u8 BattleScript_EffectElectricTerrain[]; extern const u8 BattleScript_EffectPsychicTerrain[]; extern const u8 BattleScript_EffectAttackAccUp[]; extern const u8 BattleScript_EffectAttackSpAttackUp[]; -extern const u8 BattleScript_EffectMeFirst[]; extern const u8 BattleScript_EffectQuiverDance[]; extern const u8 BattleScript_EffectCoil[]; extern const u8 BattleScript_EffectElectrify[]; extern const u8 BattleScript_EffectReflectType[]; extern const u8 BattleScript_EffectSoak[]; extern const u8 BattleScript_EffectGrowth[]; -extern const u8 BattleScript_EffectLastResort[]; extern const u8 BattleScript_EffectShellSmash[]; extern const u8 BattleScript_EffectShiftGear[]; extern const u8 BattleScript_EffectDefenseUp3[]; @@ -794,7 +777,6 @@ extern const u8 BattleScript_AbilityPreventsPhasingOutRet[]; extern const u8 BattleScript_PrintMonIsRootedRet[]; extern const u8 BattleScript_FinalGambit[]; extern const u8 BattleScript_EffectAutotomize[]; -extern const u8 BattleScript_EffectCopycat[]; extern const u8 BattleScript_EffectDefog[]; extern const u8 BattleScript_EffectHitEnemyHealAlly[]; extern const u8 BattleScript_EffectSynchronoise[]; @@ -811,14 +793,12 @@ extern const u8 BattleScript_EffectAcupressure[]; extern const u8 BattleScript_EffectAromaticMist[]; extern const u8 BattleScript_EffectPowder[]; extern const u8 BattleScript_EffectPartingShot[]; -extern const u8 BattleScript_EffectMatBlock[]; extern const u8 BattleScript_EffectInstruct[]; extern const u8 BattleScript_EffectLaserFocus[]; extern const u8 BattleScript_EffectMagneticFlux[]; extern const u8 BattleScript_EffectGearUp[]; extern const u8 BattleScript_EffectStrengthSap[]; extern const u8 BattleScript_EffectPurify[]; -extern const u8 BattleScript_FailIfNotArgType[]; extern const u8 BattleScript_EffectShoreUp[]; extern const u8 BattleScript_EffectGeomancy[]; extern const u8 BattleScript_EffectFairyLock[]; @@ -835,7 +815,6 @@ extern const u8 BattleScript_MoveEffectLeechSeed[]; extern const u8 BattleScript_MoveEffectHaze[]; extern const u8 BattleScript_MoveEffectIonDeluge[]; extern const u8 BattleScript_EffectHyperspaceFury[]; -extern const u8 BattleScript_EffectAuraWheel[]; extern const u8 BattleScript_EffectNoRetreat[]; extern const u8 BattleScript_EffectTarShot[]; extern const u8 BattleScript_EffectPoltergeist[]; @@ -845,7 +824,7 @@ extern const u8 BattleScript_EffectSkyDrop[]; extern const u8 BattleScript_EffectMeteorBeam[]; extern const u8 BattleScript_EffectCourtChange[]; extern const u8 BattleScript_EffectExtremeEvoboost[]; -extern const u8 BattleScript_EffectHitSetRemoveTerrain[]; +extern const u8 BattleScript_EffectHitSetTerrain[]; extern const u8 BattleScript_EffectDarkVoid[]; extern const u8 BattleScript_EffectVictoryDance[]; extern const u8 BattleScript_EffectTeatime[]; @@ -871,6 +850,18 @@ extern const u8 BattleScript_FickleBeamDoubled[]; extern const u8 BattleScript_QuestionForfeitBattle[]; extern const u8 BattleScript_ForfeitBattleGaveMoney[]; extern const u8 BattleScript_AbilityPopUp[]; +extern const u8 BattleScript_Attackstring[]; +extern const u8 BattleScript_SubmoveAttackstring[]; +extern const u8 BattleScript_MetronomeAttackstring[]; +extern const u8 BattleScript_SleepTalkAttackstring[]; +extern const u8 BattleScript_NaturePowerAttackstring[]; +extern const u8 BattleScript_PokemonCantUseTheMove[]; +extern const u8 BattleScript_GhostBallDodge[]; +extern const u8 BattleScript_GhostGetOutGetOut[]; +extern const u8 BattleScript_TooScaredToMove[]; +extern const u8 BattleScript_SilphScopeUnveiled[]; + + // pokefirered extern const u8 BattleScript_BattleTowerTrainerBattleWon[]; @@ -881,4 +872,4 @@ extern const u8 BattleScript_GhostBallDodge[]; extern const u8 BattleScript_OldMan_Pokedude_CaughtMessage[]; extern const u8 BattleScript_SilphScopeUnveiled[]; -#endif // GUARD_BATTLE_SCRIPTS_H \ No newline at end of file +#endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/battle_terastal.h b/include/battle_terastal.h index 6b5c38546..9c55a49d7 100644 --- a/include/battle_terastal.h +++ b/include/battle_terastal.h @@ -7,7 +7,7 @@ bool32 CanTerastallize(u32 battler); u32 GetBattlerTeraType(u32 battler); void ExpendTypeStellarBoost(u32 battler, u32 type); bool32 IsTypeStellarBoosted(u32 battler, u32 type); -uq4_12_t GetTeraMultiplier(u32 battler, u32 type); +uq4_12_t GetTeraMultiplier(struct DamageContext *ctx); u16 GetTeraTypeRGB(u32 type); diff --git a/include/battle_util.h b/include/battle_util.h index ba1f40113..f8a910b03 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -23,17 +23,12 @@ #define MOVE_LIMITATION_PLACEHOLDER (1 << 15) #define MOVE_LIMITATIONS_ALL 0xFFFF -enum NonVolatileStatus +// Switches between simulated battle calc and actual battle combat +enum FunctionCallOption { - STATUS_CHECK_TRIGGER, - STATUS_RUN_SCRIPT, -}; - -enum AbilityEffectOptions -{ - ABILITY_CHECK_TRIGGER, - ABILITY_CHECK_TRIGGER_AI, - ABILITY_RUN_SCRIPT, + CHECK_TRIGGER, // Check the function without running scripts / setting any flags. + AI_CHECK, // Check the function without running scripts / setting any flags. Same as CHECK_TRIGGER but only used when additional data has to be fetched during ai calcs + RUN_SCRIPT, // Used during actual combat where a script has to be run / flags need to be set }; enum MoveAbsorbed @@ -48,31 +43,30 @@ enum { ABILITYEFFECT_ON_SWITCHIN, ABILITYEFFECT_ENDTURN, ABILITYEFFECT_MOVE_END_ATTACKER, + ABILITYEFFECT_COLOR_CHANGE, // Color Change, Berserk, Anger Shell ABILITYEFFECT_MOVE_END, ABILITYEFFECT_IMMUNITY, ABILITYEFFECT_SYNCHRONIZE, ABILITYEFFECT_ATK_SYNCHRONIZE, ABILITYEFFECT_MOVE_END_OTHER, ABILITYEFFECT_NEUTRALIZINGGAS, - ABILITYEFFECT_FIELD_SPORT, // Only used if B_SPORT_TURNS >= GEN_6 + ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, ABILITYEFFECT_ON_WEATHER, ABILITYEFFECT_ON_TERRAIN, ABILITYEFFECT_SWITCH_IN_TERRAIN, ABILITYEFFECT_SWITCH_IN_WEATHER, ABILITYEFFECT_OPPORTUNIST, + ABILITYEFFECT_OPPORTUNIST_FIRST_TURN, ABILITYEFFECT_SWITCH_IN_STATUSES, }; -// Special cases -#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6 -#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6 - // For the first argument of ItemBattleEffects, to deteremine which block of item effects to try enum ItemCaseId { ITEMEFFECT_NONE, ITEMEFFECT_ON_SWITCH_IN, ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN, + ITEMEFFECT_LEFTOVERS, // Leftovers, Black Sludge ITEMEFFECT_NORMAL, ITEMEFFECT_TRY_HEALING, ITEMEFFECT_MOVE_END, @@ -81,7 +75,11 @@ enum ItemCaseId ITEMEFFECT_ORBS, ITEMEFFECT_LIFEORB_SHELLBELL, ITEMEFFECT_USE_LAST_ITEM, // move end effects for just the battler, not whole field - ITEMEFFECT_STATS_CHANGED, // For White Herb and Eject Pack + ITEMEFFECT_WHITE_HERB, + ITEMEFFECT_WHITE_HERB_ENDTURN, + ITEMEFFECT_WHITE_HERB_FIRST_TURN, + ITEMEFFECT_MIRROR_HERB, + ITEMEFFECT_MIRROR_HERB_FIRST_TURN, }; enum ItemEffect @@ -115,33 +113,38 @@ struct TypePower enum MoveSuccessOrder { - CANCELLER_FLAGS, + CANCELLER_CLEAR_FLAGS, CANCELLER_STANCE_CHANGE_1, CANCELLER_SKY_DROP, CANCELLER_RECHARGE, CANCELLER_ASLEEP_OR_FROZEN, + CANCELLER_POWER_POINTS, CANCELLER_OBEDIENCE, CANCELLER_TRUANT, CANCELLER_FLINCH, CANCELLER_DISABLED, - CANCELLER_VOLATILE_BLOCKED, + CANCELLER_VOLATILE_BLOCKED, // Gravity / Heal Block / Throat Chop CANCELLER_TAUNTED, CANCELLER_IMPRISONED, CANCELLER_CONFUSED, + CANCELLER_GHOST, // pokefirered CANCELLER_PARALYSED, CANCELLER_INFATUATION, - CANCELLER_GHOST, // pokefirered CANCELLER_BIDE, + CANCELLER_Z_MOVES, + CANCELLER_CHOICE_LOCK, + CANCELLER_CALLSUBMOVE, CANCELLER_THAW, CANCELLER_STANCE_CHANGE_2, + CANCELLER_ATTACKSTRING, + CANCELLER_PPDEDUCTION, CANCELLER_WEATHER_PRIMAL, - CANCELLER_DYNAMAX_BLOCKED, + CANCELLER_MOVE_FAILURE, CANCELLER_POWDER_STATUS, + CANCELLER_PRIORITY_BLOCK, CANCELLER_PROTEAN, - CANCELLER_PSYCHIC_TERRAIN, CANCELLER_EXPLODING_DAMP, CANCELLER_MULTIHIT_MOVES, - CANCELLER_Z_MOVES, CANCELLER_MULTI_TARGET_MOVES, CANCELLER_END, }; @@ -159,7 +162,8 @@ enum Obedience enum MoveCanceller { MOVE_STEP_SUCCESS, - MOVE_STEP_BREAK, + MOVE_STEP_BREAK, // Breaks out of the function to run a script + MOVE_STEP_FAILURE, // Same as break but breaks out of it due to move failure and jumps to script that handles the failure MOVE_STEP_REMOVES_STATUS, }; @@ -179,12 +183,21 @@ struct DamageContext u32 fixedBasePower:8; u32 padding2:8; uq4_12_t typeEffectivenessModifier; - u32 abilityAtk:16; - u32 abilityDef:16; + enum Ability abilityAtk; + enum Ability abilityDef; enum ItemHoldEffect holdEffectAtk:16; enum ItemHoldEffect holdEffectDef:16; }; +struct BattleContext +{ + u32 battlerAtk:3; + u32 battlerDef:3; + u32 currentMove:16; + enum BattleMoveEffects moveEffect:10; + enum Ability ability[MAX_BATTLERS_COUNT]; +}; + enum SleepClauseBlock { NOT_BLOCKED_BY_SLEEP_CLAUSE, @@ -229,7 +242,7 @@ void MarkBattlerForControllerExec(u32 battler); void MarkBattlerReceivedLinkData(u32 battler); const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState); bool32 WasUnableToUseMove(u32 battler); -bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability); +bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability); void PrepareStringBattle(enum StringID stringId, u32 battler); void ResetSentPokesToOpponentValue(void); void OpponentSwitchInResetSentPokesToOpponentValue(u32 battler); @@ -243,28 +256,27 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check); bool32 AreAllMovesUnusable(u32 battler); u8 GetImprisonedMovesCount(u32 battler, u16 move); s32 GetDrainedBigRootHp(u32 battler, s32 hp); -bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck); +bool32 IsAbilityAndRecord(u32 battler, enum Ability battlerAbility, enum Ability abilityToCheck); u32 DoEndTurnEffects(void); bool32 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); -enum MoveCanceller AtkCanceller_MoveSuccessOrder(void); -void SetAtkCancellerForCalledMove(void); +enum MoveCanceller AtkCanceller_MoveSuccessOrder(struct BattleContext *ctx); bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2); bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility); -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum AbilityEffectOptions option); -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option); -u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg); +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option); +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, u32 moveType, enum FunctionCallOption option); +u32 AbilityBattleEffects(u32 caseID, u32 battler, enum Ability ability, u32 special, u32 moveArg); bool32 TryPrimalReversion(u32 battler); bool32 IsNeutralizingGasOnField(void); -bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability); +bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability); u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler); u32 GetBattlerAbilityNoAbilityShield(u32 battler); u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield); -u32 GetBattlerAbility(u32 battler); -u32 IsAbilityOnSide(u32 battler, u32 ability); -u32 IsAbilityOnOpposingSide(u32 battler, u32 ability); -u32 IsAbilityOnField(u32 ability); -u32 IsAbilityOnFieldExcept(u32 battler, u32 ability); +enum Ability GetBattlerAbility(u32 battler); +u32 IsAbilityOnSide(u32 battler, enum Ability ability); +u32 IsAbilityOnOpposingSide(u32 battler, enum Ability ability); +u32 IsAbilityOnField(enum Ability ability); +u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability); u32 IsAbilityPreventingEscape(u32 battler); bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move); u32 GetProtectType(enum ProtectMethod method); @@ -277,21 +289,24 @@ void HandleAction_RunBattleScript(void); u32 SetRandomTarget(u32 battler); u32 GetBattleMoveTarget(u16 move, u8 setTarget); u8 GetAttackerObedienceForAction(); -enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating); -enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating); -enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility); +enum ItemHoldEffect GetBattlerHoldEffect(u32 battler); +enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler); +enum ItemHoldEffect GetBattlerHoldEffectIgnoreNegation(u32 battler); +enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, u32 ability); u32 GetBattlerHoldEffectParam(u32 battler); -bool32 IsMoveMakingContact(u32 move, u32 battlerAtk); -bool32 IsBattlerGrounded(u32 battler); +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); +bool32 IsBattlerGrounded(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect); u32 GetMoveSlot(u16 *moves, u32 move); u32 GetBattlerWeight(u32 battler); u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter); s32 CalculateMoveDamage(struct DamageContext *ctx); s32 CalculateMoveDamageVars(struct DamageContext *ctx); +s32 DoFixedDamageMoveCalc(struct DamageContext *ctx); s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg); uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx); -uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, enum Ability abilityDef); uq4_12_t GetTypeModifier(u32 atkType, u32 defType); uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType); void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags); @@ -313,7 +328,7 @@ bool32 TryClearIllusion(u32 battler, u32 caseID); u32 GetIllusionMonSpecies(u32 battler); struct Pokemon *GetIllusionMonPtr(u32 battler); void ClearIllusionMon(u32 battler); -u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon); +u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler); bool32 SetIllusionMon(struct Pokemon *mon, u32 battler); bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler); enum DamageCategory GetBattleMoveCategory(u32 move); @@ -337,7 +352,6 @@ bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes); void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast); bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u32 battler); -void BufferStatChange(u32 battler, u8 statId, enum StringID stringId); bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u32 battler); bool32 PickupHasValidTarget(u32 battler); @@ -359,15 +373,15 @@ bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef); bool32 MoodyCantRaiseStat(u32 stat); bool32 MoodyCantLowerStat(u32 stat); -bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause); -bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef); -bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 ability); -bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects secondaryMoveEffect, enum NonVolatileStatus option); +bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, enum SleepClauseBlock isBlockedBySleepClause); +bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef); +bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, enum Ability ability); +bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef); +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect secondaryMoveEffect, enum FunctionCallOption option); bool32 CanBeConfused(u32 battler); -bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag); +bool32 IsBattlerTerrainAffected(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect, u32 terrainFlag); u32 GetBattlerAffectionHearts(u32 battler); void TryToRevertMimicryAndFlags(void); bool32 BattleArenaTurnEnd(void); @@ -377,8 +391,8 @@ void RemoveConfusionStatus(u32 battler); u8 GetBattlerGender(u32 battler); bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2); bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2); -u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect); -bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect); +u32 CalcSecondaryEffectChance(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect); +bool32 MoveEffectIsGuaranteed(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect); void GetBattlerTypes(u32 battler, bool32 ignoreTera, u32 types[static 3]); u32 GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera); bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon); @@ -391,19 +405,34 @@ bool32 IsSleepClauseActiveForSide(u32 battlerSide); bool32 IsSleepClauseEnabled(); void ClearDamageCalcResults(void); u32 DoesDestinyBondFail(u32 battler); -bool32 IsMoveEffectBlockedByTarget(u32 ability); +bool32 IsMoveEffectBlockedByTarget(enum Ability ability); bool32 IsPursuitTargetSet(void); void ClearPursuitValuesIfSet(u32 battler); void ClearPursuitValues(void); bool32 HasWeatherEffect(void); -u32 RestoreWhiteHerbStats(u32 battler); bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move); bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); void UpdateStallMons(void); bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId); bool32 TrySwitchInEjectPack(enum ItemCaseId caseID); -u32 GetMonVolatile(u32 battler, enum Volatile volatile); -void SetMonVolatile(u32 battler, enum Volatile volatile, u32 newValue); -u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); +u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile); +void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue); +u32 TryBoosterEnergy(u32 battler, enum Ability ability, enum ItemCaseId caseID); +bool32 ItemHealMonVolatile(u32 battler, u16 itemId); +void PushHazardTypeToQueue(u32 side, enum Hazards hazardType); +bool32 IsHazardOnSide(u32 side, enum Hazards hazardType); +bool32 AreAnyHazardsOnSide(u32 side); +void RemoveAllHazardsFromField(u32 side); +bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType); +void RemoveHazardFromField(u32 side, enum Hazards hazardType); +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option); +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander); +bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move); +u32 GetNaturePowerMove(u32 battler); +u32 GetNaturePowerMove(u32 battler); +void RemoveAbilityFlags(u32 battler); +bool32 IsDazzlingAbility(enum Ability ability); +bool32 IsAllowedToUseBag(void); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/ai.h b/include/config/ai.h index 91ee3525a..5a7ce4078 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -13,8 +13,9 @@ // AI smart switching chances; if you want more complex behaviour, modify GetSwitchChance #define SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE 100 +#define SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE 50 #define SHOULD_SWITCH_TRAPPER_PERCENTAGE 100 -#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 100 +#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 50 #define STAY_IN_ABSORBING_PERCENTAGE 66 // Chance to stay in if outgoing mon has super effective move against player, will prevent switching out for an absorber with this likelihood #define SHOULD_SWITCH_HASBADODDS_PERCENTAGE 50 #define SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE 100 @@ -51,11 +52,16 @@ #define AI_GOOD_SCORE_THRESHOLD 100 // Move scores above this threshold are considered "good" when deciding switching // AI held item-based move scoring -#define LOW_ACCURACY_THRESHOLD 75 // Moves with accuracy equal OR below this value are considered low accuracy +#define LOW_ACCURACY_THRESHOLD 75 // Moves with accuracy equal OR below this value are considered low accuracy // AI move scoring #define STATUS_MOVE_FOCUS_PUNCH_CHANCE 50 // Chance the AI will use a status move if the player's best move is Focus Punch #define BOOST_INTO_HAZE_CHANCE 0 // Chance the AI will use a stat boosting move if the player has used Haze +#define SHOULD_RECOVER_CHANCE 50 // Chance the AI will give recovery moves score increase if less than ENABLE_RECOVERY_THRESHOLD and in no immediate danger +#define ENABLE_RECOVERY_THRESHOLD 60 // HP percentage beneath which SHOULD_RECOVER_CHANCE is active +#define SUCKER_PUNCH_CHANCE 50 // Chance for the AI to not use Sucker Punch if the player has a status move +#define SUCKER_PUNCH_PREDICTION_CHANCE 50 // Additional chance for the AI to not use Sucker Punch if actively predicting a status move if SUCKER_PUNCH_CHANCE fails +#define PRIORITIZE_LAST_CHANCE_CHANCE 50 // Chance the AI will prioritize Last Chance (priority move in the face of being outsped and KO'd) over Slow KO // AI damage calc considerations #define RISKY_AI_CRIT_STAGE_THRESHOLD 2 // Stat stages at which Risky will assume it gets a crit @@ -67,16 +73,46 @@ // AI Terastalization chances #define AI_CONSERVE_TERA_CHANCE_PER_MON 10 // Chance for AI with smart tera flag to decide not to tera before considering defensive benefit is this*(X-1), where X is the number of alive pokemon that could tera -#define AI_TERA_PREDICT_CHANCE 40 // Chance for AI with smart tera flag to tera in the situation where tera would save it from a KO, but could be punished by a KO from a different move. +#define AI_TERA_PREDICT_CHANCE 40 // Chance for AI with smart tera flag to tera in the situation where tera would save it from a KO, but could be punished by a KO from a different move. -// AI PP Stall detection chance per roll -#define PP_STALL_DISREGARD_MOVE_PERCENTAGE 50 -// Score reduction if any roll for PP stall detection passes -#define PP_STALL_SCORE_REDUCTION 20 +// AI_FLAG_PP_STALL_PREVENTION settings +#define PP_STALL_DISREGARD_MOVE_PERCENTAGE 50 // Detection chance per roll +#define PP_STALL_SCORE_REDUCTION 20 // Score reduction if any roll for PP stall detection passes -// AI's acceptable number of hits to KO the partner via friendly fire in a double battle. -#define FRIENDLY_FIRE_RISKY_THRESHOLD 2 -#define FRIENDLY_FIRE_NORMAL_THRESHOLD 3 -#define FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD 4 +// AI_FLAG_ASSUME_STAB settings +#define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience. + +// AI_FLAG_ASSUME_STATUS_MOVES settings +#define ASSUME_STATUS_MOVES_HAS_TUNING TRUE // Flag has varying rates for different kinds of status move. + // Setting to false also means it will not alert on Fake Out or Super Fang. +#define ASSUME_STATUS_HIGH_ODDS 90 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore +#define ASSUME_STATUS_MEDIUM_ODDS 70 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect +#define ASSUME_STATUS_LOW_ODDS 40 // Chance for AI to see niche moves a pokemon may have but probably won't, like Entrainment +#define ASSUME_ALL_STATUS_ODDS 25 // Chance for the AI to see any kind of status move. + +// AI_FLAG_SMART_SWITCHING settings +#define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise + +// Configurations specifically for AI_FLAG_DOUBLE_BATTLE. +#define FRIENDLY_FIRE_RISKY_THRESHOLD 2 // AI_FLAG_RISKY acceptable number of hits to KO the partner via friendly fire +#define FRIENDLY_FIRE_NORMAL_THRESHOLD 3 // typical acceptable number of hits to KO the partner via friendly fire +#define FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD 4 // AI_FLAG_CONSERVATIVE acceptable number of hits to KO the partner via friendly fire +// Counterplay on the assumption of opponents Protecting. +#define DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE 35 // both pokemon use Trick Room on turn Trick Room expires in the hopes both opponents used Protect to stall, getting a free refresh on the timer +#define TAILWIND_IN_TRICK_ROOM_CHANCE 35 // use Tailwind on turn Trick Room expires in the hopes both opponents used Protect to stall + +#define AI_FLAG_ATTACKS_PARTNER_FOCUSES_PARTNER FALSE // if TRUE, AI_FLAG_ATTACKS_PARTNER prefers attacking the partner over the ally. + // This is treated as true regardless during wild battles with AI. + +// AI's desired stat changes for Guard Split and Power Split, treated as % +#define GUARD_SPLIT_ALLY_PERCENTAGE 200 +#define GUARD_SPLIT_ENEMY_PERCENTAGE 50 +#define POWER_SPLIT_ALLY_PERCENTAGE 150 +#define POWER_SPLIT_ENEMY_PERCENTAGE 50 + +// HP thresholds to use a status z-move. +#define Z_EFFECT_FOLLOW_ME_THRESHOLD 30 +#define Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD ENABLE_RECOVERY_THRESHOLD // threshold used for moves you could conceivably use more than once +#define Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD 90 // these moves are one-time use or drop your HP #endif // GUARD_CONFIG_AI_H diff --git a/include/config/battle.h b/include/config/battle.h index 06373f2c1..8533c339a 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -28,7 +28,7 @@ #define B_BURN_DAMAGE GEN_LATEST // In Gen7+, burn damage is 1/16th of max HP instead of 1/8th. Also applies to Frostbite. #define B_BURN_FACADE_DMG GEN_LATEST // In Gen6+, burn's effect of lowering the Attack stat no longer applies to Facade. #define B_BINDING_DAMAGE GEN_LATEST // In Gen6+, binding damage is 1/8 of max HP instead of 1/16. (With Binding Band, 1/6 and 1/8 respectively.) -#define B_PSYWAVE_DMG GEN_LATEST // Psywave's damage formula. See Cmd_psywavedamageeffect. +#define B_PSYWAVE_DMG GEN_LATEST // Psywave's damage formula. See DoFixedDamageMoveCalc for details. #define B_PAYBACK_SWITCH_BOOST GEN_LATEST // In Gen5+, if the opponent switches out, Payback's damage will no longer be doubled. #define B_HIDDEN_POWER_DMG GEN_LATEST // In Gen6+, Hidden Power's base power was set to always be 60. Before, it was determined by the mon's IVs. #define B_ROUGH_SKIN_DMG GEN_LATEST // In Gen4+, Rough Skin contact damage is 1/8th of max HP instead of 1/16th. This will also affect Iron Barbs. @@ -131,7 +131,8 @@ #define B_SKIP_RECHARGE GEN_LATEST // In Gen1, recharging moves such as Hyper Beam skip the recharge if the target gets KO'd #define B_ENCORE_TARGET GEN_LATEST // In Gen5+, encored moves are allowed to choose a target #define B_TIME_OF_DAY_HEALING_MOVES GEN_LATEST // In Gen2, Morning Sun, Moonlight, and Synthesis heal twice as much HP based off the time of day. Also changes how much they heal. Evening affects Moonlight. - // If OW_TIMES_OF_DAY is set to Gen 3, then Morning Sun is boosted during the day. + // If OW_TIMES_OF_DAY is set to Gen 3, then Morning Sun is boosted during the day. +#define B_DREAM_EATER_LIQUID_OOZE GEN_LATEST // In Gen5+, Dream Eater is affected by Liquid Ooze. // Ability settings #define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger. @@ -207,7 +208,6 @@ #define B_FLAG_INVERSE_BATTLE 0 // If this flag is set, the battle's type effectiveness are inversed. For example, fire is super effective against water. #define B_FLAG_FORCE_DOUBLE_WILD 0 // If this flag is set, all land and surfing wild battles will be double battles. #define B_SMART_WILD_AI_FLAG 0 // If this flag is set, wild Pokémon will become smart, with all AI flags enabled. -#define B_FLAG_NO_BAG_USE 0 // If this flag is set, the ability to use the bag in battle is disabled. #define B_FLAG_NO_CATCHING 0 // If this flag is set, the ability to catch wild Pokémon is disabled. #define B_FLAG_NO_RUNNING 0 // If this flag is set, the ability to escape from wild battles is disabled. Also makes Roar/Whirlwind and Teleport (under Gen8) fail. #define B_FLAG_AI_VS_AI_BATTLE 0 // If this flag is set, the player's mons will be controlled by the ai next battles. @@ -229,6 +229,13 @@ #define B_VAR_DIFFICULTY 0 // If not 0, you can use this var to control which difficulty version of a Trainer is loaded. This should be manually set by the developer using Script_SetDifficulty AFTER NewGameInitData has run. +// No bag settings +#define NO_BAG_RESTRICTION 0 +#define NO_BAG_AGAINST_TRAINER 1 +#define NO_BAG_IN_BATTLE 2 + +#define B_VAR_NO_BAG_USE 0 // If 1, the ability to use the bag in battle is disabled in trainer battles. If 2, it is also disabled in wild battles. + // Sky Battles #define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles. #define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles. @@ -262,32 +269,33 @@ #define B_TERRAIN_TYPE_BOOST GEN_LATEST // In Gen8, damage is boosted by 30% instead of 50%. #define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See MOVE_EFFECT_SECRET_POWER's case in `SetMoveEffect`. #define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation. -#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves. +#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See gBattleEnvironmentInfo. #define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType. #define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain. // Interface settings -#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. -#define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. -#define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped. -#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster. -#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster. -#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move. -#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary and move relearner showing the move's category. -#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations. -#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles. -#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option -#define B_RUN_TRAINER_BATTLE TRUE // If set to TRUE, players can run from Trainer battles. This is treated as a whiteout. -#define B_MOVE_DESCRIPTION_BUTTON L_BUTTON // If set to a button other than B_LAST_USED_BALL_BUTTON, pressing this button will open the move description menu -#define B_SHOW_USELESS_Z_MOVE_INFO FALSE // If set to TRUE, Z-moves without additional effects like newer gen status moves will say "no additional effect" -#define B_ANIMATE_MON_AFTER_KO TRUE // If set to TRUE, if a Pokémon on the opposite site faints, the non-fainted Pokemon will display a victory animation. -#define B_SHOW_DYNAMAX_MESSAGE FALSE // If set to TRUE, an additional battle message is shown after completing Dynamaxing/Gigantamaxing. +#define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. +#define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped. +#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster. +#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster. +#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move. +#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary and move relearner showing the move's category. +#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations. +#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles. +#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option +#define B_RUN_TRAINER_BATTLE TRUE // If set to TRUE, players can run from Trainer battles. This is treated as a whiteout. +#define B_MOVE_DESCRIPTION_BUTTON L_BUTTON // If set to a button other than B_LAST_USED_BALL_BUTTON, pressing this button will open the move description menu +#define B_SHOW_USELESS_Z_MOVE_INFO FALSE // If set to TRUE, Z-moves without additional effects like newer gen status moves will say "no additional effect" +#define B_ANIMATE_MON_AFTER_KO TRUE // If set to TRUE, if a Pokémon on the opposite site faints, the non-fainted Pokemon will display a victory animation. +#define B_ANIMATE_MON_AFTER_FAILED_POKEBALL TRUE // If set to TRUE, if a Pokémon on the opposite side breaks out of a thrown Poké Ball, the wild Pokémon will display its animation. +#define B_SHOW_DYNAMAX_MESSAGE FALSE // If set to TRUE, an additional battle message is shown after completing Dynamaxing/Gigantamaxing. // Catching settings #define B_SEMI_INVULNERABLE_CATCH GEN_LATEST // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc) -#define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm. +#define B_CATCHING_CHARM_BOOST 100 // % boost in Critical Capture odds if player has the Catching Charm. #define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled. #define B_CRITICAL_CAPTURE_LOCAL_DEX TRUE // If set to FALSE, Critical Capture % is based off of the National Pokedex estimated by enabled generations. +#define B_CRITICAL_CAPTURE_IF_OWNED GEN_LATEST // In Gen9, a capture appear critical if the pokemon you are trying to catch already has a dex entry (has already been caught) #define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. @@ -363,5 +371,7 @@ #define B_POOL_RULE_EXCLUDE_FORMS FALSE // Exclude different forms from the Species Clause #define B_POOL_RULE_ITEM_CLAUSE FALSE // Only allow each item to be picked once #define B_POOL_RULES_USE_ITEM_EXCLUSIONS FALSE // Exclude items listed in poolItemClauseExclusions +#define B_POOL_RULE_MEGA_STONE_CLAUSE FALSE // Pick only 1 mon with mega stone +#define B_POOL_RULE_Z_CRYSTAL_CLAUSE FALSE // Pick only 1 mon with Z-crystal #endif // GUARD_CONFIG_BATTLE_H diff --git a/include/config/general.h b/include/config/general.h index 1a770cf4c..e89f83950 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -75,7 +75,6 @@ #define EXPANSION_INTRO TRUE // If TRUE, a custom RHH intro will play after the vanilla copyright screen. #define SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. #define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG. -#define COMPETITIVE_PARTY_SYNTAX TRUE // If TRUE, parties are defined in "competitive syntax". #define AUTO_SCROLL_TEXT FALSE // If TRUE, text will automatically scroll to the next line after NUM_FRAMES_AUTO_SCROLL_DELAY. Players can still press A_BUTTON or B_BUTTON to scroll on their own. #define NUM_FRAMES_AUTO_SCROLL_DELAY 49 diff --git a/include/constants/abilities.h b/include/constants/abilities.h index 856820613..7e17fd528 100644 --- a/include/constants/abilities.h +++ b/include/constants/abilities.h @@ -1,344 +1,339 @@ #ifndef GUARD_CONSTANTS_ABILITIES_H #define GUARD_CONSTANTS_ABILITIES_H -#define ABILITY_NONE 0 -#define ABILITY_STENCH 1 -#define ABILITY_DRIZZLE 2 -#define ABILITY_SPEED_BOOST 3 -#define ABILITY_BATTLE_ARMOR 4 -#define ABILITY_STURDY 5 -#define ABILITY_DAMP 6 -#define ABILITY_LIMBER 7 -#define ABILITY_SAND_VEIL 8 -#define ABILITY_STATIC 9 -#define ABILITY_VOLT_ABSORB 10 -#define ABILITY_WATER_ABSORB 11 -#define ABILITY_OBLIVIOUS 12 -#define ABILITY_CLOUD_NINE 13 -#define ABILITY_COMPOUND_EYES 14 -#define ABILITY_INSOMNIA 15 -#define ABILITY_COLOR_CHANGE 16 -#define ABILITY_IMMUNITY 17 -#define ABILITY_FLASH_FIRE 18 -#define ABILITY_SHIELD_DUST 19 -#define ABILITY_OWN_TEMPO 20 -#define ABILITY_SUCTION_CUPS 21 -#define ABILITY_INTIMIDATE 22 -#define ABILITY_SHADOW_TAG 23 -#define ABILITY_ROUGH_SKIN 24 -#define ABILITY_WONDER_GUARD 25 -#define ABILITY_LEVITATE 26 -#define ABILITY_EFFECT_SPORE 27 -#define ABILITY_SYNCHRONIZE 28 -#define ABILITY_CLEAR_BODY 29 -#define ABILITY_NATURAL_CURE 30 -#define ABILITY_LIGHTNING_ROD 31 -#define ABILITY_SERENE_GRACE 32 -#define ABILITY_SWIFT_SWIM 33 -#define ABILITY_CHLOROPHYLL 34 -#define ABILITY_ILLUMINATE 35 -#define ABILITY_TRACE 36 -#define ABILITY_HUGE_POWER 37 -#define ABILITY_POISON_POINT 38 -#define ABILITY_INNER_FOCUS 39 -#define ABILITY_MAGMA_ARMOR 40 -#define ABILITY_WATER_VEIL 41 -#define ABILITY_MAGNET_PULL 42 -#define ABILITY_SOUNDPROOF 43 -#define ABILITY_RAIN_DISH 44 -#define ABILITY_SAND_STREAM 45 -#define ABILITY_PRESSURE 46 -#define ABILITY_THICK_FAT 47 -#define ABILITY_EARLY_BIRD 48 -#define ABILITY_FLAME_BODY 49 -#define ABILITY_RUN_AWAY 50 -#define ABILITY_KEEN_EYE 51 -#define ABILITY_HYPER_CUTTER 52 -#define ABILITY_PICKUP 53 -#define ABILITY_TRUANT 54 -#define ABILITY_HUSTLE 55 -#define ABILITY_CUTE_CHARM 56 -#define ABILITY_PLUS 57 -#define ABILITY_MINUS 58 -#define ABILITY_FORECAST 59 -#define ABILITY_STICKY_HOLD 60 -#define ABILITY_SHED_SKIN 61 -#define ABILITY_GUTS 62 -#define ABILITY_MARVEL_SCALE 63 -#define ABILITY_LIQUID_OOZE 64 -#define ABILITY_OVERGROW 65 -#define ABILITY_BLAZE 66 -#define ABILITY_TORRENT 67 -#define ABILITY_SWARM 68 -#define ABILITY_ROCK_HEAD 69 -#define ABILITY_DROUGHT 70 -#define ABILITY_ARENA_TRAP 71 -#define ABILITY_VITAL_SPIRIT 72 -#define ABILITY_WHITE_SMOKE 73 -#define ABILITY_PURE_POWER 74 -#define ABILITY_SHELL_ARMOR 75 -#define ABILITY_AIR_LOCK 76 +enum __attribute__((packed)) Ability +{ + ABILITY_NONE = 0, + ABILITY_STENCH = 1, + ABILITY_DRIZZLE = 2, + ABILITY_SPEED_BOOST = 3, + ABILITY_BATTLE_ARMOR = 4, + ABILITY_STURDY = 5, + ABILITY_DAMP = 6, + ABILITY_LIMBER = 7, + ABILITY_SAND_VEIL = 8, + ABILITY_STATIC = 9, + ABILITY_VOLT_ABSORB = 10, + ABILITY_WATER_ABSORB = 11, + ABILITY_OBLIVIOUS = 12, + ABILITY_CLOUD_NINE = 13, + ABILITY_COMPOUND_EYES = 14, + ABILITY_INSOMNIA = 15, + ABILITY_COLOR_CHANGE = 16, + ABILITY_IMMUNITY = 17, + ABILITY_FLASH_FIRE = 18, + ABILITY_SHIELD_DUST = 19, + ABILITY_OWN_TEMPO = 20, + ABILITY_SUCTION_CUPS = 21, + ABILITY_INTIMIDATE = 22, + ABILITY_SHADOW_TAG = 23, + ABILITY_ROUGH_SKIN = 24, + ABILITY_WONDER_GUARD = 25, + ABILITY_LEVITATE = 26, + ABILITY_EFFECT_SPORE = 27, + ABILITY_SYNCHRONIZE = 28, + ABILITY_CLEAR_BODY = 29, + ABILITY_NATURAL_CURE = 30, + ABILITY_LIGHTNING_ROD = 31, + ABILITY_SERENE_GRACE = 32, + ABILITY_SWIFT_SWIM = 33, + ABILITY_CHLOROPHYLL = 34, + ABILITY_ILLUMINATE = 35, + ABILITY_TRACE = 36, + ABILITY_HUGE_POWER = 37, + ABILITY_POISON_POINT = 38, + ABILITY_INNER_FOCUS = 39, + ABILITY_MAGMA_ARMOR = 40, + ABILITY_WATER_VEIL = 41, + ABILITY_MAGNET_PULL = 42, + ABILITY_SOUNDPROOF = 43, + ABILITY_RAIN_DISH = 44, + ABILITY_SAND_STREAM = 45, + ABILITY_PRESSURE = 46, + ABILITY_THICK_FAT = 47, + ABILITY_EARLY_BIRD = 48, + ABILITY_FLAME_BODY = 49, + ABILITY_RUN_AWAY = 50, + ABILITY_KEEN_EYE = 51, + ABILITY_HYPER_CUTTER = 52, + ABILITY_PICKUP = 53, + ABILITY_TRUANT = 54, + ABILITY_HUSTLE = 55, + ABILITY_CUTE_CHARM = 56, + ABILITY_PLUS = 57, + ABILITY_MINUS = 58, + ABILITY_FORECAST = 59, + ABILITY_STICKY_HOLD = 60, + ABILITY_SHED_SKIN = 61, + ABILITY_GUTS = 62, + ABILITY_MARVEL_SCALE = 63, + ABILITY_LIQUID_OOZE = 64, + ABILITY_OVERGROW = 65, + ABILITY_BLAZE = 66, + ABILITY_TORRENT = 67, + ABILITY_SWARM = 68, + ABILITY_ROCK_HEAD = 69, + ABILITY_DROUGHT = 70, + ABILITY_ARENA_TRAP = 71, + ABILITY_VITAL_SPIRIT = 72, + ABILITY_WHITE_SMOKE = 73, + ABILITY_PURE_POWER = 74, + ABILITY_SHELL_ARMOR = 75, + ABILITY_AIR_LOCK = 76, + ABILITIES_COUNT_GEN3, -#define ABILITIES_COUNT_GEN3 77 + // Gen 4 + ABILITY_TANGLED_FEET = ABILITIES_COUNT_GEN3, + ABILITY_MOTOR_DRIVE = 78, + ABILITY_RIVALRY = 79, + ABILITY_STEADFAST = 80, + ABILITY_SNOW_CLOAK = 81, + ABILITY_GLUTTONY = 82, + ABILITY_ANGER_POINT = 83, + ABILITY_UNBURDEN = 84, + ABILITY_HEATPROOF = 85, + ABILITY_SIMPLE = 86, + ABILITY_DRY_SKIN = 87, + ABILITY_DOWNLOAD = 88, + ABILITY_IRON_FIST = 89, + ABILITY_POISON_HEAL = 90, + ABILITY_ADAPTABILITY = 91, + ABILITY_SKILL_LINK = 92, + ABILITY_HYDRATION = 93, + ABILITY_SOLAR_POWER = 94, + ABILITY_QUICK_FEET = 95, + ABILITY_NORMALIZE = 96, + ABILITY_SNIPER = 97, + ABILITY_MAGIC_GUARD = 98, + ABILITY_NO_GUARD = 99, + ABILITY_STALL = 100, + ABILITY_TECHNICIAN = 101, + ABILITY_LEAF_GUARD = 102, + ABILITY_KLUTZ = 103, + ABILITY_MOLD_BREAKER = 104, + ABILITY_SUPER_LUCK = 105, + ABILITY_AFTERMATH = 106, + ABILITY_ANTICIPATION = 107, + ABILITY_FOREWARN = 108, + ABILITY_UNAWARE = 109, + ABILITY_TINTED_LENS = 110, + ABILITY_FILTER = 111, + ABILITY_SLOW_START = 112, + ABILITY_SCRAPPY = 113, + ABILITY_STORM_DRAIN = 114, + ABILITY_ICE_BODY = 115, + ABILITY_SOLID_ROCK = 116, + ABILITY_SNOW_WARNING = 117, + ABILITY_HONEY_GATHER = 118, + ABILITY_FRISK = 119, + ABILITY_RECKLESS = 120, + ABILITY_MULTITYPE = 121, + ABILITY_FLOWER_GIFT = 122, + ABILITY_BAD_DREAMS = 123, + ABILITIES_COUNT_GEN4, -// Gen 4 -#define ABILITY_TANGLED_FEET 77 -#define ABILITY_MOTOR_DRIVE 78 -#define ABILITY_RIVALRY 79 -#define ABILITY_STEADFAST 80 -#define ABILITY_SNOW_CLOAK 81 -#define ABILITY_GLUTTONY 82 -#define ABILITY_ANGER_POINT 83 -#define ABILITY_UNBURDEN 84 -#define ABILITY_HEATPROOF 85 -#define ABILITY_SIMPLE 86 -#define ABILITY_DRY_SKIN 87 -#define ABILITY_DOWNLOAD 88 -#define ABILITY_IRON_FIST 89 -#define ABILITY_POISON_HEAL 90 -#define ABILITY_ADAPTABILITY 91 -#define ABILITY_SKILL_LINK 92 -#define ABILITY_HYDRATION 93 -#define ABILITY_SOLAR_POWER 94 -#define ABILITY_QUICK_FEET 95 -#define ABILITY_NORMALIZE 96 -#define ABILITY_SNIPER 97 -#define ABILITY_MAGIC_GUARD 98 -#define ABILITY_NO_GUARD 99 -#define ABILITY_STALL 100 -#define ABILITY_TECHNICIAN 101 -#define ABILITY_LEAF_GUARD 102 -#define ABILITY_KLUTZ 103 -#define ABILITY_MOLD_BREAKER 104 -#define ABILITY_SUPER_LUCK 105 -#define ABILITY_AFTERMATH 106 -#define ABILITY_ANTICIPATION 107 -#define ABILITY_FOREWARN 108 -#define ABILITY_UNAWARE 109 -#define ABILITY_TINTED_LENS 110 -#define ABILITY_FILTER 111 -#define ABILITY_SLOW_START 112 -#define ABILITY_SCRAPPY 113 -#define ABILITY_STORM_DRAIN 114 -#define ABILITY_ICE_BODY 115 -#define ABILITY_SOLID_ROCK 116 -#define ABILITY_SNOW_WARNING 117 -#define ABILITY_HONEY_GATHER 118 -#define ABILITY_FRISK 119 -#define ABILITY_RECKLESS 120 -#define ABILITY_MULTITYPE 121 -#define ABILITY_FLOWER_GIFT 122 -#define ABILITY_BAD_DREAMS 123 + // Gen 5 + ABILITY_PICKPOCKET = ABILITIES_COUNT_GEN4, + ABILITY_SHEER_FORCE = 125, + ABILITY_CONTRARY = 126, + ABILITY_UNNERVE = 127, + ABILITY_DEFIANT = 128, + ABILITY_DEFEATIST = 129, + ABILITY_CURSED_BODY = 130, + ABILITY_HEALER = 131, + ABILITY_FRIEND_GUARD = 132, + ABILITY_WEAK_ARMOR = 133, + ABILITY_HEAVY_METAL = 134, + ABILITY_LIGHT_METAL = 135, + ABILITY_MULTISCALE = 136, + ABILITY_TOXIC_BOOST = 137, + ABILITY_FLARE_BOOST = 138, + ABILITY_HARVEST = 139, + ABILITY_TELEPATHY = 140, + ABILITY_MOODY = 141, + ABILITY_OVERCOAT = 142, + ABILITY_POISON_TOUCH = 143, + ABILITY_REGENERATOR = 144, + ABILITY_BIG_PECKS = 145, + ABILITY_SAND_RUSH = 146, + ABILITY_WONDER_SKIN = 147, + ABILITY_ANALYTIC = 148, + ABILITY_ILLUSION = 149, + ABILITY_IMPOSTER = 150, + ABILITY_INFILTRATOR = 151, + ABILITY_MUMMY = 152, + ABILITY_MOXIE = 153, + ABILITY_JUSTIFIED = 154, + ABILITY_RATTLED = 155, + ABILITY_MAGIC_BOUNCE = 156, + ABILITY_SAP_SIPPER = 157, + ABILITY_PRANKSTER = 158, + ABILITY_SAND_FORCE = 159, + ABILITY_IRON_BARBS = 160, + ABILITY_ZEN_MODE = 161, + ABILITY_VICTORY_STAR = 162, + ABILITY_TURBOBLAZE = 163, + ABILITY_TERAVOLT = 164, + ABILITIES_COUNT_GEN5, -#define ABILITIES_COUNT_GEN4 124 + // Gen 6 + ABILITY_AROMA_VEIL = ABILITIES_COUNT_GEN5, + ABILITY_FLOWER_VEIL = 166, + ABILITY_CHEEK_POUCH = 167, + ABILITY_PROTEAN = 168, + ABILITY_FUR_COAT = 169, + ABILITY_MAGICIAN = 170, + ABILITY_BULLETPROOF = 171, + ABILITY_COMPETITIVE = 172, + ABILITY_STRONG_JAW = 173, + ABILITY_REFRIGERATE = 174, + ABILITY_SWEET_VEIL = 175, + ABILITY_STANCE_CHANGE = 176, + ABILITY_GALE_WINGS = 177, + ABILITY_MEGA_LAUNCHER = 178, + ABILITY_GRASS_PELT = 179, + ABILITY_SYMBIOSIS = 180, + ABILITY_TOUGH_CLAWS = 181, + ABILITY_PIXILATE = 182, + ABILITY_GOOEY = 183, + ABILITY_AERILATE = 184, + ABILITY_PARENTAL_BOND = 185, + ABILITY_DARK_AURA = 186, + ABILITY_FAIRY_AURA = 187, + ABILITY_AURA_BREAK = 188, + ABILITY_PRIMORDIAL_SEA = 189, + ABILITY_DESOLATE_LAND = 190, + ABILITY_DELTA_STREAM = 191, + ABILITIES_COUNT_GEN6, -// Gen 5 -#define ABILITY_PICKPOCKET 124 -#define ABILITY_SHEER_FORCE 125 -#define ABILITY_CONTRARY 126 -#define ABILITY_UNNERVE 127 -#define ABILITY_DEFIANT 128 -#define ABILITY_DEFEATIST 129 -#define ABILITY_CURSED_BODY 130 -#define ABILITY_HEALER 131 -#define ABILITY_FRIEND_GUARD 132 -#define ABILITY_WEAK_ARMOR 133 -#define ABILITY_HEAVY_METAL 134 -#define ABILITY_LIGHT_METAL 135 -#define ABILITY_MULTISCALE 136 -#define ABILITY_TOXIC_BOOST 137 -#define ABILITY_FLARE_BOOST 138 -#define ABILITY_HARVEST 139 -#define ABILITY_TELEPATHY 140 -#define ABILITY_MOODY 141 -#define ABILITY_OVERCOAT 142 -#define ABILITY_POISON_TOUCH 143 -#define ABILITY_REGENERATOR 144 -#define ABILITY_BIG_PECKS 145 -#define ABILITY_SAND_RUSH 146 -#define ABILITY_WONDER_SKIN 147 -#define ABILITY_ANALYTIC 148 -#define ABILITY_ILLUSION 149 -#define ABILITY_IMPOSTER 150 -#define ABILITY_INFILTRATOR 151 -#define ABILITY_MUMMY 152 -#define ABILITY_MOXIE 153 -#define ABILITY_JUSTIFIED 154 -#define ABILITY_RATTLED 155 -#define ABILITY_MAGIC_BOUNCE 156 -#define ABILITY_SAP_SIPPER 157 -#define ABILITY_PRANKSTER 158 -#define ABILITY_SAND_FORCE 159 -#define ABILITY_IRON_BARBS 160 -#define ABILITY_ZEN_MODE 161 -#define ABILITY_VICTORY_STAR 162 -#define ABILITY_TURBOBLAZE 163 -#define ABILITY_TERAVOLT 164 + // Gen 7 + ABILITY_STAMINA = ABILITIES_COUNT_GEN6, + ABILITY_WIMP_OUT = 193, + ABILITY_EMERGENCY_EXIT = 194, + ABILITY_WATER_COMPACTION = 195, + ABILITY_MERCILESS = 196, + ABILITY_SHIELDS_DOWN = 197, + ABILITY_STAKEOUT = 198, + ABILITY_WATER_BUBBLE = 199, + ABILITY_STEELWORKER = 200, + ABILITY_BERSERK = 201, + ABILITY_SLUSH_RUSH = 202, + ABILITY_LONG_REACH = 203, + ABILITY_LIQUID_VOICE = 204, + ABILITY_TRIAGE = 205, + ABILITY_GALVANIZE = 206, + ABILITY_SURGE_SURFER = 207, + ABILITY_SCHOOLING = 208, + ABILITY_DISGUISE = 209, + ABILITY_BATTLE_BOND = 210, + ABILITY_POWER_CONSTRUCT = 211, + ABILITY_CORROSION = 212, + ABILITY_COMATOSE = 213, + ABILITY_QUEENLY_MAJESTY = 214, + ABILITY_INNARDS_OUT = 215, + ABILITY_DANCER = 216, + ABILITY_BATTERY = 217, + ABILITY_FLUFFY = 218, + ABILITY_DAZZLING = 219, + ABILITY_SOUL_HEART = 220, + ABILITY_TANGLING_HAIR = 221, + ABILITY_RECEIVER = 222, + ABILITY_POWER_OF_ALCHEMY = 223, + ABILITY_BEAST_BOOST = 224, + ABILITY_RKS_SYSTEM = 225, + ABILITY_ELECTRIC_SURGE = 226, + ABILITY_PSYCHIC_SURGE = 227, + ABILITY_MISTY_SURGE = 228, + ABILITY_GRASSY_SURGE = 229, + ABILITY_FULL_METAL_BODY = 230, + ABILITY_SHADOW_SHIELD = 231, + ABILITY_PRISM_ARMOR = 232, + ABILITY_NEUROFORCE = 233, + ABILITIES_COUNT_GEN7, -#define ABILITIES_COUNT_GEN5 165 + // Gen 8 + ABILITY_INTREPID_SWORD = ABILITIES_COUNT_GEN7, + ABILITY_DAUNTLESS_SHIELD = 235, + ABILITY_LIBERO = 236, + ABILITY_BALL_FETCH = 237, + ABILITY_COTTON_DOWN = 238, + ABILITY_PROPELLER_TAIL = 239, + ABILITY_MIRROR_ARMOR = 240, + ABILITY_GULP_MISSILE = 241, + ABILITY_STALWART = 242, + ABILITY_STEAM_ENGINE = 243, + ABILITY_PUNK_ROCK = 244, + ABILITY_SAND_SPIT = 245, + ABILITY_ICE_SCALES = 246, + ABILITY_RIPEN = 247, + ABILITY_ICE_FACE = 248, + ABILITY_POWER_SPOT = 249, + ABILITY_MIMICRY = 250, + ABILITY_SCREEN_CLEANER = 251, + ABILITY_STEELY_SPIRIT = 252, + ABILITY_PERISH_BODY = 253, + ABILITY_WANDERING_SPIRIT = 254, + ABILITY_GORILLA_TACTICS = 255, + ABILITY_NEUTRALIZING_GAS = 256, + ABILITY_PASTEL_VEIL = 257, + ABILITY_HUNGER_SWITCH = 258, + ABILITY_QUICK_DRAW = 259, + ABILITY_UNSEEN_FIST = 260, + ABILITY_CURIOUS_MEDICINE = 261, + ABILITY_TRANSISTOR = 262, + ABILITY_DRAGONS_MAW = 263, + ABILITY_CHILLING_NEIGH = 264, + ABILITY_GRIM_NEIGH = 265, + ABILITY_AS_ONE_ICE_RIDER = 266, + ABILITY_AS_ONE_SHADOW_RIDER = 267, + ABILITIES_COUNT_GEN8, -// Gen 6 -#define ABILITY_AROMA_VEIL 165 -#define ABILITY_FLOWER_VEIL 166 -#define ABILITY_CHEEK_POUCH 167 -#define ABILITY_PROTEAN 168 -#define ABILITY_FUR_COAT 169 -#define ABILITY_MAGICIAN 170 -#define ABILITY_BULLETPROOF 171 -#define ABILITY_COMPETITIVE 172 -#define ABILITY_STRONG_JAW 173 -#define ABILITY_REFRIGERATE 174 -#define ABILITY_SWEET_VEIL 175 -#define ABILITY_STANCE_CHANGE 176 -#define ABILITY_GALE_WINGS 177 -#define ABILITY_MEGA_LAUNCHER 178 -#define ABILITY_GRASS_PELT 179 -#define ABILITY_SYMBIOSIS 180 -#define ABILITY_TOUGH_CLAWS 181 -#define ABILITY_PIXILATE 182 -#define ABILITY_GOOEY 183 -#define ABILITY_AERILATE 184 -#define ABILITY_PARENTAL_BOND 185 -#define ABILITY_DARK_AURA 186 -#define ABILITY_FAIRY_AURA 187 -#define ABILITY_AURA_BREAK 188 -#define ABILITY_PRIMORDIAL_SEA 189 -#define ABILITY_DESOLATE_LAND 190 -#define ABILITY_DELTA_STREAM 191 - -#define ABILITIES_COUNT_GEN6 192 - -// Gen 7 -#define ABILITY_STAMINA 192 -#define ABILITY_WIMP_OUT 193 -#define ABILITY_EMERGENCY_EXIT 194 -#define ABILITY_WATER_COMPACTION 195 -#define ABILITY_MERCILESS 196 -#define ABILITY_SHIELDS_DOWN 197 -#define ABILITY_STAKEOUT 198 -#define ABILITY_WATER_BUBBLE 199 -#define ABILITY_STEELWORKER 200 -#define ABILITY_BERSERK 201 -#define ABILITY_SLUSH_RUSH 202 -#define ABILITY_LONG_REACH 203 -#define ABILITY_LIQUID_VOICE 204 -#define ABILITY_TRIAGE 205 -#define ABILITY_GALVANIZE 206 -#define ABILITY_SURGE_SURFER 207 -#define ABILITY_SCHOOLING 208 -#define ABILITY_DISGUISE 209 -#define ABILITY_BATTLE_BOND 210 -#define ABILITY_POWER_CONSTRUCT 211 -#define ABILITY_CORROSION 212 -#define ABILITY_COMATOSE 213 -#define ABILITY_QUEENLY_MAJESTY 214 -#define ABILITY_INNARDS_OUT 215 -#define ABILITY_DANCER 216 -#define ABILITY_BATTERY 217 -#define ABILITY_FLUFFY 218 -#define ABILITY_DAZZLING 219 -#define ABILITY_SOUL_HEART 220 -#define ABILITY_TANGLING_HAIR 221 -#define ABILITY_RECEIVER 222 -#define ABILITY_POWER_OF_ALCHEMY 223 -#define ABILITY_BEAST_BOOST 224 -#define ABILITY_RKS_SYSTEM 225 -#define ABILITY_ELECTRIC_SURGE 226 -#define ABILITY_PSYCHIC_SURGE 227 -#define ABILITY_MISTY_SURGE 228 -#define ABILITY_GRASSY_SURGE 229 -#define ABILITY_FULL_METAL_BODY 230 -#define ABILITY_SHADOW_SHIELD 231 -#define ABILITY_PRISM_ARMOR 232 -#define ABILITY_NEUROFORCE 233 - -#define ABILITIES_COUNT_GEN7 234 - -// Gen 8 -#define ABILITY_INTREPID_SWORD 234 -#define ABILITY_DAUNTLESS_SHIELD 235 -#define ABILITY_LIBERO 236 -#define ABILITY_BALL_FETCH 237 -#define ABILITY_COTTON_DOWN 238 -#define ABILITY_PROPELLER_TAIL 239 -#define ABILITY_MIRROR_ARMOR 240 -#define ABILITY_GULP_MISSILE 241 -#define ABILITY_STALWART 242 -#define ABILITY_STEAM_ENGINE 243 -#define ABILITY_PUNK_ROCK 244 -#define ABILITY_SAND_SPIT 245 -#define ABILITY_ICE_SCALES 246 -#define ABILITY_RIPEN 247 -#define ABILITY_ICE_FACE 248 -#define ABILITY_POWER_SPOT 249 -#define ABILITY_MIMICRY 250 -#define ABILITY_SCREEN_CLEANER 251 -#define ABILITY_STEELY_SPIRIT 252 -#define ABILITY_PERISH_BODY 253 -#define ABILITY_WANDERING_SPIRIT 254 -#define ABILITY_GORILLA_TACTICS 255 -#define ABILITY_NEUTRALIZING_GAS 256 -#define ABILITY_PASTEL_VEIL 257 -#define ABILITY_HUNGER_SWITCH 258 -#define ABILITY_QUICK_DRAW 259 -#define ABILITY_UNSEEN_FIST 260 -#define ABILITY_CURIOUS_MEDICINE 261 -#define ABILITY_TRANSISTOR 262 -#define ABILITY_DRAGONS_MAW 263 -#define ABILITY_CHILLING_NEIGH 264 -#define ABILITY_GRIM_NEIGH 265 -#define ABILITY_AS_ONE_ICE_RIDER 266 -#define ABILITY_AS_ONE_SHADOW_RIDER 267 - -#define ABILITIES_COUNT_GEN8 268 - -// Gen 9 -#define ABILITY_LINGERING_AROMA 268 -#define ABILITY_SEED_SOWER 269 -#define ABILITY_THERMAL_EXCHANGE 270 -#define ABILITY_ANGER_SHELL 271 -#define ABILITY_PURIFYING_SALT 272 -#define ABILITY_WELL_BAKED_BODY 273 -#define ABILITY_WIND_RIDER 274 -#define ABILITY_GUARD_DOG 275 -#define ABILITY_ROCKY_PAYLOAD 276 -#define ABILITY_WIND_POWER 277 -#define ABILITY_ZERO_TO_HERO 278 -#define ABILITY_COMMANDER 279 -#define ABILITY_ELECTROMORPHOSIS 280 -#define ABILITY_PROTOSYNTHESIS 281 -#define ABILITY_QUARK_DRIVE 282 -#define ABILITY_GOOD_AS_GOLD 283 -#define ABILITY_VESSEL_OF_RUIN 284 -#define ABILITY_SWORD_OF_RUIN 285 -#define ABILITY_TABLETS_OF_RUIN 286 -#define ABILITY_BEADS_OF_RUIN 287 -#define ABILITY_ORICHALCUM_PULSE 288 -#define ABILITY_HADRON_ENGINE 289 -#define ABILITY_OPPORTUNIST 290 -#define ABILITY_CUD_CHEW 291 -#define ABILITY_SHARPNESS 292 -#define ABILITY_SUPREME_OVERLORD 293 -#define ABILITY_COSTAR 294 -#define ABILITY_TOXIC_DEBRIS 295 -#define ABILITY_ARMOR_TAIL 296 -#define ABILITY_EARTH_EATER 297 -#define ABILITY_MYCELIUM_MIGHT 298 -#define ABILITY_HOSPITALITY 299 -#define ABILITY_MINDS_EYE 300 -#define ABILITY_EMBODY_ASPECT_TEAL_MASK 301 -#define ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK 302 -#define ABILITY_EMBODY_ASPECT_WELLSPRING_MASK 303 -#define ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK 304 -#define ABILITY_TOXIC_CHAIN 305 -#define ABILITY_SUPERSWEET_SYRUP 306 -#define ABILITY_TERA_SHIFT 307 -#define ABILITY_TERA_SHELL 308 -#define ABILITY_TERAFORM_ZERO 309 -#define ABILITY_POISON_PUPPETEER 310 - -#define ABILITIES_COUNT_GEN9 311 - -#define ABILITIES_COUNT ABILITIES_COUNT_GEN9 + // Gen 9 + ABILITY_LINGERING_AROMA = ABILITIES_COUNT_GEN8, + ABILITY_SEED_SOWER = 269, + ABILITY_THERMAL_EXCHANGE = 270, + ABILITY_ANGER_SHELL = 271, + ABILITY_PURIFYING_SALT = 272, + ABILITY_WELL_BAKED_BODY = 273, + ABILITY_WIND_RIDER = 274, + ABILITY_GUARD_DOG = 275, + ABILITY_ROCKY_PAYLOAD = 276, + ABILITY_WIND_POWER = 277, + ABILITY_ZERO_TO_HERO = 278, + ABILITY_COMMANDER = 279, + ABILITY_ELECTROMORPHOSIS = 280, + ABILITY_PROTOSYNTHESIS = 281, + ABILITY_QUARK_DRIVE = 282, + ABILITY_GOOD_AS_GOLD = 283, + ABILITY_VESSEL_OF_RUIN = 284, + ABILITY_SWORD_OF_RUIN = 285, + ABILITY_TABLETS_OF_RUIN = 286, + ABILITY_BEADS_OF_RUIN = 287, + ABILITY_ORICHALCUM_PULSE = 288, + ABILITY_HADRON_ENGINE = 289, + ABILITY_OPPORTUNIST = 290, + ABILITY_CUD_CHEW = 291, + ABILITY_SHARPNESS = 292, + ABILITY_SUPREME_OVERLORD = 293, + ABILITY_COSTAR = 294, + ABILITY_TOXIC_DEBRIS = 295, + ABILITY_ARMOR_TAIL = 296, + ABILITY_EARTH_EATER = 297, + ABILITY_MYCELIUM_MIGHT = 298, + ABILITY_HOSPITALITY = 299, + ABILITY_MINDS_EYE = 300, + ABILITY_EMBODY_ASPECT_TEAL_MASK = 301, + ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK = 302, + ABILITY_EMBODY_ASPECT_WELLSPRING_MASK = 303, + ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK = 304, + ABILITY_TOXIC_CHAIN = 305, + ABILITY_SUPERSWEET_SYRUP = 306, + ABILITY_TERA_SHIFT = 307, + ABILITY_TERA_SHELL = 308, + ABILITY_TERAFORM_ZERO = 309, + ABILITY_POISON_PUPPETEER = 310, + ABILITIES_COUNT_GEN9, + ABILITIES_COUNT = ABILITIES_COUNT_GEN9, +}; #endif // GUARD_CONSTANTS_ABILITIES_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 316828c7d..eed6c6944 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -93,12 +93,10 @@ enum BattlerId #define BATTLE_TYPE_FRONTIER (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOME | BATTLE_TYPE_PALACE | BATTLE_TYPE_ARENA | BATTLE_TYPE_FACTORY | BATTLE_TYPE_PIKE | BATTLE_TYPE_PYRAMID) #define BATTLE_TYPE_FRONTIER_NO_PYRAMID (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOME | BATTLE_TYPE_PALACE | BATTLE_TYPE_ARENA | BATTLE_TYPE_FACTORY | BATTLE_TYPE_PIKE) #define BATTLE_TYPE_RECORDED_INVALID ((BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_FIRST_BATTLE \ - | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_ROAMER | BATTLE_TYPE_EREADER_TRAINER \ + | BATTLE_TYPE_CATCH_TUTORIAL | BATTLE_TYPE_ROAMER | BATTLE_TYPE_EREADER_TRAINER \ | BATTLE_TYPE_LEGENDARY \ | BATTLE_TYPE_RECORDED | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE)) -#define IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(flags) ((flags) & BATTLE_TYPE_GHOST && !((flags) & BATTLE_TYPE_GHOST_UNVEILED)) -#define IS_BATTLE_TYPE_GHOST_WITH_SCOPE(flags) ((flags) & BATTLE_TYPE_GHOST && (flags) & BATTLE_TYPE_GHOST_UNVEILED) #define WILD_DOUBLE_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER)))) #define RECORDED_WILD_BATTLE ((gBattleTypeFlags & BATTLE_TYPE_RECORDED) && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER))) #define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == 0xFFFF)) @@ -139,136 +137,119 @@ enum BattlerId #define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON) #define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) -#define STATUS1_REFRESH (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) +#define STATUS1_CAN_MOVE (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) +#define STATUS1_INCAPACITATED (STATUS1_SLEEP | STATUS1_FREEZE) +#define STATUS1_ICY_ANY (STATUS1_FREEZE | STATUS1_FROSTBITE) +#define STATUS1_DAMAGING (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_FROSTBITE) enum VolatileFlags { V_BATON_PASSABLE = (1 << 0), }; -// Volatile status ailments -// These are removed after exiting the battle or switching -/* Definitions with names e.g. "Confusion" are accessible in the debug menu - * Enum, Type, (Field name, (optional)bitSize), Flags, (optional)(Debug menu header, (optional)max. value) - */ +/* Volatile status ailments + * These are removed after exiting the battle or switching + * Enum, Type Type, max value, flags */ #define VOLATILE_DEFINITIONS(F) \ - F(VOLATILE_CONFUSION, confusionTurns, (u32, 3), V_BATON_PASSABLE) \ - F(VOLATILE_FLINCHED, flinched, (u32, 1)) \ - F(VOLATILE_UPROAR, uproarTurns, (u32, 3)) \ - F(VOLATILE_TORMENT, torment, (u32, 1)) \ - F(VOLATILE_BIDE, bideTurns, (u32, 2)) \ - F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 2)) \ - F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ - F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ - F(VOLATILE_POWDER, powder, (u32, 1)) \ - F(VOLATILE_UNUSED, padding, (u32, 1)) \ - F(VOLATILE_INFATUATION, infatuation, (u32, 4)) \ - F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ - F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ - F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ - F(VOLATILE_RAGE, rage, (u32, 1)) \ - F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \ - F(VOLATILE_ESCAPE_PREVENTION, escapePrevention, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_NIGHTMARE, nightmare, (u32, 1)) \ - F(VOLATILE_CURSED, cursed, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ - F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) + F(VOLATILE_CONFUSION, confusionTurns, (u32, 6), V_BATON_PASSABLE) \ + F(VOLATILE_FLINCHED, flinched, (u32, 1)) \ + F(VOLATILE_UPROAR, uproarTurns, (u32, 5)) \ + F(VOLATILE_TORMENT, torment, (u32, 1)) \ + F(VOLATILE_BIDE, bideTurns, (u32, 3)) \ + F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 3)) \ + F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ + F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ + F(VOLATILE_POWDER, powder, (u32, 1)) \ + F(VOLATILE_UNUSED, padding, (u32, 1)) \ + F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ + F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ + F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ + F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ + F(VOLATILE_RAGE, rage, (u32, 1)) \ + F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 2)) \ + F(VOLATILE_ESCAPE_PREVENTION, escapePrevention, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_NIGHTMARE, nightmare, (u32, 1)) \ + F(VOLATILE_CURSED, cursed, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ + F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \ + F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ + F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \ + F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \ + F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) \ + F(VOLATILE_LEECH_SEED, leechSeed, (enum BattlerId, MAX_BITS(4)), V_BATON_PASSABLE) \ + F(VOLATILE_LOCK_ON, lockOn, (u32, 2), V_BATON_PASSABLE) \ + F(VOLATILE_PERISH_SONG, perishSong, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_MINIMIZE, minimize, (u32, 1)) \ + F(VOLATILE_CHARGE, charge, (u32, 1)) \ + F(VOLATILE_ROOT, root, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_YAWN, yawn, (u32, 2)) \ + F(VOLATILE_IMPRISON, imprison, (u32, 1)) \ + F(VOLATILE_GRUDGE, grudge, (u32, 1)) \ + F(VOLATILE_GASTRO_ACID, gastroAcid, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_EMBARGO, embargo, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SMACK_DOWN, smackDown, (u32, 1)) \ + F(VOLATILE_TELEKINESIS, telekinesis, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_MIRACLE_EYE, miracleEye, (u32, 1)) \ + F(VOLATILE_MAGNET_RISE, magnetRise, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_HEAL_BLOCK, healBlock, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_AQUA_RING, aquaRing, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_LASER_FOCUS, laserFocus, (u32, 1)) \ + F(VOLATILE_POWER_TRICK, powerTrick, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_NO_RETREAT, noRetreat, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_VESSEL_OF_RUIN, vesselOfRuin, (u32, 1)) \ + F(VOLATILE_SWORD_OF_RUIN, swordOfRuin, (u32, 1)) \ + F(VOLATILE_TABLETS_OF_RUIN, tabletsOfRuin, (u32, 1)) \ + F(VOLATILE_BEADS_OF_RUIN, beadsOfRuin, (u32, 1)) -/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeBitSize and debug parameters as input. */ -#define GET_VOLATILE_MAXIMUM(_typeBitSize, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeBitSize) -#define GET_VOLATILE_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(MAX_BITS(FIRST(__VA_ARGS__)),) MAX_BITS((sizeof(_type) * 8))) + +/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ +#define GET_VOLATILE_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeMaxValue) +#define GET_VOLATILE_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(FIRST(__VA_ARGS__),) MAX_BITS((sizeof(_type) * 8))) #define UNPACK_VOLATILE_ENUMS(_enum, ...) _enum, enum Volatile { + VOLATILE_NONE, VOLATILE_DEFINITIONS(UNPACK_VOLATILE_ENUMS) /* Expands to VOLATILE_CONFUSION, VOLATILE_FLINCHED, etc. */ }; -// Old flags -#define STATUS2_CONFUSION (1 << 0 | 1 << 1 | 1 << 2) -#define STATUS2_CONFUSION_TURN(num) ((num) << 0) -#define STATUS2_FLINCHED (1 << 3) -#define STATUS2_UPROAR (1 << 4 | 1 << 5 | 1 << 6) -#define STATUS2_UPROAR_TURN(num) ((num) << 4) -#define STATUS2_TORMENT (1 << 7) -#define STATUS2_BIDE (1 << 8 | 1 << 9) -#define STATUS2_BIDE_TURN(num) (((num) << 8) & STATUS2_BIDE) -#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash -#define STATUS2_LOCK_CONFUSE_TURN(num)((num) << 10) -#define STATUS2_MULTIPLETURNS (1 << 12) -#define STATUS2_WRAPPED (1 << 13) -#define STATUS2_POWDER (1 << 14) -//#define STATUS2_UNUSED (1 << 15) -#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler -#define STATUS2_INFATUATED_WITH(battler) (1u << (battler + 16)) -#define STATUS2_DEFENSE_CURL (1 << 20) -#define STATUS2_TRANSFORMED (1 << 21) -#define STATUS2_RECHARGE (1 << 22) -#define STATUS2_RAGE (1 << 23) -#define STATUS2_SUBSTITUTE (1 << 24) -#define STATUS2_DESTINY_BOND (1 << 25) -#define STATUS2_ESCAPE_PREVENTION (1 << 26) -#define STATUS2_NIGHTMARE (1 << 27) -#define STATUS2_CURSED (1 << 28) -#define STATUS2_FORESIGHT (1 << 29) -#define STATUS2_DRAGON_CHEER (1 << 30) -#define STATUS2_FOCUS_ENERGY (1 << 31) -#define STATUS2_FOCUS_ENERGY_ANY (STATUS2_DRAGON_CHEER | STATUS2_FOCUS_ENERGY) +// Helper macros +#define INFATUATED_WITH(battler) (battler + 1) +#define LEECHSEEDED_BY(battler) (battler + 1) -#define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed -#define STATUS3_LEECHSEED (1 << 2) -#define STATUS3_ALWAYS_HITS (1 << 3 | 1 << 4) -#define STATUS3_ALWAYS_HITS_TURN(num) (((num) << 3) & STATUS3_ALWAYS_HITS) // "Always Hits" is set as a 2 turn timer, i.e. next turn is the last turn when it's active -#define STATUS3_PERISH_SONG (1 << 5) -#define STATUS3_ON_AIR (1 << 6) -#define STATUS3_UNDERGROUND (1 << 7) -#define STATUS3_MINIMIZED (1 << 8) -#define STATUS3_CHARGED_UP (1 << 9) -#define STATUS3_ROOTED (1 << 10) -#define STATUS3_YAWN (1 << 11 | 1 << 12) // Number of turns to sleep -#define STATUS3_YAWN_TURN(num) (((num) << 11) & STATUS3_YAWN) -#define STATUS3_IMPRISONED_OTHERS (1 << 13) -#define STATUS3_GRUDGE (1 << 14) -#define STATUS3_COMMANDER (1 << 15) -#define STATUS3_GASTRO_ACID (1 << 16) -#define STATUS3_EMBARGO (1 << 17) -#define STATUS3_UNDERWATER (1 << 18) -#define STATUS3_UNUSED_19 (1 << 19) -#define STATUS3_UNUSED_20 (1 << 20) -#define STATUS3_SMACKED_DOWN (1 << 21) -#define STATUS3_UNUSED_22 (1 << 22) -#define STATUS3_TELEKINESIS (1 << 23) -#define STATUS3_PHANTOM_FORCE (1 << 24) -#define STATUS3_MIRACLE_EYED (1 << 25) -#define STATUS3_MAGNET_RISE (1 << 26) -#define STATUS3_HEAL_BLOCK (1 << 27) -#define STATUS3_AQUA_RING (1 << 28) -#define STATUS3_LASER_FOCUS (1 << 29) -#define STATUS3_POWER_TRICK (1 << 30) -#define STATUS3_SKY_DROPPED (1 << 31) // Target of Sky Drop -#define STATUS3_SEMI_INVULNERABLE_NO_COMMANDER (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE) // Exception for Transform / Imposter -#define STATUS3_SEMI_INVULNERABLE (STATUS3_SEMI_INVULNERABLE_NO_COMMANDER | STATUS3_COMMANDER) +enum SemiInvulnerableState +{ + STATE_NONE, + STATE_UNDERGROUND, + STATE_UNDERWATER, + STATE_ON_AIR, + STATE_PHANTOM_FORCE, + STATE_SKY_DROP, + STATE_COMMANDER, +}; -#define STATUS4_ELECTRIFIED (1 << 0) -#define STATUS4_MUD_SPORT (1 << 1) // Only used if B_SPORT_TURNS < GEN_6 -#define STATUS4_WATER_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6 -#define STATUS4_INFINITE_CONFUSION (1 << 3) // Used for Berserk Gene -#define STATUS4_SALT_CURE (1 << 4) -#define STATUS4_SYRUP_BOMB (1 << 5) -#define STATUS4_GLAIVE_RUSH (1 << 6) +enum SemiInvulnerableExclusion +{ + CHECK_ALL, + EXCLUDE_COMMANDER, +}; #define HITMARKER_STRING_PRINTED (1 << 4) #define HITMARKER_IGNORE_BIDE (1 << 5) #define HITMARKER_DESTINYBOND (1 << 6) #define HITMARKER_NO_ANIMATIONS (1 << 7) // set from battleSceneOff. Never changed during battle #define HITMARKER_IGNORE_SUBSTITUTE (1 << 8) -#define HITMARKER_NO_ATTACKSTRING (1 << 9) -#define HITMARKER_ATTACKSTRING_PRINTED (1 << 10) -#define HITMARKER_NO_PPDEDUCT (1 << 11) +#define HITMARKER_ATTACKSTRING_PRINTED (1 << 9) +#define HITMARKER_UNUSED_10 (1 << 10) +#define HITMARKER_UNUSED_11 (1 << 11) #define HITMARKER_UNUSED_12 (1 << 12) #define HITMARKER_STATUS_ABILITY_EFFECT (1 << 13) #define HITMARKER_UNUSED_14 (1 << 14) @@ -277,10 +258,10 @@ enum Volatile #define HITMARKER_DISABLE_ANIMATION (1 << 17) // disable animations during battle scripts, e.g. for Bug Bite #define HITMARKER_UNUSED_18 (1 << 18) #define HITMARKER_UNABLE_TO_USE_MOVE (1 << 19) -#define HITMARKER_PASSIVE_DAMAGE (1 << 20) +#define HITMARKER_PASSIVE_HP_UPDATE (1 << 20) #define HITMARKER_UNUSED_21 (1 << 21) #define HITMARKER_PLAYER_FAINTED (1 << 22) -#define HITMARKER_ALLOW_NO_PP (1 << 23) +#define HITMARKER_UNUSED_23 (1 << 23) #define HITMARKER_GRUDGE (1 << 24) #define HITMARKER_OBEYS (1 << 25) #define HITMARKER_UNUSED_26 (1 << 26) @@ -291,27 +272,33 @@ enum Volatile // Per-side statuses that affect an entire party #define SIDE_STATUS_REFLECT (1 << 0) #define SIDE_STATUS_LIGHTSCREEN (1 << 1) -#define SIDE_STATUS_STICKY_WEB (1 << 2) -#define SIDE_STATUS_SPIKES (1 << 4) -#define SIDE_STATUS_SAFEGUARD (1 << 5) -#define SIDE_STATUS_FUTUREATTACK (1 << 6) -#define SIDE_STATUS_MIST (1 << 8) -// (1 << 9) previously was SIDE_STATUS_SPIKES_DAMAGED -#define SIDE_STATUS_TAILWIND (1 << 10) -#define SIDE_STATUS_AURORA_VEIL (1 << 11) -#define SIDE_STATUS_LUCKY_CHANT (1 << 12) -#define SIDE_STATUS_TOXIC_SPIKES (1 << 13) -#define SIDE_STATUS_STEALTH_ROCK (1 << 14) -// Missing flags previously were SIDE_STATUS_TOXIC_SPIKES_DAMAGED, SIDE_STATUS_STEALTH_ROCK_DAMAGED, SIDE_STATUS_STICKY_WEB_DAMAGED -#define SIDE_STATUS_STEELSURGE (1 << 18) -#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 19) -#define SIDE_STATUS_RAINBOW (1 << 20) -#define SIDE_STATUS_SEA_OF_FIRE (1 << 21) -#define SIDE_STATUS_SWAMP (1 << 22) +#define SIDE_STATUS_SAFEGUARD (1 << 2) +#define SIDE_STATUS_FUTUREATTACK (1 << 3) +#define SIDE_STATUS_MIST (1 << 4) +#define SIDE_STATUS_TAILWIND (1 << 5) +#define SIDE_STATUS_AURORA_VEIL (1 << 6) +#define SIDE_STATUS_LUCKY_CHANT (1 << 7) +#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 8) +#define SIDE_STATUS_RAINBOW (1 << 9) +#define SIDE_STATUS_SEA_OF_FIRE (1 << 10) +#define SIDE_STATUS_SWAMP (1 << 11) -#define SIDE_STATUS_HAZARDS_ANY (SIDE_STATUS_SPIKES | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE) #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) #define SIDE_STATUS_PLEDGE_ANY (SIDE_STATUS_RAINBOW | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) +#define SIDE_STATUS_GOOD_FOG (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) +#define SIDE_STATUS_GOOD_COURT (SIDE_STATUS_GOOD_FOG | SIDE_STATUS_TAILWIND | SIDE_STATUS_LUCKY_CHANT | SIDE_STATUS_RAINBOW) +#define SIDE_STATUS_BAD_COURT (SIDE_STATUS_DAMAGE_NON_TYPES | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) + +enum Hazards +{ + HAZARDS_NONE, + HAZARDS_SPIKES, + HAZARDS_STICKY_WEB, + HAZARDS_TOXIC_SPIKES, + HAZARDS_STEALTH_ROCK, + HAZARDS_STEELSURGE, + HAZARDS_MAX_COUNT, +}; // Used for damaging entry hazards based on type enum TypeSideHazard @@ -347,6 +334,7 @@ enum TypeSideHazard #define MOVE_RESULT_FOE_HUNG_ON (1 << 7) #define MOVE_RESULT_STURDIED (1 << 8) #define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) +#define MOVE_RESULT_SYNCHRONOISE_AFFECTED (1 << 10) #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) enum BattleWeather @@ -380,18 +368,22 @@ enum BattleWeather #define B_WEATHER_STRONG_WINDS (1 << BATTLE_WEATHER_STRONG_WINDS) #define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) +#define B_WEATHER_DAMAGING_ANY (B_WEATHER_HAIL | B_WEATHER_SANDSTORM) +#define B_WEATHER_ICY_ANY (B_WEATHER_HAIL | B_WEATHER_SNOW) +#define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) -enum MoveEffects +// Explicit numbers until frostbite because those shouldn't be shifted +enum __attribute__((packed)) MoveEffect { - MOVE_EFFECT_NONE, - MOVE_EFFECT_SLEEP, - MOVE_EFFECT_POISON, - MOVE_EFFECT_BURN, - MOVE_EFFECT_FREEZE, - MOVE_EFFECT_PARALYSIS, - MOVE_EFFECT_TOXIC, - MOVE_EFFECT_FROSTBITE, + MOVE_EFFECT_NONE = 0, + MOVE_EFFECT_SLEEP = 1, + MOVE_EFFECT_POISON = 2, + MOVE_EFFECT_BURN = 3, + MOVE_EFFECT_FREEZE = 4, + MOVE_EFFECT_PARALYSIS = 5, + MOVE_EFFECT_TOXIC = 6, + MOVE_EFFECT_FROSTBITE = 7, MOVE_EFFECT_CONFUSION, MOVE_EFFECT_FLINCH, MOVE_EFFECT_TRI_ATTACK, @@ -415,7 +407,6 @@ enum MoveEffects MOVE_EFFECT_REMOVE_ARG_TYPE, MOVE_EFFECT_RECHARGE, MOVE_EFFECT_RAGE, - MOVE_EFFECT_STEAL_ITEM, MOVE_EFFECT_PREVENT_ESCAPE, MOVE_EFFECT_NIGHTMARE, MOVE_EFFECT_ALL_STATS_UP, @@ -451,8 +442,6 @@ enum MoveEffects MOVE_EFFECT_TRAP_BOTH, MOVE_EFFECT_ROUND, MOVE_EFFECT_DIRE_CLAW, - MOVE_EFFECT_STEALTH_ROCK, - MOVE_EFFECT_SPIKES, MOVE_EFFECT_SYRUP_BOMB, MOVE_EFFECT_FLORAL_HEALING, MOVE_EFFECT_SECRET_POWER, @@ -466,6 +455,11 @@ enum MoveEffects MOVE_EFFECT_LIGHT_SCREEN, MOVE_EFFECT_SALT_CURE, MOVE_EFFECT_EERIE_SPELL, + + // Max move effects happen earlier in the execution chain. + // For example stealth rock from G-Max Stonesurge is set up before abilities but from Stone Axe after. + // Stone Axe can also fail to set up rocks if user faints where as Stonesurge will always go up. + // This means we need to be careful if we want to re-use those effects for (new) vanilla moves MOVE_EFFECT_RAISE_TEAM_ATTACK, MOVE_EFFECT_RAISE_TEAM_DEFENSE, MOVE_EFFECT_RAISE_TEAM_SPEED, @@ -507,11 +501,14 @@ enum MoveEffects MOVE_EFFECT_LOWER_EVASIVENESS_SIDE, MOVE_EFFECT_AROMATHERAPY, MOVE_EFFECT_CONFUSE_SIDE, - MOVE_EFFECT_STEELSURGE, + MOVE_EFFECT_STEELSURGE, // Steel type rocks + MOVE_EFFECT_STEALTH_ROCK, // Max Move rocks, not to be confused for rocks set up from Ceasless Edge (same but differ in execution order) MOVE_EFFECT_TORMENT_SIDE, MOVE_EFFECT_LOWER_SPEED_2_SIDE, MOVE_EFFECT_FIRE_SPIN_SIDE, MOVE_EFFECT_FIXED_POWER, + // Max move effects end. They can be used for (custom) normal moves. + NUM_MOVE_EFFECTS }; @@ -687,4 +684,18 @@ enum MonState MON_OUTSIDE_BATTLE, }; +enum __attribute__((packed)) CalcDamageState +{ + CAN_DAMAGE, + WILL_FAIL, + CHECK_ACCURACY, +}; + +enum SubmoveState +{ + SUBMOVE_NO_EFFECT, + SUBMOVE_SUCCESS, + SUBMOVE_FAILURE, +}; + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 1f19d3e96..c6277bf9b 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -3,52 +3,53 @@ // AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts // See docs/ai_flags.md for more details. -#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. -#define AI_FLAG_TRY_TO_FAINT (1 << 1) // AI will prioritize KOing the player's mon if able. -#define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation. -#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. -#define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. -#define AI_FLAG_TRY_TO_2HKO (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. -#define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass. -#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner. -#define AI_FLAG_HP_AWARE (1 << 8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. -#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target. +#define AI_FLAG(x) ((u64)1 << x) + +#define AI_FLAG_CHECK_BAD_MOVE AI_FLAG(0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. +#define AI_FLAG_TRY_TO_FAINT AI_FLAG(1) // AI will prioritize KOing the player's mon if able. +#define AI_FLAG_CHECK_VIABILITY AI_FLAG(2) // AI damaging moves and move effects to determine the best available move in the current situation. +#define AI_FLAG_FORCE_SETUP_FIRST_TURN AI_FLAG(3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. +#define AI_FLAG_RISKY AI_FLAG(4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. +#define AI_FLAG_TRY_TO_2HKO AI_FLAG(5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. +#define AI_FLAG_PREFER_BATON_PASS AI_FLAG(6) // AI prefers raising its own stats and setting for / using Baton Pass. +#define AI_FLAG_DOUBLE_BATTLE AI_FLAG(7) // Automatically set for double battles, handles AI behaviour with partner. +#define AI_FLAG_HP_AWARE AI_FLAG(8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. +#define AI_FLAG_POWERFUL_STATUS AI_FLAG(9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target. // New, Trainer Handicap Flags -#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc. -#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc. +#define AI_FLAG_NEGATE_UNAWARE AI_FLAG(10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc. +#define AI_FLAG_WILL_SUICIDE AI_FLAG(11) // AI will use explosion / self destruct / final gambit / etc. // New, Trainer Strategy Flags -#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves. -#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished. -#define AI_FLAG_SMART_SWITCHING (1 << 14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES. -#define AI_FLAG_ACE_POKEMON (1 << 15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. -#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items. -#define AI_FLAG_SMART_MON_CHOICES (1 << 17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING. -#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage. -#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle. -#define AI_FLAG_DOUBLE_ACE_POKEMON (1 << 20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. -#define AI_FLAG_WEIGH_ABILITY_PREDICTION (1 << 21) // AI will predict player's ability based on aiRating -#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect -#define AI_FLAG_PREDICT_SWITCH (1 << 23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT -#define AI_FLAG_PREDICT_INCOMING_MON (1 << 24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH -#define AI_FLAG_PP_STALL_PREVENTION (1 << 25) // AI keeps track of the player's switches where the incoming mon is immune to the chosen move -#define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT -#define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). - -#define AI_FLAG_COUNT 28 - -// Flags at and after 32 need different formatting, as in -// #define AI_FLAG_PLACEHOLDER ((u64)1 << 32) +#define AI_FLAG_PREFER_STATUS_MOVES AI_FLAG(12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves. +#define AI_FLAG_STALL AI_FLAG(13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished. +#define AI_FLAG_SMART_SWITCHING AI_FLAG(14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES. +#define AI_FLAG_ACE_POKEMON AI_FLAG(15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. +#define AI_FLAG_OMNISCIENT AI_FLAG(16) // AI has full knowledge of player moves, abilities, hold items. +#define AI_FLAG_SMART_MON_CHOICES AI_FLAG(17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING. +#define AI_FLAG_CONSERVATIVE AI_FLAG(18) // AI assumes all moves will low roll damage. +#define AI_FLAG_SEQUENCE_SWITCHING AI_FLAG(19) // AI switches in mons in exactly party order, and never switches mid-battle. +#define AI_FLAG_DOUBLE_ACE_POKEMON AI_FLAG(20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. +#define AI_FLAG_WEIGH_ABILITY_PREDICTION AI_FLAG(21) // AI will predict player's ability based on aiRating +#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE AI_FLAG(22) // AI adds score to highest damage move regardless of accuracy or secondary effect +#define AI_FLAG_PREDICT_SWITCH AI_FLAG(23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT +#define AI_FLAG_PREDICT_INCOMING_MON AI_FLAG(24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH +#define AI_FLAG_PP_STALL_PREVENTION AI_FLAG(25) // AI keeps track of the player's switches where the incoming mon is immune to the chosen move +#define AI_FLAG_PREDICT_MOVE AI_FLAG(26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT +#define AI_FLAG_SMART_TERA AI_FLAG(27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). +#define AI_FLAG_ASSUME_STAB AI_FLAG(28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ASSUME_STATUS_MOVES AI_FLAG(29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ATTACKS_PARTNER AI_FLAG(30) // AI specific to double battles; AI can deliberately attack its 'partner.' // The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag #define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY) #define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION | AI_FLAG_SMART_TERA) #define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON | AI_FLAG_PREDICT_MOVE) +#define AI_FLAG_ASSUMPTIONS (AI_FLAG_ASSUME_STAB | AI_FLAG_ASSUME_STATUS_MOVES | AI_FLAG_WEIGH_ABILITY_PREDICTION) // 'other' ai logic flags -#define AI_FLAG_DYNAMIC_FUNC ((u64)1 << 60) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd -#define AI_FLAG_ROAMING ((u64)1 << 61) -#define AI_FLAG_SAFARI ((u64)1 << 62) -#define AI_FLAG_FIRST_BATTLE ((u64)1 << 63) +#define AI_FLAG_DYNAMIC_FUNC AI_FLAG(60) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd +#define AI_FLAG_ROAMING AI_FLAG(61) +#define AI_FLAG_SAFARI AI_FLAG(62) +#define AI_FLAG_FIRST_BATTLE AI_FLAG(63) #define AI_SCORE_DEFAULT 100 // Default score for all AI moves. diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index ae69b5ccf..4e38768ac 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -419,6 +419,10 @@ #define ANIM_TAG_PINKVIO_ORB (ANIM_SPRITES_START + 405) #define ANIM_TAG_STARSTORM (ANIM_SPRITES_START + 406) #define ANIM_TAG_SALT_PARTICLE (ANIM_SPRITES_START + 407) +#define ANIM_TAG_TERA_SYMBOL (ANIM_SPRITES_START + 408) +#define ANIM_TAG_TATSUGIRI_CURLY (ANIM_SPRITES_START + 409) +#define ANIM_TAG_TATSUGIRI_DROOPY (ANIM_SPRITES_START + 410) +#define ANIM_TAG_TATSUGIRI_STRETCHY (ANIM_SPRITES_START + 411) // battlers #define ANIM_ATTACKER 0 @@ -588,9 +592,9 @@ #define B_ANIM_SIMPLE_HEAL 52 #define B_ANIM_POWER_CONSTRUCT 53 // pokefirered -#define B_ANIM_MON_SCARED (B_ANIM_POWER_CONSTRUCT + 1) -#define B_ANIM_GHOST_GET_OUT (B_ANIM_MON_SCARED + 1) -#define B_ANIM_SILPH_SCOPED (B_ANIM_GHOST_GET_OUT + 1) +#define B_ANIM_MON_SCARED 54 +#define B_ANIM_GHOST_GET_OUT 55 +#define B_ANIM_SILPH_SCOPED 56 #define B_ANIM_ROCK_THROW (B_ANIM_SILPH_SCOPED + 1) #define B_ANIM_SAFARI_REACTION (B_ANIM_ROCK_THROW + 1) @@ -618,8 +622,9 @@ #define B_ANIM_STATUS_FRZ 6 #define B_ANIM_STATUS_CURSED 7 #define B_ANIM_STATUS_NIGHTMARE 8 +#define B_ANIM_STATUS_FRB 9 -#define NUM_B_ANIMS_STATUS 9 +#define NUM_B_ANIMS_STATUS 10 // Tasks with return values often assign them to gBattleAnimArgs[7]. #define ARG_RET_ID 7 @@ -663,6 +668,12 @@ #define ANIM_SURF_PAL_MUDDY_WATER 1 #define ANIM_SURF_PAL_SLUDGE_WAVE 2 +// Order Up palettes for Commander +#define ANIM_ORDER_UP_NONE 0 +#define ANIM_ORDER_UP_CURLY 1 +#define ANIM_ORDER_UP_DROOPY 2 +#define ANIM_ORDER_UP_STRETCHY 3 + // Flags given to various functions to indicate which palettes to consider. // Handled by UnpackSelectedBattlePalettes #define F_PAL_BG (1 << 0) diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index f77a0d979..2ddb75adf 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -1,7 +1,7 @@ #ifndef GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H #define GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H -enum BattleMoveEffects +enum __attribute__((packed)) BattleMoveEffects { EFFECT_PLACEHOLDER, EFFECT_HIT, @@ -9,7 +9,7 @@ enum BattleMoveEffects EFFECT_ABSORB, EFFECT_EXPLOSION, EFFECT_MISTY_EXPLOSION, // Same as EFFECT_EXPLOSION but it's boosted on Misty Terrain - EFFECT_DREAM_EATER, + EFFECT_DREAM_EATER, // Same as EFFECT_ABSORB but it can only be used on sleeping targets EFFECT_MIRROR_MOVE, EFFECT_ATTACK_UP, EFFECT_DEFENSE_UP, @@ -157,6 +157,7 @@ enum BattleMoveEffects EFFECT_BRICK_BREAK, EFFECT_YAWN, EFFECT_KNOCK_OFF, + EFFECT_STEAL_ITEM, EFFECT_ENDEAVOR, EFFECT_POWER_BASED_ON_USER_HP, EFFECT_SKILL_SWAP, @@ -310,7 +311,7 @@ enum BattleMoveEffects EFFECT_MAX_HP_50_RECOIL, EFFECT_CHLOROBLAST, // Same effect as EFFECT_MAX_HP_50_RECOIL but follows the same rules as EFFECT_RECOIL EFFECT_EXTREME_EVOBOOST, - EFFECT_HIT_SET_REMOVE_TERRAIN, + EFFECT_HIT_SET_TERRAIN, EFFECT_DARK_VOID, EFFECT_VICTORY_DANCE, EFFECT_TEATIME, @@ -348,6 +349,11 @@ enum BattleMoveEffects EFFECT_SPECTRAL_THIEF, EFFECT_RECOIL, EFFECT_SMACK_DOWN, + EFFECT_LIFE_DEW, + EFFECT_ICE_SPINNER, // Removes terrain unless attacker is removed from field either by fainting or ejected out + EFFECT_STEEL_ROLLER, // Will fail if there is no terrain up but removes it regardless if attacker is removed from field or not + EFFECT_STONE_AXE, // Not to be confused with MOVE_EFFECT_STEALTH_ROCK. They have two different activation timings. + EFFECT_CEASELESS_EDGE, // Same applies to spikes NUM_BATTLE_MOVE_EFFECTS, }; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 43e8bf94c..d00b8331d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -33,7 +33,7 @@ #define sSAVED_DMG (gBattleScripting + 0x28) // savedDmg #define sSAVED_MOVE_EFFECT (gBattleScripting + 0x2C) // savedMoveEffect #define sMOVE_EFFECT (gBattleScripting + 0x2E) // moveEffect -#define sMULTIHIT_EFFECT (gBattleScripting + 0x30) // multihitMoveEffect +#define sUNUSED_0x30 (gBattleScripting + 0x30) // unused_0x30 #define sILLUSION_NICK_HACK (gBattleScripting + 0x32) // illusionNickHack #define sFIXED_ABILITY_POPUP (gBattleScripting + 0x33) // fixedPopup #define sABILITY_OVERWRITE (gBattleScripting + 0x34) // abilityPopupOverwrite @@ -88,126 +88,10 @@ #define CMP_COMMON_BITS 4 #define CMP_NO_COMMON_BITS 5 +// Veriouses have been deprecated but the enum and function will be supported for one more release cycle enum CmdVarious { - VARIOUS_CANCEL_MULTI_TURN_MOVES, - VARIOUS_IS_RUNNING_IMPOSSIBLE, - VARIOUS_GET_MOVE_TARGET, - VARIOUS_GET_BATTLER_FAINTED, - VARIOUS_RESET_SWITCH_IN_ABILITY_BITS, - VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP, - VARIOUS_RESET_PLAYER_FAINTED, - VARIOUS_PALACE_FLAVOR_TEXT, - VARIOUS_ARENA_JUDGMENT_WINDOW, - VARIOUS_ARENA_OPPONENT_MON_LOST, - VARIOUS_ARENA_PLAYER_MON_LOST, - VARIOUS_ARENA_BOTH_MONS_LOST, - VARIOUS_EMIT_YESNOBOX, - VARIOUS_DRAW_ARENA_REF_TEXT_BOX, - VARIOUS_ERASE_ARENA_REF_TEXT_BOX, - VARIOUS_ARENA_JUDGMENT_STRING, - VARIOUS_ARENA_WAIT_STRING, - VARIOUS_WAIT_CRY, - VARIOUS_RETURN_OPPONENT_MON1, - VARIOUS_RETURN_OPPONENT_MON2, - VARIOUS_VOLUME_DOWN, - VARIOUS_VOLUME_UP, - VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT, - VARIOUS_PALACE_TRY_ESCAPE_STATUS, - VARIOUS_SET_TELEPORT_OUTCOME, - VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC, - VARIOUS_STAT_TEXT_BUFFER, - VARIOUS_SWITCHIN_ABILITIES, - VARIOUS_INSTANT_HP_DROP, - VARIOUS_CLEAR_STATUS, - VARIOUS_RESTORE_PP, - VARIOUS_PLAY_MOVE_ANIMATION, - VARIOUS_SET_LUCKY_CHANT, - VARIOUS_SUCKER_PUNCH_CHECK, - VARIOUS_SET_SIMPLE_BEAM, - VARIOUS_TRY_ENTRAINMENT, - VARIOUS_SET_LAST_USED_ABILITY, - VARIOUS_INVERT_STAT_STAGES, - VARIOUS_TRY_ME_FIRST, - VARIOUS_JUMP_IF_BATTLE_END, - VARIOUS_TRY_ELECTRIFY, - VARIOUS_TRY_SOAK, - VARIOUS_TRY_LAST_RESORT, - VARIOUS_TRY_AUTOTOMIZE, - VARIOUS_ABILITY_POPUP, - VARIOUS_JUMP_IF_TARGET_ALLY, - VARIOUS_TRY_SYNCHRONOISE, - VARIOUS_PSYCHO_SHIFT, - VARIOUS_CURE_STATUS, - VARIOUS_POWER_TRICK, - VARIOUS_AFTER_YOU, - VARIOUS_BESTOW, - VARIOUS_JUMP_IF_NOT_GROUNDED, - VARIOUS_HANDLE_TRAINER_SLIDE_MSG, - VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF, - VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON, - VARIOUS_SET_AURORA_VEIL, - VARIOUS_TRY_THIRD_TYPE, - VARIOUS_ACUPRESSURE, - VARIOUS_SET_POWDER, - VARIOUS_GRAVITY_ON_AIRBORNE_MONS, - VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, - VARIOUS_JUMP_IF_ROAR_FAILS, - VARIOUS_TRY_INSTRUCT, - VARIOUS_JUMP_IF_NOT_BERRY, - VARIOUS_TRACE_ABILITY, - VARIOUS_UPDATE_NICK, - VARIOUS_TRY_ILLUSION_OFF, - VARIOUS_SET_SPRITEIGNORE0HP, - VARIOUS_HANDLE_FORM_CHANGE, - VARIOUS_GET_STAT_VALUE, - VARIOUS_JUMP_IF_FULL_HP, - VARIOUS_LOSE_TYPE, - VARIOUS_TRY_ACTIVATE_SOULHEART, - VARIOUS_TRY_ACTIVATE_RECEIVER, - VARIOUS_TRY_FRISK, - VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, - VARIOUS_TRY_FAIRY_LOCK, - VARIOUS_JUMP_IF_NO_ALLY, - VARIOUS_JUMP_IF_HOLD_EFFECT, - VARIOUS_INFATUATE_WITH_BATTLER, - VARIOUS_SET_LAST_USED_ITEM, - VARIOUS_JUMP_IF_ABSENT, - VARIOUS_DESTROY_ABILITY_POPUP, - VARIOUS_TOTEM_BOOST, - VARIOUS_MOVEEND_ITEM_EFFECTS, - VARIOUS_TERRAIN_SEED, - VARIOUS_MAKE_INVISIBLE, - VARIOUS_ROOM_SERVICE, - VARIOUS_JUMP_IF_TEAM_HEALTHY, - VARIOUS_TRY_HEAL_QUARTER_HP, - VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, - VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, - VARIOUS_GET_ROTOTILLER_TARGETS, - VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, - VARIOUS_CONSUME_BERRY, - VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, - VARIOUS_JUMP_IF_SPECIES, - VARIOUS_UPDATE_ABILITY_POPUP, - VARIOUS_JUMP_IF_WEATHER_AFFECTED, - VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED, - VARIOUS_SET_ATTACKER_STICKY_WEB_USER, - VARIOUS_TRY_NO_RETREAT, - VARIOUS_CHECK_POLTERGEIST, - VARIOUS_CUT_1_3_HP_RAISE_STATS, - VARIOUS_TRY_END_NEUTRALIZING_GAS, - VARIOUS_JUMP_IF_UNDER_200, - VARIOUS_SET_SKY_DROP, - VARIOUS_CLEAR_SKY_DROP, - VARIOUS_SKY_DROP_YAWN, - VARIOUS_CURE_CERTAIN_STATUSES, - VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES, - VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY, - VARIOUS_SAVE_BATTLER_ITEM, - VARIOUS_RESTORE_BATTLER_ITEM, - VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, - // pokefirered - VARIOUS_GET_BATTLERS_FOR_RECALL, // for battle tower + VARIOUS_NONE, }; // Cmd_manipulatedamage @@ -241,10 +125,10 @@ enum CmdVarious #define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen -// cases for Cmd_moveend +// cases for Cmd_moveend - Order matters! enum MoveEndEffects { - MOVEEND_SUM_DAMAGE, + MOVEEND_SET_VALUES, MOVEEND_PROTECT_LIKE_EFFECT, MOVEEND_ABSORB, MOVEEND_RAGE, @@ -253,12 +137,10 @@ enum MoveEndEffects MOVEEND_ABILITIES_ATTACKER, MOVEEND_STATUS_IMMUNITY_ABILITIES, MOVEEND_SYNCHRONIZE_ATTACKER, - MOVEEND_CHOICE_MOVE, MOVEEND_ATTACKER_INVISIBLE, MOVEEND_ATTACKER_VISIBLE, MOVEEND_TARGET_VISIBLE, MOVEEND_ITEM_EFFECTS_TARGET, - MOVEEND_FIRST_MOVE_BLOCK, MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_SYMBIOSIS, MOVEEND_KINGSROCK, // These item effects will occur each strike of a multi-hit move @@ -269,20 +151,23 @@ enum MoveEndEffects MOVEEND_DEFROST, MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move MOVEEND_MULTIHIT_MOVE, - MOVEEND_SECOND_MOVE_BLOCK, + MOVEEND_MOVE_BLOCK, MOVEEND_ITEM_EFFECTS_ATTACKER, MOVEEND_ABILITY_BLOCK, MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Opportunist - MOVEEND_RED_CARD, // Red Card triggers before Eject Pack + MOVEEND_COLOR_CHANGE, // Color Change / Berserk / Anger Shell + MOVEEND_RED_CARD, MOVEEND_EJECT_BUTTON, - MOVEEND_LIFEORB_SHELLBELL, // Includes shell bell, throat spray, etc + MOVEEND_LIFEORB_SHELLBELL, MOVEEND_FORM_CHANGE, MOVEEND_EMERGENCY_EXIT, MOVEEND_EJECT_PACK, MOVEEND_HIT_ESCAPE, - MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts + MOVEEND_OPPORTUNIST, + MOVEEND_MIRROR_HERB, MOVEEND_PICKPOCKET, MOVEEND_WHITE_HERB, + MOVEEND_THIRD_MOVE_BLOCK, MOVEEND_CHANGED_ITEMS, MOVEEND_SAME_MOVE_TURNS, MOVEEND_CLEAR_BITS, @@ -296,11 +181,6 @@ enum MoveEndEffects #define B_SWITCH_HIT 1 // dragon tail, circle throw #define B_SWITCH_RED_CARD 2 -// Argument labels for EFFECT_HIT_SET_REMOVE_TERRAIN -#define ARG_SET_PSYCHIC_TERRAIN 0 -#define ARG_TRY_REMOVE_TERRAIN_HIT 1 -#define ARG_TRY_REMOVE_TERRAIN_FAIL 2 - enum StatusTrigger { TRIGGER_ON_MOVE, diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 3bc3d9a2a..cbc815215 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -41,7 +41,6 @@ enum StringID STRINGID_PKMNMADESLEEP, STRINGID_PKMNALREADYASLEEP, STRINGID_PKMNALREADYASLEEP2, - STRINGID_PKMNWASNTAFFECTED, STRINGID_PKMNWASPOISONED, STRINGID_PKMNPOISONEDBY, STRINGID_PKMNHURTBYPOISON, @@ -62,11 +61,8 @@ enum StringID STRINGID_PKMNISPARALYZED, STRINGID_PKMNISALREADYPARALYZED, STRINGID_PKMNHEALEDPARALYSIS, - STRINGID_PKMNDREAMEATEN, STRINGID_STATSWONTINCREASE, STRINGID_STATSWONTDECREASE, - STRINGID_TEAMSTOPPEDWORKING, - STRINGID_FOESTOPPEDWORKING, STRINGID_PKMNISCONFUSED, STRINGID_PKMNHEALEDCONFUSION, STRINGID_PKMNWASCONFUSED, @@ -74,7 +70,6 @@ enum StringID STRINGID_PKMNFELLINLOVE, STRINGID_PKMNINLOVE, STRINGID_PKMNIMMOBILIZEDBYLOVE, - STRINGID_PKMNBLOWNAWAY, STRINGID_PKMNCHANGEDTYPE, STRINGID_PKMNFLINCHED, STRINGID_PKMNREGAINEDHEALTH, @@ -118,7 +113,6 @@ enum StringID STRINGID_PKMNCALMEDDOWN, STRINGID_PKMNCANTSLEEPINUPROAR, STRINGID_PKMNSTOCKPILED, - STRINGID_PKMNCANTSTOCKPILE, STRINGID_PKMNCANTSLEEPINUPROAR2, STRINGID_UPROARKEPTPKMNAWAKE, STRINGID_PKMNSTAYEDAWAKEUSING, @@ -180,7 +174,6 @@ enum StringID STRINGID_PKMNREADYTOHELP, STRINGID_PKMNSWITCHEDITEMS, STRINGID_PKMNCOPIEDFOE, - STRINGID_PKMNMADEWISH, STRINGID_PKMNWISHCAMETRUE, STRINGID_PKMNPLANTEDROOTS, STRINGID_PKMNABSORBEDNUTRIENTS, @@ -197,14 +190,11 @@ enum StringID STRINGID_PKMNWAITSFORTARGET, STRINGID_PKMNSNATCHEDMOVE, STRINGID_PKMNMADEITRAIN, - STRINGID_PKMNRAISEDSPEED, STRINGID_PKMNPROTECTEDBY, STRINGID_PKMNPREVENTSUSAGE, STRINGID_PKMNRESTOREDHPUSING, STRINGID_PKMNCHANGEDTYPEWITH, - STRINGID_PKMNPREVENTSPARALYSISWITH, STRINGID_PKMNPREVENTSROMANCEWITH, - STRINGID_PKMNPREVENTSPOISONINGWITH, STRINGID_PKMNPREVENTSCONFUSIONWITH, STRINGID_PKMNRAISEDFIREPOWERWITH, STRINGID_PKMNANCHORSITSELFWITH, @@ -234,7 +224,6 @@ enum StringID STRINGID_BUTNOTHINGHAPPENED, STRINGID_BUTITFAILED, STRINGID_ITHURTCONFUSION, - STRINGID_MIRRORMOVEFAILED, STRINGID_STARTEDTORAIN, STRINGID_DOWNPOURSTARTED, STRINGID_RAINCONTINUES, @@ -249,9 +238,6 @@ enum StringID STRINGID_STARTEDHAIL, STRINGID_HAILCONTINUES, STRINGID_HAILSTOPPED, - STRINGID_FAILEDTOSPITUP, - STRINGID_FAILEDTOSWALLOW, - STRINGID_WINDBECAMEHEATWAVE, STRINGID_STATCHANGESGONE, STRINGID_COINSSCATTERED, STRINGID_TOOWEAKFORSUBSTITUTE, @@ -308,7 +294,6 @@ enum StringID STRINGID_ITEMALLOWSONLYYMOVE, STRINGID_PKMNHUNGONWITHX, STRINGID_EMPTYSTRING3, - STRINGID_PKMNSXPREVENTSBURNS, STRINGID_PKMNSXBLOCKSY, STRINGID_PKMNSXRESTOREDHPALITTLE2, STRINGID_PKMNSXWHIPPEDUPSANDSTORM, @@ -327,8 +312,8 @@ enum StringID STRINGID_PLAYERDEFEATEDTRAINER1, STRINGID_SOOTHINGAROMA, STRINGID_ITEMSCANTBEUSEDNOW, - STRINGID_FORXCOMMAYZ, STRINGID_USINGITEMSTATOFPKMNROSE, + STRINGID_USINGITEMSTATOFPKMNFELL, STRINGID_PKMNUSEDXTOGETPUMPED, STRINGID_PKMNSXMADEYUSELESS, STRINGID_PKMNTRAPPEDBYSANDTOMB, @@ -344,7 +329,6 @@ enum StringID STRINGID_PKMNFLEDUSINGITS, STRINGID_PKMNFLEDUSING, STRINGID_PKMNWASDRAGGEDOUT, - STRINGID_PREVENTEDFROMWORKING, STRINGID_PKMNSITEMNORMALIZEDSTATUS, STRINGID_TRAINER1USEDITEM, STRINGID_BOXISFULL, @@ -355,17 +339,13 @@ enum StringID STRINGID_STATSWONTDECREASE2, STRINGID_PKMNSXBLOCKSY2, STRINGID_PKMNSXWOREOFF, - STRINGID_PKMNRAISEDDEFALITTLE, - STRINGID_PKMNRAISEDSPDEFALITTLE, STRINGID_THEWALLSHATTERED, - STRINGID_PKMNSXPREVENTSYSZ, STRINGID_PKMNSXCUREDITSYPROBLEM, STRINGID_ATTACKERCANTESCAPE, STRINGID_PKMNOBTAINEDX, STRINGID_PKMNOBTAINEDX2, STRINGID_PKMNOBTAINEDXYOBTAINEDZ, STRINGID_BUTNOEFFECT, - STRINGID_PKMNSXHADNOEFFECTONY, STRINGID_TWOENEMIESDEFEATED, STRINGID_TRAINER2LOSETEXT, STRINGID_PKMNINCAPABLEOFPOWER, @@ -424,10 +404,8 @@ enum StringID STRINGID_FELLSTRAIGHTDOWN, STRINGID_TARGETCHANGEDTYPE, STRINGID_PKMNACQUIREDSIMPLE, - STRINGID_EMPTYSTRING5, STRINGID_KINDOFFER, STRINGID_RESETSTARGETSSTATLEVELS, - STRINGID_EMPTYSTRING6, STRINGID_ALLYSWITCHPOSITION, STRINGID_RESTORETARGETSHEALTH, STRINGID_TOOKPJMNINTOTHESKY, @@ -481,7 +459,7 @@ enum StringID STRINGID_HEALINGWISHCAMETRUE, STRINGID_HEALINGWISHHEALED, STRINGID_LUNARDANCECAMETRUE, - STRINGID_CUSEDBODYDISABLED, + STRINGID_CURSEDBODYDISABLED, STRINGID_ATTACKERACQUIREDABILITY, STRINGID_TARGETABILITYSTATLOWER, STRINGID_TARGETSTATWONTGOHIGHER, @@ -558,10 +536,8 @@ enum StringID STRINGID_COMATOSEENTERS, STRINGID_SCREENCLEANERENTERS, STRINGID_FETCHEDPOKEBALL, - STRINGID_BATTLERABILITYRAISEDSTAT, STRINGID_ASANDSTORMKICKEDUP, STRINGID_PKMNSWILLPERISHIN3TURNS, - STRINGID_ABILITYRAISEDSTATDRASTICALLY, STRINGID_AURAFLAREDTOLIFE, STRINGID_ASONEENTERS, STRINGID_CURIOUSMEDICINEENTERS, @@ -598,7 +574,6 @@ enum StringID STRINGID_BROKETHROUGHPROTECTION, STRINGID_ABILITYALLOWSONLYMOVE, STRINGID_SWAPPEDABILITIES, - STRINGID_PASTELVEILPROTECTED, STRINGID_PASTELVEILENTERS, STRINGID_BATTLERTYPECHANGEDTO, STRINGID_BOTHCANNOLONGERESCAPE, @@ -766,33 +741,24 @@ enum StringID // They are assigned to the MULTISTRING_CHOOSER byte of gBattleCommunication // and read when e.g. the command printfromtable is used. -// gStatUpStringIds -enum StatUpStringID +// gStatUpStringIds and gStatDownStringIds +enum StatChangedStringID { - B_MSG_ATTACKER_STAT_ROSE, - B_MSG_DEFENDER_STAT_ROSE, - B_MSG_STAT_WONT_INCREASE, - B_MSG_STAT_ROSE_EMPTY, - B_MSG_STAT_ROSE_ITEM, + B_MSG_ATTACKER_STAT_CHANGED, + B_MSG_DEFENDER_STAT_CHANGED, + B_MSG_STAT_WONT_CHANGE, + B_MSG_STAT_CHANGE_EMPTY, + B_MSG_STAT_CHANGED_ITEM, B_MSG_USED_DIRE_HIT, }; -// gStatDownStringIds -enum StatDownStringID -{ - B_MSG_ATTACKER_STAT_FELL = 0, - B_MSG_DEFENDER_STAT_FELL = 1, - B_MSG_STAT_WONT_DECREASE, - B_MSG_STAT_FELL_EMPTY, -}; - // gMissStringIds enum MissStringID { B_MSG_MISSED, B_MSG_PROTECTED, B_MSG_AVOIDED_ATK, - // Ability-related messages need to below this comment + // Ability-related messages need to be below this comment B_MSG_AVOIDED_DMG, B_MSG_GROUND_MISS, }; @@ -908,20 +874,6 @@ enum UproarOverTurnStringID B_MSG_UPROAR_ENDS, }; -// gStockpileUsedStringIds -enum StockpileUsedStringID -{ - B_MSG_STOCKPILED, - B_MSG_CANT_STOCKPILE, -}; - -// gSwallowFailStringIds -enum SwallowFailStringID -{ - B_MSG_SWALLOW_FAILED, - B_MSG_SWALLOW_FULL_HP, -}; - // gKOFailedStringIds enum KOFailedStringID { @@ -1070,17 +1022,6 @@ enum GotStatusedStringID B_MSG_STATUSED_BY_ABILITY, }; -// gStatusPreventionStringIds -enum StatusPreventionStringID -{ - B_MSG_ABILITY_PREVENTS_MOVE_BURN, - B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS, - B_MSG_ABILITY_PREVENTS_MOVE_POISON, - B_MSG_ABILITY_PREVENTS_ABILITY_STATUS, - B_MSG_STATUS_HAD_NO_EFFECT, - B_MSG_ABILITY_PASTEL_VEIL, -}; - // gGotDefrostedStringIds enum GotDefrostedStringID { diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 1cf2d8007..b365a6ea8 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -20,6 +20,27 @@ enum GenConfigTag GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_CONFIG_ENCORE_TARGET, GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES, + GEN_PICKUP_WILD, + GEN_PROTEAN_LIBERO, + GEN_INTREPID_SWORD, + GEN_DAUNTLESS_SHIELD, + GEN_ILLUMINATE_EFFECT, + GEN_STEAL_WILD_ITEMS, + GEN_SNOW_WARNING, + GEN_ALLY_SWITCH_FAIL_CHANCE, + GEN_DREAM_EATER_LIQUID_OOZE, + GEN_CONFIG_TRANSISTOR_BOOST, + GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS, + GEN_CONFIG_UPDATED_INTIMIDATE, + GEN_CONFIG_DISGUISE_HP_LOSS, + GEN_CONFIG_AFTER_YOU_TURN_ORDER, + GEN_CONFIG_HEALING_WISH_SWITCH, + GEN_CONFIG_MEGA_EVO_TURN_ORDER, + GEN_CONFIG_SHEER_COLD_IMMUNITY, + GEN_CONFIG_WEAK_ARMOR_SPEED, + GEN_CONFIG_PRANKSTER_DARK_TYPES, + GEN_CONFIG_DESTINY_BOND_FAIL, + GEN_CONFIG_POWDER_RAIN, GEN_CONFIG_COUNT }; diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index c7ed81160..101a198b8 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -142,10 +142,9 @@ enum ItemHoldEffect HOLD_EFFECT_OGERPON_MASK, // Gen2 hold effect HOLD_EFFECT_BERSERK_GENE, + HOLD_EFFECT_COUNT }; -#define HOLD_EFFECT_CHOICE(holdEffect) ((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) - // Terrain seed params #define HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN 0 #define HOLD_EFFECT_PARAM_GRASSY_TERRAIN 1 diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index 996b5e4a6..dbe322bea 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -2,11 +2,11 @@ #define GUARD_CONSTANTS_ITEM_EFFECTS_H // field 0 masks -#define ITEM0_DIRE_HIT 0x30 // Works the same way as move Focus Energy. +#define ITEM0_DIRE_HIT 0x30 // Works the same way as the move Focus Energy. #define ITEM0_SACRED_ASH 0x40 #define ITEM0_INFATUATION 0x80 -// field 1 masks +// new field 1 masks #define ITEM1_X_ATTACK STAT_ATK #define ITEM1_X_DEFENSE STAT_DEF #define ITEM1_X_SPEED STAT_SPEED @@ -50,7 +50,7 @@ #define ITEM10_IS_VITAMIN 0x1 -// fields 6 and onwards are item-specific arguments +// fields 6 and onwards (except field 10) are item-specific arguments #define ITEM_EFFECT_ARG_START 6 // Special HP recovery amounts for ITEM4_HEAL_HP @@ -75,7 +75,7 @@ #define ITEM_EFFECT_CURE_POISON 3 #define ITEM_EFFECT_CURE_SLEEP 4 #define ITEM_EFFECT_CURE_BURN 5 -#define ITEM_EFFECT_CURE_FREEZE 6 +#define ITEM_EFFECT_CURE_FREEZE_FROSTBITE 6 #define ITEM_EFFECT_CURE_PARALYSIS 7 #define ITEM_EFFECT_CURE_CONFUSION 8 #define ITEM_EFFECT_CURE_INFATUATION 9 @@ -93,4 +93,8 @@ #define ITEM_EFFECT_HEAL_PP 21 #define ITEM_EFFECT_NONE 22 +// Since X item stat increases are now handled by battle scripts, the friendship increase effect is now handled by the battle controller in HandleAction_UseItem. +#define X_ITEM_FRIENDSHIP_INCREASE 1 // The amount of friendship gained by using an X item on a Pokémon in battle. +#define X_ITEM_MAX_FRIENDSHIP 200 // Friendship threshold at which Pokémon stop receiving a friendship increase from using X items on them in battle. + #endif // GUARD_CONSTANTS_ITEM_EFFECTS_H diff --git a/include/constants/items.h b/include/constants/items.h index f0c9371d3..05e2b2471 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -1033,9 +1033,6 @@ #define MAIL_NONE 0xFF #define ITEM_TO_MULCH(itemId)(((itemId) - ITEM_GROWTH_MULCH) + 1) -#define NUM_TECHNICAL_MACHINES 100 -#define NUM_HIDDEN_MACHINES 8 - #define MAX_BAG_ITEM_CAPACITY 999 #define MAX_PC_ITEM_CAPACITY 999 #define MAX_PYRAMID_BAG_ITEM_CAPACITY 99 // Values higher than 255 require free SaveBlock2 space. diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 3479a623f..4e00f6544 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -301,6 +301,8 @@ enum EvolutionConditions { IF_PID_MODULO_100_LT, // The Pokémon's personality value's modulo by 100 is lower than the defined value. IF_MIN_OVERWORLD_STEPS, // The Player has taken a specific amount of steps in the overworld with the Pokémon following them or in the first slot of the party. IF_BAG_ITEM_COUNT, // The Player has the specific amount of an item in the bag. It then removes those items. + IF_REGION, // The Player is in the specific region. + IF_NOT_REGION, // The Player is NOT in the specific region. CONDITIONS_END }; @@ -323,6 +325,7 @@ enum EvolutionMode { EVO_MODE_ITEM_CHECK, // If an Everstone is being held, still want to show that the stone *could* be used on that Pokémon to evolve EVO_MODE_BATTLE_SPECIAL, EVO_MODE_OVERWORLD_SPECIAL, + EVO_MODE_SCRIPT_TRIGGER, EVO_MODE_BATTLE_ONLY, // This mode is only used in battles to support Tandemaus' unique requirement }; diff --git a/include/data.h b/include/data.h index b682fbf15..a371bcd1c 100644 --- a/include/data.h +++ b/include/data.h @@ -42,9 +42,9 @@ struct TrainerSprite struct TrainerBacksprite { - struct MonCoords coordinates; - struct CompressedSpriteSheet backPic; - struct SpritePalette palette; + const struct MonCoords coordinates; + const struct SpriteFrameImage backPic; + const struct SpritePalette palette; const union AnimCmd *const *const animation; }; @@ -105,6 +105,8 @@ struct Trainer /*0x22*/ u8 poolRuleIndex; /*0x23*/ u8 poolPickIndex; /*0x24*/ u8 poolPruneIndex; + /*0x25*/ u16 overrideTrainer; + /*0x26*/ u8 trainerBackPic; }; struct TrainerClass diff --git a/include/follower_npc.h b/include/follower_npc.h index 039b9042b..4e4a2e0b6 100644 --- a/include/follower_npc.h +++ b/include/follower_npc.h @@ -1,7 +1,7 @@ -// #ifndef GUARD_FOLLOWER_NPC_H -// #define GUARD_FOLLOWER_NPC_H +#ifndef GUARD_FOLLOWER_NPC_H +#define GUARD_FOLLOWER_NPC_H -// #include "constants/follower_npc.h" +#include "constants/follower_npc.h" // #define MOVEMENT_INVALID 0xFE @@ -126,4 +126,4 @@ // void Task_MoveNPCFollowerAfterForcedMovement(u8 taskId); // void Task_HideNPCFollowerAfterMovementFinish(u8 taskId); -// #endif // GUARD_FOLLOWER_NPC_H +#endif // GUARD_FOLLOWER_NPC_H diff --git a/include/gba/defines.h b/include/gba/defines.h index f6aa74a04..00e5890b6 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -27,6 +27,8 @@ #define ALIGNED(n) __attribute__((aligned(n))) #define PACKED __attribute__((packed)) #define TRANSPARENT __attribute__ ((__transparent_union__)) +#define ALWAYS_INLINE inline __attribute__((always_inline)) +#define NONNULL __attribute__((__nonnull__)) #define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) #define INTR_CHECK (*(u16 *)0x3007FF8) diff --git a/include/generational_changes.h b/include/generational_changes.h index a734ee49e..a45325caa 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -23,6 +23,27 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_DEFIANT_STICKY_WEB] = B_DEFIANT_STICKY_WEB, [GEN_CONFIG_ENCORE_TARGET] = B_ENCORE_TARGET, [GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES] = B_TIME_OF_DAY_HEALING_MOVES, + [GEN_PICKUP_WILD] = B_PICKUP_WILD, + [GEN_PROTEAN_LIBERO] = B_PROTEAN_LIBERO, + [GEN_INTREPID_SWORD] = B_INTREPID_SWORD, + [GEN_DAUNTLESS_SHIELD] = B_DAUNTLESS_SHIELD, + [GEN_ILLUMINATE_EFFECT] = B_ILLUMINATE_EFFECT, + [GEN_STEAL_WILD_ITEMS] = B_STEAL_WILD_ITEMS, + [GEN_SNOW_WARNING] = B_SNOW_WARNING, + [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, + [GEN_DREAM_EATER_LIQUID_OOZE] = B_DREAM_EATER_LIQUID_OOZE, + [GEN_CONFIG_TRANSISTOR_BOOST] = B_TRANSISTOR_BOOST, + [GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS] = B_RECALC_TURN_AFTER_ACTIONS, + [GEN_CONFIG_UPDATED_INTIMIDATE] = B_UPDATED_INTIMIDATE, + [GEN_CONFIG_DISGUISE_HP_LOSS] = B_DISGUISE_HP_LOSS, + [GEN_CONFIG_AFTER_YOU_TURN_ORDER] = B_AFTER_YOU_TURN_ORDER, + [GEN_CONFIG_HEALING_WISH_SWITCH] = B_HEALING_WISH_SWITCH, + [GEN_CONFIG_MEGA_EVO_TURN_ORDER] = B_MEGA_EVO_TURN_ORDER, + [GEN_CONFIG_SHEER_COLD_IMMUNITY] = B_SHEER_COLD_IMMUNITY, + [GEN_CONFIG_WEAK_ARMOR_SPEED] = B_WEAK_ARMOR_SPEED, + [GEN_CONFIG_PRANKSTER_DARK_TYPES] = B_PRANKSTER_DARK_TYPES, + [GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL, + [GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN, }; #if TESTING diff --git a/include/item.h b/include/item.h index f64d6f998..e2ff1ab5c 100644 --- a/include/item.h +++ b/include/item.h @@ -2,8 +2,87 @@ #define GUARD_ITEM_H #include "constants/item.h" +#include "constants/item_effects.h" #include "constants/items.h" +#include "constants/moves.h" #include "constants/tms_hms.h" +#include "constants/item_effects.h" +#include "constants/hold_effects.h" + +/* Expands to: + * enum + * { + * ITEM_TM_FOCUS_PUNCH = ITEM_TM01, + * ... + * ITEM_HM_CUT = ITM_HM01, + * ... + * }; */ +#define ENUM_TM(n, id) CAT(ITEM_TM_, id) = CAT(ITEM_TM, n), +#define ENUM_HM(n, id) CAT(ITEM_HM_, id) = CAT(ITEM_HM, n), +#define TO_TMHM_NUMS(a, ...) (__VA_ARGS__) +enum TMHMItemId +{ + RECURSIVELY(R_ZIP(ENUM_TM, TO_TMHM_NUMS NUMBERS_256, (FOREACH_TM(APPEND_COMMA)))) + RECURSIVELY(R_ZIP(ENUM_HM, TO_TMHM_NUMS NUMBERS_256, (FOREACH_HM(APPEND_COMMA)))) +}; + +#undef ENUM_TM +#undef ENUM_HM +#undef TO_TMHM_NUMS + +/* Each of these TM_HM enums corresponds an index in the list of TMs + HMs item ids in + * gTMHMItemMoveIds. The index for an item can be retrieved with GetItemTMHMIndex below. + */ +#define UNPACK_TM_HM_ENUM(_tmHm) CAT(ENUM_TM_HM_, _tmHm), +enum TMHMIndex +{ + FOREACH_TMHM(UNPACK_TM_HM_ENUM) + NUM_ALL_MACHINES, + NUM_TECHNICAL_MACHINES = (0 FOREACH_TM(PLUS_ONE)), + NUM_HIDDEN_MACHINES = (0 FOREACH_HM(PLUS_ONE)), +}; + +#undef UNPACK_TM_HM_ENUM + +enum PACKED ItemSortType +{ + ITEM_TYPE_UNCATEGORIZED, + ITEM_TYPE_FIELD_USE, + ITEM_TYPE_LEVEL_UP_ITEM, + ITEM_TYPE_HEALTH_RECOVERY, + ITEM_TYPE_STATUS_RECOVERY, + ITEM_TYPE_PP_RECOVERY, + ITEM_TYPE_NATURE_MINT, + ITEM_TYPE_STAT_BOOST_DRINK, + ITEM_TYPE_STAT_BOOST_FEATHER, + ITEM_TYPE_STAT_BOOST_MOCHI, + ITEM_TYPE_BATTLE_ITEM, + ITEM_TYPE_FLUTE, + ITEM_TYPE_X_ITEM, + ITEM_TYPE_AUX_ITEM, + ITEM_TYPE_EVOLUTION_STONE, + ITEM_TYPE_EVOLUTION_ITEM, + ITEM_TYPE_SPECIAL_HELD_ITEM, + ITEM_TYPE_MEGA_STONE, + ITEM_TYPE_Z_CRYSTAL, + ITEM_TYPE_TERA_SHARD, + ITEM_TYPE_HELD_ITEM, + ITEM_TYPE_TYPE_BOOST_HELD_ITEM, + ITEM_TYPE_CONTEST_HELD_ITEM, + ITEM_TYPE_EV_BOOST_HELD_ITEM, + ITEM_TYPE_GEM, + ITEM_TYPE_PLATE, + ITEM_TYPE_MEMORY, + ITEM_TYPE_DRIVE, + ITEM_TYPE_INCENSE, + ITEM_TYPE_NECTAR, + ITEM_TYPE_GROWTH, + ITEM_TYPE_SHARD, + ITEM_TYPE_SELLABLE, + ITEM_TYPE_RELIC, + ITEM_TYPE_FOSSIL, + ITEM_TYPE_MAIL, +}; typedef void (*ItemUseFunc)(u8); @@ -14,14 +93,14 @@ struct Item ItemUseFunc fieldUseFunc; const u8 *description; const u8 *effect; - u8 name[ITEM_NAME_LENGTH]; - u8 pluralName[ITEM_NAME_PLURAL_LENGTH]; + const u8 *name; + const u8 *pluralName; u8 holdEffect; u8 holdEffectParam; u8 importance:2; u8 notConsumed:1; - u8 padding:5; - u8 pocket; + enum Pocket pocket:5; + enum ItemSortType sortType; u8 type; u8 battleUsage; u8 flingPower; @@ -35,8 +114,69 @@ struct BagPocket u8 capacity; }; +struct TmHmIndexKey +{ + enum TMHMItemId itemId:16; + u16 moveId; +}; + extern const struct Item gItemsInfo[]; extern struct BagPocket gBagPockets[]; +extern const struct TmHmIndexKey gTMHMItemMoveIds[]; + +#define UNPACK_ITEM_TO_TM_INDEX(_tm) case CAT(ITEM_TM_, _tm): return CAT(ENUM_TM_HM_, _tm) + 1; +#define UNPACK_ITEM_TO_HM_INDEX(_hm) case CAT(ITEM_HM_, _hm): return CAT(ENUM_TM_HM_, _hm) + 1; +#define UNPACK_ITEM_TO_TM_MOVE_ID(_tm) case CAT(ITEM_TM_, _tm): return CAT(MOVE_, _tm); +#define UNPACK_ITEM_TO_HM_MOVE_ID(_hm) case CAT(ITEM_HM_, _hm): return CAT(MOVE_, _hm); + +static inline enum TMHMIndex GetItemTMHMIndex(u16 item) +{ + switch (item) + { + /* Expands to: + * case ITEM_TM_FOCUS_PUNCH: + * return 1; + * case ITEM_TM_DRAGON_CLAW: + * return 2; + * etc */ + FOREACH_TM(UNPACK_ITEM_TO_TM_INDEX) + FOREACH_HM(UNPACK_ITEM_TO_HM_INDEX) + default: + return 0; + } +} + +static inline u16 GetItemTMHMMoveId(u16 item) +{ + switch (item) + { + /* Expands to: + * case ITEM_TM_FOCUS_PUNCH: + * return MOVE_FOCUS_PUNCH; + * case ITEM_TM_DRAGON_CLAW: + * return MOVE_DRAGON_CLAW; + * etc */ + FOREACH_TM(UNPACK_ITEM_TO_TM_MOVE_ID) + FOREACH_HM(UNPACK_ITEM_TO_HM_MOVE_ID) + default: + return MOVE_NONE; + } +} + +#undef UNPACK_ITEM_TO_TM_INDEX +#undef UNPACK_ITEM_TO_HM_INDEX +#undef UNPACK_ITEM_TO_TM_MOVE_ID +#undef UNPACK_ITEM_TO_HM_MOVE_ID + +static inline enum TMHMItemId GetTMHMItemId(enum TMHMIndex index) +{ + return gTMHMItemMoveIds[index].itemId; +} + +static inline u16 GetTMHMMoveId(enum TMHMIndex index) +{ + return gTMHMItemMoveIds[index].moveId; +} u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos); void GetBerryCountString(u8 *dst, const u8 *berryName, u32 quantity); @@ -94,28 +234,9 @@ bool8 IsItemBall(u16 itemId); const u8 *GetItemEffect(u32 itemId); u32 GetItemStatus1Mask(u16 itemId); -u32 GetItemStatus2Mask(u16 itemId); +bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile volatile); u32 GetItemSellPrice(u32 itemId); +bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect); -/* Expands to: - * enum - * { - * ITEM_TM_FOCUS_PUNCH, - * ... - * ITEM_HM_CUT, - * ... - * }; */ -#define ENUM_TM(id) CAT(ITEM_TM_, id), -#define ENUM_HM(id) CAT(ITEM_HM_, id), -enum -{ - ENUM_TM_START_ = ITEM_TM01 - 1, - FOREACH_TM(ENUM_TM) - - ENUM_HM_START_ = ITEM_HM01 - 1, - FOREACH_HM(ENUM_HM) -}; -#undef ENUM_TM -#undef ENUM_HM #endif // GUARD_ITEM_H diff --git a/include/math_util.h b/include/math_util.h index 37489d5c2..c18051222 100644 --- a/include/math_util.h +++ b/include/math_util.h @@ -1,8 +1,6 @@ #ifndef GUARD_MATH_UTIL_H #define GUARD_MATH_UTIL_H -// Fixed-point arithmetic library. - s16 MathUtil_Mul16(s16 x, s16 y); s16 MathUtil_Mul16Shift(u8 s, s16 x, s16 y); s32 MathUtil_Mul32(s32 x, s32 y); @@ -12,6 +10,7 @@ s32 MathUtil_Div32(s32 x, s32 y); s16 MathUtil_Inv16(s16 y); s16 MathUtil_Inv16Shift(u8 s, s16 y); s32 MathUtil_Inv32(s32 y); +u32 MathUtil_Exponent(u32 x, u32 y); // x * y s16 Q_8_8_mul(s16 x, s16 y); @@ -28,4 +27,4 @@ s16 Q_8_8_inv(s16 y); s16 Q_N_S_inv(u8 s, s16 y); s32 Q_24_8_inv(s32 y); -#endif //GUARD_MATH_UTIL_H +#endif // GUARD_MATH_UTIL_H diff --git a/include/metaprogram.h b/include/metaprogram.h index e12822946..1bf77265f 100644 --- a/include/metaprogram.h +++ b/include/metaprogram.h @@ -26,11 +26,18 @@ #define STR(...) STR_(__VA_ARGS__) #define STR_(...) #__VA_ARGS__ -/* You'll never guess what this one does */ +/* You'll never guess what these do */ #define APPEND_SEMICOLON(a) a; +#define APPEND_COMMA(a) a, /* Converts a string to a compound literal, essentially making it a pointer to const u8 */ #define COMPOUND_STRING(str) (const u8[]) _(str) +#define COMPOUND_STRING_SIZE_LIMIT(str, limit) (const u8[COMPOUND_STRING_CHECK_SIZE(str, limit)]) _(str) + +/* Used for COMPOUND_STRING_SIZE_LIMIT. Stupid, but makes sure we only get + * one error message regardless of how many characters over the limit we are. + * Otherwise, GCC gives an error for each and every character (which is annoying). */ +#define COMPOUND_STRING_CHECK_SIZE(str, limit) (sizeof(COMPOUND_STRING(str)) > limit ? sizeof(COMPOUND_STRING(str)) - 1 : sizeof(COMPOUND_STRING(str))) /* Expands to the first/second/third/fourth argument. */ #define FIRST(a, ...) a @@ -44,26 +51,26 @@ #define EXCEPT_3(a, ...) __VA_OPT__(EXCEPT_2(__VA_ARGS__)) #define EXCEPT_4(a, ...) __VA_OPT__(EXCEPT_3(__VA_ARGS__)) -/* 'UNPACK (x, y, z)' expands to 'x, y, z'. +/* 'UNPACK_META (x, y, z)' expands to 'x, y, z'. * Useful for passing arguments which may contain commas into a macro. */ -#define UNPACK(...) __VA_ARGS__ +#define UNPACK_META(...) __VA_ARGS__ -/* Updated version that can extract arguments from brackets as well. +/* Updated version that can extract arguments from brackets as well. * Examples: - * + * * UNPACK_B(a, b) => a, b * UNPACK_B((a, b)) => a, b * UNPACK_B((a)) => a - * + * * The simple UNPACK is used for extracting non-bracketed arguments. * */ #define UNPACK_EXTRA(...) IF_YOU_SEE_ME_SOMETHING_IS_WRONG, __VA_ARGS__ -#define UNPACK_B(a) INVOKE(UNPACK_B_, a, UNPACK_EXTRA a) -#define UNPACK_B_(a, b, ...) __VA_OPT__(UNPACK)a +#define UNPACK_B(a) INVOKE_WITH_(UNPACK_B_, a, UNPACK_EXTRA a) +#define UNPACK_B_(a, b, ...) __VA_OPT__(UNPACK_META)a /* Expands to 'macro(...args, ...)'. */ -#define INVOKE_WITH(macro, args, ...) INVOKE(macro, UNPACK args __VA_OPT__(, __VA_ARGS__)) -#define INVOKE(macro, ...) macro(__VA_ARGS__) +#define INVOKE_WITH(macro, args, ...) INVOKE_WITH_(macro, UNPACK_META args __VA_OPT__(, __VA_ARGS__)) +#define INVOKE_WITH_(macro, ...) macro(__VA_ARGS__) /* Same as INVOKE_WITH but uses UNPACK_B to unpack arguments and only applies macro to args if there are any. */ #define INVOKE_WITH_B(macro, args, ...) INVOKE_B(macro, UNPACK_B(args) __VA_OPT__(, __VA_ARGS__)) @@ -98,48 +105,72 @@ #define R_FOR_EACH_WITH_(macro, args, a, ...) INVOKE_WITH(macro, args, a) __VA_OPT__(R_FOR_EACH_WITH_P PARENS (macro, args, __VA_ARGS__)) #define R_FOR_EACH_WITH_P() R_FOR_EACH_WITH_ +/* Expands to 'macro(a, b)' for each 'a' in 'as' and 'b' in 'bs'. + * Uses the shorter of 'as' and 'bs'. (Credit to MGriffin) */ +#define R_ZIP(macro, as, bs) CAT(R_ZIP_, CAT(R_ZIP_NONEMPTY(as), R_ZIP_NONEMPTY(bs)))(macro, FIRST as, FIRST bs, (EXCEPT_1 as), (EXCEPT_1 bs)) +#define R_ZIP_00(macro, a, b, as, bs) +#define R_ZIP_01(macro, a, b, as, bs) +#define R_ZIP_10(macro, a, b, as, bs) +#define R_ZIP_11(macro, a, b, as, bs) macro(a, b) R_ZIP_P PARENS (macro, as, bs) +#define R_ZIP_P() R_ZIP + +#define R_ZIP_NONEMPTY(as) R_ZIP_NONEMPTY_ as +#define R_ZIP_NONEMPTY_(...) FIRST(__VA_OPT__(1,) 0) + +/* Just a lot of numbers (with leading zeroes - remove with REMOVE_LEADING_ZEROES) */ +#define NUMBERS_256 (00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255) + /* Picks the xth VA_ARG if it exists, otherwise returns a default value */ #define DEFAULT(_default, ...) FIRST(__VA_OPT__(__VA_ARGS__, ) _default) #define DEFAULT_2(_default, ...) DEFAULT(_default __VA_OPT__(, SECOND(__VA_ARGS__))) #define DEFAULT_3(_default, ...) DEFAULT(_default __VA_OPT__(, THIRD(__VA_ARGS__))) #define DEFAULT_4(_default, ...) DEFAULT(_default __VA_OPT__(, FOURTH(__VA_ARGS__))) +/* Simply a lists numbers 0-31, allows for word-spanning macros */ +#define BITS_32(F, ...) \ + F(0, __VA_ARGS__) \ + F(1, __VA_ARGS__) \ + F(2, __VA_ARGS__) \ + F(3, __VA_ARGS__) \ + F(4, __VA_ARGS__) \ + F(5, __VA_ARGS__) \ + F(6, __VA_ARGS__) \ + F(7, __VA_ARGS__) \ + F(8, __VA_ARGS__) \ + F(9, __VA_ARGS__) \ + F(10, __VA_ARGS__) \ + F(11, __VA_ARGS__) \ + F(12, __VA_ARGS__) \ + F(13, __VA_ARGS__) \ + F(14, __VA_ARGS__) \ + F(15, __VA_ARGS__) \ + F(16, __VA_ARGS__) \ + F(17, __VA_ARGS__) \ + F(18, __VA_ARGS__) \ + F(19, __VA_ARGS__) \ + F(20, __VA_ARGS__) \ + F(21, __VA_ARGS__) \ + F(22, __VA_ARGS__) \ + F(23, __VA_ARGS__) \ + F(24, __VA_ARGS__) \ + F(25, __VA_ARGS__) \ + F(26, __VA_ARGS__) \ + F(27, __VA_ARGS__) \ + F(28, __VA_ARGS__) \ + F(29, __VA_ARGS__) \ + F(30, __VA_ARGS__) \ + F(31, __VA_ARGS__) + +/* Compares _n to 1 shifted by _b by _operation (==, <, > etc) */ +#define OP_BIT_SHIFT(_b, _n, _operation) (_n) _operation (1 << _b) ? _b : + /* (Credit to MGriffin) A rather monstrous way of finding the set bit in a word. Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1hm7B */ -#define BIT_INDEX(n) \ - (n) == (1 << 0) ? 0 : \ - (n) == (1 << 1) ? 1 : \ - (n) == (1 << 2) ? 2 : \ - (n) == (1 << 3) ? 3 : \ - (n) == (1 << 4) ? 4 : \ - (n) == (1 << 5) ? 5 : \ - (n) == (1 << 6) ? 6 : \ - (n) == (1 << 7) ? 7 : \ - (n) == (1 << 8) ? 8 : \ - (n) == (1 << 9) ? 9 : \ - (n) == (1 << 10) ? 10 : \ - (n) == (1 << 11) ? 11 : \ - (n) == (1 << 12) ? 12 : \ - (n) == (1 << 13) ? 13 : \ - (n) == (1 << 14) ? 14 : \ - (n) == (1 << 15) ? 15 : \ - (n) == (1 << 16) ? 16 : \ - (n) == (1 << 17) ? 17 : \ - (n) == (1 << 18) ? 18 : \ - (n) == (1 << 19) ? 19 : \ - (n) == (1 << 20) ? 20 : \ - (n) == (1 << 21) ? 21 : \ - (n) == (1 << 22) ? 22 : \ - (n) == (1 << 23) ? 23 : \ - (n) == (1 << 24) ? 24 : \ - (n) == (1 << 25) ? 25 : \ - (n) == (1 << 26) ? 26 : \ - (n) == (1 << 27) ? 27 : \ - (n) == (1 << 28) ? 28 : \ - (n) == (1 << 29) ? 29 : \ - (n) == (1 << 30) ? 30 : \ - (n) == (1 << 31) ? 31 : \ - *(u32 *)NULL +#define BIT_INDEX(_n) BITS_32(OP_BIT_SHIFT, _n, ==) *(u32 *)NULL + +/* (Credit to MGriffin) A way to find the minimum required number of bits to +store a number (max: 32). Sample: https://godbolt.org/z/xb4KdPMhT */ +#define BIT_SIZE(_n) (BITS_32(OP_BIT_SHIFT, _n, <) 32) #define COMPRESS_BITS_0 0, 1 #define COMPRESS_BITS_1 1, 1 @@ -151,11 +182,10 @@ Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1 #define COMPRESS_BITS_7 7, 1 /* Will try and compress a set bit (or up to three sequential bits) into a single byte -Input must be of the form (upper << lower) where upper can be up to 3, lower up to 31 */ +Input must be of the form (upper << lower) where upper can be up to 7, lower up to 31 */ #define COMPRESS_BITS(_val) COMPRESS_BITS_STEP_2 _val -#define COMPRESS_BITS_STEP_2(_unpacked) COMPRESS_BITS_STEP_3(COMPRESS_BITS_## _unpacked) -#define COMPRESS_BITS_STEP_3(...) COMPRESS_BITS_STEP_4(__VA_ARGS__) -#define COMPRESS_BITS_STEP_4(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower))) +#define COMPRESS_BITS_STEP_2(_unpacked) INVOKE_WITH_(COMPRESS_BITS_STEP_3, COMPRESS_BITS_## _unpacked) +#define COMPRESS_BITS_STEP_3(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower))) /* Will read a compressed bit stored by COMPRESS_BIT into a single byte */ #define UNCOMPRESS_BITS(compressed) ((compressed >> 5) << (compressed & 0x1F)) @@ -171,4 +201,10 @@ Input must be of the form (upper << lower) where upper can be up to 3, lower up /* Finds the required digits to display the number (maximum 4) */ #define MAX_DIGITS(_num) 1 + !!(_num / 10) + !!(_num / 100) + !!(_num / 1000) +/* Converts a number with leading zeroes to a normal int (base 10 and up to three digits only!) */ +#define REMOVE_LEADING_ZEROES(_num) (((0x##_num / 256) * 100) + ((0x##_num / 16) * 10) + (0x##_num % 16)) + +/* Useful for counting arguments */ +#define PLUS_ONE(...) + 1 + #endif diff --git a/include/move.h b/include/move.h index deb9b7d85..b1e8cba99 100644 --- a/include/move.h +++ b/include/move.h @@ -4,6 +4,7 @@ #include "contest_effect.h" #include "constants/battle.h" #include "constants/battle_move_effects.h" +#include "constants/battle_string_ids.h" #include "constants/moves.h" // For defining EFFECT_HIT etc. with battle TV scores and flags etc. @@ -21,21 +22,17 @@ struct __attribute__((packed, aligned(2))) BattleMoveEffect #define EFFECTS_ARR(...) (const struct AdditionalEffect[]) {__VA_ARGS__} #define ADDITIONAL_EFFECTS(...) EFFECTS_ARR( __VA_ARGS__ ), .numAdditionalEffects = ARRAY_COUNT(EFFECTS_ARR( __VA_ARGS__ )) -enum SheerForceBoost -{ - SHEER_FORCE_AUTO_BOOST, // This is the default state when a move has a move effect with a chance - SHEER_FORCE_BOOST, // If a move effect doesn't have an effect with a chance this can force a boost - SHEER_FORCE_NO_BOOST, // Prevents a Sheer Force boost -}; - struct AdditionalEffect { - u16 moveEffect; + enum MoveEffect moveEffect; u8 self:1; u8 onlyIfTargetRaisedStats:1; u8 onChargeTurnOnly:1; - u8 sheerForceBoost:2; // Handles edge cases for Sheer Force - u8 padding:3; + u8 sheerForceOverride:1; // Handles edge cases for Sheer Force - if TRUE, boosts when it shouldn't, or doesn't boost when it should + u8 padding:4; + union PACKED { + enum WrappedStringID wrapped; + } multistring; u8 chance; // 0% = effect certain, primary effect }; @@ -67,7 +64,7 @@ struct MoveInfo { const u8 *name; const u8 *description; - u16 effect; + enum BattleMoveEffects effect; u16 type:5; // Up to 32 enum DamageCategory category:2; u16 power:9; // up to 511 @@ -492,7 +489,7 @@ static inline u32 GetMoveTwoTurnAttackStringId(u32 moveId) static inline u32 GetMoveTwoTurnAttackStatus(u32 moveId) { - return UNCOMPRESS_BITS(gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status); + return gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status; } static inline u32 GetMoveTwoTurnAttackWeather(u32 moveId) @@ -505,6 +502,11 @@ static inline enum ProtectMethod GetMoveProtectMethod(u32 moveId) return gMovesInfo[SanitizeMoveId(moveId)].argument.protectMethod; } +static inline u32 GetMoveTerrainFlag(u32 moveId) +{ + return gMovesInfo[SanitizeMoveId(moveId)].argument.moveProperty; +} + static inline u32 GetMoveEffectArg_Status(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].argument.status; diff --git a/include/pokemon.h b/include/pokemon.h index ffb52add5..44958208d 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -10,13 +10,17 @@ #include "constants/map_groups.h" #include "constants/regions.h" #include "constants/region_map_sections.h" +#include "constants/map_groups.h" +#include "constants/battle.h" +#include "constants/abilities.h" +#include "contest_effect.h" #include "constants/trainers.h" #define GET_BASE_SPECIES_ID(speciesId) (GetFormSpeciesId(speciesId, 0)) #define FORM_SPECIES_END (0xffff) // Property labels for Get(Box)MonData / Set(Box)MonData -enum { +enum MonData { MON_DATA_PERSONALITY, MON_DATA_STATUS, MON_DATA_OT_ID, @@ -232,6 +236,14 @@ struct PokemonSubstruct3 max(sizeof(struct PokemonSubstruct2), \ sizeof(struct PokemonSubstruct3))))) +enum SubstructType +{ + SUBSTRUCT_TYPE_0, + SUBSTRUCT_TYPE_1, + SUBSTRUCT_TYPE_2, + SUBSTRUCT_TYPE_3, +}; + union PokemonSubstruct { struct PokemonSubstruct0 type0; @@ -337,8 +349,8 @@ struct BattleTowerPokemon /*0x2B*/ u8 friendship; }; -#define UNPACK_VOLATILE_STRUCT(_enum, _fieldName, _typeBitSize, ...) INVOKE(UNPACK_VOLATILE_STRUCT_, _fieldName, UNPACK_B(_typeBitSize)); -#define UNPACK_VOLATILE_STRUCT_(_fieldName, _type, ...) _type FIRST(__VA_OPT__(_fieldName:FIRST(__VA_ARGS__),) _fieldName) +#define UNPACK_VOLATILE_STRUCT(_enum, _fieldName, _typeMaxValue, ...) INVOKE_WITH_(UNPACK_VOLATILE_STRUCT_, _fieldName, UNPACK_B(_typeMaxValue)); +#define UNPACK_VOLATILE_STRUCT_(_fieldName, _type, ...) _type FIRST(__VA_OPT__(_fieldName:BIT_SIZE(FIRST(__VA_ARGS__)),) _fieldName) struct Volatiles { @@ -386,7 +398,7 @@ struct BattlePokemon /*0x17*/ u32 spDefenseIV:5; /*0x17*/ u32 abilityNum:2; /*0x18*/ s8 statStages[NUM_BATTLE_STATS]; - /*0x20*/ u16 ability; + /*0x20*/ enum Ability ability; /*0x22*/ u8 types[3]; /*0x25*/ u8 pp[MAX_MON_MOVES]; /*0x29*/ u16 hp; @@ -400,12 +412,7 @@ struct BattlePokemon /*0x45*/ u32 experience; /*0x49*/ u32 personality; /*0x4D*/ u32 status1; - /*0x51*/ union { - struct { - u32 status2; // To be expanded to include Status3/4 - }; - struct Volatiles volatiles; - }; + /*0x51*/ struct Volatiles volatiles; /*0x5D*/ u32 otId; /*0x61*/ u8 metLevel; /*0x62*/ bool8 isShiny; @@ -453,7 +460,7 @@ struct SpeciesInfo /*0xC4*/ u8 friendship; u8 growthRate; u8 eggGroups[2]; - u16 abilities[NUM_ABILITY_SLOTS]; // 3 abilities, no longer u8 because we have over 255 abilities now. + enum Ability abilities[NUM_ABILITY_SLOTS]; // 3 abilities, no longer u8 because we have over 255 abilities now. u8 safariZoneFleeRate; // Pokédex data @@ -557,7 +564,7 @@ struct SpeciesInfo /*0xC4*/ #endif //OW_POKEMON_OBJECT_EVENTS }; -struct Ability +struct AbilityInfo { u8 name[ABILITY_NAME_LENGTH + 1]; const u8 *description; @@ -700,7 +707,7 @@ extern const u8 gStatStageRatios[MAX_STAT_STAGE + 1][2]; extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const u32 sExpCandyExperienceTable[]; -extern const struct Ability gAbilitiesInfo[]; +extern const struct AbilityInfo gAbilitiesInfo[]; extern const struct NatureInfo gNaturesInfo[]; #if P_TUTOR_MOVES_ARRAY extern const u16 gTutorMoves[]; @@ -775,8 +782,8 @@ u8 CalculateEnemyPartyCount(void); u8 CalculateEnemyPartyCountInSide(u32 battler); u8 GetMonsStateToDoubles(void); u8 GetMonsStateToDoubles_2(void); -u16 GetAbilityBySpecies(u16 species, u8 abilityNum); -u16 GetMonAbility(struct Pokemon *mon); +enum Ability GetAbilityBySpecies(u16 species, u8 abilityNum); +enum Ability GetMonAbility(struct Pokemon *mon); // void CreateSecretBaseEnemyParty(struct SecretBase *secretBaseRecord); u8 GetSecretBaseTrainerPicIndex(void); enum TrainerClassID GetSecretBaseTrainerClass(void); @@ -788,7 +795,7 @@ const u8 *GetSpeciesPokedexDescription(u16 species); u32 GetSpeciesHeight(u16 species); u32 GetSpeciesWeight(u16 species); u32 GetSpeciesType(u16 species, u8 slot); -u32 GetSpeciesAbility(u16 species, u8 slot); +enum Ability GetSpeciesAbility(u16 species, u8 slot); u32 GetSpeciesBaseHP(u16 species); u32 GetSpeciesBaseAttack(u16 species); u32 GetSpeciesBaseDefense(u16 species); @@ -858,7 +865,8 @@ void CreateTask_PlayMapChosenOrBattleBGM(u16 songId); const u16 *GetMonFrontSpritePal(struct Pokemon *mon); const u16 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality); const u16 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFemale); -bool8 IsMoveHM(u16 move); +bool32 IsMoveHM(u16 move); +bool32 CannotForgetMove(u16 move); bool8 IsMonSpriteNotFlipped(u16 species); s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor); s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor); @@ -911,9 +919,11 @@ uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier) u32 GetRegionalFormByRegion(u32 species, u32 region); bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion); u32 GetTeraTypeFromPersonality(struct Pokemon *mon); +bool8 ShouldSkipFriendshipChange(void); struct Pokemon *GetSavedPlayerPartyMon(u32 index); u8 *GetSavedPlayerPartyCount(void); void SavePlayerPartyMon(u32 index, struct Pokemon *mon); +u32 IsSpeciesOfType(u32 species, u32 type); // pokefirered u16 GetFirstPartnerMove(u16 species); diff --git a/include/random.h b/include/random.h index ad23e0967..f6c870ce8 100644 --- a/include/random.h +++ b/include/random.h @@ -193,7 +193,9 @@ enum RandomTag RNG_AI_SWITCH_ALL_MOVES_BAD, RNG_AI_CONSERVE_TERA, RNG_AI_SWITCH_ALL_SCORES_BAD, + RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER, RNG_AI_PP_STALL_DISREGARD_MOVE, + RNG_AI_SUCKER_PUNCH, RNG_SHELL_SIDE_ARM, RNG_RANDOM_TARGET, RNG_AI_PREDICT_ABILITY, @@ -201,8 +203,23 @@ enum RandomTag RNG_AI_PREDICT_MOVE, RNG_AI_STATUS_FOCUS_PUNCH, RNG_AI_BOOST_INTO_HAZE, + RNG_AI_SHOULD_RECOVER, + RNG_AI_PRIORITIZE_LAST_CHANCE, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, + RNG_AI_ASSUME_STATUS_SLEEP, + RNG_AI_ASSUME_STATUS_NONVOLATILE, + RNG_AI_ASSUME_STATUS_HIGH_ODDS, + RNG_AI_ASSUME_STATUS_MEDIUM_ODDS, + RNG_AI_ASSUME_STATUS_LOW_ODDS, + RNG_AI_ASSUME_ALL_STATUS, + RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, + RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, + RNG_WRAP, + RNG_BALLTHROW_CRITICAL, + RNG_BALLTHROW_SHAKE, + RNG_PRESENT, + RNG_MAGNITUDE, }; #define RandomWeighted(tag, ...) \ diff --git a/include/sprite.h b/include/sprite.h index 841dd6184..adcacc9eb 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -329,5 +329,6 @@ void ResetAffineAnimData(void); u32 GetSpanPerImage(u32 shape, u32 size); void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images); void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip); +u8 IndexOfSpriteTileTag(u16 tag); #endif //GUARD_SPRITE_H diff --git a/include/strings.h b/include/strings.h index 4abb4b16e..e9d21475a 100644 --- a/include/strings.h +++ b/include/strings.h @@ -332,6 +332,7 @@ extern const u8 gText_EscapeFromHereAndReturnTo[]; extern const u8 gText_PkmnCuredOfPoison[]; extern const u8 gText_PkmnWokeUp2[]; extern const u8 gText_PkmnBurnHealed[]; +extern const u8 gText_PkmnFrostbiteHealed[]; extern const u8 gText_PkmnThawedOut[]; extern const u8 gText_PkmnCuredOfParalysis[]; extern const u8 gText_PkmnSnappedOutOfConfusion[]; diff --git a/include/trainer_pokemon_sprites.h b/include/trainer_pokemon_sprites.h index 2c7a5bb0c..7e136e24d 100644 --- a/include/trainer_pokemon_sprites.h +++ b/include/trainer_pokemon_sprites.h @@ -16,5 +16,7 @@ u16 FreeAndDestroyMonPicSpriteNoPalette(u16 spriteId); u16 FreeAndDestroyTrainerPicSprite(u16); u16 LoadMonPicInWindow(u16 species, bool32 isShiny, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId); u16 CreateMonPicSprite(u16 species, bool32 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); +u16 PlayerGenderToFrontTrainerPicId_Debug(u8 gender, bool8 getClass); +void CopyTrainerBackspriteFramesToDest(u8 trainerPicId, u8 *dest); #endif // GUARD_TRAINER_POKEMON_SPRITES_H diff --git a/include/trainer_pools.h b/include/trainer_pools.h index 196657a55..72df3e765 100644 --- a/include/trainer_pools.h +++ b/include/trainer_pools.h @@ -56,10 +56,12 @@ enum PoolTags { struct PoolRules { - bool8 speciesClause; - bool8 excludeForms; - bool8 itemClause; - bool8 itemClauseExclusions; + u8 speciesClause:1; + u8 excludeForms:1; + u8 itemClause:1; + u8 itemClauseExclusions:1; + u8 megaStoneClause:1; + u8 zCrystalClause:1; u8 tagMaxMembers[POOL_NUM_TAGS]; bool8 tagRequired[POOL_NUM_TAGS]; }; diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c new file mode 100644 index 000000000..4579b5d9a --- /dev/null +++ b/src/battle_ai_field_statuses.c @@ -0,0 +1,498 @@ +#include "global.h" +#include "battle_z_move.h" +#include "malloc.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_ai_field_statuses.h" +#include "battle_ai_util.h" +#include "battle_ai_main.h" +#include "battle_ai_switch_items.h" +// #include "battle_factory.h" +#include "battle_setup.h" +#include "event_data.h" +#include "data.h" +#include "item.h" +#include "move.h" +#include "pokemon.h" +#include "random.h" +#include "recorded_battle.h" +#include "util.h" +#include "constants/abilities.h" +#include "constants/battle_ai.h" +#include "constants/battle_move_effects.h" +#include "constants/hold_effects.h" +#include "constants/moves.h" +#include "constants/items.h" + +static bool32 DoesAbilityBenefitFromWeather(enum Ability ability, u32 weather); +static bool32 DoesAbilityBenefitFromFieldStatus(enum Ability ability, u32 fieldStatus); +// A move is light sensitive if it is boosted by Sunny Day and weakened by low light weathers. +static bool32 IsLightSensitiveMove(u32 move); +static bool32 HasLightSensitiveMove(u32 battler); +// The following functions all feed into WeatherChecker, which is then called by ShouldSetWeather and ShouldClearWeather. +// BenefitsFrom functions all return FIELD_EFFECT_POSITIVE if the weather or field effect is good to have in place from the perspective of the battler, FIELD_EFFECT_NEUTRAL if it is neither good nor bad, and FIELD_EFFECT_NEGATIVE if it is bad. +// The purpose of WeatherChecker and FieldStatusChecker is to cleanly homogenize the logic that's the same with all of them, and to more easily apply single battle logic to double battles. +// ShouldSetWeather and ShouldClearWeather are looking for a positive or negative result respectively, and check the entire side. +// If one pokemon has a positive result and the other has a negative result, it defaults to the opinion of the battler that may change the weather or field status. +static enum FieldEffectOutcome BenefitsFromSun(u32 battler); +static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler); +static enum FieldEffectOutcome BenefitsFromHailOrSnow(u32 battler, u32 weather); +static enum FieldEffectOutcome BenefitsFromRain(u32 battler); +// The following functions all feed into FieldStatusChecker, which is then called by ShouldSetFieldStatus and ShouldClearFieldStatus. +// They work approximately the same as the weather functions. +static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromGravity(u32 battler); +static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler); + +bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredResult) +{ + if (IsWeatherActive(B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) + return (FIELD_EFFECT_BLOCKED == desiredResult); + + enum FieldEffectOutcome result = FIELD_EFFECT_NEUTRAL; + enum FieldEffectOutcome firstResult = FIELD_EFFECT_NEUTRAL; + + u32 i; + u32 battlersOnSide = 1; + + if (HasPartner(battler)) + battlersOnSide = 2; + + for (i = 0; i < battlersOnSide; i++) + { + if (weather & B_WEATHER_RAIN) + result = BenefitsFromRain(battler); + else if (weather & B_WEATHER_SUN) + result = BenefitsFromSun(battler); + else if (weather & B_WEATHER_SANDSTORM) + result = BenefitsFromSandstorm(battler); + else if (weather & B_WEATHER_ICY_ANY) + result = BenefitsFromHailOrSnow(battler, weather); + + battler = BATTLE_PARTNER(battler); + + if (result != FIELD_EFFECT_NEUTRAL) + { + if (weather & B_WEATHER_DAMAGING_ANY && i == 0 && battlersOnSide == 2) + firstResult = result; + } + } + if (firstResult != FIELD_EFFECT_NEUTRAL) + return (firstResult == result) && (result == desiredResult); + return (result == desiredResult); +} + +bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome desiredResult) +{ + enum FieldEffectOutcome result = FIELD_EFFECT_NEUTRAL; + enum FieldEffectOutcome firstResult = FIELD_EFFECT_NEUTRAL; + u32 i; + + u32 battlersOnSide = 1; + + if (HasPartner(battler)) + battlersOnSide = 2; + + for (i = 0; i < battlersOnSide; i++) + { + // terrains + if (fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN) + result = BenefitsFromElectricTerrain(battler); + if (fieldStatus & STATUS_FIELD_GRASSY_TERRAIN) + result = BenefitsFromGrassyTerrain(battler); + if (fieldStatus & STATUS_FIELD_MISTY_TERRAIN) + result = BenefitsFromMistyTerrain(battler); + if (fieldStatus & STATUS_FIELD_PSYCHIC_TERRAIN) + result = BenefitsFromPsychicTerrain(battler); + + // other field statuses + if (fieldStatus & STATUS_FIELD_GRAVITY) + result = BenefitsFromGravity(battler); + if (fieldStatus & STATUS_FIELD_TRICK_ROOM) + result = BenefitsFromTrickRoom(battler); + + battler = BATTLE_PARTNER(battler); + + if (result != FIELD_EFFECT_NEUTRAL) + { + // Trick room wants both pokemon to agree, not just one + if (fieldStatus & STATUS_FIELD_TRICK_ROOM && i == 0 && battlersOnSide == 2) + firstResult = result; + } + } + if (firstResult != FIELD_EFFECT_NEUTRAL) + return (firstResult == result) && (result == desiredResult); + return (result == desiredResult); +} + +static bool32 DoesAbilityBenefitFromWeather(enum Ability ability, u32 weather) +{ + switch (ability) + { + case ABILITY_FORECAST: + return (weather & (B_WEATHER_RAIN | B_WEATHER_SUN | B_WEATHER_ICY_ANY)); + case ABILITY_MAGIC_GUARD: + case ABILITY_OVERCOAT: + return (weather & B_WEATHER_DAMAGING_ANY); + case ABILITY_SAND_FORCE: + case ABILITY_SAND_RUSH: + case ABILITY_SAND_VEIL: + return (weather & B_WEATHER_SANDSTORM); + case ABILITY_ICE_BODY: + case ABILITY_ICE_FACE: + case ABILITY_SNOW_CLOAK: + return (weather & B_WEATHER_ICY_ANY); + case ABILITY_SLUSH_RUSH: + return (weather & B_WEATHER_SNOW); + case ABILITY_DRY_SKIN: + case ABILITY_HYDRATION: + case ABILITY_RAIN_DISH: + case ABILITY_SWIFT_SWIM: + return (weather & B_WEATHER_RAIN); + case ABILITY_CHLOROPHYLL: + case ABILITY_FLOWER_GIFT: + case ABILITY_HARVEST: + case ABILITY_LEAF_GUARD: + case ABILITY_ORICHALCUM_PULSE: + case ABILITY_PROTOSYNTHESIS: + case ABILITY_SOLAR_POWER: + return (weather & B_WEATHER_SUN); + default: + break; + } + return FALSE; +} + +static bool32 DoesAbilityBenefitFromFieldStatus(enum Ability ability, u32 fieldStatus) +{ + switch (ability) + { + case ABILITY_MIMICRY: + return (fieldStatus & STATUS_FIELD_TERRAIN_ANY); + case ABILITY_HADRON_ENGINE: + case ABILITY_QUARK_DRIVE: + case ABILITY_SURGE_SURFER: + return (fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN); + case ABILITY_GRASS_PELT: + return (fieldStatus & STATUS_FIELD_GRASSY_TERRAIN); + // no abilities inherently benefit from Misty or Psychic Terrains + // return (fieldStatus & STATUS_FIELD_MISTY_TERRAIN); + // return (fieldStatus & STATUS_FIELD_PSYCHIC_TERRAIN); + default: + break; + } + return FALSE; +} + +static bool32 IsLightSensitiveMove(u32 move) +{ + switch (GetMoveEffect(move)) + { + case EFFECT_SOLAR_BEAM: + case EFFECT_MORNING_SUN: + case EFFECT_SYNTHESIS: + case EFFECT_MOONLIGHT: + case EFFECT_GROWTH: + return TRUE; + default: + return FALSE; + } +} + +static bool32 HasLightSensitiveMove(u32 battler) +{ + s32 i; + u16 *moves = GetMovesArray(battler); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && IsLightSensitiveMove(moves[i])) + return TRUE; + } + + return FALSE; +} + +// Sun +// Utility Umbrella does NOT block Ancient Pokemon from their stat boosts. +static enum FieldEffectOutcome BenefitsFromSun(u32 battler) +{ + enum Ability ability = gAiLogicData->abilities[battler]; + + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) + { + if (ability == ABILITY_ORICHALCUM_PULSE || ability == ABILITY_PROTOSYNTHESIS) + return FIELD_EFFECT_POSITIVE; + else + return FIELD_EFFECT_NEUTRAL; + } + + if (DoesAbilityBenefitFromWeather(ability, B_WEATHER_SUN) + || HasLightSensitiveMove(battler) + || HasDamagingMoveOfType(battler, TYPE_FIRE) + || HasMoveWithEffect(battler, EFFECT_HYDRO_STEAM)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithFlag(battler, MoveHas50AccuracyInSun) || HasDamagingMoveOfType(battler, TYPE_WATER) || gAiLogicData->abilities[battler] == ABILITY_DRY_SKIN) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +// Sandstorm +static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler) +{ + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_SANDSTORM) + || IS_BATTLER_OF_TYPE(battler, TYPE_ROCK)) + return FIELD_EFFECT_POSITIVE; + + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + { + if (!(IS_BATTLER_ANY_TYPE(LEFT_FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + || gAiLogicData->holdEffects[LEFT_FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES + || DoesAbilityBenefitFromWeather(gAiLogicData->abilities[LEFT_FOE(battler)], B_WEATHER_SANDSTORM)) + return FIELD_EFFECT_POSITIVE; + else + return FIELD_EFFECT_NEUTRAL; + } + + return FIELD_EFFECT_NEGATIVE; +} + +// Hail or Snow +static enum FieldEffectOutcome BenefitsFromHailOrSnow(u32 battler, u32 weather) +{ + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], weather) + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) + || HasBattlerSideMoveWithEffect(battler, EFFECT_AURORA_VEIL)) + return FIELD_EFFECT_POSITIVE; + + if ((weather & B_WEATHER_DAMAGING_ANY) && gAiLogicData->holdEffects[battler] != HOLD_EFFECT_SAFETY_GOGGLES) + return FIELD_EFFECT_NEGATIVE; + + if (HasLightSensitiveMove(battler)) + return FIELD_EFFECT_NEGATIVE; + + if (HasMoveWithFlag(LEFT_FOE(battler), MoveAlwaysHitsInHailSnow)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +// Rain +static enum FieldEffectOutcome BenefitsFromRain(u32 battler) +{ + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) + return FIELD_EFFECT_NEUTRAL; + + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_RAIN) + || HasMoveWithFlag(battler, MoveAlwaysHitsInRain) + || HasDamagingMoveOfType(battler, TYPE_WATER)) + return FIELD_EFFECT_POSITIVE; + + if (HasLightSensitiveMove(battler) || HasDamagingMoveOfType(battler, TYPE_FIRE)) + return FIELD_EFFECT_NEGATIVE; + + if (HasMoveWithFlag(LEFT_FOE(battler), MoveAlwaysHitsInRain)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is electric terrain bad? +static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_ELECTRIC_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithEffect(battler, EFFECT_RISING_VOLTAGE)) + return FIELD_EFFECT_POSITIVE; + + if ((HasMoveWithEffect(LEFT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(LEFT_FOE(battler))) + || (HasMoveWithEffect(RIGHT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(RIGHT_FOE(battler)))) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = AI_IsBattlerGrounded(battler); + if (grounded && HasBattlerSideMoveWithAdditionalEffect(LEFT_FOE(battler), MOVE_EFFECT_SLEEP)) + return FIELD_EFFECT_POSITIVE; + + if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) + || gBattleMons[battler].volatiles.yawn + || HasDamagingMoveOfType(battler, TYPE_ELECTRIC))) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_RISING_VOLTAGE)) + return FIELD_EFFECT_NEGATIVE; + + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is grassy terrain bad? +static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_GRASSY_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) + return FIELD_EFFECT_POSITIVE; + if (HasMoveWithAdditionalEffect(battler, MOVE_EFFECT_FLORAL_HEALING)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = AI_IsBattlerGrounded(battler); + + // Weaken spamming Earthquake, Magnitude, and Bulldoze. + if (grounded && (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_EARTHQUAKE) + || HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_MAGNITUDE))) + return FIELD_EFFECT_POSITIVE; + + if (grounded && HasDamagingMoveOfType(battler, TYPE_GRASS)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_GRASSY_GLIDE)) + return FIELD_EFFECT_NEGATIVE; + + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is misty terrain bad? +static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_MISTY_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(battler, EFFECT_MISTY_EXPLOSION)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = AI_IsBattlerGrounded(battler); + bool32 allyGrounded = FALSE; + if (HasPartner(battler)) + allyGrounded = AI_IsBattlerGrounded(BATTLE_PARTNER(battler)); + + if ((HasMoveWithEffect(LEFT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(LEFT_FOE(battler))) + || (HasMoveWithEffect(RIGHT_FOE(battler), EFFECT_REST) && AI_IsBattlerGrounded(RIGHT_FOE(battler)))) + return FIELD_EFFECT_POSITIVE; + + // harass dragons + if ((grounded || allyGrounded) + && (HasDamagingMoveOfType(LEFT_FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(RIGHT_FOE(battler), TYPE_DRAGON))) + return FIELD_EFFECT_POSITIVE; + + if ((grounded || allyGrounded) + && (HasNonVolatileMoveEffect(LEFT_FOE(battler), MOVE_EFFECT_SLEEP) || HasNonVolatileMoveEffect(RIGHT_FOE(battler), MOVE_EFFECT_SLEEP))) + return FIELD_EFFECT_POSITIVE; + + if (grounded && (gBattleMons[battler].status1 & STATUS1_SLEEP || gBattleMons[battler].volatiles.yawn)) + return FIELD_EFFECT_POSITIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is Psychic Terrain negative? +static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_PSYCHIC_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = AI_IsBattlerGrounded(battler); + bool32 allyGrounded = FALSE; + if (HasPartner(battler)) + allyGrounded = AI_IsBattlerGrounded(BATTLE_PARTNER(battler)); + + // don't bother if we're not grounded + if (grounded || allyGrounded) + { + // harass priority + if (HasBattlerSideAbility(LEFT_FOE(battler), ABILITY_GALE_WINGS, gAiLogicData) + || HasBattlerSideAbility(LEFT_FOE(battler), ABILITY_TRIAGE, gAiLogicData) + || HasBattlerSideAbility(LEFT_FOE(battler), ABILITY_PRANKSTER, gAiLogicData)) + return FIELD_EFFECT_POSITIVE; + } + + if (grounded && HasDamagingMoveOfType(battler, TYPE_PSYCHIC)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(LEFT_FOE(battler), EFFECT_EXPANDING_FORCE)) + return FIELD_EFFECT_NEGATIVE; + + if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) + || HasBattlerSideAbility(battler, ABILITY_TRIAGE, gAiLogicData) + || HasBattlerSideAbility(battler, ABILITY_PRANKSTER, gAiLogicData)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +static enum FieldEffectOutcome BenefitsFromGravity(u32 battler) +{ + if (!AI_IsBattlerGrounded(battler)) + return FIELD_EFFECT_NEGATIVE; + + if (HasBattlerSideAbility(battler, ABILITY_HUSTLE, gAiLogicData)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithFlag(battler, IsMoveGravityBanned)) + return FIELD_EFFECT_NEGATIVE; + + if (IsBattlerAlive(LEFT_FOE(battler))) + { + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || (!AI_IsBattlerGrounded(LEFT_FOE(battler)) && HasDamagingMoveOfType(battler, TYPE_GROUND))) + return FIELD_EFFECT_POSITIVE; + } + + if (IsBattlerAlive(RIGHT_FOE(battler))) + { + if (HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || (!AI_IsBattlerGrounded(RIGHT_FOE(battler)) && HasDamagingMoveOfType(battler, TYPE_GROUND))) + return FIELD_EFFECT_POSITIVE; + } + + return FIELD_EFFECT_NEUTRAL; +} + + +static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) +{ + // If we're in singles, we literally only care about speed. + if (IsBattle1v1()) + { + if (gAiLogicData->speedStats[battler] < gAiLogicData->speedStats[LEFT_FOE(battler)]) + return FIELD_EFFECT_POSITIVE; + // If we tie, we shouldn't change trick room state. + else if (gAiLogicData->speedStats[battler] == gAiLogicData->speedStats[LEFT_FOE(battler)]) + return FIELD_EFFECT_NEUTRAL; + else + return FIELD_EFFECT_NEGATIVE; + } + + // First checking if we have enough priority for one pokemon to disregard Trick Room entirely. + if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)) + { + u16* aiMoves = GetMovesArray(battler); + for (int i = 0; i < MAX_MON_MOVES; i++) + { + u16 move = aiMoves[i]; + if (GetBattleMovePriority(battler, gAiLogicData->abilities[battler], move) > 0 && !(GetMovePriority(move) > 0 && IsBattleMoveStatus(move))) + { + return FIELD_EFFECT_POSITIVE; + } + } + } + + // If we are faster or tie, we don't want trick room. + if ((gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[LEFT_FOE(battler)]) || (gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[RIGHT_FOE(battler)])) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_POSITIVE; +} + + diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 83b2fe401..33f4cdcc5 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -14,6 +14,7 @@ #include "debug.h" #include "event_data.h" #include "item.h" +#include "math_util.h" #include "pokemon.h" #include "random.h" #include "recorded_battle.h" @@ -32,11 +33,13 @@ #define AI_ACTION_WATCH (1 << 2) #define AI_ACTION_DO_NOT_ATTACK (1 << 3) +static u32 ChooseMoveOrAction(u32 battler); static u32 ChooseMoveOrAction_Singles(u32 battler); static u32 ChooseMoveOrAction_Doubles(u32 battler); static inline void BattleAI_DoAIProcessing(struct AiThinkingStruct *aiThink, u32 battlerAtk, u32 battlerDef); static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AiThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef); static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect); +static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef); // ewram EWRAM_DATA const u8 *gAIScriptPtr = NULL; // Still used in contests @@ -49,6 +52,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); +static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Roaming(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); @@ -89,10 +93,10 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = [24] = NULL, // AI_FLAG_PREDICT_INCOMING_MON [25] = AI_CheckPpStall, // AI_FLAG_PP_STALL_PREVENTION [26] = NULL, // AI_FLAG_PREDICT_MOVE - [27] = NULL, // Unused - [28] = NULL, // Unused - [29] = NULL, // Unused - [30] = NULL, // Unused + [27] = NULL, // AI_FLAG_SMART_TERA + [28] = NULL, // AI_FLAG_ASSUME_STAB + [29] = NULL, // AI_FLAG_ASSUME_STATUS_MOVES + [30] = AI_AttacksPartner, // AI_FLAG_ATTACKS_PARTNER [31] = NULL, // Unused [32] = NULL, // Unused [33] = NULL, // Unused @@ -209,7 +213,7 @@ static u64 GetAiFlags(u16 trainerId) flags = GetTrainerAIFlagsFromId(trainerId); } - if (IsDoubleBattle()) + if (IsDoubleBattle() && flags != 0) { flags |= AI_FLAG_DOUBLE_BATTLE; } @@ -247,11 +251,23 @@ void BattleAI_SetupFlags(void) // smart wild AI gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(0xFFFF); gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(0xFFFF); + + // The check is here because wild natural enemies are not symmetrical. + if (B_WILD_NATURAL_ENEMIES && IsDoubleBattle()) + { + u32 speciesLeft = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES); + u32 speciesRight = GetMonData(&gEnemyParty[1], MON_DATA_SPECIES); + if (IsNaturalEnemy(speciesLeft, speciesRight)) + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] |= AI_FLAG_ATTACKS_PARTNER; + if (IsNaturalEnemy(speciesRight, speciesLeft)) + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] |= AI_FLAG_ATTACKS_PARTNER; + } + } else { gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA); - if (TRAINER_BATTLE_PARAM.opponentB != 0) + if (TRAINER_BATTLE_PARAM.opponentB != 0 && TRAINER_BATTLE_PARAM.opponentB != 0xFFFF) gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); else gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT]; @@ -259,22 +275,23 @@ void BattleAI_SetupFlags(void) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId); } else if (IsDoubleBattle() && IsAiVsAiBattle()) { gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT]; } - else + else // Assign ai flags for player for prediction { - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = 0; // player + u64 aiFlags = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA) | GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = aiFlags; + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = aiFlags; } } void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) { - u32 moveLimitations, moveLimitationsTarget; - u32 defaultScoreMovesTarget = defaultScoreMoves; + u32 moveLimitations; u64 flags[MAX_BATTLERS_COUNT]; u32 moveIndex; @@ -290,7 +307,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) { if (moveLimitations & (1u << moveIndex)) SET_SCORE(battler, moveIndex, 0); - if (defaultScoreMoves & 1) + else if (defaultScoreMoves & 1) SET_SCORE(battler, moveIndex, AI_SCORE_DEFAULT); else SET_SCORE(battler, moveIndex, 0); @@ -300,25 +317,6 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) gBattlerTarget = SetRandomTarget(battler); gAiBattleData->chosenTarget[battler] = gBattlerTarget; - - // Initialize move prediction scores - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE) - { - u32 opposingBattler = GetOppositeBattler(battler); - moveLimitationsTarget = gAiLogicData->moveLimitations[opposingBattler]; - - for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) - { - if (moveLimitationsTarget & (1u << moveIndex)) - SET_SCORE(opposingBattler, moveIndex, 0); - if (defaultScoreMovesTarget & 1) - SET_SCORE(opposingBattler, moveIndex, AI_SCORE_DEFAULT); - else - SET_SCORE(opposingBattler, moveIndex, 0); - - defaultScoreMovesTarget >>= 1; - } - } } bool32 BattlerChoseNonMoveAction(void) @@ -342,7 +340,6 @@ void SetupAIPredictionData(u32 battler, enum SwitchType switchType) { s32 opposingBattler = GetOppositeBattler(battler); gAiLogicData->aiPredictionInProgress = TRUE; - gAiLogicData->battlerDoingPrediction = battler; // Switch prediction if ((gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH)) @@ -351,31 +348,21 @@ void SetupAIPredictionData(u32 battler, enum SwitchType switchType) if (ShouldSwitch(opposingBattler)) gAiLogicData->shouldSwitch |= (1u << opposingBattler); gBattleStruct->prevTurnSpecies[opposingBattler] = gBattleMons[opposingBattler].species; - - // Determine whether AI will use predictions this turn - gAiLogicData->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, PREDICT_SWITCH_CHANCE); } - // Move prediction - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE) - { - gAiLogicData->predictedMove[opposingBattler] = gBattleMons[opposingBattler].moves[BattleAI_ChooseMoveIndex(opposingBattler)]; - ModifySwitchAfterMoveScoring(opposingBattler); + // Determine whether AI will use predictions this turn + gAiLogicData->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, PREDICT_SWITCH_CHANCE); - // Determine whether AI will use predictions this turn - gAiLogicData->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE); - } gAiLogicData->aiPredictionInProgress = FALSE; } void ComputeBattlerDecisions(u32 battler) { - if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) - && (BattlerHasAi(battler) - && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) + bool32 isAiBattler = (gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) && (BattlerHasAi(battler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE)); + if (isAiBattler || CanAiPredictMove()) { // If ai is about to flee or chosen to watch player, no need to calc anything - if (BattlerChoseNonMoveAction()) + if (isAiBattler && BattlerChoseNonMoveAction()) return; // Risky AI switches aggressively even mid battle @@ -388,10 +375,13 @@ void ComputeBattlerDecisions(u32 battler) SetupAIPredictionData(battler, switchType); // AI's own switching data - gAiLogicData->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType); - if (ShouldSwitch(battler)) - gAiLogicData->shouldSwitch |= (1u << battler); - gBattleStruct->prevTurnSpecies[battler] = gBattleMons[battler].species; + if (isAiBattler) + { + gAiLogicData->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType); + if (ShouldSwitch(battler)) + gAiLogicData->shouldSwitch |= (1u << battler); + gBattleStruct->prevTurnSpecies[battler] = gBattleMons[battler].species; + } // AI's move scoring gAiBattleData->chosenMoveIndex[battler] = BattleAI_ChooseMoveIndex(battler); // Calculate score and chose move index @@ -412,6 +402,13 @@ void ReconsiderGimmick(u32 battlerAtk, u32 battlerDef, u16 move) SetAIUsingGimmick(battlerAtk, NO_GIMMICK); } +static u32 ChooseMoveOrAction(u32 battler) +{ + if (IsDoubleBattle()) + return ChooseMoveOrAction_Doubles(battler); + return ChooseMoveOrAction_Singles(battler); +} + u32 BattleAI_ChooseMoveIndex(u32 battler) { u32 chosenMoveIndex; @@ -421,16 +418,11 @@ u32 BattleAI_ChooseMoveIndex(u32 battler) if (gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_TERA && (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_TERA)) DecideTerastal(battler); - - if (!IsDoubleBattle()) - chosenMoveIndex = ChooseMoveOrAction_Singles(battler); - else - chosenMoveIndex = ChooseMoveOrAction_Doubles(battler); + chosenMoveIndex = ChooseMoveOrAction(battler); if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE) ReconsiderGimmick(battler, gBattlerTarget, gBattleMons[battler].moves[chosenMoveIndex]); - // Clear protect structures, some flags may be set during AI calcs // e.g. pranksterElevated from GetBattleMovePriority memset(&gProtectStructs, 0, MAX_BATTLERS_COUNT * sizeof(struct ProtectStruct)); @@ -535,9 +527,32 @@ void Ai_UpdateFaintData(u32 battler) aiMon->isFainted = TRUE; } +void RecordMovesBasedOnStab(u32 battler) +{ + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 playerMove = gBattleMons[battler].moves[i]; + if (IsSpeciesOfType(gBattleMons[battler].species, GetMoveType(playerMove)) && GetMovePower(playerMove != 0)) + RecordKnownMove(battler, playerMove); + } +} + +void RecordStatusMoves(u32 battler) +{ + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 playerMove = gBattleMons[battler].moves[i]; + if (ShouldRecordStatusMove(playerMove)) + RecordKnownMove(battler, playerMove); + } +} + void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) { - u32 ability, holdEffect; + enum Ability ability; + u32 holdEffect; ability = aiData->abilities[battler] = AI_DecideKnownAbilityForTurn(battler); aiData->items[battler] = gBattleMons[battler].item; @@ -547,20 +562,35 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) aiData->hpPercents[battler] = GetHealthPercentage(battler); aiData->moveLimitations[battler] = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); aiData->speedStats[battler] = GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); + + if (IsAiBattlerAssumingStab()) + RecordMovesBasedOnStab(battler); + + if (IsAiBattlerAssumingStatusMoves()) + RecordStatusMoves(battler); } +#define BYPASSES_ACCURACY_CALC 101 // 101 indicates for ai that the move will always hit static u32 Ai_SetMoveAccuracy(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 move) { u32 accuracy; - u32 abilityAtk = aiData->abilities[battlerAtk]; - u32 abilityDef = aiData->abilities[battlerDef]; - if (abilityAtk == ABILITY_NO_GUARD || abilityDef == ABILITY_NO_GUARD || GetMoveAccuracy(move) == 0) // Moves with accuracy 0 or no guard ability always hit. - accuracy = 100; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; + if (CanMoveSkipAccuracyCalc(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) + { + accuracy = BYPASSES_ACCURACY_CALC; + } else + { accuracy = GetTotalAccuracy(battlerAtk, battlerDef, move, abilityAtk, abilityDef, aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]); + // Cap normal accuracy at 100 for ai calcs. + // Done for comparison with moves that bypass accuracy checks (will be seen as 101 for ai calcs)) + accuracy = (accuracy > 100) ? 100 : accuracy; + } return accuracy; } +#undef BYPASSES_ACCURACY_CALC static void CalcBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 weather) { @@ -641,6 +671,20 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData) SetBattlerAiMovesData(aiData, battlerAtk, battlersCount, weather); } + + for (battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++) + { + // Prediction limited to player side but can be expanded to read partners move in the future + if (!IsOnPlayerSide(battlerAtk) || !CanAiPredictMove()) + continue; + + // This can potentially be cleaned up more + BattleAI_SetupAIData(0xF, battlerAtk); + u32 chosenMoveIndex = ChooseMoveOrAction(battlerAtk); + gAiLogicData->predictedMove[battlerAtk] = gBattleMons[battlerAtk].moves[chosenMoveIndex]; + aiData->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE); + } + if (DEBUG_AI_DELAY_TIMER) // We add to existing to compound multiple calls gBattleStruct->aiDelayCycles += CycleCountEnd(); @@ -651,7 +695,7 @@ u32 GetPartyMonAbility(struct Pokemon *mon) { // Doesn't have any special handling yet u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM)); + enum Ability ability = GetSpeciesAbility(species, GetMonData(mon, MON_DATA_ABILITY_NUM)); return ability; } @@ -671,11 +715,11 @@ static u32 PpStallReduction(u32 move, u32 battlerAtk) continue; PokemonToBattleMon(&gPlayerParty[partyIndex], &gBattleMons[tempBattleMonIndex]); u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES); - u32 abilityAtk = ABILITY_NONE; - u32 abilityDef = GetPartyMonAbility(&gPlayerParty[partyIndex]); + enum Ability abilityAtk = ABILITY_NONE; + enum Ability abilityDef = GetPartyMonAbility(&gPlayerParty[partyIndex]); u32 moveType = GetBattleMoveType(move); // Probably doesn't handle dynamic types right now - if (CanAbilityAbsorbMove(battlerAtk, tempBattleMonIndex, abilityDef, move, moveType, ABILITY_CHECK_TRIGGER) - || CanAbilityBlockMove(battlerAtk, tempBattleMonIndex, abilityAtk, abilityDef, move, ABILITY_CHECK_TRIGGER) + if (CanAbilityAbsorbMove(battlerAtk, tempBattleMonIndex, abilityDef, move, moveType, CHECK_TRIGGER) + || CanAbilityBlockMove(battlerAtk, tempBattleMonIndex, abilityAtk, abilityDef, move, CHECK_TRIGGER) || (CalcPartyMonTypeEffectivenessMultiplier(move, species, abilityDef) == 0)) { totalStallValue += currentStallValue; @@ -699,10 +743,13 @@ static u32 ChooseMoveOrAction_Singles(u32 battler) u8 consideredMoveArray[MAX_MON_MOVES]; u32 numOfBestMoves; s32 i; - u64 flags = gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)]; + u64 flags = gAiThinkingStruct->aiFlags[battler]; u32 opposingBattler = GetOppositeBattler(battler); + gAiThinkingStruct->aiLogicId = 0; + gAiThinkingStruct->movesetIndex = 0; gAiLogicData->partnerMove = 0; // no ally + while (flags != 0) { if (flags & 1) @@ -716,6 +763,9 @@ static u32 ChooseMoveOrAction_Singles(u32 battler) gAiThinkingStruct->aiLogicId++; } + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CHECK_VIABILITY) + AI_CompareDamagingMoves(battler, opposingBattler); + for (i = 0; i < MAX_MON_MOVES; i++) { gAiBattleData->finalScore[battler][opposingBattler][i] = gAiThinkingStruct->score[i]; @@ -768,17 +818,17 @@ static u32 ChooseMoveOrAction_Doubles(u32 battler) } else { - // if (gBattleTypeFlags & BATTLE_TYPE_PALACE) - // BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4, battler); - // else - BattleAI_SetupAIData(0xF, battler); + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4, battler); + else + BattleAI_SetupAIData(0xF, battler); gBattlerTarget = i; gAiLogicData->partnerMove = GetAllyChosenMove(battler); gAiThinkingStruct->aiLogicId = 0; gAiThinkingStruct->movesetIndex = 0; - flags = gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)]; + flags = gAiThinkingStruct->aiFlags[battler]; while (flags != 0) { @@ -792,6 +842,8 @@ static u32 ChooseMoveOrAction_Doubles(u32 battler) flags >>= (u64)1; gAiThinkingStruct->aiLogicId++; } + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CHECK_VIABILITY) + AI_CompareDamagingMoves(battler, gBattlerTarget); mostViableMovesScores[0] = gAiThinkingStruct->score[0]; mostViableMovesIndices[0] = 0; @@ -1017,6 +1069,9 @@ void BattleAI_DoAIProcessing_PredictedSwitchin(struct AiThinkingStruct *aiThink, // AI_FLAG_CHECK_BAD_MOVE - decreases move scores static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { + if (IsTargetingPartner(battlerAtk, battlerDef)) + return score; + // move data enum BattleMoveEffects moveEffect = GetMoveEffect(move); u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); @@ -1024,24 +1079,24 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; - bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); + bool32 isBattle1v1 = IsBattle1v1(); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); + bool32 hasPartner = HasPartner(battlerAtk); u32 i; u32 weather; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); - u32 abilityAtk = aiData->abilities[battlerAtk]; - u32 abilityDef = aiData->abilities[battlerDef]; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; s32 atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) - return score; - SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); - if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move)) + if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) RETURN_SCORE_MINUS(10); if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk)) @@ -1061,7 +1116,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // Don't use anything but super effective thawing moves if target is frozen if any other attack available - if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & (STATUS1_FROSTBITE | STATUS1_FREEZE))) + if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY)) { u32 aiMove; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1076,41 +1131,27 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } if (effectiveness == UQ_4_12(0.0)) - { RETURN_SCORE_MINUS(20); - } - else if (effectiveness < UQ_4_12(0.5)) - { - switch (moveEffect) - { - case EFFECT_FIXED_HP_DAMAGE: - case EFFECT_LEVEL_DAMAGE: - case EFFECT_PSYWAVE: - case EFFECT_OHKO: - case EFFECT_SHEER_COLD: - case EFFECT_BIDE: - case EFFECT_FIXED_PERCENT_DAMAGE: - case EFFECT_ENDEAVOR: - case EFFECT_COUNTER: - case EFFECT_MIRROR_COAT: - case EFFECT_METAL_BURST: - case EFFECT_FINAL_GAMBIT: - break; - default: - RETURN_SCORE_MINUS(10); - } - } if (DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)) abilityDef = ABILITY_NONE; + // If a pokemon can be guaranteed flinched, don't target the pokemon that can't be flinched. + if (hasTwoOpponents + && !IsFlinchGuaranteed(battlerAtk, battlerDef, move) && IsFlinchGuaranteed(battlerAtk, BATTLE_PARTNER(battlerDef), move) + && aiData->effectiveness[battlerAtk][BATTLE_PARTNER(battlerDef)][gAiThinkingStruct->movesetIndex] != UQ_4_12(0.0)) + ADJUST_SCORE(-5); + // check non-user target if (!(moveTarget & MOVE_TARGET_USER)) { - if (CanAbilityBlockMove(battlerAtk, battlerDef, abilityAtk, abilityDef, move, ABILITY_CHECK_TRIGGER_AI)) + if (Ai_IsPriorityBlocked(battlerAtk, battlerDef, move, aiData)) RETURN_SCORE_MINUS(20); - if (CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, move, moveType, ABILITY_CHECK_TRIGGER_AI)) + if (CanAbilityBlockMove(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) + RETURN_SCORE_MINUS(20); + + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, move, moveType, AI_CHECK)) RETURN_SCORE_MINUS(20); switch (abilityDef) @@ -1136,15 +1177,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case MOVE_EFFECT_BURN: ADJUST_SCORE(-5); break; + default: + break; } break; - break; case ABILITY_WONDER_GUARD: if (effectiveness < UQ_4_12(2.0)) RETURN_SCORE_MINUS(20); break; case ABILITY_JUSTIFIED: - if (moveType == TYPE_DARK && !IsBattleMoveStatus(move) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (moveType == TYPE_DARK && !IsBattleMoveStatus(move) && !IsTargetingPartner(battlerAtk, battlerDef)) RETURN_SCORE_MINUS(10); break; case ABILITY_RATTLED: @@ -1186,10 +1228,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && IsNonVolatileStatusMove(move)) RETURN_SCORE_MINUS(10); break; + default: + break; } // def ability checks // target partner ability checks & not attacking partner - if (isDoubleBattle) + if (hasTwoOpponents) { switch (aiData->abilities[BATTLE_PARTNER(battlerDef)]) { @@ -1217,29 +1261,31 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsAromaVeilProtectedEffect(moveEffect)) RETURN_SCORE_MINUS(10); break; + default: + break; } } // def partner ability checks // gen7+ dark type mons immune to priority->elevated moves from prankster - if (B_PRANKSTER_DARK_TYPES >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) + if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move) && !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) RETURN_SCORE_MINUS(10); // terrain & effect checks - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, abilityDef, aiData->holdEffects[battlerDef], STATUS_FIELD_ELECTRIC_TERRAIN)) { if (nonVolatileStatus == MOVE_EFFECT_SLEEP) RETURN_SCORE_MINUS(20); } - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, abilityDef, aiData->holdEffects[battlerDef], STATUS_FIELD_MISTY_TERRAIN)) { if (IsNonVolatileStatusMove(move) || IsConfusionMoveEffect(moveEffect)) RETURN_SCORE_MINUS(20); } - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0) + if (IsBattlerTerrainAffected(battlerAtk, abilityAtk, aiData->holdEffects[battlerAtk], STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0) { RETURN_SCORE_MINUS(20); } @@ -1251,7 +1297,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gDisableStructs[battlerAtk].throatChopTimer > gBattleTurnCounter && IsSoundMove(move)) return 0; // Can't even select move at all // heal block check - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(battlerAtk, move)) + if (gBattleMons[battlerAtk].volatiles.healBlock && IsHealBlockPreventingMove(battlerAtk, move)) return 0; // Can't even select heal blocked move // primal weather check @@ -1290,7 +1336,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (moveEffect) { case EFFECT_HIT: // only applies to Vital Throw - if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40) + if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && aiData->hpPercents[battlerAtk] < 40) ADJUST_SCORE(-2); // don't want to move last break; default: @@ -1402,7 +1448,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_CHARGE: - if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP) + if (gBattleMons[battlerAtk].volatiles.charge) ADJUST_SCORE(-20); else if (!HasMoveWithType(battlerAtk, TYPE_ELECTRIC)) ADJUST_SCORE(-10); @@ -1460,13 +1506,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_ROTOTILLER: - if (isDoubleBattle) + if (hasPartner) { if (!(IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && IsBattlerGrounded(battlerAtk) + && AI_IsBattlerGrounded(battlerAtk) && (BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_ATK) || BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPATK))) && !(IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) - && IsBattlerGrounded(BATTLE_PARTNER(battlerAtk)) + && AI_IsBattlerGrounded(BATTLE_PARTNER(battlerAtk)) && aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_CONTRARY && (BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_ATK) || BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPATK)))) @@ -1475,7 +1521,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } } else if (!(IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && IsBattlerGrounded(battlerAtk) + && AI_IsBattlerGrounded(battlerAtk) && (BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_ATK) || BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPATK)))) { ADJUST_SCORE(-10); @@ -1491,12 +1537,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; } - else if (!isDoubleBattle) - { - ADJUST_SCORE(-10); // no partner and our stats wont rise, so don't use - } - - if (isDoubleBattle) + else if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1509,6 +1550,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // nor our or our partner's ability is plus/minus } } + else + { + ADJUST_SCORE(-10); // no partner and our stats wont rise, so don't use + } break; case EFFECT_ACUPRESSURE: if (DoesSubstituteBlockMove(battlerAtk, battlerDef, move) || AreBattlersStatsMaxed(battlerDef)) @@ -1522,12 +1567,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (!BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) ADJUST_SCORE(-8); } - else if (!isDoubleBattle) - { - ADJUST_SCORE(-10); // our stats wont rise from this move - } - - if (isDoubleBattle) + else if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1541,44 +1581,48 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // nor our or our partner's ability is plus/minus } } + else + { + ADJUST_SCORE(-10); // our stats wont rise from this move + } break; // stat lowering effects case EFFECT_ATTACK_DOWN: case EFFECT_ATTACK_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); break; case EFFECT_DEFENSE_DOWN: case EFFECT_DEFENSE_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_DEF)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_DEF)) ADJUST_SCORE(-10); break; case EFFECT_SPEED_DOWN: case EFFECT_SPEED_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-10); break; case EFFECT_SPECIAL_ATTACK_DOWN: case EFFECT_SPECIAL_ATTACK_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-10); break; case EFFECT_SPECIAL_DEFENSE_DOWN: case EFFECT_SPECIAL_DEFENSE_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPDEF)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPDEF)) ADJUST_SCORE(-10); break; case EFFECT_ACCURACY_DOWN: case EFFECT_ACCURACY_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ACC)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ACC)) ADJUST_SCORE(-10); break; case EFFECT_EVASION_DOWN: case EFFECT_EVASION_DOWN_2: case EFFECT_TICKLE: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_DEF)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_DEF)) ADJUST_SCORE(-8); break; case EFFECT_VENOM_DRENCH: @@ -1588,18 +1632,18 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-8); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-6); } break; case EFFECT_NOBLE_ROAR: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-8); break; case EFFECT_CAPTIVATE: @@ -1608,7 +1652,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; // other case EFFECT_HAZE: - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); // partner already using haze } @@ -1632,19 +1676,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // AI_CBM_HighRiskForDamage if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(-10); - if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + if (HasDamagingMove(battlerDef) && !(gBattleMons[battlerAtk].volatiles.substitute || IsBattlerIncapacitated(battlerDef, abilityDef) || gBattleMons[battlerDef].volatiles.infatuation || gBattleMons[battlerDef].volatiles.confusionTurns)) ADJUST_SCORE(-10); - if (HasMoveWithEffect(battlerAtk, EFFECT_SUBSTITUTE) && !(gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)) + if (HasMoveWithEffect(battlerAtk, EFFECT_SUBSTITUTE) && !gBattleMons[battlerAtk].volatiles.substitute) ADJUST_SCORE(-10); if (HasNonVolatileMoveEffect(battlerAtk, MOVE_EFFECT_SLEEP) && ! (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)) ADJUST_SCORE(-10); break; case EFFECT_COUNTER: case EFFECT_MIRROR_COAT: - if (IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION)) + if (IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) ADJUST_SCORE(-1); if ((predictedMove == MOVE_NONE || GetBattleMoveCategory(predictedMove) == DAMAGE_CATEGORY_STATUS || DoesSubstituteBlockMove(battlerAtk, BATTLE_PARTNER(battlerDef), predictedMove)) @@ -1661,27 +1707,29 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_TOXIC_THREAD: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-1); // may still want to just poison - //fallthrough + if (!AI_CanPoison(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; case EFFECT_LIGHT_SCREEN: - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_LIGHTSCREEN - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_REFLECT: - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_REFLECT - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_REFLECT | SIDE_STATUS_AURORA_VEIL) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_AURORA_VEIL: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_AURORA_VEIL - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) - || !(weather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || !(weather & (B_WEATHER_ICY_ANY))) ADJUST_SCORE(-10); break; case EFFECT_SHEER_COLD: - if (B_SHEER_COLD_IMMUNITY >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) + if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) RETURN_SCORE_MINUS(20); // fallthrough case EFFECT_OHKO: @@ -1692,21 +1740,26 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MIST: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_MIST - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_FOCUS_ENERGY: - if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (gBattleMons[battlerAtk].volatiles.dragonCheer || gBattleMons[battlerAtk].volatiles.focusEnergy) + ADJUST_SCORE(-10); + break; + case EFFECT_NON_VOLATILE_STATUS: + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_CONFUSE: case EFFECT_SWAGGER: case EFFECT_FLATTER: - if (!AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) + || !AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_SUBSTITUTE: - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) + if (gBattleMons[battlerAtk].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) ADJUST_SCORE(-8); else if (aiData->hpPercents[battlerAtk] <= 25) ADJUST_SCORE(-10); @@ -1716,7 +1769,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_SHED_TAIL: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) + if (gBattleMons[battlerAtk].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) ADJUST_SCORE(-8); else if (aiData->hpPercents[battlerAtk] <= 50) ADJUST_SCORE(-10); @@ -1724,7 +1777,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; case EFFECT_LEECH_SEED: - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED + if (gBattleMons[battlerDef].volatiles.leechSeed || IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -1736,9 +1789,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (gDisableStructs[battlerDef].disableTimer == 0 && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) - && !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to disable @@ -1760,7 +1813,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to encore @@ -1787,7 +1840,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NIGHTMARE: - if (gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) + if (gBattleMons[battlerDef].volatiles.nightmare) ADJUST_SCORE(-10); else if (!AI_IsBattlerAsleepOrComatose(battlerDef)) ADJUST_SCORE(-8); @@ -1797,7 +1850,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CURSE: if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) { - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED + if (gBattleMons[battlerDef].volatiles.cursed || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] <= 50) @@ -1819,7 +1872,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // only one mon needs to set up the last layer of Spikes break; case EFFECT_STEALTH_ROCK: - if (gSideTimers[GetBattlerSide(battlerDef)].stealthRockAmount > 0 + if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STEALTH_ROCK) || PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) //Only one mon needs to set up Stealth Rocks ADJUST_SCORE(-10); break; @@ -1830,13 +1883,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // only one mon needs to set up the last layer of Toxic Spikes break; case EFFECT_STICKY_WEB: - if (gSideTimers[GetBattlerSide(battlerDef)].stickyWebAmount) + if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); - else if (PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) && gSideTimers[GetBattlerSide(battlerDef)].stickyWebAmount) + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: - if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT) + if (gBattleMons[battlerDef].volatiles.foresight) ADJUST_SCORE(-10); else if (gBattleMons[battlerDef].statStages[STAT_EVASION] <= 4 || !(IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST)) @@ -1844,19 +1897,19 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-9); break; case EFFECT_PERISH_SONG: - if (isDoubleBattle) + if (!isBattle1v1) { if (CountUsablePartyMons(battlerAtk) == 0 && aiData->abilities[battlerAtk] != ABILITY_SOUNDPROOF - && aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_SOUNDPROOF - && CountUsablePartyMons(FOE(battlerAtk)) >= 1) + && CountUsablePartyMons(battlerDef) >= 1 + && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] != ABILITY_SOUNDPROOF || !IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))) { ADJUST_SCORE(-10); //Don't wipe your team if you're going to lose } - else if ((!IsBattlerAlive(FOE(battlerAtk)) || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF - || gStatuses3[FOE(battlerAtk)] & STATUS3_PERISH_SONG) - && (!IsBattlerAlive(BATTLE_PARTNER(FOE(battlerAtk))) || aiData->abilities[BATTLE_PARTNER(FOE(battlerAtk))] == ABILITY_SOUNDPROOF - || gStatuses3[BATTLE_PARTNER(FOE(battlerAtk))] & STATUS3_PERISH_SONG)) + else if ((!IsBattlerAlive(LEFT_FOE(battlerAtk)) || aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_SOUNDPROOF + || gBattleMons[LEFT_FOE(battlerAtk)].volatiles.perishSong) + && (!IsBattlerAlive(RIGHT_FOE(battlerAtk)) || aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_SOUNDPROOF + || gBattleMons[RIGHT_FOE(battlerAtk)].volatiles.perishSong)) { ADJUST_SCORE(-10); //Both enemies are perish songed } @@ -1871,38 +1924,30 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && CountUsablePartyMons(battlerDef) >= 1) ADJUST_SCORE(-10); - if (gStatuses3[FOE(battlerAtk)] & STATUS3_PERISH_SONG || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF) + if (gBattleMons[battlerDef].volatiles.perishSong || aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) ADJUST_SCORE(-10); } break; case EFFECT_SANDSTORM: if (weather & (B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_SUNNY_DAY: if (weather & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_RAIN_DANCE: if (weather & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_HAIL: - if (weather & (B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) - ADJUST_SCORE(-8); - else if (weather & B_WEATHER_SNOW) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow - break; case EFFECT_SNOWSCAPE: - if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); - else if (weather & B_WEATHER_HAIL) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow break; case EFFECT_ATTRACT: if (!AI_CanBeInfatuated(battlerAtk, battlerDef, aiData->abilities[battlerDef])) @@ -1910,7 +1955,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SAFEGUARD: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_SAFEGUARD - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_MAGNITUDE: @@ -1924,9 +1969,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_BATON_PASS: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE - || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) - || AnyStatIsRaised(battlerAtk)) + else if (gBattleMons[battlerAtk].volatiles.substitute + || gBattleMons[battlerAtk].volatiles.powerTrick + || gBattleMons[battlerAtk].volatiles.magnetRise + || gBattleMons[battlerAtk].volatiles.aquaRing + || gBattleMons[battlerAtk].volatiles.root + || AnyStatIsRaised(battlerAtk)) break; else ADJUST_SCORE(-6); @@ -1936,10 +1984,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CHILLY_RECEPTION: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) + else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); - else if (weather & B_WEATHER_HAIL) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow break; case EFFECT_BELLY_DRUM: case EFFECT_FILLET_AWAY: @@ -1947,7 +1994,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) ADJUST_SCORE(-10); - else if (aiData->hpPercents[battlerAtk] <= 60) + else if (aiData->hpPercents[battlerAtk] <= 60 && !IsConsideringZMove(battlerAtk, battlerDef, move)) ADJUST_SCORE(-10); break; case EFFECT_FUTURE_SIGHT: @@ -1963,6 +2010,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_FIRST_TURN_ONLY: if (!gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(-10); + if (HasChoiceEffect(battlerAtk)) + ADJUST_SCORE(-5); break; case EFFECT_STOCKPILE: if (gDisableStructs[battlerAtk].stockpileCounter >= 3) @@ -1984,7 +2033,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TORMENT: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); - else if (gBattleMons[battlerDef].status2 & STATUS2_TORMENT + else if (gBattleMons[battlerDef].volatiles.torment || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); @@ -2001,12 +2050,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_FOLLOW_ME: case EFFECT_HELPING_HAND: - if (!isDoubleBattle - || !IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) + if (!hasPartner + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove)) || gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battlerAtk)] != PARTY_SIZE) //Partner is switching out. - ADJUST_SCORE(-10); + ADJUST_SCORE(-20); break; case EFFECT_TRICK: case EFFECT_KNOCK_OFF: @@ -2015,11 +2063,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_INGRAIN: - if (gStatuses3[battlerAtk] & STATUS3_ROOTED) + if (gBattleMons[battlerAtk].volatiles.root) ADJUST_SCORE(-10); break; case EFFECT_AQUA_RING: - if (gStatuses3[battlerAtk] & STATUS3_AQUA_RING) + if (gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(-10); break; case EFFECT_RECYCLE: @@ -2027,11 +2075,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_IMPRISON: - if (gStatuses3[battlerAtk] & STATUS3_IMPRISONED_OTHERS) + if (gBattleMons[battlerAtk].volatiles.imprison) ADJUST_SCORE(-10); break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_FROSTBITE))) + if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)) ADJUST_SCORE(-10); break; case EFFECT_PSYCHO_SHIFT: @@ -2052,14 +2100,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MUD_SPORT: if (gFieldStatuses & STATUS_FIELD_MUDSPORT - || gStatuses4[battlerAtk] & STATUS4_MUD_SPORT - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || gBattleMons[battlerAtk].volatiles.mudSport + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_WATER_SPORT: if (gFieldStatuses & STATUS_FIELD_WATERSPORT - || gStatuses4[battlerAtk] & STATUS4_WATER_SPORT - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || gBattleMons[battlerAtk].volatiles.waterSport + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_ABSORB: @@ -2069,25 +2117,29 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_STRENGTH_SAP: if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, aiData->abilities[battlerDef], STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); break; case EFFECT_COPYCAT: case EFFECT_MIRROR_MOVE: - return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + else + ADJUST_SCORE(-10); + break; case EFFECT_FLOWER_SHIELD: if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && !(isDoubleBattle && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) + && !(hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) ADJUST_SCORE(-10); break; case EFFECT_AROMATIC_MIST: - if (!isDoubleBattle || gBattleMons[BATTLE_PARTNER(battlerAtk)].hp == 0 || !BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPDEF)) + if (!hasPartner || !BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPDEF)) ADJUST_SCORE(-10); break; case EFFECT_BIDE: if (!HasDamagingMove(battlerDef) || aiData->hpPercents[battlerAtk] < 30 //Close to death - || gBattleMons[battlerDef].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) //No point in biding if can't take damage + || gBattleMons[battlerDef].status1 & STATUS1_INCAPACITATED) //No point in biding if can't take damage ADJUST_SCORE(-10); break; case EFFECT_HIT_SWITCH_TARGET: @@ -2095,7 +2147,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // don't scare away pokemon twice else if (aiData->hpPercents[battlerDef] < 10 && GetBattlerSecondaryDamage(battlerDef)) ADJUST_SCORE(-10); // don't blow away mon that will faint soon - else if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) + else if (gBattleMons[battlerDef].volatiles.perishSong) ADJUST_SCORE(-10); break; case EFFECT_CONVERSION: @@ -2118,12 +2170,26 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MORNING_SUN: case EFFECT_SYNTHESIS: case EFFECT_MOONLIGHT: - if ((AI_GetWeather() & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_FOG))) - ADJUST_SCORE(-3); - else if (AI_BattlerAtMaxHp(battlerAtk)) + if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 90) ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better + else if ((AI_GetWeather() & (B_WEATHER_LOW_LIGHT))) + ADJUST_SCORE(-3); + break; + case EFFECT_LIFE_DEW: + if (AI_BattlerAtMaxHp(battlerAtk)) + { + if (hasPartner) + { + if (AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk))) + ADJUST_SCORE(-10); + } + else + { + ADJUST_SCORE(-10); + } + } break; case EFFECT_PURIFY: if (!(gBattleMons[battlerDef].status1 & STATUS1_ANY)) @@ -2141,13 +2207,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-6); break; case EFFECT_TRANSFORM: - if (gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED - || (gBattleMons[battlerDef].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE))) //Leave out Illusion b/c AI is supposed to be fooled + if (gBattleMons[battlerAtk].volatiles.transformed + || gBattleMons[battlerDef].volatiles.transformed + || gBattleMons[battlerDef].volatiles.substitute) //Leave out Illusion b/c AI is supposed to be fooled ADJUST_SCORE(-10); break; case EFFECT_SPITE: case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) @@ -2166,14 +2233,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) //TODO break; case EFFECT_LOCK_ON: - if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS + if (gBattleMons[battlerDef].volatiles.lockOn || aiData->abilities[battlerAtk] == ABILITY_NO_GUARD || aiData->abilities[battlerDef] == ABILITY_NO_GUARD || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_LASER_FOCUS: - if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS) + if (gBattleMons[battlerDef].volatiles.laserFocus) ADJUST_SCORE(-10); else if (aiData->abilities[battlerDef] == ABILITY_SHELL_ARMOR || aiData->abilities[battlerDef] == ABILITY_BATTLE_ARMOR) ADJUST_SCORE(-8); @@ -2185,13 +2252,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_DESTINY_BOND: if (DoesDestinyBondFail(battlerAtk)) ADJUST_SCORE(-10); - if (gBattleMons[battlerDef].status2 & STATUS2_DESTINY_BOND) + if (gBattleMons[battlerDef].volatiles.destinyBond) ADJUST_SCORE(-10); else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); break; case EFFECT_HEAL_BELL: - if (!AnyPartyMemberStatused(battlerAtk, IsSoundMove(move)) || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (!AnyPartyMemberStatused(battlerAtk, IsSoundMove(move)) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_ENDURE: @@ -2210,14 +2277,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); decreased = TRUE; } + break; case PROTECT_WIDE_GUARD: if(!(GetBattlerMoveTargetType(battlerAtk, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))) { ADJUST_SCORE(-10); decreased = TRUE; } + break; case PROTECT_CRAFTY_SHIELD: - if (!isDoubleBattle) + if (!hasPartner) { ADJUST_SCORE(-10); decreased = TRUE; @@ -2253,7 +2322,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else if (gDisableStructs[battlerAtk].protectUses == 1 && Random() % 100 < 50) { - if (!isDoubleBattle) + if (isBattle1v1) ADJUST_SCORE(-6); else ADJUST_SCORE(-10); //Don't try double protecting in doubles @@ -2276,7 +2345,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_MIRACLE_EYE: - if (gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) + if (gBattleMons[battlerDef].volatiles.miracleEye) ADJUST_SCORE(-10); if (gBattleMons[battlerDef].statStages[STAT_EVASION] <= 4 @@ -2284,28 +2353,44 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-9); break; - case EFFECT_DEFOG: - if (gSideStatuses[GetBattlerSide(battlerDef)] - & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) - || gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY) + case EFFECT_COURT_CHANGE: + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_BAD_COURT) + ADJUST_SCORE(BAD_EFFECT); + if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_GOOD_COURT) + ADJUST_SCORE(BAD_EFFECT); + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerAtk) != 0) + ADJUST_SCORE(WORST_EFFECT); + if (hasPartner) { - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the Court Change + { + ADJUST_SCORE(-10); + break; // Don't use Defog if partner is going to set up hazards + } + } + break; + case EFFECT_DEFOG: + if (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) + || AreAnyHazardsOnSide(GetBattlerSide(battlerAtk))) + { + if (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); //Only need one hazards removal break; } } - if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef))) { ADJUST_SCORE(-10); //Don't blow away opposing hazards break; } - if (isDoubleBattle) + if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards - && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove)) // partner is going to set up before the potential Defog + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // partner is going to set up before the potential Defog { ADJUST_SCORE(-10); break; // Don't use Defog if partner is going to set up hazards @@ -2314,7 +2399,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // evasion check if (gBattleMons[battlerDef].statStages[STAT_EVASION] == MIN_STAT_STAGE - || ((aiData->abilities[battlerDef] == ABILITY_CONTRARY) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner + || ((aiData->abilities[battlerDef] == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner ADJUST_SCORE(-10); break; case EFFECT_PSYCH_UP: // haze stats check @@ -2333,12 +2418,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SEMI_INVULNERABLE: if (predictedMove != MOVE_NONE - && AI_IsSlower(battlerAtk, battlerDef, move) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && GetMoveEffect(predictedMove) == EFFECT_SEMI_INVULNERABLE) ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you if (BattlerWillFaintFromWeather(battlerAtk, aiData->abilities[battlerAtk]) - && GetMoveTwoTurnAttackStatus(move) == STATUS3_ON_AIR) + && GetMoveTwoTurnAttackStatus(move) == STATE_ON_AIR) ADJUST_SCORE(-10); // Attacker will faint while in the air break; case EFFECT_HEALING_WISH: //healing wish, lunar dance @@ -2352,7 +2437,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NATURE_POWER: - return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + predictedMove = GetNaturePowerMove(battlerAtk); + if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + break; case EFFECT_TAUNT: if (gDisableStructs[battlerDef].tauntTimer > 0 || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) @@ -2363,26 +2451,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || !CanBattlerGetOrLoseItem(battlerAtk, gBattleMons[battlerAtk].item)) // AI knows its own item ADJUST_SCORE(-10); break; - case EFFECT_ROLE_PLAY: - if (aiData->abilities[battlerAtk] == aiData->abilities[battlerDef] - || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied) - ADJUST_SCORE(-10); - else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5)) - ADJUST_SCORE(-4); - break; - case EFFECT_DOODLE: // Same as Role Play, but also check if the partner's ability should be replaced - if (aiData->abilities[battlerAtk] == aiData->abilities[battlerDef] - || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == aiData->abilities[battlerDef] - || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[BATTLE_PARTNER(battlerAtk)]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied) - ADJUST_SCORE(-10); - else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5) || IsAbilityOfRating(aiData->abilities[BATTLE_PARTNER(battlerAtk)], 5)) - ADJUST_SCORE(-4); - break; case EFFECT_WISH: if (gWishFutureKnock.wishCounter[battlerAtk] > gBattleTurnCounter) ADJUST_SCORE(-10); @@ -2396,75 +2464,51 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_YAWN: - if (gStatuses3[battlerDef] & STATUS3_YAWN) + if (gBattleMons[battlerDef].volatiles.yawn) ADJUST_SCORE(-10); else if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove)) ADJUST_SCORE(-10); if (PartnerMoveActivatesSleepClause(aiData->partnerMove)) ADJUST_SCORE(-20); break; - case EFFECT_SKILL_SWAP: - if (aiData->abilities[battlerAtk] == ABILITY_NONE || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSwapped - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeSwapped - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - ADJUST_SCORE(-10); - break; - case EFFECT_WORRY_SEED: - if (aiData->abilities[battlerDef] == ABILITY_INSOMNIA - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - break; - case EFFECT_GASTRO_ACID: - if (gStatuses3[battlerDef] & STATUS3_GASTRO_ACID - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeSuppressed) - ADJUST_SCORE(-10); - break; + case EFFECT_DOODLE: case EFFECT_ENTRAINMENT: - if (aiData->abilities[battlerAtk] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeCopied - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - ADJUST_SCORE(-10); - break; + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: case EFFECT_SIMPLE_BEAM: - if (aiData->abilities[battlerDef] == ABILITY_SIMPLE - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + if (!CanEffectChangeAbility(battlerAtk, battlerDef, moveEffect, aiData) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + ADJUST_AND_RETURN_SCORE(NO_DAMAGE_OR_FAILS); break; case EFFECT_SNATCH: if (!HasMoveWithFlag(battlerDef, MoveCanBeSnatched) - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_POWER_TRICK: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].defense >= gBattleMons[battlerAtk].attack && !HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) ADJUST_SCORE(-10); break; case EFFECT_POWER_SWAP: // Don't use if attacker's stat stages are higher than opponents - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].statStages[STAT_ATK] >= gBattleMons[battlerDef].statStages[STAT_ATK] && gBattleMons[battlerAtk].statStages[STAT_SPATK] >= gBattleMons[battlerDef].statStages[STAT_SPATK]) ADJUST_SCORE(-10); break; case EFFECT_GUARD_SWAP: // Don't use if attacker's stat stages are higher than opponents - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].statStages[STAT_DEF] >= gBattleMons[battlerDef].statStages[STAT_DEF] && gBattleMons[battlerAtk].statStages[STAT_SPDEF] >= gBattleMons[battlerDef].statStages[STAT_SPDEF]) ADJUST_SCORE(-10); break; case EFFECT_SPEED_SWAP: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2477,7 +2521,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_HEART_SWAP: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2494,11 +2538,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_POWER_SPLIT: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) - { - ADJUST_SCORE(-10); - } - else + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 atkAttack = gBattleMons[battlerAtk].attack; u32 defAttack = gBattleMons[battlerDef].attack; @@ -2511,11 +2551,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_GUARD_SPLIT: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) - { - ADJUST_SCORE(-10); - } - else + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 atkDefense = gBattleMons[battlerAtk].defense; u32 defDefense = gBattleMons[battlerDef].defense; @@ -2530,9 +2566,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ME_FIRST: if (predictedMove != MOVE_NONE) { - if (AI_IsSlower(battlerAtk, battlerDef, move)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail - else + else if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); } else @@ -2545,29 +2581,38 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_GRASSY_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_ELECTRIC_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_PSYCHIC_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_MISTY_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) + ADJUST_SCORE(-10); + break; + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_PLEDGE: - if (isDoubleBattle && gBattleMons[BATTLE_PARTNER(battlerAtk)].hp > 0) + if (hasPartner && gBattleMons[BATTLE_PARTNER(battlerAtk)].hp > 0) { if (aiData->partnerMove != MOVE_NONE && GetMoveEffect(aiData->partnerMove) == EFFECT_PLEDGE && move != aiData->partnerMove) // Different pledge moves { - if (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) + if (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_INCAPACITATED) // && gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 != 1) // Will wake up this turn - how would AI know ADJUST_SCORE(-10); // Don't use combo move if your partner will cause failure } @@ -2576,20 +2621,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TRICK_ROOM: if (PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TRICK_ROOM)) { - ADJUST_SCORE(-10); + // This only happens if the ally already rolled on double trick room on final turn. + // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1)) + ADJUST_SCORE(PERFECT_EFFECT); + else + ADJUST_SCORE(-10); } else if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS)) { - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) // Trick Room Up - { - if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) // Attacker side slower than target side - ADJUST_SCORE(-10); // Keep the Trick Room up - } - else - { - if (GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) // Attacker side faster than target side - ADJUST_SCORE(-10); // Keep the Trick Room down - } + // Don't set a trick room you don't benefit from. + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(-10); + // Don't unset a trick room that doesn't harm you unless it's about to expire. + else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(-10); } break; case EFFECT_MAGIC_ROOM: @@ -2638,7 +2684,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_EMBARGO: if (!IsBattlerItemEnabled(battlerAtk) - || gStatuses3[battlerDef] & STATUS3_EMBARGO + || gBattleMons[battlerDef].volatiles.embargo || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; @@ -2648,15 +2694,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_TELEKINESIS: - if (gStatuses3[battlerDef] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) - || gFieldStatuses & STATUS_FIELD_GRAVITY - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_IRON_BALL - || IsTelekinesisBannedSpecies(gBattleMons[battlerDef].species) - || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + if (gBattleMons[battlerDef].volatiles.telekinesis + || gBattleMons[battlerDef].volatiles.root + || gBattleMons[battlerDef].volatiles.smackDown + || gFieldStatuses & STATUS_FIELD_GRAVITY + || aiData->holdEffects[battlerDef] == HOLD_EFFECT_IRON_BALL + || IsTelekinesisBannedSpecies(gBattleMons[battlerDef].species) + || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_HEAL_BLOCK: - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK + if (gBattleMons[battlerDef].volatiles.healBlock || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; @@ -2676,16 +2724,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_HEAL_PULSE: // and floral healing - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) // Don't heal enemies + if (!IsTargetingPartner(battlerAtk, battlerDef)) // Don't heal enemies { ADJUST_SCORE(-10); break; } // fallthrough case EFFECT_HIT_ENEMY_HEAL_ALLY: // pollen puff - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerDef].volatiles.healBlock) return 0; // cannot even select if (AI_BattlerAtMaxHp(battlerDef)) ADJUST_SCORE(-10); @@ -2694,13 +2742,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_ELECTRIFY: - if (AI_IsSlower(battlerAtk, battlerDef, move) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) //|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_TOPSY_TURVY: - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 targetPositiveStages = CountPositiveStatStages(battlerDef); u32 targetNegativeStages = CountNegativeStatStages(battlerDef); @@ -2721,12 +2769,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_HOLD_HANDS: case EFFECT_CELEBRATE: case EFFECT_HAPPY_HOUR: + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + break; ADJUST_SCORE(-10); break; case EFFECT_INSTRUCT: { u32 instructedMove; - if (AI_IsSlower(battlerAtk, battlerDef, move)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = predictedMove; else instructedMove = gLastMoves[battlerDef]; @@ -2736,16 +2786,16 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || MoveHasAdditionalEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE) || IsZMove(instructedMove) || (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF) - || gBattleMons[battlerDef].status2 & STATUS2_MULTIPLETURNS + || gBattleMons[battlerDef].volatiles.multipleTurns || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); } else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); - else if (isDoubleBattle) + else if (hasPartner) { - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (!IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); } else @@ -2762,29 +2812,28 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_QUASH: - if (!isDoubleBattle - || AI_IsSlower(battlerAtk, battlerDef, move) + if (!hasPartner + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef) - || !isDoubleBattle - || AI_IsSlower(battlerAtk, battlerDef, move) + if (!IsTargetingPartner(battlerAtk, battlerDef) + || !hasPartner + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_SUCKER_PUNCH: - if (predictedMove != MOVE_NONE) - { - if (IsBattleMoveStatus(predictedMove) || AI_IsSlower(battlerAtk, battlerDef, move)) // Opponent going first - ADJUST_SCORE(-10); - } + if ((HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_STATUS) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_CHANCE)) // Player has a status move + || (IsBattleMoveStatus(predictedMove) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_PREDICTION_CHANCE) && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_PREDICT_MOVE)) // AI actively predicting incoming status move + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent going first + ADJUST_SCORE(-10); break; case EFFECT_TAILWIND: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND) - || gFieldStatuses & STATUS_FIELD_TRICK_ROOM) + || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1))) ADJUST_SCORE(-10); break; case EFFECT_LUCKY_CHANT: @@ -2794,10 +2843,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAGNET_RISE: if (gFieldStatuses & STATUS_FIELD_GRAVITY - || gDisableStructs[battlerAtk].magnetRiseTimer != 0 + || gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_IRON_BALL - || gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_MAGNET_RISE | STATUS3_SMACKED_DOWN) - || !IsBattlerGrounded(battlerAtk)) + || gBattleMons[battlerAtk].volatiles.smackDown + || gBattleMons[battlerAtk].volatiles.root + || gBattleMons[battlerAtk].volatiles.magnetRise + || !AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(-10); break; case EFFECT_CAMOUFLAGE: @@ -2813,7 +2864,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_FLAIL: - if (AI_IsSlower(battlerAtk, battlerDef, move) // Opponent should go first + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent should go first || aiData->hpPercents[battlerAtk] > 50) ADJUST_SCORE(-4); break; @@ -2830,25 +2881,25 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || GetBattlerWeight(battlerDef) >= 2000) //200.0 kg ADJUST_SCORE(-10); break; - /*case EFFECT_NO_RETREAT: - if (TrappedByNoRetreat(battlerAtk)) + case EFFECT_NO_RETREAT: + if (gBattleMons[battlerAtk].volatiles.noRetreat) ADJUST_SCORE(-10); break; case EFFECT_EXTREME_EVOBOOST: - if (MainStatsMaxed(battlerAtk)) + if (AreBattlersStatsMaxed(battlerAtk)) ADJUST_SCORE(-10); break; case EFFECT_CLANGOROUS_SOUL: if (gBattleMons[battlerAtk].hp <= gBattleMons[battlerAtk].maxHP / 3) ADJUST_SCORE(-10); - break;*/ + break; case EFFECT_REVIVAL_BLESSING: if (GetFirstFaintedPartyIndex(battlerAtk) == PARTY_SIZE) ADJUST_SCORE(-10); else if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) ADJUST_SCORE(-10); else if (CanTargetFaintAi(battlerDef, battlerAtk) - && AI_IsSlower(battlerAtk, battlerDef, move)) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); break; case EFFECT_JUNGLE_HEALING: @@ -2879,12 +2930,24 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 defPrio = GetBattleMovePriority(battlerDef, aiData->abilities[battlerDef], predictedMove); if (predictedMove == MOVE_NONE || IsBattleMoveStatus(predictedMove) - || AI_IsSlower(battlerAtk, battlerDef, move) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || defPrio < 1 || defPrio > 3) // Opponent going first or not using priority move ADJUST_SCORE(-10); } break; + case EFFECT_TEATIME: + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; + case EFFECT_DARK_VOID: + if (B_DARK_VOID_FAIL >= GEN_7 && gBattleMons[battlerAtk].species != SPECIES_DARKRAI) + ADJUST_SCORE(-10); + break; + case EFFECT_HYPERSPACE_FURY: + if (gBattleMons[battlerAtk].species != SPECIES_HOOPA_UNBOUND) + ADJUST_SCORE(-10); + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks @@ -2920,18 +2983,18 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // Choice items - if (HOLD_EFFECT_CHOICE(aiData->holdEffects[battlerAtk]) && IsBattlerItemEnabled(battlerAtk)) + if (IsHoldEffectChoice(aiData->holdEffects[battlerAtk]) && IsBattlerItemEnabled(battlerAtk)) { // Don't use user-target moves ie. Swords Dance, with exceptions if ((moveTarget & MOVE_TARGET_USER) && moveEffect != EFFECT_DESTINY_BOND && moveEffect != EFFECT_WISH && moveEffect != EFFECT_HEALING_WISH - && !(moveEffect == EFFECT_AURORA_VEIL && (AI_GetWeather() & (B_WEATHER_SNOW | B_WEATHER_HAIL)))) + && !(moveEffect == EFFECT_AURORA_VEIL && (AI_GetWeather() & B_WEATHER_ICY_ANY))) ADJUST_SCORE(-30); // Don't use a status move if the mon is the last one in the party, has no good switchin, or is trapped else if (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_STATUS && (CountUsablePartyMons(battlerAtk) < 1 || gAiLogicData->mostSuitableMonId[battlerAtk] == PARTY_SIZE - || (!AI_CanBattlerEscape(battlerAtk) && IsBattlerTrapped(battlerDef, battlerAtk)))) + || IsBattlerTrapped(battlerDef, battlerAtk))) ADJUST_SCORE(-30); } @@ -2944,8 +3007,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 movesetIndex = gAiThinkingStruct->movesetIndex; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (IsBattleMoveStatus(move)) @@ -2955,9 +3019,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, AI_ATTACKING) && effect != EFFECT_EXPLOSION && effect != EFFECT_MISTY_EXPLOSION) { - if (CanIndexMoveGuaranteeFaintTarget(battlerAtk, battlerDef, movesetIndex)) - ADJUST_SCORE(1); // Bonus point if the KO is guaranteed - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(FAST_KILL); else ADJUST_SCORE(SLOW_KILL); @@ -2966,7 +3028,10 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) > 0) { - ADJUST_SCORE(LAST_CHANCE); + if (RandomPercentage(RNG_AI_PRIORITIZE_LAST_CHANCE, PRIORITIZE_LAST_CHANCE_CHANCE)) + ADJUST_SCORE(SLOW_KILL + 2); // Don't outscore Fast Kill (which gets a bonus point in AI_CompareDamagingMoves), but do outscore Slow Kill getting the same + else + ADJUST_SCORE(LAST_CHANCE); } return score; @@ -2986,22 +3051,28 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 atkPartnerHoldEffect = aiData->holdEffects[BATTLE_PARTNER(battlerAtk)]; enum BattleMoveEffects partnerEffect = GetMoveEffect(aiData->partnerMove); bool32 partnerProtecting = IsAllyProtectingFromMove(battlerAtk, move, aiData->partnerMove) && !MoveIgnoresProtect(move); - bool32 attackerHasBadAbility = (gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating < 0); bool32 partnerHasBadAbility = (gAbilitiesInfo[atkPartnerAbility].aiRating < 0); u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); + bool32 hasPartner = HasPartner(battlerAtk); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING); - bool32 wouldPartnerFaint = CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) - && !partnerProtecting && IsBattlerAlive(battlerAtkPartner); + bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) + && !partnerProtecting; bool32 isFriendlyFireOK = !wouldPartnerFaint && (noOfHitsToKOPartner == 0 || noOfHitsToKOPartner > friendlyFireThreshold); // check what effect partner is using - if (aiData->partnerMove != 0) + if (aiData->partnerMove != 0 && hasPartner) { + // This catches weather, terrain, screens, etc + if (AreMovesEquivalent(battlerAtk, battlerAtkPartner, move, aiData->partnerMove)) + ADJUST_SCORE(-10); + switch (partnerEffect) { case EFFECT_HELPING_HAND: @@ -3009,21 +3080,19 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-7); break; case EFFECT_PERISH_SONG: - if (!(gBattleMons[battlerDef].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED))) + if (!(gBattleMons[battlerDef].volatiles.escapePrevention || gBattleMons[battlerDef].volatiles.wrapped)) { if (IsTrappingMove(aiData->partnerMove) || predictedMove == MOVE_INGRAIN) ADJUST_SCORE(WEAK_EFFECT); } break; - // Don't change weather if ally already decided to do so. - case EFFECT_SUNNY_DAY: - case EFFECT_HAIL: - case EFFECT_SNOWSCAPE: - case EFFECT_RAIN_DANCE: - case EFFECT_SANDSTORM: - case EFFECT_CHILLY_RECEPTION: - if (IsMoveEffectWeather(move)) - ADJUST_SCORE(-10); + case EFFECT_AFTER_YOU: + if (effect == EFFECT_TRICK_ROOM && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case EFFECT_TRICK_ROOM: + if (effect == EFFECT_AFTER_YOU && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(DECENT_EFFECT); break; default: break; @@ -3033,7 +3102,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Adjust for always crit moves if (MoveAlwaysCrits(aiData->partnerMove) && aiData->abilities[battlerAtk] == ABILITY_ANGER_POINT) { - if (AI_IsSlower(battlerAtk, battlerAtkPartner, move)) // Partner moving first + if (AI_IsSlower(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Partner moving first { // discourage raising our attack since it's about to be maxed out if (IsAttackBoostMoveEffect(effect)) @@ -3048,23 +3117,70 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (effect) { case EFFECT_HELPING_HAND: - if (!IsBattlerAlive(battlerAtkPartner) || !HasDamagingMove(battlerAtkPartner)) - ADJUST_SCORE(-20); + if (!hasPartner + || !HasDamagingMove(battlerAtkPartner) + || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove))) + { + ADJUST_SCORE(WORST_EFFECT); + } + else + { + u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, LEFT_FOE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, LEFT_FOE(battlerAtk), AI_ATTACKING); + u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, RIGHT_FOE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, RIGHT_FOE(battlerAtk), AI_ATTACKING); + + if (hasTwoOpponents) + { + // Might be about to die + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), battlerAtk) && CanTargetFaintAi(RIGHT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1 + && ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) + ADJUST_SCORE(GOOD_EFFECT); + } + else if (IsBattlerAlive(LEFT_FOE(battlerAtk))) + { + // Might be about to die + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1) + ADJUST_SCORE(GOOD_EFFECT); + } + else if (IsBattlerAlive(RIGHT_FOE(battlerAtk))) + { + // Might be about to die + if (CanTargetFaintAi(RIGHT_FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) + ADJUST_SCORE(GOOD_EFFECT); + + } + } break; case EFFECT_PERISH_SONG: if (aiData->partnerMove != 0 && HasTrappingMoveEffect(battlerAtkPartner)) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_MAGNET_RISE: - if (IsBattlerGrounded(battlerAtk) - && (HasMove(battlerAtkPartner, MOVE_EARTHQUAKE) || HasMove(battlerAtkPartner, MOVE_MAGNITUDE)) + if (AI_IsBattlerGrounded(battlerAtk) + && (HasMoveWithEffect(battlerAtkPartner, EFFECT_EARTHQUAKE) || HasMoveWithEffect(battlerAtkPartner, EFFECT_MAGNITUDE)) && (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != UQ_4_12(0.0))) // Doesn't resist ground move { RETURN_SCORE_PLUS(DECENT_EFFECT); // partner has earthquake or magnitude -> good idea to use magnet rise } break; case EFFECT_DRAGON_CHEER: - if (gBattleMons[battlerAtkPartner].status2 & STATUS2_FOCUS_ENERGY_ANY || !HasDamagingMove(battlerAtkPartner)) + if (gBattleMons[battlerAtkPartner].volatiles.dragonCheer + || gBattleMons[battlerAtkPartner].volatiles.focusEnergy + || !HasDamagingMove(battlerAtkPartner)) ADJUST_SCORE(-5); else if (atkPartnerHoldEffect == HOLD_EFFECT_SCOPE_LENS || IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_DRAGON) @@ -3072,6 +3188,20 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || HasMoveWithCriticalHitChance(battlerAtkPartner)) ADJUST_SCORE(GOOD_EFFECT); break; + case EFFECT_COACHING: + if (!hasPartner + || !HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)) + { + ADJUST_SCORE(WORST_EFFECT); + } + else + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), STAT_CHANGE_DEF)); + } + break; default: break; } // our effect relative to partner @@ -3079,38 +3209,20 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // consider global move effects switch (effect) { - case EFFECT_SANDSTORM: - if (ShouldSetSandstorm(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from sandstorm - } + // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. + // This unsets Trick Room and resets it with a full timer. + case EFFECT_TRICK_ROOM: + if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) + && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) + && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM) + && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) + ADJUST_SCORE(PERFECT_EFFECT); break; - case EFFECT_RAIN_DANCE: - if (ShouldSetRain(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from rain - } - break; - case EFFECT_SUNNY_DAY: - if (ShouldSetSun(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from sun - } - break; - case EFFECT_HAIL: - if (IsBattlerAlive(battlerAtkPartner) - && ShouldSetHail(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); // our partner benefits from hail - } - break; - case EFFECT_SNOWSCAPE: - case EFFECT_CHILLY_RECEPTION: - if (IsBattlerAlive(battlerAtkPartner) - && ShouldSetSnow(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); // our partner benefits from snow - } + case EFFECT_TAILWIND: + // Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind. + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) + && RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE)) + ADJUST_SCORE(BEST_EFFECT); break; default: break; @@ -3176,7 +3288,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - ADJUST_SCORE(-DECENT_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); } } // No reason to kill partner has been found. @@ -3205,7 +3317,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // check specific target - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { bool32 isMoveAffectedByPartnerAbility = TRUE; @@ -3222,7 +3334,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_ANGER_POINT: if (MoveAlwaysCrits(move) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && AI_IsFaster(battlerAtk, battlerAtkPartner, move) + && AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && isFriendlyFireOK) { if (MoveAlwaysCrits(move)) @@ -3254,7 +3366,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - else if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + else if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3300,7 +3412,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - else if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + else if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3316,7 +3428,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case ABILITY_WATER_COMPACTION: if (moveType == TYPE_WATER && isFriendlyFireOK - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3335,7 +3447,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case ABILITY_STEAM_ENGINE: if (isFriendlyFireOK && (moveType == TYPE_WATER || moveType == TYPE_FIRE) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3351,7 +3463,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_THERMAL_EXCHANGE: if (moveType == TYPE_FIRE && isFriendlyFireOK && !IsBattleMoveStatus(move) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3378,7 +3490,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3396,7 +3508,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(DECENT_EFFECT); } - if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3409,7 +3521,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_JUSTIFIED: if (moveType == TYPE_DARK && isFriendlyFireOK && !IsBattleMoveStatus(move) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3431,7 +3543,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_RATTLED: if (!IsBattleMoveStatus(move) && isFriendlyFireOK && (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3447,7 +3559,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_CONTRARY: case ABILITY_DEFIANT: case ABILITY_COMPETITIVE: - if (IsStatLoweringEffect(effect) && isFriendlyFireOK && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (IsStatLoweringEffect(effect) && isFriendlyFireOK && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3473,6 +3585,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (effect) { + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + AbilityChangeScore(battlerAtk, battlerAtkPartner, effect, &score, aiData); + return score; case EFFECT_SPICY_EXTRACT: if (AI_ShouldSpicyExtract(battlerAtk, battlerAtkPartner, move, aiData)) { @@ -3482,7 +3603,9 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_PURIFY: if (gBattleMons[battlerAtkPartner].status1 & STATUS1_ANY) { - RETURN_SCORE_PLUS(WEAK_EFFECT); + if (gBattleMons[battlerAtkPartner].status1 & STATUS1_CAN_MOVE) + RETURN_SCORE_PLUS(WEAK_EFFECT); + RETURN_SCORE_PLUS(GOOD_EFFECT); } break; case EFFECT_SWAGGER: @@ -3521,51 +3644,6 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) RETURN_SCORE_PLUS(WEAK_EFFECT); } break; - case EFFECT_SKILL_SWAP: - if (aiData->abilities[battlerAtk] != aiData->abilities[BATTLE_PARTNER(battlerAtk)] && !attackerHasBadAbility) - { - // Partner abilities - if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_TRUANT) - { - ADJUST_SCORE(10); - } - else if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_INTIMIDATE) - { - ADJUST_SCORE(DECENT_EFFECT); - } - // Active mon abilities - if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES - && HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)])) - { - ADJUST_SCORE(GOOD_EFFECT); - } - else if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY && HasMoveThatLowersOwnStats(battlerAtkPartner)) - { - ADJUST_SCORE(GOOD_EFFECT); - } - return score; - } - break; - case EFFECT_ROLE_PLAY: - if (attackerHasBadAbility && !partnerHasBadAbility) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); - } - break; - case EFFECT_WORRY_SEED: - case EFFECT_GASTRO_ACID: - case EFFECT_SIMPLE_BEAM: - if (partnerHasBadAbility) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); - } - break; - case EFFECT_ENTRAINMENT: - if (partnerHasBadAbility && IsAbilityOfRating(aiData->abilities[battlerAtk], 0)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); - } - break; case EFFECT_SOAK: if (atkPartnerAbility == ABILITY_WONDER_GUARD && !IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_WATER) @@ -3577,7 +3655,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INSTRUCT: { u16 instructedMove; - if (AI_IsFaster(battlerAtk, battlerAtkPartner, move)) + if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = aiData->partnerMove; else instructedMove = gLastMoves[battlerAtkPartner]; @@ -3591,21 +3669,73 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_AFTER_YOU: - if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove) // Opponent mon 1 goes before partner - || AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove)) // Opponent mon 2 goes before partner + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)) + ADJUST_SCORE(DECENT_EFFECT); + + if (AI_IsSlower(battlerAtkPartner, LEFT_FOE(battlerAtk), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner + && AI_IsSlower(battlerAtkPartner, RIGHT_FOE(battlerAtk), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner { if (partnerEffect == EFFECT_COUNTER || partnerEffect == EFFECT_MIRROR_COAT) break; // These moves need to go last - RETURN_SCORE_PLUS(WEAK_EFFECT); + ADJUST_SCORE(WEAK_EFFECT); } break; case EFFECT_HEAL_PULSE: case EFFECT_HIT_ENEMY_HEAL_ALLY: - if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move) - && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move) + if (AI_IsFaster(battlerAtk, LEFT_FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, RIGHT_FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2) RETURN_SCORE_PLUS(WEAK_EFFECT); break; + case EFFECT_SPEED_SWAP: + break; + case EFFECT_GUARD_SPLIT: + { + u32 atkDefense = gBattleMons[battlerAtk].defense; + u32 defDefense = gBattleMons[battlerDef].defense; + u32 atkSpDefense = gBattleMons[battlerAtk].spDefense; + u32 defSpDefense = gBattleMons[battlerDef].spDefense; + + // It's actually * 100 and / 2 + u32 newDefense = (atkDefense + defDefense) * 50; + u32 newSpDefense = (atkSpDefense + defSpDefense) * 50; + + // We want to massively raise our defense. + if (newDefense > atkDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > atkSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newDefense > defDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > defSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); + break; + } + case EFFECT_POWER_SPLIT: + { + u32 atkAttack = gBattleMons[battlerAtk].attack; + u32 defAttack = gBattleMons[battlerDef].attack; + u32 atkSpAttack = gBattleMons[battlerAtk].spAttack; + u32 defSpAttack = gBattleMons[battlerDef].spAttack; + + // * 100 and / 2 + u32 newAttack = (atkAttack + defAttack) * 50; + u32 newSpAtk = (atkSpAttack + defSpAttack) * 50; + + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && newAttack > atkAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) && newAttack > defAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > atkSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > defSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); + break; + } default: break; } // attacker move effects @@ -3621,6 +3751,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else // checking opponent { // these checks mostly handled in AI_CheckBadMove and AI_CheckViability +/* switch (effect) { case EFFECT_SKILL_SWAP: @@ -3632,7 +3763,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) default: break; } - +*/ // lightning rod, flash fire against enemy handled in AI_CheckBadMove } @@ -3658,16 +3789,50 @@ static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect) } } -static s32 CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) +static enum MoveComparisonResult CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) { u32 acc1 = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][moveSlot1]; u32 acc2 = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][moveSlot2]; if (acc1 > acc2) - return 1; + return MOVE_WON_COMPARISON; else if (acc2 > acc1) - return -1; - return 0; + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; +} + +static enum MoveComparisonResult CompareMoveSpeeds(u32 battlerAtk, u32 battlerDef, u16 move1, u16 move2) +{ + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + u32 speed1 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move1, predictedMoveSpeedCheck, CONSIDER_PRIORITY); + u32 speed2 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move2, predictedMoveSpeedCheck, CONSIDER_PRIORITY); + + if (speed1 == AI_IS_FASTER && speed2 == AI_IS_SLOWER) + return MOVE_WON_COMPARISON; + if (speed2 == AI_IS_FASTER && speed1 == AI_IS_SLOWER) + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; +} + +static enum MoveComparisonResult CompareGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u16 moveSlot1, u16 moveSlot2, u16 *moves) +{ + s32 dmg1, dmg2; + bool32 guarantee1, guarantee2; + + if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)) + return 0; + + // Explictly care about guaranteed KOs universally + dmg1 = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveSlot1].minimum; + guarantee1 = (gBattleMons[battlerDef].hp <= dmg1 && !CanEndureHit(battlerAtk, battlerDef, moves[moveSlot1])); + dmg2 = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveSlot2].minimum; + guarantee2 = (gBattleMons[battlerDef].hp <= dmg2 && !CanEndureHit(battlerAtk, battlerDef, moves[moveSlot2])); + + if (guarantee1 && !guarantee2) + return MOVE_WON_COMPARISON; + if (guarantee2 && !guarantee1) + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; } static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 moveIndex, u32 hitsToFaintOpposingBattler) @@ -3675,117 +3840,169 @@ static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 mov u32 partnerBattler = BATTLE_PARTNER(battlerAtk); u32 noOfHitsToFaintPartner = GetNoOfHitsToKOBattler(battlerAtk, partnerBattler, moveIndex, AI_ATTACKING); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); - return (IsDoubleBattle() + return (HasPartnerIgnoreFlags(battlerAtk) && noOfHitsToFaintPartner != 0 // Immunity check - && IsBattlerAlive(partnerBattler) && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY && !(noOfHitsToFaintPartner < friendlyFireThreshold && hitsToFaintOpposingBattler == 1) && noOfHitsToFaintPartner < (friendlyFireThreshold * 2)); } -static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) +static bool32 ShouldCompareMove(u32 battlerAtk, u32 battlerDef, u32 moveIndex, u16 move) { - u32 i; + if (IsTargetingPartner(battlerAtk, battlerDef)) + return FALSE; + if (GetMovePower(move) == 0) + return FALSE; + if (GetNoOfHitsToKOBattler(battlerAtk, battlerDef, moveIndex, AI_ATTACKING) == 0) + return FALSE; + if (gAiThinkingStruct->aiFlags[battlerAtk] & (AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE) && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + return FALSE; + return TRUE; +} + +static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef) +{ + u32 i, currId; + u32 tempMoveScores[MAX_MON_MOVES]; + u32 moveComparisonScores[MAX_MON_MOVES]; + u32 bestScore = AI_SCORE_DEFAULT; bool32 multipleBestMoves = FALSE; - s32 viableMoveScores[MAX_MON_MOVES]; - s32 bestViableMoveScore; s32 noOfHits[MAX_MON_MOVES]; - s32 score = 0; s32 leastHits = 1000; u16 *moves = GetMovesArray(battlerAtk); bool8 isTwoTurnNotSemiInvulnerableMove[MAX_MON_MOVES]; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (moves[i] != MOVE_NONE && GetMovePower(moves[i]) != 0) - { - noOfHits[i] = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, i, AI_ATTACKING); - if (ShouldUseSpreadDamageMove(battlerAtk,moves[i], i, noOfHits[i])) - { - noOfHits[i] = -1; - viableMoveScores[i] = 0; - isTwoTurnNotSemiInvulnerableMove[i] = FALSE; - } - else if (noOfHits[i] < leastHits && noOfHits[i] != 0) - { - leastHits = noOfHits[i]; - } - viableMoveScores[i] = AI_SCORE_DEFAULT; - isTwoTurnNotSemiInvulnerableMove[i] = IsTwoTurnNotSemiInvulnerableMove(battlerAtk, moves[i]); - } - else - { - noOfHits[i] = -1; - viableMoveScores[i] = 0; - isTwoTurnNotSemiInvulnerableMove[i] = FALSE; - } - } - - // Priority list: - // 1. Less no of hits to ko - // 2. Not charging - // 3. More accuracy - // 4. Better effect - - // Current move requires the least hits to KO. Compare with other moves. - if (leastHits == noOfHits[currId]) + for (currId = 0; currId < MAX_MON_MOVES; currId++) { + moveComparisonScores[currId] = 0; + if (!ShouldCompareMove(battlerAtk, battlerDef, currId, moves[currId])) + continue; for (i = 0; i < MAX_MON_MOVES; i++) { - if (i == currId) - continue; - if (noOfHits[currId] == noOfHits[i]) + if (moves[i] != MOVE_NONE && GetMovePower(moves[i]) != 0) { - multipleBestMoves = TRUE; - // We need to make sure it's the current move which is objectively better. - if (isTwoTurnNotSemiInvulnerableMove[i] && !isTwoTurnNotSemiInvulnerableMove[currId]) - viableMoveScores[i] -= 3; - else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId]) - viableMoveScores[currId] -= 3; - - switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) + noOfHits[i] = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, i, AI_ATTACKING); + if (ShouldUseSpreadDamageMove(battlerAtk,moves[i], i, noOfHits[i])) { - case 1: - viableMoveScores[i] -= 2; - break; - case -1: - viableMoveScores[currId] -= 2; - break; + noOfHits[i] = -1; + tempMoveScores[i] = 0; + isTwoTurnNotSemiInvulnerableMove[i] = FALSE; } - switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) + else if (noOfHits[i] < leastHits && noOfHits[i] != 0) { - case 1: - viableMoveScores[i] -= 1; - break; - case -1: - viableMoveScores[currId] -= 1; - break; + leastHits = noOfHits[i]; } + tempMoveScores[i] = AI_SCORE_DEFAULT; + isTwoTurnNotSemiInvulnerableMove[i] = IsTwoTurnNotSemiInvulnerableMove(battlerAtk, moves[i]); + } + else + { + noOfHits[i] = -1; + tempMoveScores[i] = 0; + isTwoTurnNotSemiInvulnerableMove[i] = FALSE; } } - // Turns out the current move deals the most dmg compared to the other 3. - if (!multipleBestMoves) - ADJUST_SCORE(BEST_DAMAGE_MOVE); - else + + // Priority list: + // 1. Less no of hits to ko + // 2. Priority if outsped and a OHKO + // 3. Not charging + // 4. More accuracy + // 5. Guaranteed KO + // 6. Better effect + + // Current move requires the least hits to KO. Compare with other moves. + if (leastHits == noOfHits[currId]) { - bestViableMoveScore = 0; for (i = 0; i < MAX_MON_MOVES; i++) { - if (viableMoveScores[i] > bestViableMoveScore) - bestViableMoveScore = viableMoveScores[i]; + if (i == currId) + continue; + if (noOfHits[currId] == noOfHits[i]) + { + multipleBestMoves = TRUE; + // We need to make sure it's the current move which is objectively better. + if (isTwoTurnNotSemiInvulnerableMove[i] && !isTwoTurnNotSemiInvulnerableMove[currId]) + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_NOT_CHARGING); + else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId]) + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_NOT_CHARGING); + + // Comparing KOs + if (noOfHits[currId] == 1) + { + // Use priority to get fast KO if outsped + switch (CompareMoveSpeeds(battlerAtk, battlerDef, moves[currId], moves[i])) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_SPEED); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_SPEED); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + // Min roll KOs + switch (CompareGuaranteeFaintTarget(battlerAtk, battlerDef, currId, i, moves)) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_GUARANTEE); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_GUARANTEE); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + } + switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + } } - // Unless a better move was found increase score of current move - if (viableMoveScores[currId] == bestViableMoveScore) - ADJUST_SCORE(BEST_DAMAGE_MOVE); + // Turns out the current move deals the most dmg compared to the other 3. + if (!multipleBestMoves) + moveComparisonScores[currId] = UINT32_MAX; + else + moveComparisonScores[currId] = tempMoveScores[currId]; } } - return score; + // Find highest comparison score + for (int i = 0; i < MAX_MON_MOVES; i++) + { + if (moveComparisonScores[i] > bestScore) + bestScore = moveComparisonScores[i]; + } + // Increase score for corresponding move(s), accomodating ties + for (int i = 0; i < MAX_MON_MOVES; i++) + { + if (moveComparisonScores[i] == bestScore) + gAiThinkingStruct->score[i] += BEST_DAMAGE_MOVE; + } } -static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) +static s32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { - struct AiLogicData *aiData = gAiLogicData; enum ItemHoldEffect holdEffect = aiData->holdEffects[battlerAtk]; s32 score = 0; @@ -3802,7 +4019,7 @@ static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) } else { - ADJUST_SCORE(-DECENT_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); } } break; @@ -3813,19 +4030,22 @@ static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) return score; } -static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) +static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { // move data enum BattleMoveEffects moveEffect = GetMoveEffect(move); - struct AiLogicData *aiData = gAiLogicData; u32 movesetIndex = gAiThinkingStruct->movesetIndex; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex]; s32 score = 0; - u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, aiData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, aiData); u32 predictedType = GetMoveType(predictedMove); u32 predictedMoveSlot = GetMoveSlot(GetMovesArray(battlerDef), predictedMove); - bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); + bool32 isBattle1v1 = IsBattle1v1(); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); + bool32 hasPartner = HasPartner(battlerAtk); + bool32 moveTargetsBothOpponents = hasTwoOpponents && (gMovesInfo[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS)); u32 i; // The AI should understand that while Dynamaxed, status moves function like Protect. @@ -3837,17 +4057,21 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(10); // check thawing moves - if ((gBattleMons[battlerAtk].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) && MoveThawsUser(move)) + if (gBattleMons[battlerAtk].status1 & STATUS1_ICY_ANY && MoveThawsUser(move)) ADJUST_SCORE(10); // check burn / frostbite - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING && gAiLogicData->abilities[battlerAtk] == ABILITY_NATURAL_CURE) + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING && aiData->abilities[battlerAtk] == ABILITY_NATURAL_CURE) { if ((gBattleMons[battlerAtk].status1 & STATUS1_BURN && HasOnlyMovesWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL, TRUE)) || (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && HasOnlyMovesWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL, TRUE))) ADJUST_SCORE(-20); // Force switch if all your attacking moves are physical and you have Natural Cure. } + // check guaranteed flinch, a la Fake Out + if (IsFlinchGuaranteed(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + // Non-volatile statuses switch(GetMoveNonVolatileStatus(move)) { @@ -3876,11 +4100,25 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_DREAM_EATER: - case EFFECT_STRENGTH_SAP: case EFFECT_AQUA_RING: if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) ADJUST_SCORE(DECENT_EFFECT); break; + case EFFECT_STRENGTH_SAP: + { + u32 atkStat = gBattleMons[battlerDef].attack; + u32 atkStage = gBattleMons[battlerDef].statStages[STAT_ATK]; + atkStat *= gStatStageRatios[atkStage][0]; + atkStat /= gStatStageRatios[atkStage][1]; + u32 healPercent = atkStat * 100 / gBattleMons[battlerAtk].maxHP; + if (ShouldRecover(battlerAtk, battlerDef, move, healPercent)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + } case EFFECT_EXPLOSION: case EFFECT_MISTY_EXPLOSION: case EFFECT_MEMENTO: @@ -3895,26 +4133,31 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_MIRROR_MOVE: - if (predictedMove != MOVE_NONE) + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckViability(battlerAtk, battlerDef, predictedMove, score); break; - case EFFECT_ATTACK_UP: case EFFECT_ATTACK_UP_USER_ALLY: + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + case EFFECT_ATTACK_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); break; case EFFECT_ATTACK_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); break; case EFFECT_DEFENSE_UP: - case EFFECT_DEFENSE_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; + case EFFECT_STUFF_CHEEKS: case EFFECT_DEFENSE_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_2)); break; + case EFFECT_DEFENSE_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_3)); + break; case EFFECT_SPEED_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); break; + case EFFECT_AUTOTOMIZE: case EFFECT_SPEED_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED_2)); break; @@ -3922,9 +4165,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; case EFFECT_SPECIAL_ATTACK_UP_2: - case EFFECT_SPECIAL_ATTACK_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); break; + case EFFECT_SPECIAL_ATTACK_UP_3: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_3)); + break; case EFFECT_SPECIAL_DEFENSE_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; @@ -3973,7 +4218,34 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_BIDE: if (aiData->hpPercents[battlerAtk] < 90) ADJUST_SCORE(-2); // Should be either removed or turned into increasing score + // treat as offense booster case EFFECT_ACUPRESSURE: + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK_2)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK_2)); + break; + case EFFECT_GEAR_UP: + if (aiData->abilities[battlerAtk] == ABILITY_PLUS || aiData->abilities[battlerAtk] == ABILITY_MINUS) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); + } + if (hasPartner && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPATK)); + } + break; + case EFFECT_MAGNETIC_FLUX: + if (aiData->abilities[battlerAtk] == ABILITY_PLUS || aiData->abilities[battlerAtk] == ABILITY_MINUS) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); + } + if (hasPartner && (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_DEF)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPDEF)); + } break; case EFFECT_ATTACK_ACCURACY_UP: // hone claws ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); @@ -3984,11 +4256,61 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; + case EFFECT_ROTOTILLER: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && AI_IsBattlerGrounded(battlerAtk)) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); + } + if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(BATTLE_PARTNER(battlerAtk))) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPATK)); + } + if (IS_BATTLER_OF_TYPE(LEFT_FOE(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(LEFT_FOE(battlerAtk))) + { + if (aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + if (IS_BATTLER_OF_TYPE(RIGHT_FOE(battlerAtk), TYPE_GRASS) && AI_IsBattlerGrounded(RIGHT_FOE(battlerAtk))) + { + if (aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + break; + case EFFECT_FLOWER_SHIELD: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS)) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); + } + if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS)) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_DEF)); + } + if (IS_BATTLER_OF_TYPE(LEFT_FOE(battlerAtk), TYPE_GRASS)) + { + if (aiData->abilities[LEFT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + if (IS_BATTLER_OF_TYPE(RIGHT_FOE(battlerAtk), TYPE_GRASS)) + { + if (aiData->abilities[RIGHT_FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + break; case EFFECT_HAZE: if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk)) - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) break; - score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; case EFFECT_ROAR: if ((IsSoundMove(move) && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) @@ -3996,7 +4318,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; case EFFECT_MULTI_HIT: case EFFECT_TRIPLE_KICK: @@ -4008,7 +4330,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_CONVERSION: if (!IS_BATTLER_OF_TYPE(battlerAtk, GetMoveType(gBattleMons[battlerAtk].moves[0]))) + { ADJUST_SCORE(WEAK_EFFECT); + if (aiData->abilities[battlerAtk] == ABILITY_ADAPTABILITY) + ADJUST_SCORE(WEAK_EFFECT); + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + } break; case EFFECT_SWALLOW: if (gDisableStructs[battlerAtk].stockpileCounter == 0) @@ -4033,7 +4361,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; } - if (ShouldRecover(battlerAtk, battlerDef, move, healPercent, AI_DEFENDING)) + if (ShouldRecover(battlerAtk, battlerDef, move, healPercent)) ADJUST_SCORE(DECENT_EFFECT); } break; @@ -4043,7 +4371,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_MORNING_SUN: case EFFECT_SYNTHESIS: case EFFECT_MOONLIGHT: - if (ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING)) + if (ShouldRecover(battlerAtk, battlerDef, move, 50)) + ADJUST_SCORE(GOOD_EFFECT); + break; + case EFFECT_LIFE_DEW: + if (ShouldRecover(battlerAtk, battlerDef, move, 25)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_LIGHT_SCREEN: @@ -4061,12 +4395,12 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { break; } - else if (ShouldRecover(battlerAtk, battlerDef, move, 100, AI_DEFENDING)) + else if (ShouldRecover(battlerAtk, battlerDef, move, 100)) { if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_SLP || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_STATUS - || HasMoveWithEffect(EFFECT_SLEEP_TALK, battlerAtk) - || HasMoveWithEffect(EFFECT_SNORE, battlerAtk) + || HasMoveWithEffect(battlerAtk, EFFECT_SLEEP_TALK) + || HasMoveWithEffect(battlerAtk, EFFECT_SNORE) || aiData->abilities[battlerAtk] == ABILITY_SHED_SKIN || aiData->abilities[battlerAtk] == ABILITY_EARLY_BIRD || (AI_GetWeather() & B_WEATHER_RAIN && gWishFutureKnock.weatherDuration != 1 && aiData->abilities[battlerAtk] == ABILITY_HYDRATION && aiData->holdEffects[battlerAtk] != HOLD_EFFECT_UTILITY_UMBRELLA)) @@ -4077,7 +4411,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_SHEER_COLD: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - else if (gStatuses3[battlerAtk] & STATUS3_ALWAYS_HITS) + else if (gBattleMons[battlerAtk].volatiles.lockOn) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_MEAN_LOOK: @@ -4100,22 +4434,23 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move)); break; case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { - if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF) + if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF + && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); } break; case EFFECT_LEECH_SEED: if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) - || gStatuses3[battlerDef] & STATUS3_LEECHSEED + || gBattleMons[battlerDef].volatiles.leechSeed || HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) || aiData->abilities[battlerDef] == ABILITY_LIQUID_OOZE || aiData->abilities[battlerDef] == ABILITY_MAGIC_GUARD) break; ADJUST_SCORE(GOOD_EFFECT); if (!HasDamagingMove(battlerDef) - || (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + || IsBattlerTrapped(battlerAtk, battlerDef) || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) ADJUST_SCORE(DECENT_EFFECT); break; @@ -4123,7 +4458,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_HOLD_HANDS: case EFFECT_CELEBRATE: case EFFECT_HAPPY_HOUR: - //todo - check z splash, z celebrate, z happy hour (lol) + case EFFECT_LAST_RESORT: + if (IsConsideringZMove(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_TELEPORT: // Either remove or add better logic if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) || !IsOnPlayerSide(battlerAtk)) @@ -4132,7 +4469,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: case EFFECT_CHILLY_RECEPTION: - if (!IsDoubleBattle()) + if (!hasPartner) { switch (ShouldPivot(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, movesetIndex)) { @@ -4156,8 +4493,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_BATON_PASS: - if ((gAiLogicData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE - || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) + if ((aiData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].volatiles.substitute + || gBattleMons[battlerAtk].volatiles.powerTrick + || gBattleMons[battlerAtk].volatiles.magnetRise + || gBattleMons[battlerAtk].volatiles.aquaRing + || gBattleMons[battlerAtk].volatiles.root || AnyStatIsRaised(battlerAtk))) ADJUST_SCORE(BEST_EFFECT); break; @@ -4168,7 +4508,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) && (gLastMoves[battlerDef] != MOVE_NONE) && (gLastMoves[battlerDef] != 0xFFFF) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) - && (AI_IsFaster(battlerAtk, battlerDef, move))) + && (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))) { if (CanTargetMoveFaintAi(gLastMoves[battlerDef], battlerDef, battlerAtk, 1)) ADJUST_SCORE(GOOD_EFFECT); // Disable move that can kill attacker @@ -4202,13 +4542,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_LOCK_ON: if (HasMoveWithEffect(battlerAtk, EFFECT_OHKO) || HasMoveWithEffect(battlerAtk, EFFECT_SHEER_COLD)) ADJUST_SCORE(GOOD_EFFECT); - else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 85, TRUE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef])) + else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 85, TRUE)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_DESTINY_BOND: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - else if (AI_IsFaster(battlerAtk, battlerDef, move) && CanTargetFaintAi(battlerDef, battlerAtk)) + else if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SPITE: @@ -4222,7 +4562,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_CURSE: if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) { - if (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + if (IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(WEAK_EFFECT); @@ -4250,7 +4590,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove)); } - else if (isDoubleBattle && GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) + else if (hasPartner && GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) { if (aiData->abilities[battlerAtk] != ABILITY_TELEPATHY) ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove)); @@ -4291,11 +4631,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); } break; + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)) { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -4318,13 +4660,16 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_PERISH_SONG: - if (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef)) + if (IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SANDSTORM: - if (ShouldSetSandstorm(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SANDSTORM)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_SMOOTH_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4334,13 +4679,14 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_HAIL: - if (ShouldSetHail(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_HAIL)) { - if ((HasMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_AURORA_VEIL)) - && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) - ADJUST_SCORE(GOOD_EFFECT); - ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + ADJUST_SCORE(GOOD_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ICY_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4350,13 +4696,14 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_SNOWSCAPE: - if (ShouldSetSnow(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SNOW)) { - if ((HasMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_AURORA_VEIL)) - && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) - ADJUST_SCORE(GOOD_EFFECT); - ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + ADJUST_SCORE(GOOD_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ICY_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4366,27 +4713,33 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_RAIN_DANCE: - if (ShouldSetRain(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_RAIN)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_DAMP_ROCK) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) - || HasMoveWithEffect(battlerDef, EFFECT_SYNTHESIS) - || HasMoveWithEffect(battlerDef, EFFECT_SOLAR_BEAM) - || HasMoveWithEffect(battlerDef, EFFECT_MOONLIGHT)) + if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_SYNTHESIS) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_SOLAR_BEAM) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_MOONLIGHT)) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithType(battlerDef, TYPE_FIRE) || HasMoveWithType(BATTLE_PARTNER(battlerDef), TYPE_FIRE)) + if (HasDamagingMoveOfType(battlerDef, TYPE_FIRE) || HasDamagingMoveOfType(BATTLE_PARTNER(battlerDef), TYPE_FIRE)) ADJUST_SCORE(WEAK_EFFECT); } break; case EFFECT_SUNNY_DAY: - if (ShouldSetSun(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SUN)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_HEAT_ROCK) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithType(battlerDef, TYPE_WATER) || HasMoveWithType(BATTLE_PARTNER(battlerDef), TYPE_WATER)) + if (HasDamagingMoveOfType(battlerDef, TYPE_WATER) || HasDamagingMoveOfType(BATTLE_PARTNER(battlerDef), TYPE_WATER)) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithFlag(battlerDef, MoveHas50AccuracyInSun) || HasMoveWithFlag(BATTLE_PARTNER(battlerDef), MoveHas50AccuracyInSun)) ADJUST_SCORE(WEAK_EFFECT); @@ -4409,27 +4762,25 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef); break; case EFFECT_SEMI_INVULNERABLE: - if (predictedMove != MOVE_NONE && !isDoubleBattle) + if (predictedMove != MOVE_NONE && isBattle1v1) { enum BattleMoveEffects predictedEffect = GetMoveEffect(predictedMove); - if ((AI_IsFaster(battlerAtk, battlerDef, move)) + if ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && (predictedEffect == EFFECT_EXPLOSION || predictedEffect == EFFECT_MISTY_EXPLOSION || predictedEffect == EFFECT_PROTECT)) ADJUST_SCORE(GOOD_EFFECT); - else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) ADJUST_SCORE(GOOD_EFFECT); } break; case EFFECT_DEFENSE_CURL: - if (HasMoveWithEffect(battlerAtk, EFFECT_ROLLOUT) && !(gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL)) + if (HasMoveWithEffect(battlerAtk, EFFECT_ROLLOUT) && !gBattleMons[battlerAtk].volatiles.defenseCurl) ADJUST_SCORE(DECENT_EFFECT); ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; case EFFECT_FIRST_TURN_ONLY: - if (ShouldFakeOut(battlerAtk, battlerDef, move) && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100)) - ADJUST_SCORE(GOOD_EFFECT); - else if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_STOCKPILE: @@ -4441,49 +4792,77 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; case EFFECT_SWAGGER: + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_FOUL_PLAY) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) + ADJUST_SCORE(DECENT_EFFECT); + if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) + ADJUST_SCORE(GOOD_EFFECT); + IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); + break; case EFFECT_FLATTER: - if (HasMoveWithEffect(battlerAtk, EFFECT_FOUL_PLAY) - || HasMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) - || HasMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) ADJUST_SCORE(DECENT_EFFECT); if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) ADJUST_SCORE(GOOD_EFFECT); IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); break; case EFFECT_FURY_CUTTER: - if (!isDoubleBattle && aiData->holdEffects[battlerAtk] == HOLD_EFFECT_METRONOME) + if (isBattle1v1 && aiData->holdEffects[battlerAtk] == HOLD_EFFECT_METRONOME) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_ATTRACT: - if (!isDoubleBattle - && (AI_IsSlower(battlerAtk, battlerDef, move)) + if (isBattle1v1 + && (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef])) break; // Don't use if the attract won't have a change to activate if (gBattleMons[battlerDef].status1 & STATUS1_ANY - || (gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) - || (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef))) + || gBattleMons[battlerDef].volatiles.confusionTurns > 0 + || IsBattlerTrapped(battlerAtk, battlerDef)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SAFEGUARD: - if (!IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_MISTY_TERRAIN) || !IsBattlerGrounded(battlerAtk)) + if (!IsBattlerTerrainAffected(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk], STATUS_FIELD_MISTY_TERRAIN) || !AI_IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); // TODO: check if opp has status move? //if (CountUsablePartyMons(battlerDef) != 0) //ADJUST_SCORE(8); break; + case EFFECT_COURT_CHANGE: + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_GOOD_COURT) + ADJUST_SCORE(WEAK_EFFECT); + if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_BAD_COURT) + ADJUST_SCORE(WEAK_EFFECT); + + if (AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) + { + ADJUST_SCORE(DECENT_EFFECT); + } + + if (hasPartner) + { + if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the Court Change + { + ADJUST_SCORE(-10); + break; + } + } + break; case EFFECT_DEFOG: - if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) - || (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST))) + if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) + || (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_GOOD_FOG)) { ADJUST_SCORE(GOOD_EFFECT); } - else if (!(gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SPIKES)) //Don't blow away hazards if you set them up + else if (!AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) || CountUsablePartyMons(battlerDef) == 0) //Don't blow away hazards if you set them up { - if (isDoubleBattle) + if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // Partner is going to set up hazards - && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move)) // Partner going first + && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Partner going first break; // Don't use Defog if partner is going to set up hazards } ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_EVASION)); @@ -4492,11 +4871,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_TORMENT: break; case EFFECT_FOLLOW_ME: - if (isDoubleBattle + if (hasPartner && GetMoveTarget(move) == MOVE_TARGET_USER && !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) // Rage Powder doesn't affect powder immunities - && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) + // Rage Powder doesn't affect powder immunities { u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; if (predictedMoveOnPartner != MOVE_NONE && !IsBattleMoveStatus(predictedMoveOnPartner)) @@ -4543,7 +4922,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case HOLD_EFFECT_IRON_BALL: - if (!HasMoveWithEffect(battlerDef, EFFECT_FLING) || !IsBattlerGrounded(battlerDef)) + if (!HasMoveWithEffect(battlerDef, EFFECT_FLING) || !AI_IsBattlerGrounded(battlerDef)) ADJUST_SCORE(DECENT_EFFECT); break; case HOLD_EFFECT_LAGGING_TAIL: @@ -4564,13 +4943,15 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (AI_GetWeather() & B_WEATHER_SUN) ADJUST_SCORE(DECENT_EFFECT); // Slow 'em down break; + default: + break; } } break; case HOLD_EFFECT_EJECT_BUTTON: //if (!IsRaidBattle() && GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX && gNewBS->dynamaxData.timer[battlerDef] > 1 && if (HasDamagingMove(battlerAtk) - || (isDoubleBattle && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && HasDamagingMove(BATTLE_PARTNER(battlerAtk)))) + || (hasPartner && HasDamagingMove(BATTLE_PARTNER(battlerAtk)))) ADJUST_SCORE(DECENT_EFFECT); // Force 'em out next turn break; default: @@ -4624,11 +5005,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } } break; - case EFFECT_ROLE_PLAY: - case EFFECT_DOODLE: - if (IsAbilityOfRating(aiData->abilities[battlerDef], 5)) - ADJUST_SCORE(DECENT_EFFECT); - break; case EFFECT_INGRAIN: ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) @@ -4665,29 +5041,15 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_AURORA_VEIL) ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_SKILL_SWAP: - if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - break; - else if (gAbilitiesInfo[aiData->abilities[battlerDef]].aiRating > gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating) - ADJUST_SCORE(DECENT_EFFECT); - break; - case EFFECT_WORRY_SEED: - case EFFECT_GASTRO_ACID: - case EFFECT_SIMPLE_BEAM: - if (IsAbilityOfRating(aiData->abilities[battlerDef], 5)) - ADJUST_SCORE(DECENT_EFFECT); - break; + case EFFECT_DOODLE: case EFFECT_ENTRAINMENT: - if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - break; - if (aiData->abilities[battlerDef] != aiData->abilities[battlerAtk] && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID)) - { - if (gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0) - ADJUST_SCORE(DECENT_EFFECT); - else if (IsAbilityOfRating(aiData->abilities[battlerDef], 5) && gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 3) - ADJUST_SCORE(WEAK_EFFECT); - } - break; + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + AbilityChangeScore(battlerAtk, battlerDef, moveEffect, &score, aiData); + return score; case EFFECT_IMPRISON: if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove)) ADJUST_SCORE(DECENT_EFFECT); @@ -4695,7 +5057,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_REFRESH: - if (gBattleMons[battlerAtk].status1 & STATUS1_ANY) + if (gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TAKE_HEART: @@ -4791,9 +5153,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_POWER_TRICK: - if (!(gStatuses3[battlerAtk] & STATUS3_POWER_TRICK) - && gBattleMons[battlerAtk].defense > gBattleMons[battlerAtk].attack - && HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) + if (!gBattleMons[battlerAtk].volatiles.powerTrick + && gBattleMons[battlerAtk].defense > gBattleMons[battlerAtk].attack + && HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEART_SWAP: @@ -4815,46 +5177,122 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gBattleMons[battlerDef].speed > gBattleMons[battlerAtk].speed) ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_GUARD_SPLIT: - { - u32 newDefense = (gBattleMons[battlerAtk].defense + gBattleMons[battlerDef].defense) / 2; - u32 newSpDef = (gBattleMons[battlerAtk].spDefense + gBattleMons[battlerDef].spDefense) / 2; +case EFFECT_GUARD_SPLIT: + { + u32 atkDefense = gBattleMons[battlerAtk].defense; + u32 defDefense = gBattleMons[battlerDef].defense; + u32 atkSpDefense = gBattleMons[battlerAtk].spDefense; + u32 defSpDefense = gBattleMons[battlerDef].spDefense; - if ((newDefense > gBattleMons[battlerAtk].defense && newSpDef >= gBattleMons[battlerAtk].spDefense) - || (newSpDef > gBattleMons[battlerAtk].spDefense && newDefense >= gBattleMons[battlerAtk].defense)) - ADJUST_SCORE(DECENT_EFFECT); - } + // It's actually * 100 and / 2; + u32 newDefense = (atkDefense + defDefense) * 50; + u32 newSpDefense = (atkSpDefense + defSpDefense) * 50; + + // We want to massively raise our defense. + if (newDefense > atkDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > atkSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + // We also want to massively lower theirs. + if (newDefense < defDefense * GUARD_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense < defSpDefense * GUARD_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); break; + } case EFFECT_POWER_SPLIT: - { - u32 newAttack = (gBattleMons[battlerAtk].attack + gBattleMons[battlerDef].attack) / 2; - u32 newSpAtk = (gBattleMons[battlerAtk].spAttack + gBattleMons[battlerDef].spAttack) / 2; + { + u32 atkAttack = gBattleMons[battlerAtk].attack; + u32 defAttack = gBattleMons[battlerDef].attack; + u32 atkSpAttack = gBattleMons[battlerAtk].spAttack; + u32 defSpAttack = gBattleMons[battlerDef].spAttack; - if ((newAttack > gBattleMons[battlerAtk].attack && newSpAtk >= gBattleMons[battlerAtk].spAttack) - || (newSpAtk > gBattleMons[battlerAtk].spAttack && newAttack >= gBattleMons[battlerAtk].attack)) + // It's actually * 100 and / 2 + u32 newAttack = (atkAttack + defAttack) * 50; + u32 newSpAtk = (atkSpAttack + defSpAttack) * 50; + + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && newAttack > atkAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > atkSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newAttack < defAttack * POWER_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpAtk < defSpAttack * POWER_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); + } + case EFFECT_ELECTRIC_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (gBattleMons[battlerAtk].volatiles.yawn && AI_IsBattlerGrounded(battlerAtk)) + ADJUST_SCORE(BEST_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + case EFFECT_MISTY_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (gBattleMons[battlerAtk].volatiles.yawn && AI_IsBattlerGrounded(battlerAtk)) + ADJUST_SCORE(BEST_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + case EFFECT_GRASSY_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + case EFFECT_PSYCHIC_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + case EFFECT_STEEL_ROLLER: + { + u32 terrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + if (ShouldClearFieldStatus(battlerAtk, terrain)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldSetFieldStatus(battlerDef, terrain)) ADJUST_SCORE(DECENT_EFFECT); } break; - case EFFECT_ELECTRIC_TERRAIN: - case EFFECT_MISTY_TERRAIN: - if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) - ADJUST_SCORE(BEST_EFFECT); - case EFFECT_GRASSY_TERRAIN: - case EFFECT_PSYCHIC_TERRAIN: - ADJUST_SCORE(GOOD_EFFECT); - if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER) - ADJUST_SCORE(GOOD_EFFECT); + case EFFECT_ICE_SPINNER: + { + u32 terrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + if (ShouldClearFieldStatus(battlerAtk, terrain)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldSetFieldStatus(battlerDef, terrain)) + ADJUST_SCORE(DECENT_EFFECT); + } break; case EFFECT_PLEDGE: - if (isDoubleBattle && HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_PLEDGE)) + if (hasPartner && HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_PLEDGE)) ADJUST_SCORE(GOOD_EFFECT); // Partner might use pledge move break; case EFFECT_TRICK_ROOM: if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS)) { - if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); - else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) + // Set it for next pokemon in singles. + else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0)) + ADJUST_SCORE(DECENT_EFFECT); + // Don't unset it on last turn. + else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); } break; @@ -4862,7 +5300,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_NONE && aiData->holdEffects[battlerDef] != HOLD_EFFECT_NONE) ADJUST_SCORE(WEAK_EFFECT); - if (isDoubleBattle && aiData->holdEffects[BATTLE_PARTNER(battlerAtk)] == HOLD_EFFECT_NONE && aiData->holdEffects[BATTLE_PARTNER(battlerDef)] != HOLD_EFFECT_NONE) + if (!isBattle1v1 && aiData->holdEffects[BATTLE_PARTNER(battlerAtk)] == HOLD_EFFECT_NONE && aiData->holdEffects[BATTLE_PARTNER(battlerDef)] != HOLD_EFFECT_NONE) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_WONDER_ROOM: @@ -4871,11 +5309,16 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_GRAVITY: - if (!(gFieldStatuses & STATUS_FIELD_GRAVITY)) + if (!(gFieldStatuses & STATUS_FIELD_GRAVITY || ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY))) { - if (HasSleepMoveWithLowAccuracy(battlerAtk, battlerDef)) // Has Gravity for a move like Hypnosis + // improve accuracy of Hypnosis + if (HasSleepMoveWithLowAccuracy(battlerAtk, battlerDef) + || HasSleepMoveWithLowAccuracy(BATTLE_PARTNER(battlerAtk), battlerDef)) IncreaseSleepScore(battlerAtk, battlerDef, move, &score); - if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef])) + if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, TRUE) + || HasMoveWithLowAccuracy(BATTLE_PARTNER(battlerAtk), battlerDef, 90, TRUE)) + ADJUST_SCORE(WEAK_EFFECT); + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY)) ADJUST_SCORE(DECENT_EFFECT); } break; @@ -4918,19 +5361,20 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TELEKINESIS: - if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]) - || !IsBattlerGrounded(battlerDef)) + if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, FALSE) || !AI_IsBattlerGrounded(battlerDef)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEAL_BLOCK: - if (AI_IsFaster(battlerAtk, battlerDef, move) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) ADJUST_SCORE(DECENT_EFFECT); // Try to cancel healing move else if (HasHealingEffect(battlerDef) || aiData->holdEffects[battlerDef] == HOLD_EFFECT_LEFTOVERS || (aiData->holdEffects[battlerDef] == HOLD_EFFECT_BLACK_SLUDGE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_POISON))) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SOAK: - if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) || (HasMoveWithEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && GetMoveArgType(move) == TYPE_WATER) ) + if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) + || HasMoveWithType(BATTLE_PARTNER(battlerAtk), TYPE_ELECTRIC) || HasMoveWithType(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) + || (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && GetMoveArgType(move) == TYPE_WATER) ) ADJUST_SCORE(DECENT_EFFECT); // Get some super effective moves break; case EFFECT_THIRD_TYPE: @@ -4955,22 +5399,58 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_QUASH: - if (isDoubleBattle && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove)) + if (hasPartner && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target break; case EFFECT_TAILWIND: - if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) - ADJUST_SCORE(GOOD_EFFECT); + { + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1)) + break; + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)) + ADJUST_SCORE(WEAK_EFFECT); + + if (isBattle1v1) + { + if (aiData->speedStats[battlerAtk] * 2 > aiData->speedStats[battlerDef]) + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); + + if (CountUsablePartyMons(battlerAtk) != 0) + ADJUST_SCORE(WEAK_EFFECT); + } + else + { + u32 tailwindScore = 0; + u32 speed = aiData->speedStats[battlerAtk]; + u32 partnerSpeed = aiData->speedStats[BATTLE_PARTNER(battlerAtk)]; + u32 foe1Speed = aiData->speedStats[LEFT_FOE(battlerAtk)]; + u32 foe2Speed = aiData->speedStats[RIGHT_FOE(battlerAtk)]; + + if (speed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + if (speed <= foe2Speed && (speed * 2) > foe2Speed) + tailwindScore += 1; + if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + + if (tailwindScore > 0) + tailwindScore += 1; + + ADJUST_SCORE(tailwindScore); + } break; + } case EFFECT_LUCKY_CHANT: - if (!isDoubleBattle && CountUsablePartyMons(battlerDef) > 0) + if (isBattle1v1 && CountUsablePartyMons(battlerDef) > 0) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_MAGNET_RISE: - if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) + if (AI_IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) && !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first { if (predictedType == TYPE_GROUND) ADJUST_SCORE(GOOD_EFFECT); // Cause the enemy's move to fail @@ -4985,7 +5465,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_CAMOUFLAGE: - if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move) // Attacker goes first + if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Attacker goes first && !IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(DECENT_EFFECT); break; @@ -5006,22 +5486,22 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SHORE_UP: - if ((AI_GetWeather() & B_WEATHER_SANDSTORM) && ShouldRecover(battlerAtk, battlerDef, move, 67, AI_DEFENDING)) + if ((AI_GetWeather() & B_WEATHER_SANDSTORM) && ShouldRecover(battlerAtk, battlerDef, move, 67)) ADJUST_SCORE(DECENT_EFFECT); - else if (ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING)) + else if (ShouldRecover(battlerAtk, battlerDef, move, 50)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_ENDEAVOR: - if (AI_IsSlower(battlerAtk, battlerDef, move) && !CanTargetFaintAi(battlerDef, battlerAtk)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && !CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_REVIVAL_BLESSING: if (GetFirstFaintedPartyIndex(battlerAtk) != PARTY_SIZE) { ADJUST_SCORE(DECENT_EFFECT); - if (gAiLogicData->shouldSwitch & (1u << battlerAtk)) // Bad matchup + if (aiData->shouldSwitch & (1u << battlerAtk)) // Bad matchup ADJUST_SCORE(WEAK_EFFECT); - if (gAiLogicData->mostSuitableMonId[battlerAtk] != PARTY_SIZE) // Good mon to send in after + if (aiData->mostSuitableMonId[battlerAtk] != PARTY_SIZE) // Good mon to send in after ADJUST_SCORE(WEAK_EFFECT); } break; @@ -5034,21 +5514,22 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //case EFFECT_SKY_DROP //break; case EFFECT_JUNGLE_HEALING: - if (ShouldRecover(battlerAtk, battlerDef, move, 25, AI_DEFENDING) - || ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25, AI_DEFENDING) + if (ShouldRecover(battlerAtk, battlerDef, move, 25) + || ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25) || gBattleMons[battlerAtk].status1 & STATUS1_ANY || gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RAPID_SPIN: - if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) - || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)) + if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) + || (gBattleMons[battlerAtk].volatiles.leechSeed || gBattleMons[battlerAtk].volatiles.wrapped)) ADJUST_SCORE(GOOD_EFFECT); + break; case EFFECT_SPECTRAL_THIEF: ADJUST_SCORE(AI_ShouldCopyStatChanges(battlerAtk, battlerDef)); break; case EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(battlerDef) && HasDamagingMoveOfType(battlerAtk, TYPE_GROUND) && !CanTargetFaintAi(battlerDef, battlerAtk)) + if (!AI_IsBattlerGrounded(battlerDef) && HasDamagingMoveOfType(battlerAtk, TYPE_GROUND) && !CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_KNOCK_OFF: @@ -5069,15 +5550,87 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } } break; + case EFFECT_STEAL_ITEM: + { + bool32 canSteal = FALSE; + + if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) + canSteal = TRUE; + + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) + canSteal = TRUE; + + if (canSteal && aiData->items[battlerAtk] == ITEM_NONE + && aiData->items[battlerDef] != ITEM_NONE + && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) + && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) + && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) + && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) + { + switch (aiData->holdEffects[battlerDef]) + { + case HOLD_EFFECT_NONE: + break; + case HOLD_EFFECT_CHOICE_BAND: + case HOLD_EFFECT_CHOICE_SCARF: + case HOLD_EFFECT_CHOICE_SPECS: + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_TOXIC_ORB: + if (ShouldPoison(battlerAtk, battlerAtk)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_FLAME_ORB: + if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_BLACK_SLUDGE: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_IRON_BALL: + if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_LAGGING_TAIL: + case HOLD_EFFECT_STICKY_BARB: + break; + default: + ADJUST_SCORE(WEAK_EFFECT); + break; + } + } + break; + } + break; default: break; } // move effect checks + return score; +} + +static s32 AI_CalcAdditionalEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) +{ + // move data + s32 score = 0; + + u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, aiData); + bool32 hasPartner = HasPartner(battlerAtk); + u32 i; u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + // check move additional effects that are likely to happen for (i = 0; i < additionalEffectCount; i++) { const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + + if (aiData->abilities[battlerAtk] == ABILITY_SHEER_FORCE) + { + if ((additionalEffect->chance > 0) != additionalEffect->sheerForceOverride) + continue; + } + // Only consider effects with a guaranteed chance to happen if (!MoveEffectIsGuaranteed(battlerAtk, aiData->abilities[battlerAtk], additionalEffect)) continue; @@ -5115,6 +5668,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case MOVE_EFFECT_EVS_PLUS_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_EVASION)); break; + default: + break; } } else @@ -5158,6 +5713,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); ADJUST_SCORE(IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; + default: + break; } } } @@ -5165,145 +5722,210 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { switch (additionalEffect->moveEffect) { - case MOVE_EFFECT_FLINCH: - score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move); - break; - case MOVE_EFFECT_SPD_MINUS_1: - case MOVE_EFFECT_SPD_MINUS_2: + case MOVE_EFFECT_FLINCH: + score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move); + break; + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + if (CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_SPEED)); - break; - case MOVE_EFFECT_ATK_MINUS_1: - case MOVE_EFFECT_DEF_MINUS_1: - case MOVE_EFFECT_SP_ATK_MINUS_1: - case MOVE_EFFECT_SP_DEF_MINUS_1: - case MOVE_EFFECT_ACC_MINUS_1: - case MOVE_EFFECT_EVS_MINUS_1: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_ATK_MINUS_2: - case MOVE_EFFECT_DEF_MINUS_2: - case MOVE_EFFECT_SP_ATK_MINUS_2: - case MOVE_EFFECT_SP_DEF_MINUS_2: - case MOVE_EFFECT_ACC_MINUS_2: - case MOVE_EFFECT_EVS_MINUS_2: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_POISON: - IncreasePoisonScore(battlerAtk, battlerDef, move, &score); - break; - case MOVE_EFFECT_CLEAR_SMOG: - score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); - break; - case MOVE_EFFECT_BUG_BITE: // And pluck - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) - break; - else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_INCINERATE: - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) - break; - else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_STEAL_ITEM: - { - bool32 canSteal = FALSE; + break; + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_2: + if (CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ACC)) + { + u32 scoreIncrease = IncreaseStatDownScore(battlerAtk, battlerDef, STAT_ACC); + if (scoreIncrease == WEAK_EFFECT) + scoreIncrease = DECENT_EFFECT; + ADJUST_SCORE(scoreIncrease); + } + break; + case MOVE_EFFECT_ATK_MINUS_1: + case MOVE_EFFECT_DEF_MINUS_1: + case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_1: + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); + break; + } + case MOVE_EFFECT_ATK_MINUS_2: + case MOVE_EFFECT_DEF_MINUS_2: + case MOVE_EFFECT_SP_ATK_MINUS_2: + case MOVE_EFFECT_SP_DEF_MINUS_2: + case MOVE_EFFECT_EVS_MINUS_2: + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); + break; + } + case MOVE_EFFECT_RAISE_TEAM_ATTACK: + case MOVE_EFFECT_RAISE_TEAM_DEFENSE: + case MOVE_EFFECT_RAISE_TEAM_SPEED: + case MOVE_EFFECT_RAISE_TEAM_SP_ATK: + case MOVE_EFFECT_RAISE_TEAM_SP_DEF: + { + enum StatChange StageStatId = STAT_CHANGE_ATK + additionalEffect->moveEffect - MOVE_EFFECT_RAISE_TEAM_ATTACK; + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, StageStatId)); + if (hasPartner) + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, StageStatId)); + break; + } + case MOVE_EFFECT_LOWER_ATTACK_SIDE: + case MOVE_EFFECT_LOWER_DEFENSE_SIDE: + case MOVE_EFFECT_LOWER_SPEED_SIDE: + case MOVE_EFFECT_LOWER_SP_ATK_SIDE: + case MOVE_EFFECT_LOWER_SP_DEF_SIDE: + { + u32 statId = STAT_ATK + additionalEffect->moveEffect - MOVE_EFFECT_LOWER_ATTACK_SIDE; + if (CanLowerStat(battlerAtk, battlerDef, aiData, statId)) + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, statId)); + break; + } + case MOVE_EFFECT_POISON: + IncreasePoisonScore(battlerAtk, battlerDef, move, &score); + break; + case MOVE_EFFECT_CLEAR_SMOG: + { + bool32 moveTargetsBothOpponents = HasTwoOpponents(battlerAtk) && (gMovesInfo[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS)); - if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) - canSteal = TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) - canSteal = TRUE; - - if (canSteal && aiData->items[battlerAtk] == ITEM_NONE - && aiData->items[battlerDef] != ITEM_NONE - && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) - && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) - && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) - && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) - { - switch (aiData->holdEffects[battlerDef]) - { - case HOLD_EFFECT_NONE: - break; - case HOLD_EFFECT_CHOICE_BAND: - case HOLD_EFFECT_CHOICE_SCARF: - case HOLD_EFFECT_CHOICE_SPECS: - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_TOXIC_ORB: - if (ShouldPoison(battlerAtk, battlerAtk)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_FLAME_ORB: - if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_BLACK_SLUDGE: - if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_IRON_BALL: - if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_LAGGING_TAIL: - case HOLD_EFFECT_STICKY_BARB: - break; - default: - ADJUST_SCORE(WEAK_EFFECT); - break; - } - } - break; - } + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); + break; + } + case MOVE_EFFECT_BUG_BITE: // And pluck + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; - case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); - { - if (gDisableStructs[battlerAtk].isFirstTurn) - ADJUST_SCORE(BEST_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } + else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_INCINERATE: + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; - case MOVE_EFFECT_FEINT: - if (GetMoveEffect(predictedMove) == EFFECT_PROTECT) - ADJUST_SCORE(GOOD_EFFECT); - break; - case MOVE_EFFECT_THROAT_CHOP: - if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) - { - if (AI_IsFaster(battlerAtk, battlerDef, move)) - ADJUST_SCORE(GOOD_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; - case MOVE_EFFECT_WRAP: - if (!HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move)) + else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_STEALTH_ROCK: + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)); + { + if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); - break; - case MOVE_EFFECT_SALT_CURE: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + else ADJUST_SCORE(DECENT_EFFECT); - break; + } + break; + case MOVE_EFFECT_FEINT: + if (GetMoveEffect(predictedMove) == EFFECT_PROTECT) + ADJUST_SCORE(GOOD_EFFECT); + break; + case MOVE_EFFECT_THROAT_CHOP: + if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) + { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, aiData); + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + else + ADJUST_SCORE(DECENT_EFFECT); + } + break; + case MOVE_EFFECT_WRAP: + if (!HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + break; + case MOVE_EFFECT_SALT_CURE: + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_SUN: + if (ShouldSetWeather(battlerAtk, B_WEATHER_SUN)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_SUN)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_RAIN: + if (ShouldSetWeather(battlerAtk, B_WEATHER_RAIN)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_RAIN)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_SANDSTORM: + if (ShouldSetWeather(battlerAtk, B_WEATHER_SANDSTORM)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_SANDSTORM)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_HAIL: + if (ShouldSetWeather(battlerAtk, B_WEATHER_HAIL)) + ADJUST_SCORE(DECENT_EFFECT); + if (ShouldClearWeather(battlerAtk, B_WEATHER_HAIL)) + ADJUST_SCORE(BAD_EFFECT); + break; + case MOVE_EFFECT_MISTY_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_GRASSY_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_ELECTRIC_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_PSYCHIC_TERRAIN: + if (ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + { + ADJUST_SCORE(BAD_EFFECT); + break; + } + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) + || ShouldClearFieldStatus(battlerAtk, gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_GRAVITY: + if (!(gFieldStatuses & STATUS_FIELD_GRAVITY) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRAVITY)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_AURORA_VEIL: + if (ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + ADJUST_SCORE(DECENT_EFFECT); + break; + default: + break; } } } - return score; } // AI_FLAG_CHECK_VIABILITY - Chooses best possible move to hit player static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { + struct AiLogicData *aiData = gAiLogicData; + // Targeting partner, check benefits of doing that instead - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetMovePower(move) != 0) @@ -5315,13 +5937,12 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score if (gAiThinkingStruct->aiFlags[battlerAtk] & (AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE) && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) ADJUST_SCORE(BEST_DAMAGE_MOVE); - else - ADJUST_SCORE(AI_CompareDamagingMoves(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex)); } } - ADJUST_SCORE(AI_CalcMoveEffectScore(battlerAtk, battlerDef, move)); - ADJUST_SCORE(AI_CalcHoldEffectMoveScore(battlerAtk, battlerDef, move)); + ADJUST_SCORE(AI_CalcMoveEffectScore(battlerAtk, battlerDef, move, aiData)); + ADJUST_SCORE(AI_CalcAdditionalEffectScore(battlerAtk, battlerDef, move, aiData)); + ADJUST_SCORE(AI_CalcHoldEffectMoveScore(battlerAtk, battlerDef, move, aiData)); return score; } @@ -5329,13 +5950,14 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score // Effects that are encouraged on the first turn of battle static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - u8 i; - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) + if (IsTargetingPartner(battlerAtk, battlerDef) || gBattleResults.battleTurnCounter != 0) return score; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING - && AI_IsSlower(battlerAtk, battlerDef, move) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk) && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) == 0) { @@ -5427,27 +6049,10 @@ static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 case EFFECT_CHILLY_RECEPTION: case EFFECT_GEOMANCY: case EFFECT_VICTORY_DANCE: + case EFFECT_CEASELESS_EDGE: + case EFFECT_STONE_AXE: ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_HIT: - { - // TEMPORARY - should applied to all moves regardless of EFFECT - // Consider move effects - u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); - for (i = 0; i < additionalEffectCount; i++) - { - const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - switch (additionalEffect->moveEffect) - { - case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: - ADJUST_SCORE(DECENT_EFFECT); - break; - default: - break; - } - } - } default: break; } @@ -5461,7 +6066,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u8 i; struct AiLogicData *aiData = gAiLogicData; - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetMoveCriticalHitStage(move) > 0) @@ -5534,7 +6139,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Adds score bonus to OHKOs and 2HKOs static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING) == 1) @@ -5545,14 +6150,39 @@ static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return score; } +// Adds score bonus to targeting "partner" +static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) +{ + if (battlerDef == BATTLE_PARTNER(battlerAtk) + // natural enemies in wild battles try to kill each other + && ((IsNaturalEnemy(gBattleMons[battlerAtk].species, gBattleMons[battlerDef].species) && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER))) + || AI_FLAG_ATTACKS_PARTNER_FOCUSES_PARTNER)) + { + u32 movesetIndex = gAiThinkingStruct->movesetIndex; + + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, AI_ATTACKING)) + ADJUST_SCORE(BEST_EFFECT); + + u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING); + + if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 && + (GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, LEFT_FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) + ADJUST_SCORE(BEST_EFFECT); + + if (hitsToKO > 0) + ADJUST_SCORE(DECENT_EFFECT); + } + return score; +} + // Prefers moves that are good for baton pass static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) + if (IsTargetingPartner(battlerAtk, battlerDef) || CountUsablePartyMons(battlerAtk) == 0 || !IsBattleMoveStatus(move) || !HasMoveWithEffect(battlerAtk, EFFECT_BATON_PASS) - || (!AI_CanBattlerEscape(battlerAtk) && IsBattlerTrapped(battlerDef, battlerAtk))) + || IsBattlerTrapped(battlerAtk, battlerDef)) return score; enum BattleMoveEffects effect = GetMoveEffect(move); @@ -5571,11 +6201,11 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor switch (effect) { case EFFECT_INGRAIN: - if (!(gStatuses3[battlerAtk] & STATUS3_ROOTED)) + if (!gBattleMons[battlerAtk].volatiles.root) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_AQUA_RING: - if (!(gStatuses3[battlerAtk] & STATUS3_AQUA_RING)) + if (!gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_PROTECT: @@ -5585,9 +6215,9 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_BATON_PASS: - if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING)) + if (gBattleMons[battlerAtk].volatiles.root || gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(DECENT_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) + if (gBattleMons[battlerAtk].volatiles.leechSeed) ADJUST_SCORE(-3); ADJUST_SCORE(CountPositiveStatStages(battlerAtk) - CountNegativeStatStages(battlerAtk)); break; @@ -5606,18 +6236,18 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY) || (moveType == TYPE_ELECTRIC && gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_VOLT_ABSORB) || (moveType == TYPE_GROUND && gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_EARTH_EATER) || (moveType == TYPE_WATER && (gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_DRY_SKIN || gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_WATER_ABSORB))) { - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerDef].volatiles.healBlock) return 0; - if (CanTargetFaintAi(FOE(battlerAtk), BATTLE_PARTNER(battlerAtk)) - || (CanTargetFaintAi(BATTLE_PARTNER(FOE(battlerAtk)), BATTLE_PARTNER(battlerAtk)))) + if (CanTargetFaintAi(LEFT_FOE(battlerAtk), BATTLE_PARTNER(battlerAtk)) + || CanTargetFaintAi(RIGHT_FOE(battlerAtk), BATTLE_PARTNER(battlerAtk))) ADJUST_SCORE(-1); if (gAiLogicData->hpPercents[battlerDef] <= 50) @@ -5845,7 +6475,7 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, gAiLogicData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, gAiLogicData)) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_GRASSY_TERRAIN: @@ -5877,11 +6507,8 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_HAIL: - if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) - ADJUST_SCORE(POWERFUL_STATUS_MOVE); - break; case EFFECT_SNOWSCAPE: - if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) + if (IsWeatherActive(B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; default: @@ -5891,17 +6518,36 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score return score; } +bool32 DoesSideHaveDamagingHazards(u32 side) +{ + for (u32 counter = 0; counter < HAZARDS_MAX_COUNT; counter++) + { + switch (gBattleStruct->hazardsQueue[side][counter]) + { + case HAZARDS_SPIKES: + case HAZARDS_TOXIC_SPIKES: + case HAZARDS_STEALTH_ROCK: + case HAZARDS_STEELSURGE: + return TRUE; + default: + return FALSE; + } + } + return FALSE; +} + static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 i; u32 unmodifiedScore = score; - u32 ability = gBattleMons[battlerAtk].ability; - u32 opposingHazardFlags = gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_TOXIC_SPIKES); - u32 aiHazardFlags = gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_HAZARDS_ANY); + enum Ability ability = gBattleMons[battlerAtk].ability; + bool32 opposingHazardFlags = DoesSideHaveDamagingHazards(GetBattlerSide(battlerDef)); + bool32 aiHazardFlags = AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)); enum BattleMoveEffects moveEffect = GetMoveEffect(move); struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); // Switch benefit switch (moveEffect) @@ -5913,7 +6559,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(GOOD_EFFECT); else if (hitsToKO == 1) ADJUST_SCORE(BEST_EFFECT); - else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER) // Pursuit against fast U-Turn + else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) == AI_IS_SLOWER) // Pursuit against fast U-Turn ADJUST_SCORE(DECENT_EFFECT); break; } @@ -5924,9 +6570,10 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(10); - if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + if (HasDamagingMove(battlerDef) && !(gBattleMons[battlerAtk].volatiles.substitute || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION))) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0)) ADJUST_SCORE(10); } break; @@ -5958,21 +6605,21 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_HIT_SWITCH_TARGET: - if (opposingHazardFlags != 0) + if (opposingHazardFlags) ADJUST_SCORE(BEST_EFFECT); else ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_ROAR: - if (opposingHazardFlags != 0) + if (opposingHazardFlags) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RAPID_SPIN: - if (aiHazardFlags != 0) + if (aiHazardFlags) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_DEFOG: - if (aiHazardFlags != 0) + if (aiHazardFlags) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_WISH: @@ -6004,7 +6651,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ION_DELUGE: case EFFECT_MAGIC_COAT: case EFFECT_SNATCH: - ADJUST_SCORE(-BEST_EFFECT); + ADJUST_SCORE(WORST_EFFECT); break; // Get stuck in bad matchup @@ -6014,7 +6661,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INGRAIN: case EFFECT_NO_RETREAT: case EFFECT_MEAN_LOOK: - ADJUST_SCORE(-GOOD_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); break; default: @@ -6026,18 +6673,20 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { switch (GetMoveAdditionalEffectById(move, i)->moveEffect) { - case MOVE_EFFECT_WRAP: - ADJUST_SCORE(-GOOD_EFFECT); - break; - case MOVE_EFFECT_FEINT: - ADJUST_SCORE(-BEST_EFFECT); - break; + case MOVE_EFFECT_WRAP: + ADJUST_SCORE(AWFUL_EFFECT); + break; + case MOVE_EFFECT_FEINT: + ADJUST_SCORE(WORST_EFFECT); + break; + default: + break; } } // Take advantage of ability damage bonus if ((ability == ABILITY_STAKEOUT || ability == ABILITY_ANALYTIC) && IsBattleMoveStatus(move)) - ADJUST_SCORE(-WEAK_EFFECT); + ADJUST_SCORE(BAD_EFFECT); // This must be last or the player can gauge whether the AI is predicting based on how long it thinks if (!IsBattlerPredictedToSwitch(battlerDef)) @@ -6097,8 +6746,8 @@ static s32 AI_Safari(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // First battle logic static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - // if (gAiLogicData->hpPercents[battlerDef] <= 20) - // AI_Flee(); + if (!IS_FRLG && gAiLogicData->hpPercents[battlerDef] <= 20) + AI_Flee(); return score; } diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index dde743415..120d6f910 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -29,8 +29,9 @@ static bool32 AiExpectsToFaintPlayer(u32 battler); static bool32 AI_ShouldHeal(u32 battler, u32 healAmount); static bool32 AI_OpponentCanFaintAiWithMod(u32 battler, u32 healAmount); static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon); -static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent); +static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent); static u32 GetHPHealAmount(u8 itemEffectParam, struct Pokemon *mon); +static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struct BattlePokemon battleMon); static void InitializeSwitchinCandidate(struct Pokemon *mon) { @@ -110,11 +111,11 @@ u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario) static bool32 IsAceMon(u32 battler, u32 monPartyId) { - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_ACE_POKEMON + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && monPartyId == CalculateEnemyPartyCountInSide(battler)-1) return TRUE; - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_DOUBLE_ACE_POKEMON + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2)) return TRUE; @@ -160,30 +161,61 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId) return TRUE; } -static bool32 AI_DoesChoiceItemBlockMove(u32 battler, u32 move) +static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) { // Choice locked into something else - if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move && HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) + if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move + && (IsHoldEffectChoice(GetBattlerHoldEffect(battler) && IsBattlerItemEnabled(battler)) + || gBattleMons[battler].ability == ABILITY_GORILLA_TACTICS)) return TRUE; return FALSE; } +static inline bool32 CanBattlerWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool32 isBattlerFirst) +{ + // Player's best move deals 0 damage + if (hitsToKOAI == 0 && hitsToKOPlayer > 0) + return TRUE; + + // AI's best move deals 0 damage + if (hitsToKOPlayer == 0 && hitsToKOAI > 0) + return FALSE; + + // Neither mon can damage the other + if (hitsToKOPlayer == 0 && hitsToKOAI == 0) + return FALSE; + + // Different KO thresholds depending on who goes first + if (isBattlerFirst) + { + if (hitsToKOAI >= hitsToKOPlayer) + return TRUE; + } + else + { + if (hitsToKOAI > hitsToKOPlayer) + return TRUE; + } + return FALSE; +} + // Note that as many return statements as possible are INTENTIONALLY put after all of the loops; // the function can take a max of about 0.06s to run, and this prevents the player from identifying // whether the mon will switch or not by seeing how long the delay is before they select a move static bool32 ShouldSwitchIfHasBadOdds(u32 battler) { //Variable initialization - u8 opposingPosition, atkType1, atkType2, defType1, defType2; - s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0; - u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; + u8 opposingPosition; + s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0, maxDamageTakenPriority = 0; + u32 aiMove, playerMove, bestPlayerPriorityMove = MOVE_NONE, bestPlayerMove = MOVE_NONE, expectedMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE; - u16 typeEffectiveness = UQ_4_12(1.0); //baseline typing damage + u32 typeMatchup; enum BattleMoveEffects aiMoveEffect; - u32 hitsToKoPlayer = 0, hitsToKoAI = 0; + u32 hitsToKoAI = 0, hitsToKoAIPriority = 0, hitsToKoPlayer = 0; + bool32 canBattlerWin1v1 = FALSE, isBattlerFirst, isBattlerFirstPriority; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic @@ -192,18 +224,37 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); opposingBattler = GetBattlerAtPosition(opposingPosition); + u16 *playerMoves = GetMovesArray(opposingBattler); - // Gets types of player (opposingBattler) and computer (battler) - atkType1 = gBattleMons[opposingBattler].types[0]; - atkType2 = gBattleMons[opposingBattler].types[1]; - defType1 = gBattleMons[battler].types[0]; - defType2 = gBattleMons[battler].types[1]; + // Get max damage mon could take + for (i = 0; i < MAX_MON_MOVES; i++) + { + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) + { + damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); + if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) + { + maxDamageTaken = damageTaken; + bestPlayerMove = playerMove; + } + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 && damageTaken > maxDamageTakenPriority && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) + { + maxDamageTakenPriority = damageTaken; + bestPlayerPriorityMove = playerMove; + } + } + } + + hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler); + hitsToKoAIPriority = GetNoOfHitsToKOBattlerDmg(maxDamageTakenPriority, battler); + expectedMove = gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE ? GetIncomingMove(battler, opposingBattler, gAiLogicData) : bestPlayerMove; for (i = 0; i < MAX_MON_MOVES; i++) { aiMove = gBattleMons[battler].moves[i]; aiMoveEffect = GetMoveEffect(aiMove); - if (aiMove != MOVE_NONE) + if (aiMove != MOVE_NONE && gBattleMons[battler].pp[i] > 0) { u32 nonVolatileStatus = GetMoveNonVolatileStatus(aiMove); // Check if mon has an "important" status move @@ -222,64 +273,39 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) } // Only check damage if it's a damaging move - if (!IsBattleMoveStatus(aiMove)) + if (!IsBattleMoveStatus(aiMove) && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) { // Check if mon has a super effective move - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceItemBlockMove(battler, aiMove)) + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) hasSuperEffectiveMove = TRUE; // Get maximum damage mon can deal damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData); - if (damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove)) - { + if (damageDealt > maxDamageDealt) maxDamageDealt = damageDealt; - aiBestMove = aiMove; + if (!canBattlerWin1v1 ) // Once we can win a 1v1 we don't need to track this, but want to run the rest of the function to keep the runtime the same regardless of when we find the winning move + { + hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); + isBattlerFirst = AI_IsFaster(battler, opposingBattler, aiMove, expectedMove, CONSIDER_PRIORITY); + isBattlerFirstPriority = AI_IsFaster(battler, opposingBattler, aiMove, bestPlayerPriorityMove, CONSIDER_PRIORITY); + canBattlerWin1v1 = CanBattlerWin1v1(hitsToKoAI, hitsToKoPlayer, isBattlerFirst) && CanBattlerWin1v1(hitsToKoAIPriority, hitsToKoPlayer, isBattlerFirstPriority); } } } } - hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(maxDamageDealt, opposingBattler); - // Calculate type advantage - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); - if (defType2 != defType1) - { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); - } - - // Get max damage mon could take - for (i = 0; i < MAX_MON_MOVES; i++) - { - playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) - { - damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); - if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move - { - return maxDamageTaken = damageTaken; - break; - } - if (damageTaken > maxDamageTaken) - maxDamageTaken = damageTaken; - } - } - - hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler); + typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gBattleMons[battler]); // Check if mon gets one shot if (maxDamageTaken > gBattleMons[battler].hp - && !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gBattleMons[opposingBattler].ability) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY))) + && !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gAiLogicData->abilities[opposingBattler]) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY))) { getsOneShot = TRUE; } // Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can - if (hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove))) + if (canBattlerWin1v1) return FALSE; // If we don't have any other viable options, don't switch out @@ -288,11 +314,8 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) // Start assessing whether or not mon has bad odds // Jump straight to switching out in cases where mon gets OHKO'd - if (((getsOneShot && gBattleMons[opposingBattler].speed > gBattleMons[battler].speed) // If the player OHKOs and outspeeds OR OHKOs, doesn't outspeed but isn't 2HKO'd - || (getsOneShot && gBattleMons[opposingBattler].speed <= gBattleMons[battler].speed && maxDamageDealt < gBattleMons[opposingBattler].hp / 2)) - && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator - || (aiAbility == ABILITY_REGENERATOR - && gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4))) + if ((getsOneShot && !canBattlerWin1v1) && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator + || (aiAbility == ABILITY_REGENERATOR && gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4))) { // 50% chance to stay in regardless if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !gAiLogicData->aiPredictionInProgress) @@ -303,7 +326,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) } // General bad type matchups have more wiggle room - if (typeEffectiveness >= UQ_4_12(2.0)) // If the player has at least a 2x type advantage + if (typeMatchup > UQ_4_12(2.0)) // If the player has favourable offensive matchup (2.0 is neutral, this must be worse) { if (!hasSuperEffectiveMove // If the AI doesn't have a super effective move && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator @@ -385,9 +408,10 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) - || AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0)) - && aiMove != MOVE_NONE) + if (aiMove == MOVE_NONE) + continue; + if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0) + || gAiLogicData->effectiveness[battler][opposingPartner][moveIndex] > UQ_4_12(0.0)) return FALSE; } } @@ -396,7 +420,9 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { aiMove = gBattleMons[battler].moves[moveIndex]; - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE + if (gAiLogicData->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0) && aiMove != MOVE_NONE + && !CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], aiMove, GetBattleMoveType(aiMove), AI_CHECK) + && !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gAiLogicData->abilities[opposingBattler], aiMove, AI_CHECK) && (!ALL_MOVES_BAD_STATUS_MOVES_BAD || gMovesInfo[aiMove].power != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero return FALSE; } @@ -416,7 +442,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) static bool32 ShouldSwitchIfWonderGuard(u32 battler) { u32 opposingBattler = GetOppositeBattler(battler); - u32 i, move; + u32 i; if (IsDoubleBattle()) return FALSE; @@ -427,12 +453,8 @@ static bool32 ShouldSwitchIfWonderGuard(u32 battler) // Check if Pokémon has a super effective move. for (i = 0; i < MAX_MON_MOVES; i++) { - move = gBattleMons[battler].moves[i]; - if (move != MOVE_NONE) - { - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - return FALSE; - } + if (gBattleMons[battler].moves[i] != MOVE_NONE && gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) + return FALSE; } if (RandomPercentage(RNG_AI_SWITCH_WONDER_GUARD, GetSwitchChance(SHOULD_SWITCH_WONDER_GUARD))) @@ -454,14 +476,17 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) s32 firstId; s32 lastId; struct Pokemon *party; - u16 monAbility, aiMove; + enum Ability monAbility; + u16 aiMove; u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); - u32 incomingType = GetMoveType(incomingMove); - bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); + u32 incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE); + bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); s32 i, j; - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + return FALSE; + if (GetMoveEffect(incomingMove) == EFFECT_HIDDEN_POWER && RandomPercentage(RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER, SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE)) return FALSE; if (gBattleStruct->prevTurnSpecies[battler] != gBattleMons[battler].species && !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE)) // AI mon has changed, player's behaviour no longer reliable; override this if using AI_FLAG_PREDICT_MOVE return FALSE; @@ -481,7 +506,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) // Only check damage if it's a damaging move if (!IsBattleMoveStatus(aiMove)) { - if (!AI_DoesChoiceItemBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp) + if (!AI_DoesChoiceEffectBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp) return FALSE; } } @@ -589,11 +614,12 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler) u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); - bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); + bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); - if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; + // In a world with a unified ShouldSwitch function, also want to check whether we already win 1v1 and if we do don't switch; not worth doubling the HasBadOdds computation for now if (isOpposingBattlerChargingOrInvulnerable && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); @@ -606,11 +632,11 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) s32 lastId; struct Pokemon *party; s32 i; - u16 monAbility; + enum Ability monAbility; s32 opposingBattler = GetOppositeBattler(battler); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Check if current mon has an ability that traps opponent @@ -631,7 +657,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) if (CanAbilityTrapOpponent(monAbility, opposingBattler) || (CanAbilityTrapOpponent(gAiLogicData->abilities[opposingBattler], opposingBattler) && monAbility == ABILITY_TRACE)) { // If mon in slot i is the most suitable switchin candidate, then it's a trapper than wins 1v1 - if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN))) + if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_TRAPPER, GetSwitchChance(SHOULD_SWITCH_TRAPPER))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } } @@ -641,23 +667,23 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) static bool32 ShouldSwitchIfBadlyStatused(u32 battler) { bool32 switchMon = FALSE; - u16 monAbility = gAiLogicData->abilities[battler]; + enum Ability monAbility = gAiLogicData->abilities[battler]; enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; u8 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); u8 opposingBattler = GetBattlerAtPosition(opposingPosition); bool32 hasStatRaised = AnyStatIsRaised(battler); //Perish Song - if (gStatuses3[battler] & STATUS3_PERISH_SONG + if (gBattleMons[battler].volatiles.perishSong && gDisableStructs[battler].perishSongTimer == 0 && monAbility != ABILITY_SOUNDPROOF && RandomPercentage(RNG_AI_SWITCH_PERISH_SONG, GetSwitchChance(SHOULD_SWITCH_PERISH_SONG))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) { //Yawn - if (gStatuses3[battler] & STATUS3_YAWN + if (gBattleMons[battler].volatiles.yawn && CanBeSlept(battler, battler, monAbility, BLOCKED_BY_SLEEP_CLAUSE) // TODO: ask for help from pawwkie && gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3 && RandomPercentage(RNG_AI_SWITCH_YAWN, GetSwitchChance(SHOULD_SWITCH_YAWN))) @@ -679,8 +705,8 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) || monAbility == ABILITY_EARLY_BIRD) || holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS) || HasMove(battler, MOVE_SLEEP_TALK) - || (HasMoveWithEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0)) - || (IsBattlerGrounded(battler) + || (HasMove(battler, MOVE_SNORE) && gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, MOVE_SNORE)] >= UQ_4_12(2.0)) + || (IsBattlerGrounded(battler, monAbility, gAiLogicData->holdEffects[battler]) && (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN))) ) switchMon = FALSE; @@ -690,9 +716,9 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && gAiLogicData->abilities[opposingBattler] != ABILITY_UNAWARE && gAiLogicData->abilities[opposingBattler] != ABILITY_KEEN_EYE && gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE - && (B_ILLUMINATE_EFFECT >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) - && !(gBattleMons[battler].status2 & STATUS2_FORESIGHT) - && !(gStatuses3[battler] & STATUS3_MIRACLE_EYED)) + && (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) + && !gBattleMons[battler].volatiles.foresight + && !gBattleMons[battler].volatiles.miracleEye) switchMon = FALSE; if (switchMon) @@ -712,23 +738,23 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Cursed - if (gBattleMons[battler].status2 & STATUS2_CURSED + if (gBattleMons[battler].volatiles.cursed && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Nightmare - if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE + if (gBattleMons[battler].volatiles.nightmare && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Leech Seed - if (gStatuses3[battler] & STATUS3_LEECHSEED + if (gBattleMons[battler].volatiles.leechSeed && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } // Infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION + if (gBattleMons[battler].volatiles.infatuation && !AiExpectsToFaintPlayer(battler) && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_INFATUATION, GetSwitchChance(SHOULD_SWITCH_INFATUATION))) @@ -743,7 +769,7 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler) bool32 hasStatRaised = AnyStatIsRaised(battler); //Check if ability is blocked - if (gStatuses3[battler] & STATUS3_GASTRO_ACID + if (gBattleMons[battler].volatiles.gastroAcid || IsNeutralizingGasOnField()) return FALSE; @@ -800,13 +826,11 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { move = gBattleMons[battler].moves[i]; - if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move)) + if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - { + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) return TRUE; - } } } if (!IsDoubleBattle()) @@ -819,13 +843,11 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { move = gBattleMons[battler].moves[i]; - if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move)) + if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; - if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) - { + if (gAiLogicData->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0)) return TRUE; - } } } @@ -842,7 +864,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc u16 move; // Similar functionality handled more thoroughly by ShouldSwitchIfHasBadOdds - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) return FALSE; if (gLastLandedMoves[battler] == MOVE_NONE) @@ -873,7 +895,8 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc for (i = firstId; i < lastId; i++) { - u16 species, monAbility; + u16 species; + enum Ability monAbility; uq4_12_t typeMultiplier; u16 moveFlags = 0; @@ -917,7 +940,7 @@ static bool32 CanMonSurviveHazardSwitchin(u32 battler) { u32 battlerIn1, battlerIn2; u32 hazardDamage = 0, battlerHp = gBattleMons[battler].hp; - u32 ability = gAiLogicData->abilities[battler], aiMove; + enum Ability ability = gAiLogicData->abilities[battler], aiMove; s32 firstId, lastId, i, j; struct Pokemon *party; @@ -980,7 +1003,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) u32 opposingBattler = GetOppositeBattler(battler); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // If not Encore'd don't switch @@ -992,7 +1015,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); // Stay in if effective move - else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0)) + else if (gAiLogicData->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, encoredMove)] >= UQ_4_12(2.0)) return FALSE; // Switch out 50% of the time otherwise @@ -1004,17 +1027,17 @@ static bool32 ShouldSwitchIfEncored(u32 battler) static bool32 ShouldSwitchIfBadChoiceLock(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); u32 lastUsedMove = gAiLogicData->lastUsedMove[battler]; u32 opposingBattler = GetOppositeBattler(battler); bool32 moveAffectsTarget = TRUE; if (lastUsedMove != MOVE_NONE && (AI_GetMoveEffectiveness(lastUsedMove, battler, opposingBattler) == UQ_4_12(0.0) - || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, GetMoveType(lastUsedMove), ABILITY_CHECK_TRIGGER) - || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, ABILITY_CHECK_TRIGGER))) + || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, CheckDynamicMoveType(GetBattlerMon(battler), lastUsedMove, battler, MON_IN_BATTLE), AI_CHECK) + || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, AI_CHECK))) moveAffectsTarget = FALSE; - if (HOLD_EFFECT_CHOICE(holdEffect) && IsBattlerItemEnabled(battler)) + if (IsHoldEffectChoice(holdEffect) && IsBattlerItemEnabled(battler)) { if ((GetMoveCategory(lastUsedMove) == DAMAGE_CATEGORY_STATUS || !moveAffectsTarget) && RandomPercentage(RNG_AI_SWITCH_CHOICE_LOCKED, GetSwitchChance(SHOULD_SWITCH_CHOICE_LOCKED))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); @@ -1030,7 +1053,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler) s8 spAttackingStage = gBattleMons[battler].statStages[STAT_SPATK]; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Physical attacker @@ -1078,9 +1101,11 @@ bool32 ShouldSwitch(u32 battler) s32 i; s32 availableToSwitch; - if (gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + if (gBattleMons[battler].volatiles.wrapped) return FALSE; - if (gStatuses3[battler] & STATUS3_ROOTED) + if (gBattleMons[battler].volatiles.escapePrevention) + return FALSE; + if (gBattleMons[battler].volatiles.root) return FALSE; if (IsAbilityPreventingEscape(battler)) return FALSE; @@ -1088,7 +1113,7 @@ bool32 ShouldSwitch(u32 battler) return FALSE; // Sequence Switching AI never switches mid-battle - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) return FALSE; availableToSwitch = 0; @@ -1140,7 +1165,7 @@ bool32 ShouldSwitch(u32 battler) if (ShouldSwitchIfWonderGuard(battler)) return TRUE; - if ((gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) + if ((gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) return FALSE; if (ShouldSwitchIfTrapperInParty(battler)) return TRUE; @@ -1168,7 +1193,7 @@ bool32 ShouldSwitch(u32 battler) // Removing switch capabilites under specific conditions // These Functions prevent the "FindMonWithFlagsAndSuperEffective" from getting out of hand. // We don't use FindMonWithFlagsAndSuperEffective with AI_FLAG_SMART_SWITCHING, so we can bail early. - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) return FALSE; if (CanUseSuperEffectiveMoveAgainstOpponents(battler)) return FALSE; @@ -1187,7 +1212,7 @@ bool32 ShouldSwitch(u32 battler) bool32 ShouldSwitchIfAllScoresBad(u32 battler) { u32 i, score, opposingBattler = GetOppositeBattler(battler); - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1227,9 +1252,11 @@ void ModifySwitchAfterMoveScoring(u32 battler) s32 i; s32 availableToSwitch; - if (gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + if (gBattleMons[battler].volatiles.wrapped) return; - if (gStatuses3[battler] & STATUS3_ROOTED) + if (gBattleMons[battler].volatiles.escapePrevention) + return; + if (gBattleMons[battler].volatiles.root) return; if (IsAbilityPreventingEscape(battler)) return; @@ -1237,7 +1264,7 @@ void ModifySwitchAfterMoveScoring(u32 battler) return; // Sequence Switching AI never switches mid-battle - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) return; availableToSwitch = 0; @@ -1414,33 +1441,18 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, u8 invalidMons, u32 battler, u32 opposingBattler) { int i, bits = 0; - while (bits != 0x3F) // All mons were checked. { - uq4_12_t bestResist = UQ_4_12(1.0); + u32 bestResist = UQ_4_12(2.0); int bestMonId = PARTY_SIZE; // Find the mon whose type is the most suitable defensively. for (i = firstId; i < lastId; i++) { if (!((1u << i) & invalidMons) && !((1u << i) & bits)) { - u16 species = GetMonData(&party[i], MON_DATA_SPECIES); - uq4_12_t typeEffectiveness = UQ_4_12(1.0); + InitializeSwitchinCandidate(&party[i]); - u8 atkType1 = gBattleMons[opposingBattler].types[0]; - u8 atkType2 = gBattleMons[opposingBattler].types[1]; - u8 defType1 = GetSpeciesType(species, 0); - u8 defType2 = GetSpeciesType(species, 1); - - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); - if (defType2 != defType1) - { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); - } + u32 typeEffectiveness = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); if (typeEffectiveness < bestResist) { bestResist = typeEffectiveness; @@ -1478,8 +1490,8 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva int i, j; int dmg, bestDmg = 0; int bestMonId = PARTY_SIZE; - u32 aiMove; + uq4_12_t effectiveness; // If we couldn't find the best mon in terms of typing, find the one that deals most damage. for (i = firstId; i < lastId; i++) @@ -1493,7 +1505,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) { aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j); - dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING); if (bestDmg < dmg) { bestDmg = dmg; @@ -1506,7 +1518,25 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva return bestMonId; } -bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2) +static u32 GetFirstNonIvalidMon(u32 firstId, u32 lastId, u32 invalidMons, u32 battlerIn1, u32 battlerIn2) +{ + if (!IsDoubleBattle()) + return PARTY_SIZE; + + if (PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn1] + && PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn2]) + return PARTY_SIZE; + + for (u32 chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--) + { + if ((1 << (chosenMonId)) & invalidMons) + continue; + return chosenMonId; // first non invalid mon found + } + return PARTY_SIZE; +} + +bool32 IsMonGrounded(u16 heldItemEffect, enum Ability ability, u8 type1, u8 type2) { // List that makes mon not grounded if (type1 == TYPE_FLYING || type2 == TYPE_FLYING || ability == ABILITY_LEVITATE @@ -1527,22 +1557,23 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon { u8 defType1 = battleMon->types[0], defType2 = battleMon->types[1], tSpikesLayers; u16 heldItemEffect = GetItemHoldEffect(battleMon->item); - u32 maxHP = battleMon->maxHP, ability = battleMon->ability, status = battleMon->status1; + u32 maxHP = battleMon->maxHP; + enum Ability ability = battleMon->ability, status = battleMon->status1; u32 spikesDamage = 0, tSpikesDamage = 0, hazardDamage = 0; - u32 hazardFlags = gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_SAFEGUARD); + u32 side = GetBattlerSide(battler); // Check ways mon might avoid all hazards if (ability != ABILITY_MAGIC_GUARD || (heldItemEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !((gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) || ability == ABILITY_KLUTZ))) { // Stealth Rock - if ((hazardFlags & SIDE_STATUS_STEALTH_ROCK) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) + if (IsHazardOnSide(side, HAZARDS_STEALTH_ROCK) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, defType1, defType2, battleMon->maxHP); // G-Max Steelsurge - if ((hazardFlags & SIDE_STATUS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) + if (IsHazardOnSide(side, HAZARDS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, defType1, defType2, battleMon->maxHP); // Spikes - if ((hazardFlags & SIDE_STATUS_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) + if (IsHazardOnSide(side, HAZARDS_TOXIC_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) { spikesDamage = maxHP / ((5 - gSideTimers[GetBattlerSide(battler)].spikesAmount) * 2); if (spikesDamage == 0) @@ -1550,13 +1581,13 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon hazardDamage += spikesDamage; } - if ((hazardFlags & SIDE_STATUS_TOXIC_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON + if (IsHazardOnSide(side, HAZARDS_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON && defType1 != TYPE_STEEL && defType2 != TYPE_STEEL && ability != ABILITY_IMMUNITY && ability != ABILITY_POISON_HEAL && ability != ABILITY_COMATOSE && status == 0 - && !(hazardFlags & SIDE_STATUS_SAFEGUARD) + && !(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) && !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL) - && !IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) + && !IsBattlerTerrainAffected(battler, ability, gAiLogicData->holdEffects[battler], STATUS_FIELD_MISTY_TERRAIN) && !IsAbilityStatusProtected(battler, ability) && heldItemEffect != HOLD_EFFECT_CURE_PSN && heldItemEffect != HOLD_EFFECT_CURE_STATUS && IsMonGrounded(heldItemEffect, ability, defType1, defType2))) @@ -1583,7 +1614,8 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon // Gets damage / healing from weather static s32 GetSwitchinWeatherImpact(void) { - s32 weatherImpact = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; + s32 weatherImpact = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); if (HasWeatherEffect()) @@ -1647,7 +1679,8 @@ static s32 GetSwitchinWeatherImpact(void) // Gets one turn of recurring healing static u32 GetSwitchinRecurringHealing(void) { - u32 recurringHealing = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; + u32 recurringHealing = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); // Items @@ -1681,7 +1714,8 @@ static u32 GetSwitchinRecurringHealing(void) // Gets one turn of recurring damage static u32 GetSwitchinRecurringDamage(void) { - u32 passiveDamage = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, ability = gAiLogicData->switchinCandidate.battleMon.ability; + u32 passiveDamage = 0, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability; enum ItemHoldEffect holdEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); // Items @@ -1715,7 +1749,8 @@ static u32 GetSwitchinStatusDamage(u32 battler) u8 defType1 = gAiLogicData->switchinCandidate.battleMon.types[0], defType2 = gAiLogicData->switchinCandidate.battleMon.types[1]; u8 tSpikesLayers = gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount; u16 heldItemEffect = GetItemHoldEffect(gAiLogicData->switchinCandidate.battleMon.item); - u32 status = gAiLogicData->switchinCandidate.battleMon.status1, ability = gAiLogicData->switchinCandidate.battleMon.ability, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; + u32 status = gAiLogicData->switchinCandidate.battleMon.status1; + enum Ability ability = gAiLogicData->switchinCandidate.battleMon.ability, maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP; u32 statusDamage = 0; // Status condition damage @@ -1791,17 +1826,17 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) u32 recurringDamage = GetSwitchinRecurringDamage(); u32 recurringHealing = GetSwitchinRecurringHealing(); u32 statusDamage = GetSwitchinStatusDamage(battler); - u32 hitsToKO = 0, singleUseItemHeal = 0; + u32 hitsToKO = 0; u16 maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, item = gAiLogicData->switchinCandidate.battleMon.item, heldItemEffect = GetItemHoldEffect(item); u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = GetItemHoldEffectParam(item); u32 opposingBattler = GetOppositeBattler(battler); - u32 opposingAbility = gBattleMons[opposingBattler].ability, ability = gAiLogicData->switchinCandidate.battleMon.ability; + enum Ability opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->switchinCandidate.battleMon.ability; bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility); - s32 currentHP = startingHP; + s32 currentHP = startingHP, singleUseItemHeal = 0; // No damage being dealt if ((damageTaken + statusDamage + recurringDamage <= recurringHealing) || damageTaken + statusDamage + recurringDamage == 0) - return startingHP; + return hitsToKO; // Mon fainted to hazards if (startingHP == 0) @@ -1822,11 +1857,11 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) currentHP = 1; // If mon is still alive, apply weather impact first, as it might KO the mon before it can heal with its item (order is weather -> item -> status) - if (currentHP != 0) + if (currentHP > 0) currentHP = currentHP - weatherImpact; // Check if we're at a single use healing item threshold - if (gAiLogicData->switchinCandidate.battleMon.ability != ABILITY_KLUTZ && usedSingleUseHealingItem == FALSE + if (currentHP > 0 && gAiLogicData->switchinCandidate.battleMon.ability != ABILITY_KLUTZ && usedSingleUseHealingItem == FALSE && !(opposingAbility == ABILITY_UNNERVE && GetItemPocket(item) == POCKET_BERRIES)) { switch (heldItemEffect) @@ -1869,7 +1904,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) } // Healing from items occurs before status so we can do the rest in one line - if (currentHP >= 0) + if (currentHP > 0) currentHP = currentHP + recurringHealing - recurringDamage - statusDamage; // Recalculate toxic damage if needed @@ -1884,7 +1919,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) } // Disguise will always add an extra hit to KO - if (opponentCanBreakMold && gAiLogicData->switchinCandidate.battleMon.species == SPECIES_MIMIKYU_DISGUISED) + if (!opponentCanBreakMold && gAiLogicData->switchinCandidate.battleMon.species == SPECIES_MIMIKYU_DISGUISED) hitsToKO++; // If mon had a hypothetical status from TSpikes, clear it @@ -1896,25 +1931,34 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) return hitsToKO; } -static u16 GetSwitchinTypeMatchup(u32 opposingBattler, struct BattlePokemon battleMon) +static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struct BattlePokemon battleMon) { - // Check type matchup - u16 typeEffectiveness = UQ_4_12(1.0); - u8 atkType1 = GetSpeciesType(gBattleMons[opposingBattler].species, 0), atkType2 = GetSpeciesType(gBattleMons[opposingBattler].species, 1), + u32 typeEffectiveness1 = UQ_4_12(1.0), typeEffectiveness2 = UQ_4_12(1.0); + u8 atkType1 = opposingBattleMon.types[0], atkType2 = opposingBattleMon.types[1], defType1 = battleMon.types[0], defType2 = battleMon.types[1]; - // Multiply type effectiveness by a factor depending on type matchup - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); + // Add each independent defensive type matchup together + typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType1))); if (defType2 != defType1) + typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType2))); + if (typeEffectiveness1 == 0) // Immunity + typeEffectiveness1 = UQ_4_12(0.1); + + if (atkType2 != atkType1) { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); + typeEffectiveness2 = uq4_12_multiply(typeEffectiveness2, (GetTypeModifier(atkType2, defType1))); + if (defType2 != defType1) + typeEffectiveness2 = uq4_12_multiply(typeEffectiveness2, (GetTypeModifier(atkType2, defType2))); + if (typeEffectiveness2 == 0) // Immunity + typeEffectiveness2 = UQ_4_12(0.1); } - return typeEffectiveness; + else + { + typeEffectiveness2 = typeEffectiveness1; + } + + return typeEffectiveness1 + typeEffectiveness2; } static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId, int lastId, int currentMonId) @@ -1937,28 +1981,60 @@ static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId, return PARTY_SIZE; } -static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon) +static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon, u32 *bestPlayerMove) { int i = 0; u32 playerMove; + u16 *playerMoves = GetMovesArray(opposingBattler); s32 damageTaken = 0, maxDamageTaken = 0; + uq4_12_t effectiveness; for (i = 0; i < MAX_MON_MOVES; i++) { - playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { - damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); + damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING); if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move return damageTaken; if (damageTaken > maxDamageTaken) + { maxDamageTaken = damageTaken; + *bestPlayerMove = playerMove; + } } } return maxDamageTaken; } -static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent) +static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon, u32 *bestPlayerPriorityMove) +{ + int i = 0; + u32 playerMove; + u16 *playerMoves = GetMovesArray(opposingBattler); + s32 damageTaken = 0, maxDamageTaken = 0; + uq4_12_t effectiveness = UQ_4_12(1.0); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 + && playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) + { + damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, AI_DEFENDING); + if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move + return damageTaken; + if (damageTaken > maxDamageTaken) + { + maxDamageTaken = damageTaken; + *bestPlayerPriorityMove = playerMove; + } + } + } + return maxDamageTaken; +} + +static bool32 CanAbilityTrapOpponent(enum Ability ability, u32 opponent) { if ((B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(opponent, TYPE_GHOST))) return FALSE; @@ -1969,7 +2045,7 @@ static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent) else return TRUE; } - else if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(opponent)) + else if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(opponent, gAiLogicData->abilities[opponent], gAiLogicData->holdEffects[opponent])) return TRUE; else if (ability == ABILITY_MAGNET_PULL && IS_BATTLER_OF_TYPE(opponent, TYPE_STEEL)) return TRUE; @@ -1990,7 +2066,7 @@ static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchi return TRUE; if (gAiLogicData->ejectPackSwitch) { - u32 opposingAbility = GetBattlerAbilityIgnoreMoldBreaker(opposingBattler); + enum Ability opposingAbility = GetBattlerAbilityIgnoreMoldBreaker(opposingBattler); // If faster, not a free switch; likely lowered own stats if (!movedSecond && opposingAbility != ABILITY_INTIMIDATE && opposingAbility != ABILITY_SUPERSWEET_SYRUP) // Intimidate triggers switches before turn starts return FALSE; @@ -2008,6 +2084,18 @@ static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchi static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool32 isSwitchinFirst, bool32 isFreeSwitch) { + // Player's best move deals 0 damage + if (hitsToKOAI == 0 && hitsToKOPlayer > 0) + return TRUE; + + // AI's best move deals 0 damage + if (hitsToKOPlayer == 0 && hitsToKOAI > 0) + return FALSE; + + // Neither mon can damage the other + if (hitsToKOPlayer == 0 && hitsToKOAI == 0) + return FALSE; + // Free switch, need to outspeed or take 1 extra hit if (isFreeSwitch) { @@ -2024,14 +2112,16 @@ static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool3 // Everything runs in the same loop to minimize computation time. This makes it harder to read, but hopefully the comments can guide you! static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, enum SwitchType switchType) { - int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE; + int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE, generic1v1MonId = PARTY_SIZE; int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE; int i, j, aliveCount = 0, bits = 0, aceMonCount = 0; s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0; - u32 aiMove, hitsToKOAI, maxHitsToKO = 0; - u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup; - bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1; + u32 aiMove, hitsToKOAI, hitsToKOPlayer, hitsToKOAIPriority, bestPlayerMove = MOVE_NONE, bestPlayerPriorityMove = MOVE_NONE, maxHitsToKO = 0; + u32 bestResist = UQ_4_12(2.0), bestResistEffective = UQ_4_12(2.0), typeMatchup; // 2.0 is the default "Neutral" matchup from GetBattleMonTypeMatchup + bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, isSwitchinFirstPriority, canSwitchinWin1v1; + u32 invalidMons = 0; + uq4_12_t effectiveness = UQ_4_12(1.0); // Iterate through mons for (i = firstId; i < lastId; i++) @@ -2043,6 +2133,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, || i == gBattleStruct->monToSwitchIntoId[battlerIn1] || i == gBattleStruct->monToSwitchIntoId[battlerIn2]) { + invalidMons |= 1u << i; continue; } // Save Ace Pokemon for last @@ -2050,6 +2141,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { aceMonId = i; aceMonCount++; + invalidMons |= 1u << i; continue; } else @@ -2062,20 +2154,25 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, continue; // Get max number of hits for player to KO AI mon and type matchup for defensive switching - hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon), battler); - typeMatchup = GetSwitchinTypeMatchup(opposingBattler, gAiLogicData->switchinCandidate.battleMon); + hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &bestPlayerMove), battler); + hitsToKOAIPriority = GetSwitchinHitsToKO(GetMaxPriorityDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &bestPlayerPriorityMove), battler); + typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); // Check through current mon's moves for (j = 0; j < MAX_MON_MOVES; j++) { - aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; + // Check that move has PP remaining before running calcs + if (gAiLogicData->switchinCandidate.battleMon.pp[j] < 1) + continue; - if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) - damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; + damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &effectiveness, AI_ATTACKING); + hitsToKOPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); // Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1 - isSwitchinFirst = AI_WhoStrikesFirstPartyMon(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove); - canSwitchinWin1v1 = CanSwitchinWin1v1(hitsToKOAI, GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler), isSwitchinFirst, isFreeSwitch); + isSwitchinFirst = AI_IsPartyMonFaster(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove, bestPlayerMove, CONSIDER_PRIORITY); + isSwitchinFirstPriority = AI_IsPartyMonFaster(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove, bestPlayerPriorityMove, CONSIDER_PRIORITY); + canSwitchinWin1v1 = CanSwitchinWin1v1(hitsToKOAI, hitsToKOPlayer, isSwitchinFirst, isFreeSwitch) && CanSwitchinWin1v1(hitsToKOAIPriority, hitsToKOPlayer, isSwitchinFirstPriority, isFreeSwitch); // AI must successfully 1v1 with and without priority to be considered a good option // Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not if (GetMoveEffect(aiMove) == EFFECT_BATON_PASS) @@ -2102,12 +2199,15 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, defensiveMonId = i; } + if (canSwitchinWin1v1) + generic1v1MonId = i; + // Check for mon with resistance and super effective move for best type matchup mon with effective move if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) { if (typeMatchup < bestResistEffective) { - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) + if (effectiveness >= UQ_4_12(2.0)) { if (canSwitchinWin1v1) { @@ -2182,6 +2282,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (typeMatchupEffectiveId != PARTY_SIZE) return typeMatchupEffectiveId; else if (typeMatchupId != PARTY_SIZE) return typeMatchupId; else if (batonPassId != PARTY_SIZE) return batonPassId; + else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId; else if (damageMonId != PARTY_SIZE) return damageMonId; } else @@ -2192,12 +2293,18 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (typeMatchupId != PARTY_SIZE) return typeMatchupId; else if (defensiveMonId != PARTY_SIZE) return defensiveMonId; else if (batonPassId != PARTY_SIZE) return batonPassId; + else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId; } // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) return aceMonId; + // Fallback + u32 bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + if (bestMonId != PARTY_SIZE) + return bestMonId; + return PARTY_SIZE; } @@ -2257,14 +2364,14 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) GetAIPartyIndexes(battler, &firstId, &lastId); party = GetBattlerParty(battler); - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) { bestMonId = GetNextMonInParty(party, firstId, lastId, battlerIn1, battlerIn2); return bestMonId; } // Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer. - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic { bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchType); return bestMonId; @@ -2315,6 +2422,11 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) return aceMonId; + // Fallback + bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + if (bestMonId != PARTY_SIZE) + return bestMonId; + return PARTY_SIZE; } } @@ -2328,7 +2440,7 @@ static bool32 AiExpectsToFaintPlayer(u32 battler) if (!IsBattlerAlly(target, battler) && CanIndexMoveFaintTarget(battler, target, gAiBattleData->chosenMoveIndex[battler], AI_ATTACKING) - && AI_IsFaster(battler, target, GetAIChosenMove(battler))) + && AI_IsFaster(battler, target, GetAIChosenMove(battler), GetIncomingMove(battler, target, gAiLogicData), CONSIDER_PRIORITY)) { // We expect to faint the target and move first -> dont use an item return TRUE; @@ -2350,10 +2462,10 @@ static bool32 ShouldUseItem(u32 battler) // If teaming up with player and Pokemon is on the right, or Pokemon is currently held by Sky Drop if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT) - || gStatuses3[battler] & STATUS3_SKY_DROPPED) + || gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; - if (gStatuses3[battler] & STATUS3_EMBARGO) + if (gBattleMons[battler].volatiles.embargo) return FALSE; if (AiExpectsToFaintPlayer(battler)) @@ -2395,16 +2507,15 @@ static bool32 ShouldUseItem(u32 battler) case EFFECT_ITEM_CURE_STATUS: if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[battler].status1 & STATUS1_SLEEP) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_POISON && (gBattleMons[battler].status1 & STATUS1_POISON - || gBattleMons[battler].status1 & STATUS1_TOXIC_POISON)) + if (itemEffects[3] & ITEM3_POISON && gBattleMons[battler].status1 & STATUS1_PSN_ANY) shouldUse = TRUE; if (itemEffects[3] & ITEM3_BURN && gBattleMons[battler].status1 & STATUS1_BURN) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_FREEZE && (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE)) + if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[battler].status1 & STATUS1_ICY_ANY) shouldUse = TRUE; if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[battler].status1 & STATUS1_PARALYSIS) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].volatiles.confusionTurns > 0) shouldUse = TRUE; break; case EFFECT_ITEM_INCREASE_STAT: @@ -2416,7 +2527,8 @@ static bool32 ShouldUseItem(u32 battler) break; case EFFECT_ITEM_SET_FOCUS_ENERGY: if (!gDisableStructs[battler].isFirstTurn - || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY + || gBattleMons[battler].volatiles.dragonCheer + || gBattleMons[battler].volatiles.focusEnergy || AI_OpponentCanFaintAiWithMod(battler, 0)) break; shouldUse = TRUE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index cb30d6d8b..46ff7aac8 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3,6 +3,7 @@ #include "malloc.h" #include "battle.h" #include "battle_anim.h" +#include "battle_ai_field_statuses.h" #include "battle_ai_util.h" #include "battle_ai_main.h" #include "battle_ai_switch_items.h" @@ -23,7 +24,21 @@ #include "constants/moves.h" #include "constants/items.h" +static u32 GetAIEffectGroup(enum BattleMoveEffects effect); +static u32 GetAIEffectGroupFromMove(u32 battler, u32 move); + // Functions +static u32 AI_GetMoldBreakerSanitizedAbility(u32 battlerAtk, enum Ability abilityAtk, enum Ability abilityDef, u32 holdEffectDef, u32 move) +{ + if (MoveIgnoresTargetAbility(move)) + return ABILITY_NONE; + + if (holdEffectDef != HOLD_EFFECT_ABILITY_SHIELD && IsMoldBreakerTypeAbility(battlerAtk, abilityAtk)) + return ABILITY_NONE; + + return abilityDef; +} + static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move) { u32 numOfTargets = 0; @@ -50,6 +65,11 @@ static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move) return FALSE; } +bool32 AI_IsBattlerGrounded(u32 battler) +{ + return IsBattlerGrounded(battler, gAiLogicData->abilities[battler], gAiLogicData->holdEffects[battler]); +} + u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData) { if (calcContext == AI_ATTACKING && BattlerHasAi(battlerAtk)) @@ -75,14 +95,24 @@ u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcC } } -bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move) +bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) { - return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_FASTER); + return (AI_WhoStrikesFirst(battlerAi, battlerDef, aiMove, playerMove, considerPriority) == AI_IS_FASTER); } -bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move) +bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) { - return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_SLOWER); + return (AI_WhoStrikesFirst(battlerAi, battlerDef, aiMove, playerMove, considerPriority) == AI_IS_SLOWER); +} + +bool32 AI_IsPartyMonFaster(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) +{ + return (AI_WhoStrikesFirstPartyMon(battlerAi, battlerDef, switchinCandidate, aiMove, playerMove, considerPriority) == AI_IS_FASTER); +} + +bool32 AI_IsPartyMonSlower(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) +{ + return (AI_WhoStrikesFirstPartyMon(battlerAi, battlerDef, switchinCandidate, aiMove, playerMove, considerPriority) == AI_IS_SLOWER); } u32 GetAIChosenMove(u32 battlerId) @@ -132,6 +162,24 @@ bool32 IsAiBattlerAware(u32 battlerId) return BattlerHasAi(battlerId); } +bool32 IsAiBattlerAssumingStab() +{ + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_STAB + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_STAB) + return TRUE; + + return FALSE; +} + +bool32 IsAiBattlerAssumingStatusMoves() +{ + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_STATUS_MOVES + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_STATUS_MOVES) + return TRUE; + + return FALSE; +} + bool32 IsAiBattlerPredictingAbility(u32 battlerId) { if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_WEIGH_ABILITY_PREDICTION @@ -141,11 +189,17 @@ bool32 IsAiBattlerPredictingAbility(u32 battlerId) return BattlerHasAi(battlerId); } +bool32 CanAiPredictMove(void) +{ + return gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_PREDICT_MOVE + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_PREDICT_MOVE; +} + bool32 IsBattlerPredictedToSwitch(u32 battler) { // Check for prediction flag on AI, whether they're using those predictions this turn, and whether the AI thinks the player should switch - if (gAiThinkingStruct->aiFlags[gAiLogicData->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH - || gAiThinkingStruct->aiFlags[gAiLogicData->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH) + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_PREDICT_SWITCH + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_PREDICT_SWITCH) { if (gAiLogicData->predictingSwitch && gAiLogicData->shouldSwitch & (1u << battler)) return TRUE; @@ -156,12 +210,19 @@ bool32 IsBattlerPredictedToSwitch(u32 battler) // Either a predicted move or the last used move from an opposing battler u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData) { - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE && aiData->predictingMove) + if (aiData->predictingMove && CanAiPredictMove()) return aiData->predictedMove[opposingBattler]; - return aiData->lastUsedMove[opposingBattler]; } +// When not predicting, don't want to reference player's previous move; leads to weird behaviour for cases like Fake Out or Protect, especially in doubles +u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicData *aiData) +{ + if (aiData->predictingMove && CanAiPredictMove()) + return aiData->predictedMove[opposingBattler]; + return MOVE_NONE; +} + void ClearBattlerMoveHistory(u32 battlerId) { memset(gBattleHistory->usedMoves[battlerId], 0, sizeof(gBattleHistory->usedMoves[battlerId])); @@ -200,7 +261,7 @@ void RecordAllMoves(u32 battler) memcpy(gAiPartyData->mons[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].moves, gBattleMons[battler].moves, MAX_MON_MOVES * sizeof(u16)); } -void RecordAbilityBattle(u32 battlerId, u32 abilityId) +void RecordAbilityBattle(u32 battlerId, enum Ability abilityId) { gBattleHistory->abilities[battlerId] = abilityId; gAiPartyData->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability = abilityId; @@ -240,6 +301,66 @@ void SaveBattlerData(u32 battlerId) gAiThinkingStruct->saved[battlerId].types[1] = gBattleMons[battlerId].types[1]; } +bool32 ShouldRecordStatusMove(u32 move) +{ + if (ASSUME_STATUS_MOVES_HAS_TUNING) + { + switch (GetMoveEffect(move)) + { + // variable odds by additional effect + case EFFECT_NON_VOLATILE_STATUS: + if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP && RandomPercentage(RNG_AI_ASSUME_STATUS_SLEEP, ASSUME_STATUS_HIGH_ODDS)) + return TRUE; + else if (RandomPercentage(RNG_AI_ASSUME_STATUS_NONVOLATILE, ASSUME_STATUS_MEDIUM_ODDS)) + return TRUE; + break; + // High odds + case EFFECT_AURORA_VEIL: + case EFFECT_CHILLY_RECEPTION: + case EFFECT_FIRST_TURN_ONLY: + case EFFECT_FOLLOW_ME: + case EFFECT_INSTRUCT: + case EFFECT_JUNGLE_HEALING: + case EFFECT_SHED_TAIL: + return RandomPercentage(RNG_AI_ASSUME_STATUS_HIGH_ODDS, ASSUME_STATUS_HIGH_ODDS); + // Medium odds + case EFFECT_AFTER_YOU: + case EFFECT_DOODLE: + case EFFECT_ENCORE: + case EFFECT_HAZE: + case EFFECT_PARTING_SHOT: + case EFFECT_PROTECT: + case EFFECT_REST: + case EFFECT_ROAR: + case EFFECT_ROOST: + case EFFECT_SLEEP_TALK: + case EFFECT_TAUNT: + case EFFECT_TAILWIND: + case EFFECT_TRICK: + case EFFECT_TRICK_ROOM: + // defoggables / screens and hazards + case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: + case EFFECT_SPIKES: + case EFFECT_STEALTH_ROCK: + case EFFECT_STICKY_WEB: + case EFFECT_TOXIC_SPIKES: + return RandomPercentage(RNG_AI_ASSUME_STATUS_MEDIUM_ODDS, ASSUME_STATUS_MEDIUM_ODDS); + // Low odds + case EFFECT_ENTRAINMENT: + case EFFECT_FIXED_PERCENT_DAMAGE: + case EFFECT_GASTRO_ACID: + case EFFECT_IMPRISON: + case EFFECT_TELEPORT: + return RandomPercentage(RNG_AI_ASSUME_STATUS_LOW_ODDS, ASSUME_STATUS_LOW_ODDS); + default: + break; + } + } + + return RandomPercentage(RNG_AI_ASSUME_ALL_STATUS, ASSUME_ALL_STATUS_ODDS) && IsBattleMoveStatus(move); +} + static bool32 ShouldFailForIllusion(u32 illusionSpecies, u32 battlerId) { u32 i, j; @@ -364,9 +485,16 @@ bool32 AI_CanBattlerEscape(u32 battler) bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) { - if (gBattleMons[battlerDef].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) + if (AI_CanBattlerEscape(battlerDef)) + return FALSE; + + if (gBattleMons[battlerDef].volatiles.wrapped) return TRUE; - if (gStatuses3[battlerDef] & (STATUS3_ROOTED | STATUS3_SKY_DROPPED)) + if (gBattleMons[battlerDef].volatiles.escapePrevention) + return TRUE; + if (gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_SKY_DROP) + return TRUE; + if (gBattleMons[battlerDef].volatiles.root) return TRUE; if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return TRUE; @@ -374,28 +502,32 @@ bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) && (B_SHADOW_TAG_ESCAPE >= GEN_4 && gAiLogicData->abilities[battlerDef] != ABILITY_SHADOW_TAG)) return TRUE; if (AI_IsAbilityOnSide(battlerAtk, ABILITY_ARENA_TRAP) - && IsBattlerGrounded(battlerAtk)) + && AI_IsBattlerGrounded(battlerAtk)) return TRUE; if (AI_IsAbilityOnSide(battlerAtk, ABILITY_MAGNET_PULL) && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_STEEL)) return TRUE; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && CountUsablePartyMons(battlerDef) == 0) + return TRUE; + return FALSE; } u32 GetTotalBaseStat(u32 species) { return GetSpeciesBaseHP(species) - + GetSpeciesBaseAttack(species) - + GetSpeciesBaseDefense(species) - + GetSpeciesBaseSpeed(species) - + GetSpeciesBaseSpAttack(species) - + GetSpeciesBaseSpDefense(species); + + GetSpeciesBaseAttack(species) + + GetSpeciesBaseDefense(species) + + GetSpeciesBaseSpeed(species) + + GetSpeciesBaseSpAttack(species) + + GetSpeciesBaseSpDefense(species); } bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) { int i; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAI, opposingBattler, gAiLogicData); for (i = 0; i < MAX_MON_MOVES; i++) { @@ -403,14 +535,14 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_PROTECT && move != MOVE_ENDURE) return TRUE; - if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI))) + if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI), predictedMoveSpeedCheck, CONSIDER_PRIORITY)) return TRUE; } return FALSE; } // move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 IsAffectedByPowder(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect) { if (ability == ABILITY_OVERCOAT || (B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) @@ -419,6 +551,24 @@ bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffe return TRUE; } +bool32 Ai_IsPriorityBlocked(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) +{ + s32 atkPriority = GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move); + + if (atkPriority <= 0 || IsBattlerAlly(battlerAtk, battlerDef)) + return FALSE; + + if (IsMoldBreakerTypeAbility(battlerAtk, aiData->abilities[battlerAtk]) || MoveIgnoresTargetAbility(move)) + return FALSE; + + if (IsDazzlingAbility(aiData->abilities[battlerDef])) + return TRUE; + + if (IsDoubleBattle() && IsDazzlingAbility(aiData->abilities[BATTLE_PARTNER(battlerDef)])) + return TRUE; + + return FALSE; +} // This function checks if all physical/special moves are either unusable or unreasonable to use. // Consider a pokemon boosting their attack against a ghost pokemon having only normal-type physical attacks. bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category) @@ -493,8 +643,8 @@ static inline s32 DmgRoll(s32 dmg) bool32 IsDamageMoveUnusable(struct DamageContext *ctx) { - u32 battlerDefAbility; - u32 partnerDefAbility; + enum Ability battlerDefAbility; + enum Ability partnerDefAbility; struct AiLogicData *aiData = gAiLogicData; if (ctx->typeEffectivenessModifier == UQ_4_12(0.0)) @@ -514,16 +664,19 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) partnerDefAbility = aiData->abilities[BATTLE_PARTNER(ctx->battlerDef)]; } - if (CanAbilityBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, battlerDefAbility, ctx->move, ABILITY_CHECK_TRIGGER)) + if (Ai_IsPriorityBlocked(ctx->battlerAtk, ctx->battlerDef, ctx->move, aiData)) return TRUE; - if (CanAbilityAbsorbMove(ctx->battlerAtk, ctx->battlerDef, battlerDefAbility, ctx->move, ctx->moveType, ABILITY_CHECK_TRIGGER)) + if (CanAbilityBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, battlerDefAbility, ctx->move, AI_CHECK)) + return TRUE; + + if (CanAbilityAbsorbMove(ctx->battlerAtk, ctx->battlerDef, battlerDefAbility, ctx->move, ctx->moveType, AI_CHECK)) return TRUE; // Limited to Lighning Rod and Storm Drain because otherwise the AI would consider Water Absorb, etc... if (partnerDefAbility == ABILITY_LIGHTNING_ROD || partnerDefAbility == ABILITY_STORM_DRAIN) { - if (CanAbilityAbsorbMove(ctx->battlerAtk, BATTLE_PARTNER(ctx->battlerDef), partnerDefAbility, ctx->move, ctx->moveType, ABILITY_CHECK_TRIGGER)) + if (CanAbilityAbsorbMove(ctx->battlerAtk, BATTLE_PARTNER(ctx->battlerDef), partnerDefAbility, ctx->move, ctx->moveType, AI_CHECK)) return TRUE; } @@ -549,7 +702,7 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) return TRUE; break; case EFFECT_LAST_RESORT: - if (!CanUseLastResort(ctx->battlerAtk)) + if (!CanUseLastResort(ctx->battlerAtk) && !IsConsideringZMove(ctx->battlerAtk, ctx->battlerDef, ctx->move)) return TRUE; break; case EFFECT_LOW_KICK: @@ -561,8 +714,8 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) if (!IS_BATTLER_OF_TYPE(ctx->battlerAtk, GetMoveArgType(ctx->move))) return TRUE; break; - case EFFECT_HIT_SET_REMOVE_TERRAIN: - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && GetMoveEffectArg_MoveProperty(ctx->move) == ARG_TRY_REMOVE_TERRAIN_FAIL) + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) return TRUE; break; case EFFECT_POLTERGEIST: @@ -754,10 +907,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u if (gBattleStruct->gimmick.usableGimmick[battlerAtk] && GetActiveGimmick(battlerAtk) == GIMMICK_NONE && gBattleStruct->gimmick.usableGimmick[battlerAtk] != GIMMICK_NONE && considerGimmickAtk == USE_GIMMICK) { - // Set Z-Move variables if needed - if (gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && IsViableZMove(battlerAtk, move)) - gBattleStruct->zmove.baseMoves[battlerAtk] = move; - toggledGimmickAtk = TRUE; SetActiveGimmick(battlerAtk, gBattleStruct->gimmick.usableGimmick[battlerAtk]); } @@ -772,6 +921,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u SetDynamicMoveCategory(battlerAtk, battlerDef, move); SetTypeBeforeUsingMove(move, battlerAtk); + // We can set those globals because they are going to get rerolled on attack execution + gBattleStruct->magnitudeBasePower = 70; + gBattleStruct->presentBasePower = 80; + struct DamageContext ctx; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; @@ -782,10 +935,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u ctx.updateFlags = FALSE; ctx.weather = weather; ctx.fixedBasePower = SetFixedMoveBasePower(battlerAtk, move); - ctx.abilityAtk = aiData->abilities[battlerAtk]; - ctx.abilityDef = aiData->abilities[battlerDef]; ctx.holdEffectAtk = aiData->holdEffects[battlerAtk]; ctx.holdEffectDef = aiData->holdEffects[battlerDef]; + ctx.abilityAtk = aiData->abilities[battlerAtk]; + ctx.abilityDef = AI_GetMoldBreakerSanitizedAbility(battlerAtk, ctx.abilityAtk, aiData->abilities[battlerDef], ctx.holdEffectDef, move); ctx.typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(&ctx); u32 movePower = GetMovePower(move); @@ -798,7 +951,12 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u AI_StoreBattlerTypes(battlerAtk, types); ProteanTryChangeType(battlerAtk, aiData->abilities[battlerAtk], move, ctx.moveType); - if (moveEffect == EFFECT_TRIPLE_KICK) + s32 fixedDamage = DoFixedDamageMoveCalc(&ctx); + if (fixedDamage != INT32_MAX) + { + simDamage.minimum = simDamage.median = simDamage.maximum = fixedDamage; + } + else if (moveEffect == EFFECT_TRIPLE_KICK) { for (gMultiHitCounter = GetMoveStrikeCount(move); gMultiHitCounter > 0; gMultiHitCounter--) // The global is used to simulate actual damage done { @@ -848,7 +1006,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u // Undo temporary settings gBattleStruct->dynamicMoveType = 0; gBattleStruct->swapDamageCategory = FALSE; - gBattleStruct->zmove.baseMoves[battlerAtk] = MOVE_NONE; if (toggledGimmickAtk) SetActiveGimmick(battlerAtk, GIMMICK_NONE); if (toggledGimmickDef) @@ -859,7 +1016,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u bool32 AI_IsDamagedByRecoil(u32 battler) { - u32 ability = gAiLogicData->abilities[battler]; + enum Ability ability = gAiLogicData->abilities[battler]; if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_ROCK_HEAD) return FALSE; return TRUE; @@ -869,8 +1026,8 @@ bool32 AI_IsDamagedByRecoil(u32 battler) static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s32 noOfHitsToKo) { u32 i; - u32 abilityDef = gAiLogicData->abilities[battlerDef]; - u32 abilityAtk = gAiLogicData->abilities[battlerAtk]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityAtk = gAiLogicData->abilities[battlerAtk]; switch (GetMoveEffect(move)) { @@ -937,6 +1094,8 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 return TRUE; } break; + default: + break; } } else // consider move effects that hinder the target @@ -975,7 +1134,7 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 case MOVE_EFFECT_SP_DEF_MINUS_1: case MOVE_EFFECT_ACC_MINUS_1: case MOVE_EFFECT_EVS_MINUS_1: - if (CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1) + if (CanLowerStat(battlerAtk, battlerDef, gAiLogicData, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1) return TRUE; break; case MOVE_EFFECT_ATK_MINUS_2: @@ -985,9 +1144,11 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 case MOVE_EFFECT_SP_DEF_MINUS_2: case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_EVS_MINUS_2: - if (CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1) + if (CanLowerStat(battlerAtk, battlerDef, gAiLogicData, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1) return TRUE; break; + default: + break; } } } @@ -997,8 +1158,8 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s32 noOfHitsToKo) { - u32 abilityAtk = gAiLogicData->abilities[battlerAtk]; - u32 abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityAtk = gAiLogicData->abilities[battlerAtk]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; u8 i; switch (GetMoveEffect(move)) @@ -1064,6 +1225,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s || (noOfHitsToKo != 1 && !(abilityDef == ABILITY_CONTRARY && !DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)))) return TRUE; break; + default: + break; } } break; @@ -1073,11 +1236,11 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s } // Checks if one of the moves has side effects or perks, assuming equal dmg or equal no of hits to KO -s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) +enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) { bool32 effect1, effect2; - u32 defAbility = gAiLogicData->abilities[battlerDef]; - u32 atkAbility = gAiLogicData->abilities[battlerAtk]; + enum Ability defAbility = gAiLogicData->abilities[battlerDef]; + enum Ability atkAbility = gAiLogicData->abilities[battlerAtk]; // Check if physical moves hurt. if (gAiLogicData->holdEffects[battlerAtk] != HOLD_EFFECT_PROTECTIVE_PADS && atkAbility != ABILITY_LONG_REACH @@ -1087,27 +1250,27 @@ s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 bool32 moveContact1 = MoveMakesContact(move1); bool32 moveContact2 = MoveMakesContact(move2); if (moveContact1 && !moveContact2) - return -1; + return MOVE_LOST_COMPARISON; if (moveContact2 && !moveContact1) - return 1; + return MOVE_WON_COMPARISON; } // Check additional effects. effect1 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return 1; + return MOVE_WON_COMPARISON; if (effect1 && !effect2) - return -1; + return MOVE_LOST_COMPARISON; effect1 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return -1; + return MOVE_LOST_COMPARISON; if (effect1 && !effect2) - return 1; + return MOVE_WON_COMPARISON; - return 0; + return MOVE_NEUTRAL_COMPARISON; } u32 GetNoOfHitsToKO(u32 dmg, s32 hp) @@ -1127,6 +1290,29 @@ u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum D return GetNoOfHitsToKOBattlerDmg(AI_GetDamage(battlerAtk, battlerDef, moveIndex, calcContext, gAiLogicData), battlerDef); } +u32 GetBestNoOfHitsToKO(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) +{ + u32 result = 100; + u32 tempResult = 0; + + struct AiLogicData *aiData = gAiLogicData; + s32 moveIndex; + u16 *moves = GetMovesArray(battlerAtk); + u32 moveLimitations = aiData->moveLimitations[battlerAtk]; + + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (IsMoveUnusable(moveIndex, moves[moveIndex], moveLimitations)) + continue; + + tempResult = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, moveIndex, calcContext); + if (tempResult != 0 && tempResult < result) + result = tempResult; + } + + return result; +} + u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) { int bestDmg = AI_GetDamage(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, calcContext, gAiLogicData); @@ -1170,23 +1356,24 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) * AI_IS_FASTER: is user(ai) faster * AI_IS_SLOWER: is target faster */ -s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority) { u32 speedBattlerAI, speedBattler; enum ItemHoldEffect holdEffectAI = gAiLogicData->holdEffects[battlerAI]; enum ItemHoldEffect holdEffectPlayer = gAiLogicData->holdEffects[battler]; - u32 abilityAI = gAiLogicData->abilities[battlerAI]; - u32 abilityPlayer = gAiLogicData->abilities[battler]; + enum Ability abilityAI = gAiLogicData->abilities[battlerAI]; + enum Ability abilityPlayer = gAiLogicData->abilities[battler]; - u32 predictedMove = GetIncomingMove(battlerAI, battler, gAiLogicData); + if (considerPriority == CONSIDER_PRIORITY) + { + s8 aiPriority = GetBattleMovePriority(battlerAI, abilityAI, aiMoveConsidered); + s8 playerPriority = GetBattleMovePriority(battler, abilityPlayer, playerMoveConsidered); - s8 aiPriority = GetBattleMovePriority(battlerAI, abilityAI, moveConsidered); - s8 playerPriority = GetBattleMovePriority(battler, abilityPlayer, predictedMove); - - if (aiPriority > playerPriority) - return AI_IS_FASTER; - else if (aiPriority < playerPriority) - return AI_IS_SLOWER; + if (aiPriority > playerPriority) + return AI_IS_FASTER; + else if (aiPriority < playerPriority) + return AI_IS_SLOWER; + } speedBattlerAI = GetBattlerTotalSpeedStatArgs(battlerAI, abilityAI, holdEffectAI); speedBattler = GetBattlerTotalSpeedStatArgs(battler, abilityPlayer, holdEffectPlayer); @@ -1223,12 +1410,12 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) return AI_IS_SLOWER; } -static bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) +bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) { enum BattleMoveEffects effect = GetMoveEffect(move); if (!AI_BattlerAtMaxHp(battlerTarget) || effect == EFFECT_MULTI_HIT) return FALSE; - if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && IsValidDoubleBattle(battlerTarget))) + if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && !HasTwoOpponents(battler))) return FALSE; if (gAiLogicData->holdEffects[battlerTarget] == HOLD_EFFECT_FOCUS_SASH) return TRUE; @@ -1265,7 +1452,7 @@ bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk) return FALSE; } -u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk) +u32 NoOfHitsForTargetToFaintBattler(u32 battlerDef, u32 battlerAtk) { u32 i; u32 currNumberOfHits; @@ -1283,6 +1470,32 @@ u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk) return leastNumberOfHits; } +u32 NoOfHitsForTargetToFaintBattlerWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod) +{ + u32 i; + u32 currNumberOfHits; + u32 leastNumberOfHits = UNKNOWN_NO_OF_HITS; + u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod; + u32 damageDealt = 0; + + if (hpCheck > gBattleMons[battlerAtk].maxHP) + hpCheck = gBattleMons[battlerAtk].maxHP; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + damageDealt = AI_GetDamage(battlerDef, battlerAtk, i, AI_DEFENDING, gAiLogicData); + if (damageDealt == 0) + continue; + currNumberOfHits = hpCheck / (damageDealt + 1) + 1; + if (currNumberOfHits != 0) + { + if (currNumberOfHits < leastNumberOfHits) + leastNumberOfHits = currNumberOfHits; + } + } + return leastNumberOfHits; +} + u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) { struct AiLogicData *aiData = gAiLogicData; @@ -1359,12 +1572,33 @@ bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits) return FALSE; } +// Can battler KO the target ignoring any Endure effects (Sturdy, Focus Sash, etc.) +bool32 CanBattlerKOTargetIgnoringSturdy(u32 battlerAtk, u32 battlerDef) +{ + struct AiLogicData *aiData = gAiLogicData; + s32 moveIndex, dmg; + u16 *moves = GetMovesArray(battlerAtk); + u32 moveLimitations = aiData->moveLimitations[battlerAtk]; + + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (IsMoveUnusable(moveIndex, moves[moveIndex], moveLimitations)) + continue; + dmg = AI_GetDamage(battlerAtk, battlerDef, moveIndex, AI_ATTACKING, aiData); + + if (gBattleMons[battlerDef].hp <= dmg && CanEndureHit(battlerAtk, battlerDef, moves[moveIndex])) + return TRUE; + } + return FALSE; +} + bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits) { u32 indexSlot = GetMoveSlot(GetMovesArray(battlerDef), move); if (indexSlot < MAX_MON_MOVES) { - if (GetNoOfHitsToKO(AI_GetDamage(battlerDef, battlerAtk, indexSlot, AI_DEFENDING, gAiLogicData), gBattleMons[battlerAtk].hp) <= nHits) + u32 hitsToKO = GetNoOfHitsToKO(AI_GetDamage(battlerDef, battlerAtk, indexSlot, AI_DEFENDING, gAiLogicData), gBattleMons[battlerAtk].hp); + if (hitsToKO <= nHits && hitsToKO != 0 && !(CanEndureHit(battlerDef, battlerAtk, move) && hitsToKO == 1)) return TRUE; } return FALSE; @@ -1393,14 +1627,21 @@ bool32 CanTargetFaintAiWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod, s32 dm if (dmgMod) dmg *= dmgMod; - if (dmg >= hpCheck) + // Applies modified HP percent to AI data for consideration when running CanEndureHit + gAiLogicData->hpPercents[battlerAtk] = (hpCheck/gBattleMons[battlerAtk].maxHP)*100; + + if (dmg >= hpCheck && !(CanEndureHit(battlerDef, battlerAtk, moves[moveIndex]) && (dmgMod <= 1))) + { + gAiLogicData->hpPercents[battlerAtk] = (gBattleMons[battlerAtk].hp / gBattleMons[battlerAtk].maxHP) * 100; return TRUE; + } + gAiLogicData->hpPercents[battlerAtk] = (gBattleMons[battlerAtk].hp / gBattleMons[battlerAtk].maxHP) * 100; } return FALSE; } -bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) +bool32 AI_IsAbilityOnSide(u32 battlerId, enum Ability ability) { if (IsBattlerAlive(battlerId) && gAiLogicData->abilities[battlerId] == ability) return TRUE; @@ -1411,20 +1652,20 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) } // does NOT include ability suppression checks -s32 AI_DecideKnownAbilityForTurn(u32 battlerId) +enum Ability AI_DecideKnownAbilityForTurn(u32 battlerId) { u32 validAbilities[NUM_ABILITY_SLOTS]; u8 i, numValidAbilities = 0; - u32 knownAbility = GetBattlerAbilityIgnoreMoldBreaker(battlerId); // during ai checking for mold breaker could lead to inaccuracies - u32 indexAbility; - u32 abilityAiRatings[NUM_ABILITY_SLOTS] = {0}; + enum Ability knownAbility = GetBattlerAbilityIgnoreMoldBreaker(battlerId); + enum Ability indexAbility; + enum Ability abilityAiRatings[NUM_ABILITY_SLOTS] = {0}; // We've had ability overwritten by e.g. Worry Seed. It is not part of gAiPartyData in case of switching if (gDisableStructs[battlerId].overwrittenAbility) return gDisableStructs[battlerId].overwrittenAbility; - // The AI knows its own ability. - if (IsAiBattlerAware(battlerId)) + // The AI knows its own ability, and omniscience handling + if (IsAiBattlerAware(battlerId) || (IsAiBattlerAssumingStab() && ASSUME_STAB_SEES_ABILITY)) return knownAbility; // Check neutralizing gas, gastro acid @@ -1464,26 +1705,29 @@ enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) if (!IsAiBattlerAware(battlerId)) holdEffect = gAiPartyData->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else - holdEffect = GetBattlerHoldEffect(battlerId, FALSE); + holdEffect = GetBattlerHoldEffectIgnoreNegation(battlerId); if (gAiThinkingStruct->aiFlags[battlerId] & AI_FLAG_NEGATE_UNAWARE) return holdEffect; - if (gStatuses3[battlerId] & STATUS3_EMBARGO) + if (gBattleMons[battlerId].volatiles.embargo) return HOLD_EFFECT_NONE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return HOLD_EFFECT_NONE; - if (gAiLogicData->abilities[battlerId] == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID)) + if (gAiLogicData->abilities[battlerId] == ABILITY_KLUTZ && !gBattleMons[battlerId].volatiles.gastroAcid) return HOLD_EFFECT_NONE; return holdEffect; } -bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move) +bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, enum Ability atkAbility, u32 move) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; // AI handicap flag: doesn't understand ability suppression concept + if (atkAbility == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(move)) + return TRUE; + if (IsMoldBreakerTypeAbility(battlerAtk, atkAbility) || MoveIgnoresTargetAbility(move)) return TRUE; @@ -1508,6 +1752,33 @@ u32 AI_GetWeather(void) return gBattleWeather; } +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon) +{ + enum Ability ability = battleMon.ability; + // Forced weather behaviour + if (!AI_WeatherHasEffect()) + return B_WEATHER_NONE; + if (ability == ABILITY_CLOUD_NINE || ability == ABILITY_AIR_LOCK) + return B_WEATHER_NONE; + if (gBattleWeather & B_WEATHER_PRIMAL_ANY) + return gBattleWeather; + + // Switchin will introduce new weather + switch(ability) + { + case ABILITY_DRIZZLE: + return B_WEATHER_RAIN_NORMAL; + case ABILITY_DROUGHT: + return B_WEATHER_SUN_NORMAL; + case ABILITY_SAND_STREAM: + return B_WEATHER_SANDSTORM; + case ABILITY_SNOW_WARNING: + return B_SNOW_WARNING >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL; + default: + return gBattleWeather; + } +} + enum WeatherState IsWeatherActive(u32 flags) { enum WeatherState state = WEATHER_INACTIVE; @@ -1568,10 +1839,12 @@ bool32 IsHazardMove(u32 move) u32 i, moveEffect = GetMoveEffect(move); switch (moveEffect) { + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: - case EFFECT_TOXIC_SPIKES: - case EFFECT_STICKY_WEB: case EFFECT_STEALTH_ROCK: + case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: + case EFFECT_TOXIC_SPIKES: return TRUE; } @@ -1581,8 +1854,11 @@ bool32 IsHazardMove(u32 move) const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); switch (additionalEffect->moveEffect) { + case MOVE_EFFECT_STEALTH_ROCK: case MOVE_EFFECT_STEELSURGE: return TRUE; + default: + break; } } return FALSE; @@ -1611,6 +1887,8 @@ bool32 IsHazardClearingMove(u32 move) { case MOVE_EFFECT_DEFOG: return TRUE; + default: + break; } } @@ -1662,7 +1940,7 @@ bool32 IsAllyProtectingFromMove(u32 battlerAtk, u32 attackerMove, u32 allyMove) } } -bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility) +bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, enum Ability atkAbility) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; @@ -1676,61 +1954,7 @@ bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility) return FALSE; } -bool32 IsSemiInvulnerable(u32 battlerDef, u32 move) -{ - if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) - return TRUE; - else if (gBattleStruct->battlerState[battlerDef].commandingDondozo) - return TRUE; - else if (!MoveDamagesAirborne(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR) - return TRUE; - else if (!MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER) - return TRUE; - else if (!MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND) - return TRUE; - else - return FALSE; -} - -bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move) -{ - u32 weather; - if (IsSemiInvulnerable(battlerDef, move)) - return FALSE; - - //TODO - anticipate protect move? - - // always hits - if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) - return TRUE; - - if (gAiLogicData->abilities[battlerDef] == ABILITY_NO_GUARD || gAiLogicData->abilities[battlerAtk] == ABILITY_NO_GUARD) - return TRUE; - - u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - if (B_TOXIC_NEVER_MISS >= GEN_6 - && nonVolatileStatus == MOVE_EFFECT_TOXIC - && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - return TRUE; - - // discouraged from hitting - weather = AI_GetWeather(); - if ((weather & B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) - return FALSE; - - if ((weather & B_WEATHER_RAIN) && MoveAlwaysHitsInRain(move)) - return TRUE; - if ((weather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) - return TRUE; - if (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && MoveIncreasesPowerToMinimizedTargets(move)) - return TRUE; - if (GetMoveAccuracy(move) == 0) - return TRUE; - - return FALSE; -} - -bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) +bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move) { enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerDef]; u32 accuracy = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; @@ -1744,7 +1968,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, atkAbility, move) && defAbility == ABILITY_STURDY) return FALSE; - if ((((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS) + if (((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) || atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD) && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level) @@ -1762,118 +1986,72 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil return FALSE; } -bool32 ShouldSetSandstorm(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 ShouldRaiseAnyStat(u32 battlerAtk, u32 battlerDef) { - if (IsWeatherActive(B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) + if (AreBattlersStatsMaxed(battlerAtk)) return FALSE; - if (ability == ABILITY_SAND_VEIL - || ability == ABILITY_SAND_RUSH - || ability == ABILITY_SAND_FORCE - || ability == ABILITY_OVERCOAT - || ability == ABILITY_MAGIC_GUARD - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) - || HasMoveWithEffect(battler, EFFECT_SHORE_UP) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + // Don't increase stats if opposing battler has Unaware + if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, gAiLogicData)) + return FALSE; + + // Don't set up if AI is dead to residual damage from weather + if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) + return FALSE; + + // Don't increase stats if opposing battler has Opportunist + if (HasBattlerSideAbility(battlerDef, ABILITY_OPPORTUNIST, gAiLogicData)) + return FALSE; + + // Don't increase stats if opposing battler has Encore + if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) + return FALSE; + + // Don't increase stats if opposing battler has used Haze effect or AI effect + if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) + && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) + return FALSE; + + if (CountPositiveStatStages(battlerAtk) > 0 + && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) + return FALSE; + + // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs + if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) + return FALSE; + + return TRUE; } -bool32 ShouldSetHail(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 ShouldSetWeather(u32 battler, u32 weather) { - if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || ability == ABILITY_MAGIC_GUARD - || ability == ABILITY_OVERCOAT - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) - || HasMoveWithEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + return WeatherChecker(battler, weather, FIELD_EFFECT_POSITIVE); } -bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect) +bool32 ShouldClearWeather(u32 battler, u32 weather) { - if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA - && (atkAbility == ABILITY_SWIFT_SWIM - || atkAbility == ABILITY_FORECAST - || atkAbility == ABILITY_HYDRATION - || atkAbility == ABILITY_RAIN_DISH - || atkAbility == ABILITY_DRY_SKIN - || HasMoveWithFlag(battlerAtk, MoveAlwaysHitsInRain) - || HasMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL) - || HasMoveWithType(battlerAtk, TYPE_WATER))) - { - return TRUE; - } - return FALSE; + return WeatherChecker(battler, weather, FIELD_EFFECT_NEGATIVE); } -bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect) +bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus) { - if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA - && (atkAbility == ABILITY_CHLOROPHYLL - || atkAbility == ABILITY_FLOWER_GIFT - || atkAbility == ABILITY_FORECAST - || atkAbility == ABILITY_LEAF_GUARD - || atkAbility == ABILITY_SOLAR_POWER - || atkAbility == ABILITY_HARVEST - || HasMoveWithEffect(battlerAtk, EFFECT_SOLAR_BEAM) - || HasMoveWithEffect(battlerAtk, EFFECT_MORNING_SUN) - || HasMoveWithEffect(battlerAtk, EFFECT_SYNTHESIS) - || HasMoveWithEffect(battlerAtk, EFFECT_MOONLIGHT) - || HasMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL) - || HasMoveWithEffect(battlerAtk, EFFECT_GROWTH) - || HasMoveWithType(battlerAtk, TYPE_FIRE))) - { - return TRUE; - } - return FALSE; + return FieldStatusChecker(battler, fieldStatus, FIELD_EFFECT_POSITIVE); } -bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 ShouldClearFieldStatus(u32 battler, u32 fieldStatus) { - if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) - || HasMoveWithEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + return FieldStatusChecker(battler, fieldStatus, FIELD_EFFECT_NEGATIVE); } bool32 IsBattlerDamagedByStatus(u32 battler) { - return gBattleMons[battler].status1 & (STATUS1_BURN | STATUS1_FROSTBITE | STATUS1_POISON | STATUS1_TOXIC_POISON) - || gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_NIGHTMARE | STATUS2_CURSED) - || gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED) - || gStatuses4[battler] & (STATUS4_SALT_CURE) + return gBattleMons[battler].status1 & STATUS1_DAMAGING + || gBattleMons[battler].volatiles.wrapped + || gBattleMons[battler].volatiles.nightmare + || gBattleMons[battler].volatiles.cursed + || gBattleMons[battler].volatiles.saltCure + || gBattleMons[battler].volatiles.leechSeed + || gBattleMons[battler].volatiles.perishSong || gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_DAMAGE_NON_TYPES); } @@ -1899,7 +2077,7 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove) } else { - if (IsDoubleBattle()) + if (!IsBattle1v1()) score -= (2 * min(uses, 3)); else score -= (min(uses, 3)); @@ -1919,49 +2097,64 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove) } // stat stages -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat) +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat) { if (gBattleMons[battlerDef].statStages[stat] == MIN_STAT_STAGE) return FALSE; - if (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_CLEAR_AMULET) + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_CLEAR_AMULET) return FALSE; - switch (abilityDef) - { - case ABILITY_SPEED_BOOST: - if (stat == STAT_SPEED) - return FALSE; - case ABILITY_HYPER_CUTTER: - if (stat == STAT_ATK) - return FALSE; - case ABILITY_BIG_PECKS: - if (stat == STAT_DEF) - return FALSE; - case ABILITY_ILLUMINATE: - if (B_ILLUMINATE_EFFECT < GEN_9) - break; - case ABILITY_KEEN_EYE: - case ABILITY_MINDS_EYE: - if (stat == STAT_ACC) - return FALSE; - case ABILITY_FLOWER_VEIL: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)) - return FALSE; - break; - case ABILITY_CONTRARY: - case ABILITY_CLEAR_BODY: - case ABILITY_WHITE_SMOKE: - case ABILITY_FULL_METAL_BODY: + u32 move = gAiThinkingStruct->moveConsidered; + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MIST && abilityAtk != ABILITY_INFILTRATOR) return FALSE; + + if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)) + { + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) && AI_IsAbilityOnSide(battlerDef, ABILITY_FLOWER_VEIL)) + return FALSE; + + switch (aiData->abilities[battlerDef]) + { + case ABILITY_SPEED_BOOST: + if (stat == STAT_SPEED) + return FALSE; + case ABILITY_HYPER_CUTTER: + if (stat == STAT_ATK) + return FALSE; + case ABILITY_BIG_PECKS: + if (stat == STAT_DEF) + return FALSE; + case ABILITY_ILLUMINATE: + if (GetGenConfig(GEN_ILLUMINATE_EFFECT) < GEN_9) + break; + case ABILITY_KEEN_EYE: + case ABILITY_MINDS_EYE: + if (stat == STAT_ACC) + return FALSE; + case ABILITY_CONTRARY: + case ABILITY_CLEAR_BODY: + case ABILITY_WHITE_SMOKE: + case ABILITY_FULL_METAL_BODY: + return FALSE; + case ABILITY_SHIELD_DUST: + if (!IsBattleMoveStatus(move) && GetActiveGimmick(battlerAtk) != GIMMICK_DYNAMAX) + return FALSE; + break; + default: + break; + } } if (stat == STAT_SPEED) { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); // If AI is faster and doesn't have any mons left, lowering speed doesn't give any - return !(AI_IsFaster(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered) + return !(AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY) && CountUsablePartyMons(battlerAtk) == 0 - && !HasMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); + && !HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); } return TRUE; @@ -1979,10 +2172,13 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) if (GetBattlerSecondaryDamage(battlerDef) >= gBattleMons[battlerDef].hp) return NO_INCREASE; - // Don't decrese stat if opposing battler has Encore + // Don't decrease stat if opposing battler has Encore if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) return NO_INCREASE; + if (DoesAbilityRaiseStatsWhenLowered(gAiLogicData->abilities[battlerDef])) + return NO_INCREASE; + // TODO: Avoid decreasing stat if // player can kill ai in 2 hits with decreased attack / sp atk stages // ai can kill target in 2 hits without decreasing defense / sp def stages @@ -1994,39 +2190,44 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_DEF: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) + || HasMoveWithCategory(BATTLE_PARTNER(battlerAtk), DAMAGE_CATEGORY_PHYSICAL)) tempScore += DECENT_EFFECT; break; case STAT_SPEED: - if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered)) + { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (AI_IsSlower(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY) + || AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) tempScore += DECENT_EFFECT; break; + } case STAT_SPATK: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) tempScore += DECENT_EFFECT; break; case STAT_SPDEF: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)) + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) + || HasMoveWithCategory(BATTLE_PARTNER(battlerAtk), DAMAGE_CATEGORY_SPECIAL)) tempScore += DECENT_EFFECT; break; case STAT_ACC: - if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) + tempScore += WEAK_EFFECT; + if (IsBattlerTrapped(battlerAtk, battlerDef)) + tempScore += DECENT_EFFECT; + if (gBattleMons[battlerDef].volatiles.leechSeed) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) - tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_ROOTED) - tempScore += WEAK_EFFECT; - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED) + if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; case STAT_EVASION: if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) + if (gBattleMons[battlerDef].volatiles.leechSeed) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_ROOTED) + if (gBattleMons[battlerDef].volatiles.root) tempScore += WEAK_EFFECT; - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED) + if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; } @@ -2034,7 +2235,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) return (tempScore > BEST_EFFECT) ? BEST_EFFECT : tempScore; // don't inflate score so only max +4 } -bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat) +bool32 BattlerStatCanRise(u32 battler, enum Ability battlerAbility, u32 stat) { if ((gBattleMons[battler].statStages[stat] < MAX_STAT_STAGE && battlerAbility != ABILITY_CONTRARY) || (battlerAbility == ABILITY_CONTRARY && gBattleMons[battler].statStages[stat] > MIN_STAT_STAGE)) @@ -2104,18 +2305,6 @@ bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 moveIndex, en return FALSE; } -bool32 CanIndexMoveGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u32 moveIndex) -{ - s32 dmg; - u16 *moves = gBattleMons[battlerAtk].moves; - - dmg = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum; // Explictly care about guaranteed KOs universally - - if (gBattleMons[battlerDef].hp <= dmg && !CanEndureHit(battlerAtk, battlerDef, moves[moveIndex])) - return TRUE; - return FALSE; -} - u16 *GetMovesArray(u32 battler) { if (IsAiBattlerAware(battler) || IsAiBattlerAware(BATTLE_PARTNER(battler))) @@ -2124,6 +2313,18 @@ u16 *GetMovesArray(u32 battler) return gBattleHistory->usedMoves[battler]; } +u32 GetIndexInMoveArray(u32 battler, u32 move) +{ + u16 *moves = GetMovesArray(battler); + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == move) + return i; + } + return MAX_MON_MOVES; +} + bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive) { u32 i; @@ -2167,42 +2368,84 @@ bool32 HasMoveWithType(u32 battler, u32 type) return FALSE; } -bool32 HasMoveWithEffect(u32 battlerId, enum BattleMoveEffects effect) +bool32 HasMoveWithEffect(u32 battler, enum BattleMoveEffects effect) { s32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && GetMoveEffect(moves[i]) == effect) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMoveEffect(moves[i]) == effect) return TRUE; } return FALSE; } +bool32 HasMoveWithAIEffect(u32 battler, u32 aiEffect) +{ + s32 i; + u16 *moves = GetMovesArray(battler); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE) + { + if (GetAIEffectGroupFromMove(battler, moves[i]) & aiEffect) + return TRUE; + } + } + + return FALSE; +} + bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect) { if (HasMoveWithEffect(battler, effect)) return TRUE; - if (IsDoubleBattle() && HasMoveWithEffect(BATTLE_OPPOSITE(battler), effect)) + if (HasPartnerIgnoreFlags(battler) && HasMoveWithEffect(BATTLE_PARTNER(battler), effect)) + return TRUE; + return FALSE; +} + +bool32 HasBattlerSideMoveWithAIEffect(u32 battler, u32 aiEffect) +{ + if (HasMoveWithAIEffect(battler, aiEffect)) + return TRUE; + if (HasPartnerIgnoreFlags(battler) && HasMoveWithAIEffect(BATTLE_PARTNER(battler), aiEffect)) return TRUE; return FALSE; } // HasBattlerSideMoveWithEffect checks if the AI knows a side has a move effect, -// while HasBattlerSideUsedMoveWithEffect checks if the side has ever used a move effect. -// The former acts the same way as the latter if AI_FLAG_OMNISCIENT isn't used. +// while HasBattlerSideUsedMoveWithEffect checks if the side has actively USED the move effect. +// It matches both on move effect and on AI move effect; eg, EFFECT_HAZE will also bring up Freezy Frost or Clear Smog, anything with AI_EFFECT_RESET_STATS. bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect) { + u32 aiEffect = GetAIEffectGroup(effect); u32 i; for (i = 0; i < MAX_MON_MOVES; i++) { if (GetMoveEffect(gBattleHistory->usedMoves[battler][i]) == effect) return TRUE; - if (IsDoubleBattle() && GetMoveEffect(gBattleHistory->usedMoves[BATTLE_OPPOSITE(battler)][i]) == effect) - return TRUE; + + if (aiEffect != AI_EFFECT_NONE) + { + if (GetAIEffectGroupFromMove(battler, gBattleHistory->usedMoves[battler][i]) & aiEffect) + return TRUE; + } + + if (HasPartnerIgnoreFlags(battler)) + { + if (GetMoveEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) == effect) + return TRUE; + + if (aiEffect != AI_EFFECT_NONE) + { + if (GetAIEffectGroupFromMove(battler, gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) & aiEffect) + return TRUE; + } + } } return FALSE; } @@ -2256,27 +2499,11 @@ bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect) { if (HasMoveWithAdditionalEffect(battler, moveEffect)) return TRUE; - if (IsDoubleBattle() && HasMoveWithAdditionalEffect(BATTLE_OPPOSITE(battler), moveEffect)) + if (HasPartnerIgnoreFlags(battler) && HasMoveWithAdditionalEffect(BATTLE_PARTNER(battler), moveEffect)) return TRUE; return FALSE; } -// HasBattlerSideMoveWithAdditionalEffect checks if the AI knows a side has a move effect, -// while HasBattlerSideUsedMoveWithAdditionalEffect checks if the side has ever used a move effect. -// The former acts the same way as the latter if AI_FLAG_OMNISCIENT isn't used. -bool32 HasBattlerSideUsedMoveWithAdditionalEffect(u32 battler, u32 moveEffect) -{ - u32 i; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (MoveHasAdditionalEffect(gBattleHistory->usedMoves[battler][i], moveEffect)) - return TRUE; - if (IsDoubleBattle() && MoveHasAdditionalEffect(gBattleHistory->usedMoves[BATTLE_OPPOSITE(battler)][i], moveEffect)) - return TRUE; - } - return FALSE; -} - bool32 HasMoveWithCriticalHitChance(u32 battlerId) { s32 i; @@ -2358,7 +2585,29 @@ bool32 HasMoveThatLowersOwnStats(u32 battlerId) return FALSE; } -bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) +bool32 HasMoveThatRaisesOwnStats(u32 battlerId) +{ + s32 i, j; + u32 aiMove; + u16 *moves = GetMovesArray(battlerId); + for (i = 0; i < MAX_MON_MOVES; i++) + { + aiMove = moves[i]; + if (aiMove != MOVE_NONE && aiMove != MOVE_UNAVAILABLE) + { + u32 additionalEffectCount = GetMoveAdditionalEffectCount(aiMove); + for (j = 0; j < additionalEffectCount; j++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(aiMove, j); + if (IsSelfStatRaisingEffect(additionalEffect->moveEffect) && additionalEffect->self) + return TRUE; + } + } + } + return FALSE; +} + +bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus) { s32 i; u16 *moves = GetMovesArray(battlerAtk); @@ -2490,11 +2739,13 @@ bool32 IsStatRaisingEffect(enum BattleMoveEffects effect) { switch (effect) { + case EFFECT_ATTACK_UP_USER_ALLY: case EFFECT_ATTACK_UP: case EFFECT_ATTACK_UP_2: case EFFECT_DEFENSE_UP: case EFFECT_DEFENSE_UP_2: case EFFECT_DEFENSE_UP_3: + case EFFECT_AUTOTOMIZE: case EFFECT_SPEED_UP: case EFFECT_SPEED_UP_2: case EFFECT_SPECIAL_ATTACK_UP: @@ -2560,7 +2811,7 @@ bool32 IsStatLoweringEffect(enum BattleMoveEffects effect) } } -bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect) +bool32 IsSelfStatLoweringEffect(enum MoveEffect effect) { // Self stat lowering moves like Overheart, Superpower etc. switch (effect) @@ -2588,13 +2839,38 @@ bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect) } } +bool32 IsSelfStatRaisingEffect(enum MoveEffect effect) +{ + // Self stat lowering moves like Power Up Punch or Charge Beam + switch (effect) + { + case MOVE_EFFECT_ATK_PLUS_1: + case MOVE_EFFECT_DEF_PLUS_1: + case MOVE_EFFECT_SPD_PLUS_1: + case MOVE_EFFECT_SP_ATK_PLUS_1: + case MOVE_EFFECT_SP_DEF_PLUS_1: + case MOVE_EFFECT_EVS_PLUS_1: + case MOVE_EFFECT_ACC_PLUS_1: + case MOVE_EFFECT_ATK_PLUS_2: + case MOVE_EFFECT_DEF_PLUS_2: + case MOVE_EFFECT_SPD_PLUS_2: + case MOVE_EFFECT_SP_ATK_PLUS_2: + case MOVE_EFFECT_SP_DEF_PLUS_2: + case MOVE_EFFECT_EVS_PLUS_2: + case MOVE_EFFECT_ACC_PLUS_2: + return TRUE; + default: + return FALSE; + } +} + bool32 IsSwitchOutEffect(enum BattleMoveEffects effect) { // Switch out effects like U-Turn, Volt Switch, etc. switch (effect) { case EFFECT_TELEPORT: - if (B_TELEPORT_BEHAVIOR >= GEN_8) + if (GetGenConfig(GEN_CONFIG_TELEPORT_BEHAVIOR) >= GEN_8) return TRUE; case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: @@ -2663,35 +2939,45 @@ static inline bool32 IsMoveSleepClauseTrigger(u32 move) case MOVE_EFFECT_EFFECT_SPORE_SIDE: case MOVE_EFFECT_YAWN_FOE: return TRUE; + default: + break; } } return FALSE; } -bool32 HasDamagingMove(u32 battlerId) +bool32 HasDamagingMove(u32 battler) { u32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && !IsBattleMoveStatus(moves[i])) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMovePower(moves[i]) > 0) return TRUE; } return FALSE; } -bool32 HasDamagingMoveOfType(u32 battlerId, u32 type) +bool32 HasDamagingMoveOfType(u32 battler, u32 type) { s32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && GetMoveType(moves[i]) == type && !IsBattleMoveStatus(moves[i])) - return TRUE; + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMovePower(moves[i]) > 0) + { + u32 moveType = GetDynamicMoveType(GetBattlerMon(battler), moves[i], battler, MON_IN_BATTLE); + + if (moveType != TYPE_NONE && type == moveType) + return TRUE; + if (GetMoveType(moves[i]) == type) + return TRUE; + if (GetMoveEffect(moves[i]) == EFFECT_NATURE_POWER && GetMoveType(GetNaturePowerMove(moves[i])) == type) + return TRUE; + } } return FALSE; @@ -2726,13 +3012,13 @@ bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move) } } -static u32 GetLeechSeedDamage(u32 battlerId) +static u32 GetLeechSeedDamage(u32 battler) { u32 damage = 0; - if ((gStatuses3[battlerId] & STATUS3_LEECHSEED) - && gBattleMons[gStatuses3[battlerId] & STATUS3_LEECHSEED_BATTLER].hp != 0) + u32 leechSeeder = gBattleMons[battler].volatiles.leechSeed; + if (leechSeeder && gBattleMons[leechSeeder - 1].hp != 0) { - damage = GetNonDynamaxMaxHP(battlerId) / 8; + damage = GetNonDynamaxMaxHP(battler) / 8; if (damage == 0) damage = 1; } @@ -2742,7 +3028,7 @@ static u32 GetLeechSeedDamage(u32 battlerId) static u32 GetNightmareDamage(u32 battlerId) { u32 damage = 0; - if ((gBattleMons[battlerId].status2 & STATUS2_NIGHTMARE) && gBattleMons[battlerId].status1 & STATUS1_SLEEP) + if (gBattleMons[battlerId].volatiles.nightmare && gBattleMons[battlerId].status1 & STATUS1_SLEEP) { damage = GetNonDynamaxMaxHP(battlerId) / 4; if (damage == 0) @@ -2754,7 +3040,7 @@ static u32 GetNightmareDamage(u32 battlerId) static u32 GetCurseDamage(u32 battlerId) { u32 damage = 0; - if (gBattleMons[battlerId].status2 & STATUS2_CURSED) + if (gBattleMons[battlerId].volatiles.cursed) { damage = GetNonDynamaxMaxHP(battlerId) / 4; if (damage == 0) @@ -2768,7 +3054,7 @@ static u32 GetTrapDamage(u32 battlerId) // ai has no knowledge about turns remaining u32 damage = 0; enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[gBattleStruct->wrappedBy[battlerId]]; - if (gBattleMons[battlerId].status2 & STATUS2_WRAPPED) + if (gBattleMons[battlerId].volatiles.wrapped) { if (holdEffect == HOLD_EFFECT_BINDING_BAND) damage = GetNonDynamaxMaxHP(battlerId) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); @@ -2807,7 +3093,7 @@ static u32 GetPoisonDamage(u32 battlerId) return damage; } -static bool32 BattlerAffectedBySandstorm(u32 battlerId, u32 ability) +static bool32 BattlerAffectedBySandstorm(u32 battlerId, enum Ability ability) { if (!IS_BATTLER_ANY_TYPE(battlerId, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) && ability != ABILITY_SAND_VEIL @@ -2818,7 +3104,7 @@ static bool32 BattlerAffectedBySandstorm(u32 battlerId, u32 ability) return FALSE; } -static bool32 BattlerAffectedByHail(u32 battlerId, u32 ability) +static bool32 BattlerAffectedByHail(u32 battlerId, enum Ability ability) { if (!IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) && ability != ABILITY_SNOW_CLOAK @@ -2830,7 +3116,7 @@ static bool32 BattlerAffectedByHail(u32 battlerId, u32 ability) static u32 GetWeatherDamage(u32 battlerId) { - u32 ability = gAiLogicData->abilities[battlerId]; + enum Ability ability = gAiLogicData->abilities[battlerId]; enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerId]; u32 damage = 0; u32 weather = AI_GetWeather(); @@ -2840,7 +3126,8 @@ static u32 GetWeatherDamage(u32 battlerId) if (weather & B_WEATHER_SANDSTORM) { if (BattlerAffectedBySandstorm(battlerId, ability) - && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = GetNonDynamaxMaxHP(battlerId) / 16; @@ -2851,7 +3138,8 @@ static u32 GetWeatherDamage(u32 battlerId) if ((weather & B_WEATHER_HAIL) && ability != ABILITY_ICE_BODY) { if (BattlerAffectedByHail(battlerId, ability) - && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = GetNonDynamaxMaxHP(battlerId) / 16; @@ -2879,7 +3167,7 @@ u32 GetBattlerSecondaryDamage(u32 battlerId) return secondaryDamage; } -bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) +bool32 BattlerWillFaintFromWeather(u32 battler, enum Ability ability) { if ((BattlerAffectedBySandstorm(battler, ability) || BattlerAffectedByHail(battler, ability)) && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) @@ -2888,7 +3176,7 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability) return FALSE; } -bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability) +bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, enum Ability ability) { if (GetBattlerSecondaryDamage(battler) != 0 && gBattleMons[battler].hp <= max(1, gBattleMons[battler].maxHP / 16)) @@ -2926,16 +3214,16 @@ static bool32 AnyUsefulStatIsRaised(u32 battler) static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) { struct Pokemon *mon = &GetBattlerParty(currBattler)[switchBattler]; - u32 ability = GetMonAbility(mon); // we know our own party data + enum Ability ability = GetMonAbility(mon); // we know our own party data enum ItemHoldEffect holdEffect; u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); s32 hazardDamage = 0; u32 type1 = GetSpeciesType(species, 0); u32 type2 = GetSpeciesType(species, 1); u32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); + u32 side = GetBattlerSide(currBattler); - if (flags == 0) + if (!AreAnyHazardsOnSide(side)) return FALSE; if (ability == ABILITY_MAGIC_GUARD) @@ -2947,12 +3235,12 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) if (holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) return FALSE; - if (flags & SIDE_STATUS_STEALTH_ROCK) + if (IsHazardOnSide(side, HAZARDS_STEALTH_ROCK)) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, type1, type2, maxHp); - if ((flags & SIDE_STATUS_STEELSURGE)) + if (IsHazardOnSide(side, HAZARDS_STEELSURGE)) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, type1, type2, maxHp); - if (flags & SIDE_STATUS_SPIKES && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING + if (IsHazardOnSide(side, HAZARDS_SPIKES) && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING && ability != ABILITY_LEVITATE && holdEffect != HOLD_EFFECT_AIR_BALLOON) || holdEffect == HOLD_EFFECT_IRON_BALL || gFieldStatuses & STATUS_FIELD_GRAVITY)) { @@ -2967,10 +3255,11 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) return FALSE; } -enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex) +enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 moveIndex) { bool32 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class u32 battlerToSwitch; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); battlerToSwitch = gBattleStruct->AI_monToSwitchIntoId[battlerAtk]; @@ -2983,7 +3272,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (PartyBattlerShouldAvoidHazards(battlerAtk, battlerToSwitch)) return DONT_PIVOT; - if (!IsDoubleBattle()) + if (IsBattle1v1()) { if (CountUsablePartyMons(battlerAtk) == 0) return CAN_TRY_PIVOT; // can't switch, but attack might still be useful @@ -2991,7 +3280,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (IsBattlerPredictedToSwitch(battlerDef)) return SHOULD_PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first { if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise { @@ -3020,7 +3309,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov return SHOULD_PIVOT; /* TODO - check if switchable mon unafffected by/will remove hazards - if (gSideStatuses[battlerAtk] & SIDE_STATUS_SPIKES && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) + if (IsHazardOnSide(GetBattlerSide(battlerAtk, HAZARDS_SPIKES) && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) return SHOULD_PIVOT;*/ /*if (BattlerWillFaintFromSecondaryDamage(battlerAtk, gAiLogicData->abilities[battlerAtk]) && switchScore >= SWITCHING_INCREASE_WALLS_FOE) @@ -3102,7 +3391,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (!hasStatBoost) { // TODO - check if switching prevents/removes hazards - //if (gSideStatuses[battlerAtk] & SIDE_STATUS_SPIKES && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) + //if (IsHazardOnSide(GetBattlerSide(battlerAtk, HAZARDS_SPIKES) && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) //return SHOULD_PIVOT; // TODO - not always a good idea @@ -3166,7 +3455,7 @@ bool32 CanKnockOffItem(u32 battler, u32 item) } // status checks -bool32 IsBattlerIncapacitated(u32 battler, u32 ability) +bool32 IsBattlerIncapacitated(u32 battler, enum Ability ability) { if ((gBattleMons[battler].status1 & STATUS1_FREEZE) && !HasThawingMove(battler)) return TRUE; // if battler has thawing move we assume they will definitely use it, and thus being frozen should be neglected @@ -3174,13 +3463,13 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !HasMoveWithEffect(battler, EFFECT_SLEEP_TALK)) return TRUE; - if (gBattleMons[battler].status2 & STATUS2_RECHARGE || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) + if (gBattleMons[battler].volatiles.recharge || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) return TRUE; return FALSE; } -bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBeSlept(battlerAtk, battlerDef, defAbility, BLOCKED_BY_SLEEP_CLAUSE) || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) @@ -3189,7 +3478,7 @@ bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move return TRUE; } -static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, u32 ability) +static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, enum Ability ability) { if (ability == ABILITY_MARVEL_SCALE || ability == ABILITY_QUICK_FEET @@ -3203,7 +3492,7 @@ static inline bool32 DoesBattlerBenefitFromAllVolatileStatus(u32 battler, u32 ab bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef) { - u32 abilityDef = gAiLogicData->abilities[battlerDef]; + enum Ability abilityDef = gAiLogicData->abilities[battlerDef]; // Battler can be poisoned and has move/ability that synergizes with being poisoned if (CanBePoisoned(battlerAtk, battlerDef, gAiLogicData->abilities[battlerAtk], abilityDef) && ( DoesBattlerBenefitFromAllVolatileStatus(battlerDef, abilityDef) @@ -3221,7 +3510,7 @@ bool32 ShouldPoison(u32 battlerAtk, u32 battlerDef) return TRUE; } -bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { // Battler can be burned and has move/ability that synergizes with being burned if (CanBeBurned(battlerAtk, battlerDef, abilityDef) && ( @@ -3241,7 +3530,7 @@ bool32 ShouldBurn(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return TRUE; } -bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { if (!B_USE_FROSTBITE) { @@ -3273,7 +3562,7 @@ bool32 ShouldFreezeOrFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) } } -bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { // Battler can be paralyzed and has move/ability that synergizes with being paralyzed if (CanBeParalyzed(battlerAtk, battlerDef, abilityDef) && ( @@ -3290,7 +3579,7 @@ bool32 ShouldParalyze(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return TRUE; } -bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBePoisoned(battlerAtk, battlerDef, gAiLogicData->abilities[battlerAtk], defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3301,7 +3590,7 @@ bool32 AI_CanPoison(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u3 return TRUE; } -bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove) +bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 move, u32 partnerMove) { if (!CanBeParalyzed(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3311,18 +3600,18 @@ bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, return TRUE; } -bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability) +bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability abilityDef) { - if ((gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) - || (ability == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(battlerAtk, gAiLogicData->abilities[battlerAtk], move)) - || IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) + if (gBattleMons[battlerDef].volatiles.confusionTurns > 0 + || (abilityDef == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(battlerAtk, gAiLogicData->abilities[battlerAtk], move)) + || IsBattlerTerrainAffected(battlerDef, abilityDef, gAiLogicData->holdEffects[battlerDef], STATUS_FIELD_MISTY_TERRAIN) || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD || DoesSubstituteBlockMove(battlerAtk, battlerDef, move)) return FALSE; return TRUE; } -bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY && AI_CanBeConfused(battlerAtk, battlerDef, move, defAbility) @@ -3336,7 +3625,7 @@ bool32 AI_CanConfuse(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battler return TRUE; } -bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!CanBeBurned(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3348,7 +3637,7 @@ bool32 AI_CanBurn(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtk return TRUE; } -bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) +bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability defAbility, u32 battlerAtkPartner, u32 move, u32 partnerMove) { if (!CanBeFrozen(battlerAtk, battlerDef, defAbility) || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) @@ -3360,9 +3649,9 @@ bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 b return TRUE; } -bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) +bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, enum Ability defAbility) { - if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) + if (gBattleMons[battlerDef].volatiles.infatuation || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) || defAbility == ABILITY_OBLIVIOUS || !AreBattlersOfOppositeGender(battlerAtk, battlerDef) @@ -3371,20 +3660,21 @@ bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) return TRUE; } -u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) +u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, enum Ability atkAbility, enum Ability defAbility, u32 move) { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (((!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) || gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - || AI_IsSlower(battlerAtk, battlerDef, move))) // Opponent goes first + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))) // Opponent goes first { return 0; } else if ((atkAbility == ABILITY_SERENE_GRACE || gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION - || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) - || ((AI_IsFaster(battlerAtk, battlerDef, move)) && CanTargetFaintAi(battlerDef, battlerAtk))) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) + || ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && CanTargetFaintAi(battlerDef, battlerAtk))) { return 2; // good idea to flinch } @@ -3412,18 +3702,58 @@ bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; } -bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move) +bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move) { - if ((!gDisableStructs[battlerAtk].isFirstTurn && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100)) - || gAiLogicData->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS - || gAiLogicData->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND - || gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK - || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - || (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) - && (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS))) + if (!MoveHasAdditionalEffect(move, MOVE_EFFECT_FLINCH)) return FALSE; - return TRUE; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) + return FALSE; + + u32 i; + u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + // check move additional effects that are likely to happen + for (i = 0; i < additionalEffectCount; i++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + // Only consider effects with a guaranteed chance to happen + if (!MoveEffectIsGuaranteed(battlerAtk, gAiLogicData->abilities[battlerAtk], additionalEffect)) + continue; + + if (additionalEffect->moveEffect == MOVE_EFFECT_FLINCH) + { + if (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) + || (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) + && (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS))) + return FALSE; + else + return TRUE; + } + } + return FALSE; +} + +bool32 HasChoiceEffect(u32 battler) +{ + enum Ability ability = gAiLogicData->abilities[battler]; + if (ability == ABILITY_GORILLA_TACTICS) + return TRUE; + + if (ability == ABILITY_KLUTZ) + return FALSE; + + enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; + switch (holdEffect) + { + case HOLD_EFFECT_CHOICE_BAND: + case HOLD_EFFECT_CHOICE_SCARF: + case HOLD_EFFECT_CHOICE_SPECS: + return TRUE; + default: + return FALSE; + } } static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x) @@ -3453,7 +3783,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) party = GetBattlerParty(battlerId); - if (IsDoubleBattle()) + if (HasPartner(battlerId)) { battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)]; @@ -3493,27 +3823,6 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) return FALSE; } -u32 GetBattlerSideSpeedAverage(u32 battler) -{ - u32 speed1 = 0; - u32 speed2 = 0; - u32 numBattlersAlive = 0; - - if (IsBattlerAlive(battler)) - { - speed1 = gAiLogicData->speedStats[battler]; - numBattlersAlive++; - } - - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) - { - speed2 = gAiLogicData->speedStats[BATTLE_PARTNER(battler)]; - numBattlersAlive++; - } - - return (speed1 + speed2) / numBattlersAlive; -} - bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex) { if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker @@ -3530,12 +3839,13 @@ bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 mo bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) { - if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { // using item or user goes first s32 healDmg = (GetMoveAbsorbPercentage(move) * damage) / 100; - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerAtk].volatiles.healBlock) healDmg = 0; if (CanTargetFaintAi(battlerDef, battlerAtk) @@ -3554,21 +3864,31 @@ bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) return FALSE; } -bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent, enum DamageCalcContext calcContext) +bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent) { - if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move)) + u32 maxHP = gBattleMons[battlerAtk].maxHP; + u32 healAmount = (healPercent * maxHP) / 100; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (healAmount > maxHP) + healAmount = maxHP; + if (gBattleMons[battlerAtk].volatiles.healBlock) + healAmount = 0; + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { - // using item or user going first - s32 damage = AI_GetDamage(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, calcContext, gAiLogicData); - s32 healAmount = (healPercent * damage) / 100; - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) - healAmount = 0; - if (CanTargetFaintAi(battlerDef, battlerAtk) && !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healAmount, 0)) return TRUE; // target can faint attacker unless they heal - else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < 60 && (Random() % 3)) - return TRUE; // target can't faint attacker at all, attacker health is about half, 2/3rds rate of encouraging healing + else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < ENABLE_RECOVERY_THRESHOLD && RandomPercentage(RNG_AI_SHOULD_RECOVER, SHOULD_RECOVER_CHANCE)) + return TRUE; // target can't faint attacker at all, generally safe + } + else + { + if (!CanTargetFaintAi(battlerDef, battlerAtk) + && GetBestDmgFromBattler(battlerDef, battlerAtk, AI_DEFENDING) < healAmount + && NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk) < NoOfHitsForTargetToFaintBattlerWithMod(battlerDef, battlerAtk, healAmount)) + return TRUE; // target can't faint attacker and is dealing less damage than we're healing + else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < ENABLE_RECOVERY_THRESHOLD && RandomPercentage(RNG_AI_SHOULD_RECOVER, SHOULD_RECOVER_CHANCE)) + return TRUE; // target can't faint attacker at all, generally safe } return FALSE; } @@ -3578,28 +3898,27 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo u32 atkSide = GetBattlerSide(battlerAtk); // Don't waste a turn if screens will be broken - if (HasMoveWithEffect(battlerDef, EFFECT_BRICK_BREAK) - || HasMoveWithEffect(battlerDef, EFFECT_RAGING_BULL)) + if (HasMoveWithAIEffect(battlerDef, AI_EFFECT_BREAK_SCREENS)) return FALSE; switch (moveEffect) { case EFFECT_AURORA_VEIL: // Use only in Hail and only if AI doesn't already have Reflect, Light Screen or Aurora Veil itself active. - if ((AI_GetWeather() & (B_WEATHER_HAIL | B_WEATHER_SNOW)) + if ((AI_GetWeather() & (B_WEATHER_ICY_ANY)) && !(gSideStatuses[atkSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; case EFFECT_REFLECT: // Use only if the player has a physical move and AI doesn't already have Reflect itself active. if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) - && !(gSideStatuses[atkSide] & SIDE_STATUS_REFLECT)) + && !(gSideStatuses[atkSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; case EFFECT_LIGHT_SCREEN: // Use only if the player has a special move and AI doesn't already have Light Screen itself active. if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) - && !(gSideStatuses[atkSide] & SIDE_STATUS_LIGHTSCREEN)) + && !(gSideStatuses[atkSide] & (SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; default: @@ -3610,14 +3929,51 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo } // Partner Logic -bool32 IsValidDoubleBattle(u32 battlerAtk) +bool32 IsBattle1v1() { if (IsDoubleBattle() - && ((IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk)) && IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerAtk)))) || IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))) + && ((IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) + || (IsBattlerAlive(B_POSITION_OPPONENT_LEFT) && IsBattlerAlive(B_POSITION_OPPONENT_RIGHT)))) + return FALSE; + return TRUE; +} + +bool32 HasTwoOpponents(u32 battler) +{ + if (IsDoubleBattle() + && IsBattlerAlive(LEFT_FOE(battler)) && IsBattlerAlive(RIGHT_FOE(battler))) return TRUE; return FALSE; } +bool32 HasPartner(u32 battler) +{ + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ATTACKS_PARTNER) + return FALSE; + else + return TRUE; + } + return FALSE; +} + +bool32 HasPartnerIgnoreFlags(u32 battler) +{ + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + return TRUE; + } + return FALSE; +} + +bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef) +{ + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_ATTACKS_PARTNER) + return FALSE; + return ((battlerAtk) == (battlerDef ^ BIT_FLANK)); +} + u32 GetAllyChosenMove(u32 battlerId) { u32 partnerBattler = BATTLE_PARTNER(battlerId); @@ -3627,40 +3983,185 @@ u32 GetAllyChosenMove(u32 battlerId) else if (partnerBattler > battlerId) // Battler with the lower id chooses the move first. return gLastMoves[partnerBattler]; else - return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]]; + return GetChosenMoveFromPosition(partnerBattler); } -//PARTNER_MOVE_EFFECT_IS_SAME -bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) +bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!IsBattlerAlive(battlerAtkPartner) || partnerMove == MOVE_NONE) return FALSE; - if (GetMoveEffect(move) == GetMoveEffect(partnerMove) - && partnerMove != MOVE_NONE - && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) + u32 battlerDef = gBattleStruct->moveTarget[battlerAtk]; + + // We don't care the effect is basically the same; we would use this move anyway. + if (GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + return FALSE; + + u32 atkEffect = GetAIEffectGroupFromMove(battlerAtk, move); + u32 partnerEffect = GetAIEffectGroupFromMove(battlerAtkPartner, partnerMove); + + // shared bits indicate they're meaningfully the same in some way + if (atkEffect & partnerEffect) { + if (gMovesInfo[move].target == MOVE_TARGET_SELECTED && gMovesInfo[partnerMove].target == MOVE_TARGET_SELECTED) + { + if (battlerDef == gBattleStruct->moveTarget[battlerAtkPartner]) + return TRUE; + else + return FALSE; + } return TRUE; } return FALSE; } -//PARTNER_MOVE_EFFECT_IS_SAME_NO_TARGET -bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove) +static u32 GetAIEffectGroup(enum BattleMoveEffects effect) { - if (!IsDoubleBattle()) + u32 aiEffect = AI_EFFECT_NONE; + + switch (effect) + { + case EFFECT_SUNNY_DAY: + case EFFECT_RAIN_DANCE: + case EFFECT_SANDSTORM: + case EFFECT_HAIL: + case EFFECT_SNOWSCAPE: + case EFFECT_CHILLY_RECEPTION: + aiEffect |= AI_EFFECT_WEATHER; + break; + case EFFECT_ELECTRIC_TERRAIN: + case EFFECT_GRASSY_TERRAIN: + case EFFECT_MISTY_TERRAIN: + case EFFECT_PSYCHIC_TERRAIN: + case EFFECT_STEEL_ROLLER: + case EFFECT_ICE_SPINNER: + aiEffect |= AI_EFFECT_TERRAIN; + break; + case EFFECT_COURT_CHANGE: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_AURORA_VEIL | AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_DEFOG: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_RAPID_SPIN: + case EFFECT_TIDY_UP: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS; + break; + case EFFECT_BRICK_BREAK: + case EFFECT_RAGING_BULL: + aiEffect |= AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_HAZE: + aiEffect |= AI_EFFECT_RESET_STATS; + break; + case EFFECT_HIT_SWITCH_TARGET: + case EFFECT_ROAR: + aiEffect |= AI_EFFECT_FORCE_SWITCH; + break; + case EFFECT_TORMENT: + aiEffect |= AI_EFFECT_TORMENT; + break; + case EFFECT_AURORA_VEIL: + aiEffect |= AI_EFFECT_AURORA_VEIL; + break; + case EFFECT_LIGHT_SCREEN: + aiEffect |= AI_EFFECT_LIGHT_SCREEN; + break; + case EFFECT_REFLECT: + aiEffect |= AI_EFFECT_REFLECT; + break; + case EFFECT_GRAVITY: + aiEffect |= AI_EFFECT_GRAVITY; + break; + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + aiEffect |= AI_EFFECT_CHANGE_ABILITY; + break; + default: + break; + } + return aiEffect; +} + +static u32 GetAIEffectGroupFromMove(u32 battler, u32 move) +{ + u32 aiEffect = GetAIEffectGroup(GetMoveEffect(move)); + + u32 i; + u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + for (i = 0; i < additionalEffectCount; i++) + { + switch (GetMoveAdditionalEffectById(move, i)->moveEffect) + { + case MOVE_EFFECT_SUN: + case MOVE_EFFECT_RAIN: + case MOVE_EFFECT_SANDSTORM: + case MOVE_EFFECT_HAIL: + aiEffect |= AI_EFFECT_WEATHER; + break; + case MOVE_EFFECT_ELECTRIC_TERRAIN: + case MOVE_EFFECT_GRASSY_TERRAIN: + case MOVE_EFFECT_MISTY_TERRAIN: + case MOVE_EFFECT_PSYCHIC_TERRAIN: + aiEffect |= AI_EFFECT_TERRAIN; + break; + case MOVE_EFFECT_DEFOG: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_BREAK_SCREENS; + break; + case MOVE_EFFECT_CLEAR_SMOG: + case MOVE_EFFECT_HAZE: + aiEffect |= AI_EFFECT_RESET_STATS; + break; + case MOVE_EFFECT_TORMENT_SIDE: + aiEffect |= AI_EFFECT_TORMENT; + break; + case MOVE_EFFECT_LIGHT_SCREEN: + aiEffect |= AI_EFFECT_LIGHT_SCREEN; + break; + case MOVE_EFFECT_REFLECT: + aiEffect |= AI_EFFECT_REFLECT; + break; + case MOVE_EFFECT_AURORA_VEIL: + aiEffect |= AI_EFFECT_AURORA_VEIL; + break; + case MOVE_EFFECT_GRAVITY: + aiEffect |= AI_EFFECT_GRAVITY; + break; + default: + break; + } + } + + return aiEffect; +} + +// It matches both on move effect and on AI move effect; eg, EFFECT_HAZE will also bring up Freezy Frost or Clear Smog, anything with AI_EFFECT_RESET_STATS. +bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) +{ + if (!HasPartner(battlerAtkPartner)) return FALSE; if (GetMoveEffect(move) == GetMoveEffect(partnerMove) && partnerMove != MOVE_NONE) + { + if (gMovesInfo[move].target == MOVE_TARGET_SELECTED && gMovesInfo[partnerMove].target == MOVE_TARGET_SELECTED) + { + return gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef; + } return TRUE; + } return FALSE; } //PARTNER_MOVE_EFFECT_IS_STATUS_SAME_TARGET bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove); @@ -3677,41 +4178,10 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef return FALSE; } -bool32 IsMoveEffectWeather(u32 move) -{ - enum BattleMoveEffects effect = GetMoveEffect(move); - if (move != MOVE_NONE - && (effect == EFFECT_SUNNY_DAY - || effect == EFFECT_RAIN_DANCE - || effect == EFFECT_SANDSTORM - || effect == EFFECT_HAIL - || effect == EFFECT_SNOWSCAPE - || effect == EFFECT_CHILLY_RECEPTION)) - return TRUE; - return FALSE; -} - -//PARTNER_MOVE_EFFECT_IS_TERRAIN -bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove) -{ - if (!IsDoubleBattle()) - return FALSE; - - enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove); - if (partnerMove != MOVE_NONE - && (partnerEffect == EFFECT_GRASSY_TERRAIN - || partnerEffect == EFFECT_MISTY_TERRAIN - || partnerEffect == EFFECT_ELECTRIC_TERRAIN - || partnerEffect == EFFECT_PSYCHIC_TERRAIN)) - return TRUE; - - return FALSE; -} - //PARTNER_MOVE_EFFECT_IS bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMoveEffects effectCheck) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && GetMoveEffect(partnerMove) == effectCheck) @@ -3723,7 +4193,7 @@ bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMo //PARTNER_MOVE_IS_TAILWIND_TRICKROOM bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && partnerMove == moveCheck) @@ -3734,7 +4204,7 @@ bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck) //PARTNER_MOVE_IS_SAME bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && move == partnerMove && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) @@ -3745,7 +4215,7 @@ bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 mo //PARTNER_MOVE_IS_SAME_NO_TARGET bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && move == partnerMove) return TRUE; @@ -3754,7 +4224,7 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov bool32 PartnerMoveActivatesSleepClause(u32 partnerMove) { - if (!IsDoubleBattle() || !IsSleepClauseEnabled()) + if (IsBattle1v1() || !IsSleepClauseEnabled()) return FALSE; return IsMoveSleepClauseTrigger(partnerMove); } @@ -3789,7 +4259,7 @@ bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) } } - if (!IsDoubleBattle()) + if (IsBattle1v1()) { switch (GetMoveEffect(move)) { @@ -3810,7 +4280,7 @@ bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) switch (GetMoveEffect(move)) { case EFFECT_WISH: - return ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING); // Switch recovery isn't good idea in doubles + return ShouldRecover(battlerAtk, battlerDef, move, 50); // Switch recovery isn't good idea in doubles case EFFECT_HEAL_BELL: if (hasStatus) return TRUE; @@ -3838,11 +4308,32 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons) Free(savedBattleMons); } +// Set potential field effect from ability for switch in +static void SetBattlerFieldStatusForSwitchin(u32 battler) +{ + switch (gAiLogicData->abilities[battler]) + { + case ABILITY_VESSEL_OF_RUIN: + gBattleMons[battler].volatiles.vesselOfRuin = TRUE; + break; + case ABILITY_SWORD_OF_RUIN: + gBattleMons[battler].volatiles.swordOfRuin = TRUE; + break; + case ABILITY_TABLETS_OF_RUIN: + gBattleMons[battler].volatiles.tabletsOfRuin = TRUE; + break; + case ABILITY_BEADS_OF_RUIN: + gBattleMons[battler].volatiles.beadsOfRuin = TRUE; + break; + default: + break; + } +} + // party logic -s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext) +s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, enum DamageCalcContext calcContext) { struct SimulatedDamage dmg; - uq4_12_t effectiveness; struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); if (calcContext == AI_ATTACKING) @@ -3850,6 +4341,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gBattleMons[battlerAtk] = switchinCandidate; gAiThinkingStruct->saved[battlerDef].saved = TRUE; SetBattlerAiData(battlerAtk, gAiLogicData); // set known opposing battler data + SetBattlerFieldStatusForSwitchin(battlerAtk); gAiThinkingStruct->saved[battlerDef].saved = FALSE; } else if (calcContext == AI_DEFENDING) @@ -3857,10 +4349,11 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gBattleMons[battlerDef] = switchinCandidate; gAiThinkingStruct->saved[battlerAtk].saved = TRUE; SetBattlerAiData(battlerDef, gAiLogicData); // set known opposing battler data + SetBattlerFieldStatusForSwitchin(battlerDef); gAiThinkingStruct->saved[battlerAtk].saved = FALSE; } - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetWeather()); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate)); // restores original gBattleMon struct FreeRestoreBattleMons(savedBattleMons); @@ -3889,17 +4382,17 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl return dmg.median; } -u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 moveConsidered) +u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority) { struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); gBattleMons[battlerAtk] = switchinCandidate; SetBattlerAiData(battlerAtk, gAiLogicData); - u32 aiMonFaster = AI_IsFaster(battlerAtk, battlerDef, moveConsidered); + u32 aiWhoStrikesFirst = AI_WhoStrikesFirst(battlerAtk, battlerDef, aiMoveConsidered, playerMoveConsidered, considerPriority); FreeRestoreBattleMons(savedBattleMons); SetBattlerAiData(battlerAtk, gAiLogicData); - return aiMonFaster; + return aiWhoStrikesFirst; } s32 CountUsablePartyMons(u32 battlerId) @@ -3981,7 +4474,7 @@ bool32 PartyHasMoveCategory(u32 battlerId, enum DamageCategory category) bool32 SideHasMoveCategory(u32 battlerId, enum DamageCategory category) { - if (IsDoubleBattle()) + if (HasPartnerIgnoreFlags(battlerId)) { if (HasMoveWithCategory(battlerId, category) || HasMoveWithCategory(BATTLE_PARTNER(battlerId), category)) return TRUE; @@ -3994,7 +4487,7 @@ bool32 SideHasMoveCategory(u32 battlerId, enum DamageCategory category) return FALSE; } -bool32 IsAbilityOfRating(u32 ability, s8 rating) +bool32 IsAbilityOfRating(enum Ability ability, s8 rating) { if (gAbilitiesInfo[ability].aiRating >= rating) return TRUE; @@ -4078,19 +4571,112 @@ bool32 IsRecycleEncouragedItem(u32 item) return FALSE; } -static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statId, bool32 considerContrary) +static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiIsFaster) +{ + s32 i; + u16 *moves = GetMovesArray(battlerId); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == MOVE_NONE || moves[i] == MOVE_UNAVAILABLE) + continue; + if (noOfHitsToFaint <= 2) + { + if (GetMovePriority(moves[i]) > 0) + return TRUE; + + switch (gMovesInfo[moves[i]].additionalEffects[i].moveEffect) + { + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + { + if(aiIsFaster) + return TRUE; + } + default: + break; + } + } + } + + return FALSE; +} + +static u32 GetStatBeingChanged(enum StatChange statChange) +{ + switch(statChange) + { + case STAT_CHANGE_ATK: + case STAT_CHANGE_ATK_2: + case STAT_CHANGE_ATK_3: + return STAT_ATK; + case STAT_CHANGE_DEF: + case STAT_CHANGE_DEF_2: + case STAT_CHANGE_DEF_3: + return STAT_DEF; + case STAT_CHANGE_SPEED: + case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPEED_3: + return STAT_SPEED; + case STAT_CHANGE_SPATK: + case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPATK_3: + return STAT_SPATK; + case STAT_CHANGE_SPDEF: + case STAT_CHANGE_SPDEF_2: + case STAT_CHANGE_SPDEF_3: + return STAT_SPDEF; + case STAT_CHANGE_ACC: + return STAT_ACC; + case STAT_CHANGE_EVASION: + return STAT_EVASION; + } + return 0; // STAT_HP, should never be getting changed +} + +static u32 GetStagesOfStatChange(enum StatChange statChange) +{ + switch(statChange) + { + case STAT_CHANGE_ATK: + case STAT_CHANGE_DEF: + case STAT_CHANGE_SPEED: + case STAT_CHANGE_SPATK: + case STAT_CHANGE_SPDEF: + case STAT_CHANGE_ACC: + case STAT_CHANGE_EVASION: + return 1; + case STAT_CHANGE_ATK_2: + case STAT_CHANGE_DEF_2: + case STAT_CHANGE_SPEED_2: + case STAT_CHANGE_SPATK_2: + case STAT_CHANGE_SPDEF_2: + return 2; + case STAT_CHANGE_ATK_3: + case STAT_CHANGE_DEF_3: + case STAT_CHANGE_SPEED_3: + case STAT_CHANGE_SPATK_3: + case STAT_CHANGE_SPDEF_3: + return 3; + } + return 0; // STAT_HP, should never be getting changed +} + +static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statChange, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; - u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk); - u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE); + u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; + u32 statId = GetStatBeingChanged(statChange); + u32 stages = GetStagesOfStatChange(statChange); if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; - // Don't increase stats if opposing battler has Unaware - if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, gAiLogicData)) + if (!ShouldRaiseAnyStat(battlerAtk, battlerDef)) return NO_INCREASE; // Don't increase stat if AI is at +4 @@ -4101,30 +4687,13 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (gAiLogicData->hpPercents[battlerAtk] < 70 && noOfHitsToFaint == UNKNOWN_NO_OF_HITS) return NO_INCREASE; - // Don't set up if AI is dead to residual damage from weather - if (GetBattlerSecondaryDamage(battlerAtk) >= gBattleMons[battlerAtk].hp) + // Don't increase stats if player has a move that can change the KO threshold + if (HasMoveThatChangesKOThreshold(battlerDef, noOfHitsToFaint, aiIsFaster)) return NO_INCREASE; - // Don't increase stats if opposing battler has Opportunist - if (gAiLogicData->abilities[battlerDef] == ABILITY_OPPORTUNIST) - return NO_INCREASE; - - // Don't increase stats if opposing battler has Encore - if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) - return NO_INCREASE; - - // Don't increase stats if opposing battler has used Haze effect - if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) && - (HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE) - || HasBattlerSideUsedMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_CLEAR_SMOG) - || HasBattlerSideUsedMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_HAZE))) - return NO_INCREASE; - - // Don't increase if AI is at +1 and opponent has Haze effect - if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 5 && (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_HAZE) - || HasBattlerSideMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_CLEAR_SMOG) - || HasBattlerSideMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_HAZE))) - return NO_INCREASE; + // Stat stages are effectively doubled under Simple. + if (gAiLogicData->abilities[battlerAtk] == ABILITY_SIMPLE) + stages *= 2; // Predicting switch if (IsBattlerPredictedToSwitch(battlerDef)) @@ -4146,71 +4715,60 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, switch (statId) { - case STAT_CHANGE_ATK: + case STAT_ATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_DEF: + case STAT_DEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; + else + tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED: + case STAT_SPEED: if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPATK: + case STAT_SPATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += DECENT_EFFECT; + { + if (stages == 1) + tempScore += DECENT_EFFECT; + else + tempScore += GOOD_EFFECT; + } break; - case STAT_CHANGE_SPDEF: + case STAT_SPDEF: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) { if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += DECENT_EFFECT; - else tempScore += WEAK_EFFECT; - } - break; - case STAT_CHANGE_ATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_DEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; + if (stages == 1) + tempScore += WEAK_EFFECT; else tempScore += DECENT_EFFECT; } break; - case STAT_CHANGE_SPEED_2: - if ((noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPATK_2: - if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && shouldSetUp) - tempScore += GOOD_EFFECT; - break; - case STAT_CHANGE_SPDEF_2: - if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) || !HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)) - { - if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_STALL) - tempScore += GOOD_EFFECT; - else - tempScore += DECENT_EFFECT; - } - break; - case STAT_CHANGE_ACC: - if (gBattleMons[battlerAtk].statStages[STAT_ACC] <= 3) // Increase only if necessary + case STAT_ACC: + if (gBattleMons[battlerAtk].statStages[statId] <= 3) // Increase only if necessary tempScore += DECENT_EFFECT; break; - case STAT_CHANGE_EVASION: + case STAT_EVASION: if (noOfHitsToFaint > 3 || noOfHitsToFaint == UNKNOWN_NO_OF_HITS) tempScore += GOOD_EFFECT; else @@ -4218,17 +4776,21 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, break; } + // if already inclined to boost, be slightly more likely to if boost levels matter + if (tempScore > 0 && HasMoveWithEffect(battlerAtk, EFFECT_STORED_POWER)) + tempScore += WEAK_EFFECT; + return tempScore; } -u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statId) +u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statChange) { - return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, TRUE); + return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, TRUE); } -u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statId) +u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statChange) { - return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, FALSE); + return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, FALSE); } void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) @@ -4292,8 +4854,8 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe || IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS) || (HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FIRST_TURN_ONLY)) // filter out Fake Out - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION - || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) ADJUST_SCORE_PTR(GOOD_EFFECT); else ADJUST_SCORE_PTR(DECENT_EFFECT); @@ -4331,7 +4893,7 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score && gAiLogicData->holdEffects[battlerDef] != HOLD_EFFECT_CURE_STATUS) { if (gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION + || gBattleMons[battlerDef].volatiles.infatuation || (gAiLogicData->abilities[battlerAtk] == ABILITY_SERENE_GRACE && HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FIRST_TURN_ONLY))) ADJUST_SCORE_PTR(GOOD_EFFECT); else @@ -4362,7 +4924,7 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score } } -bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move) +bool32 AI_MoveMakesContact(enum Ability ability, enum ItemHoldEffect holdEffect, u32 move) { if (MoveMakesContact(move) && ability != ABILITY_LONG_REACH @@ -4371,19 +4933,149 @@ bool32 AI_MoveMakesContact(u32 ability, enum ItemHoldEffect holdEffect, u32 move return FALSE; } + +bool32 IsConsideringZMove(u32 battlerAtk, u32 battlerDef, u32 move) +{ + if (GetMovePower(move) == 0 && GetMoveZEffect(move) == Z_EFFECT_NONE) + return FALSE; + + return gBattleStruct->gimmick.usableGimmick[battlerAtk] == GIMMICK_Z_MOVE && ShouldUseZMove(battlerAtk, battlerDef, move); +} + //TODO - this could use some more sophisticated logic bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) { + // simple logic. just upgrades chosen move to z move if possible, unless regular move would kill opponent - if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk)) + if ((IsDoubleBattle()) && battlerDef == BATTLE_PARTNER(battlerAtk) && !(GetBattlerMoveTargetType(battlerAtk, chosenMove) & MOVE_TARGET_ALLY)) return FALSE; // don't use z move on partner if (HasTrainerUsedGimmick(battlerAtk, GIMMICK_Z_MOVE)) return FALSE; // can't use z move twice if (IsViableZMove(battlerAtk, chosenMove)) { - uq4_12_t effectiveness; + enum BattleMoveEffects baseEffect = GetMoveEffect(chosenMove); + bool32 isEager = FALSE; // more likely to use a z move than typical + + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + bool32 isSlower = AI_IsSlower(battlerAtk, battlerDef, chosenMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY); + + switch (baseEffect) + { + case EFFECT_BELLY_DRUM: + case EFFECT_FILLET_AWAY: + if (isSlower) + return TRUE; + isEager = TRUE; + break; + case EFFECT_PROTECT: + if (HasDamagingMoveOfType(battlerAtk, GetMoveType(gMovesInfo[chosenMove].type))) + return FALSE; + else + isEager = TRUE; + break; + case EFFECT_TELEPORT: + isEager = TRUE; + break; + case EFFECT_TRANSFORM: + if (IsBattlerTrapped(battlerDef, battlerAtk) && !HasDamagingMoveOfType(battlerDef, GetMoveType(gMovesInfo[chosenMove].type))) + return TRUE; + if (isSlower) + isEager = TRUE; + break; + default: + break; + } + u32 zMove = GetUsableZMove(battlerAtk, chosenMove); + + if (IsBattleMoveStatus(chosenMove)) + { + u8 zEffect = GetMoveZEffect(chosenMove); + enum StatChange statChange = 0; + + if (zEffect == Z_EFFECT_CURSE) + { + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) + zEffect = Z_EFFECT_RECOVER_HP; + else + zEffect = Z_EFFECT_ATK_UP_1; + } + + switch (zEffect) + { + case Z_EFFECT_NONE: + if (GetMovePower(chosenMove) == 0) + return FALSE; + break; + case Z_EFFECT_RESET_STATS: + if (CountNegativeStatStages(battlerAtk) > 1) + return TRUE; + break; + case Z_EFFECT_ALL_STATS_UP_1: + return ShouldRaiseAnyStat(battlerAtk, battlerDef); + case Z_EFFECT_BOOST_CRITS: + return TRUE; + case Z_EFFECT_FOLLOW_ME: + return HasPartnerIgnoreFlags(battlerAtk) && (GetHealthPercentage(battlerAtk) <= Z_EFFECT_FOLLOW_ME_THRESHOLD || GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1); + break; + case Z_EFFECT_RECOVER_HP: + if (GetBestNoOfHitsToKO(battlerDef, battlerAtk, AI_DEFENDING) == 1 && GetHealthPercentage(battlerAtk) > Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD) + return TRUE; + if (isEager) + return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_HIGHER_THRESHOLD; + return GetHealthPercentage(battlerAtk) <= Z_EFFECT_RESTORE_HP_LOWER_THRESHOLD; + case Z_EFFECT_RESTORE_REPLACEMENT_HP: + break; + case Z_EFFECT_ACC_UP_1: + case Z_EFFECT_ACC_UP_2: + case Z_EFFECT_ACC_UP_3: + statChange = STAT_CHANGE_ACC; + break; + case Z_EFFECT_EVSN_UP_1: + case Z_EFFECT_EVSN_UP_2: + case Z_EFFECT_EVSN_UP_3: + statChange = STAT_CHANGE_EVASION; + break; + case Z_EFFECT_ATK_UP_1: + case Z_EFFECT_DEF_UP_1: + case Z_EFFECT_SPD_UP_1: + case Z_EFFECT_SPATK_UP_1: + case Z_EFFECT_SPDEF_UP_1: + statChange = STAT_CHANGE_ATK + zEffect - Z_EFFECT_ATK_UP_1; + break; + case Z_EFFECT_ATK_UP_2: + case Z_EFFECT_DEF_UP_2: + case Z_EFFECT_SPD_UP_2: + case Z_EFFECT_SPATK_UP_2: + case Z_EFFECT_SPDEF_UP_2: + statChange = STAT_CHANGE_ATK_2 + zEffect - Z_EFFECT_ATK_UP_2; + break; + case Z_EFFECT_ATK_UP_3: + case Z_EFFECT_DEF_UP_3: + case Z_EFFECT_SPD_UP_3: + case Z_EFFECT_SPATK_UP_3: + case Z_EFFECT_SPDEF_UP_3: + statChange = STAT_CHANGE_ATK_2 + zEffect - Z_EFFECT_ATK_UP_3; + break; + default: + return FALSE; + } + + if (statChange != 0 && (isEager || IncreaseStatUpScore(battlerAtk, battlerDef, statChange) > 0)) + return TRUE; + + } + else if (GetMoveEffect(zMove) == EFFECT_EXTREME_EVOBOOST) + { + return ShouldRaiseAnyStat(battlerAtk, battlerDef); + } + else if (!IsBattleMoveStatus(chosenMove) && IsBattleMoveStatus(zMove)) + { + return FALSE; + } + + uq4_12_t effectiveness; struct SimulatedDamage dmg; if (gBattleMons[battlerDef].ability == ABILITY_DISGUISE @@ -4395,11 +5087,6 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE_ICE && IsBattleMovePhysical(chosenMove)) return FALSE; // Don't waste a Z-Move busting Ice Face - if (IsBattleMoveStatus(chosenMove) && !IsBattleMoveStatus(zMove)) - return FALSE; - else if (!IsBattleMoveStatus(chosenMove) && IsBattleMoveStatus(zMove)) - return FALSE; - dmg = AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK); if (!IsBattleMoveStatus(chosenMove) && dmg.minimum >= gBattleMons[battlerDef].hp) @@ -4440,7 +5127,7 @@ void DecideTerastal(u32 battler) return; // TODO: Currently only single battles are considered. - if (IsDoubleBattle()) + if (!IsBattle1v1()) return; // TODO: A lot of these checks are most effective for an omnicient ai. @@ -4622,8 +5309,9 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str } else { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battler, opposingBattler, gAiLogicData); // will we go first? - if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) + if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) return USE_GIMMICK; } } @@ -4700,7 +5388,7 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) case STAT_SPATK: return (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)); case STAT_ACC: - return (HasLowAccuracyMove(battlerAtk, battlerDef)); + return HasMoveWithLowAccuracy(battlerAtk, battlerDef, LOW_ACCURACY_THRESHOLD, FALSE); case STAT_EVASION: case STAT_SPEED: return TRUE; @@ -4715,60 +5403,63 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) } //TODO - track entire opponent party data to determine hazard effectiveness -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData) +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { - if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE - || CountUsablePartyMons(battlerDef) == 0 - || HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) - || HasMoveWithEffect(battlerDef, EFFECT_TIDY_UP) - || HasMoveWithEffect(battlerDef, EFFECT_DEFOG) - || HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_DEFOG) - || HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) + if (CountUsablePartyMons(battlerDef) == 0 + || HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_CLEAR_HAZARDS)) return FALSE; + if (IsBattleMoveStatus(move)) + { + if (HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) + return FALSE; + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE) + return FALSE; + } + else + { + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_SHIELD_DUST) + return FALSE; + } return TRUE; } void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) { - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) ADJUST_SCORE_PTR(GOOD_EFFECT); - if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerDef) != 0) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerDef) != 0) ADJUST_SCORE_PTR(-2); - - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_IsFaster(battlerAtk, battlerDef, move)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE_PTR(-10); - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[battlerDef].volatiles.substitute) ADJUST_SCORE_PTR(GOOD_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) + if (gBattleMons[battlerAtk].volatiles.leechSeed) ADJUST_SCORE_PTR(DECENT_EFFECT); - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) + if (gBattleMons[battlerDef].volatiles.leechSeed) ADJUST_SCORE_PTR(-2); } bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData) { u32 preventsStatLoss; - u32 partnerAbility; - u32 partnerHoldEffect = aiData->holdEffects[battlerAtkPartner]; - - if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) - partnerAbility = ABILITY_NONE; - else - partnerAbility = aiData->abilities[battlerAtkPartner]; + enum Ability partnerAbility = aiData->abilities[battlerAtkPartner]; + u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battlerAtk)); + u32 opposingBattler = GetBattlerAtPosition(opposingPosition); if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] == MAX_STAT_STAGE || partnerAbility == ABILITY_CONTRARY || partnerAbility == ABILITY_GOOD_AS_GOLD - || HasMoveWithEffect(BATTLE_OPPOSITE(battlerAtk), EFFECT_FOUL_PLAY) - || HasMoveWithEffect(BATTLE_OPPOSITE(battlerAtkPartner), EFFECT_FOUL_PLAY)) + || HasBattlerSideMoveWithEffect(LEFT_FOE(battlerAtk), EFFECT_FOUL_PLAY)) return FALSE; - preventsStatLoss = (partnerAbility == ABILITY_CLEAR_BODY - || partnerAbility == ABILITY_FULL_METAL_BODY - || partnerAbility == ABILITY_WHITE_SMOKE - || partnerHoldEffect == HOLD_EFFECT_CLEAR_AMULET); + preventsStatLoss = !CanLowerStat(battlerAtk, battlerAtkPartner, aiData, STAT_DEF); switch (GetMoveEffect(aiData->partnerMove)) { @@ -4782,9 +5473,9 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st default: break; } - + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, opposingBattler, gAiLogicData); return (preventsStatLoss - && AI_IsFaster(battlerAtk, battlerAtkPartner, TRUE) + && AI_IsFaster(battlerAtk, battlerAtkPartner, MOVE_NONE, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)); } @@ -4804,12 +5495,12 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) scoreIncrease += BEST_EFFECT; } - if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) + if (gBattleMons[battlerDef].volatiles.perishSong) scoreIncrease += GOOD_EFFECT; if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP) scoreIncrease += GOOD_EFFECT; - else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE)) + else if (gBattleMons[battlerDef].status1 & STATUS1_DAMAGING) scoreIncrease += DECENT_EFFECT; if (IsBattlerPredictedToSwitch(battlerDef)) @@ -4828,35 +5519,24 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) return scoreIncrease; } -bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef) -{ - int i; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gAiLogicData->moveAccuracy[battlerAtk][battlerDef][i] <= LOW_ACCURACY_THRESHOLD) - return TRUE; - } - return FALSE; -} - bool32 IsBattlerItemEnabled(u32 battler) { if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_NEGATE_UNAWARE) return TRUE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return FALSE; - if (gStatuses3[battler] & STATUS3_EMBARGO) + if (gBattleMons[battler].volatiles.embargo) return FALSE; - if (gBattleMons[battler].ability == ABILITY_KLUTZ && !(gStatuses3[battler] & STATUS3_GASTRO_ACID)) + if (gBattleMons[battler].ability == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) return FALSE; return TRUE; } -bool32 HasBattlerSideAbility(u32 battler, u32 ability, struct AiLogicData *aiData) +bool32 HasBattlerSideAbility(u32 battler, enum Ability ability, struct AiLogicData *aiData) { if (aiData->abilities[battler] == ability) return TRUE; - if (IsDoubleBattle() && gAiLogicData->abilities[BATTLE_PARTNER(battler)] == ability) + if (HasPartnerIgnoreFlags(battler) && gAiLogicData->abilities[BATTLE_PARTNER(battler)] == ability) return TRUE; return FALSE; } @@ -4867,11 +5547,13 @@ u32 GetFriendlyFireKOThreshold(u32 battler) return FRIENDLY_FIRE_RISKY_THRESHOLD; if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CONSERVATIVE) return FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD; + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ATTACKS_PARTNER) + return 0; return FRIENDLY_FIRE_NORMAL_THRESHOLD; } -bool32 IsMoxieTypeAbility(u32 ability) +bool32 IsMoxieTypeAbility(enum Ability ability) { switch (ability) { @@ -4887,55 +5569,442 @@ bool32 IsMoxieTypeAbility(u32 ability) } } -// Should the AI use a spread move to deliberately activate its partner's ability? -bool32 ShouldTriggerAbility(u32 battler, u32 ability) +bool32 DoesAbilityRaiseStatsWhenLowered(enum Ability ability) { switch (ability) { + case ABILITY_CONTRARY: + case ABILITY_COMPETITIVE: + case ABILITY_DEFIANT: + return TRUE; + default: + return FALSE; + } +} + +bool32 DoesIntimidateRaiseStats(enum Ability ability) +{ + switch (ability) + { + case ABILITY_COMPETITIVE: + case ABILITY_CONTRARY: + case ABILITY_DEFIANT: + case ABILITY_GUARD_DOG: + case ABILITY_RATTLED: + return TRUE; + default: + return FALSE; + } +} + +// TODO: work out when to attack into the player's contextually 'beneficial' ability +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability) +{ + if (IsTargetingPartner(battlerAtk, battlerDef)) + { + switch (ability) + { case ABILITY_LIGHTNING_ROD: case ABILITY_STORM_DRAIN: if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) return FALSE; else - return (BattlerStatCanRise(battler, ability, STAT_SPATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_SPECIAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_SPATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)); case ABILITY_DEFIANT: case ABILITY_JUSTIFIED: case ABILITY_MOXIE: case ABILITY_SAP_SIPPER: case ABILITY_THERMAL_EXCHANGE: - return (BattlerStatCanRise(battler, ability, STAT_ATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_ATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)); case ABILITY_COMPETITIVE: - return (BattlerStatCanRise(battler, ability, STAT_SPATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_SPECIAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_SPATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)); + // TODO: logic for when to trigger Contrary case ABILITY_CONTRARY: return TRUE; case ABILITY_DRY_SKIN: case ABILITY_VOLT_ABSORB: case ABILITY_WATER_ABSORB: - return (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_HP_AWARE); + return (gAiThinkingStruct->aiFlags[battlerDef] & AI_FLAG_HP_AWARE); case ABILITY_RATTLED: case ABILITY_STEAM_ENGINE: - return BattlerStatCanRise(battler, ability, STAT_SPEED); + return BattlerStatCanRise(battlerDef, ability, STAT_SPEED); case ABILITY_FLASH_FIRE: - return (HasMoveWithType(battler, TYPE_FIRE) && !gDisableStructs[battler].flashFireBoosted); + return (HasMoveWithType(battlerDef, TYPE_FIRE) && !gDisableStructs[battlerDef].flashFireBoosted); case ABILITY_WATER_COMPACTION: case ABILITY_WELL_BAKED_BODY: - return (BattlerStatCanRise(battler, ability, STAT_DEF)); + return (BattlerStatCanRise(battlerDef, ability, STAT_DEF)); default: return FALSE; + } + } + else + { + return FALSE; } } -u32 GetThinkingBattler(u32 battler) +// Used by CheckBadMove; this is determining purely if the effect CAN change an ability, not if it SHOULD. +// At the moment, the parts about Mummy and Wandering Spirit are not actually used. +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData) { - if (gAiLogicData->aiPredictionInProgress) - return gAiLogicData->battlerDoingPrediction; - return battler; + // Dynamaxed Pokemon are immune to some ability-changing effects. + if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) + { + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_SKILL_SWAP: + return FALSE; + default: + break; + } + } + + if (gBattleMons[battlerDef].volatiles.gastroAcid) + return FALSE; + + enum Ability atkAbility = aiData->abilities[battlerAtk]; + enum Ability defAbility = aiData->abilities[battlerDef]; + bool32 hasSameAbility = (atkAbility == defAbility); + + if (defAbility == ABILITY_NONE) + return FALSE; + + if (atkAbility == ABILITY_NONE) + { + switch (effect) + { + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_ROLE_PLAY: + case EFFECT_SKILL_SWAP: + return FALSE; + + default: + break; + } + } + + // Checking for Ability-specific immunities. + switch (effect) + { + case EFFECT_DOODLE: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSuppressed || gAbilitiesInfo[defAbility].cantBeCopied) + return FALSE; + + if (HasPartnerIgnoreFlags(battlerAtk)) + { + u32 partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; + if (gAbilitiesInfo[partnerAbility].cantBeSuppressed) + return FALSE; + if (partnerAbility == defAbility) + return FALSE; + } + break; + + case EFFECT_ROLE_PLAY: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSuppressed || gAbilitiesInfo[defAbility].cantBeCopied) + return FALSE; + break; + + case EFFECT_SKILL_SWAP: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSwapped || gAbilitiesInfo[defAbility].cantBeSwapped) + return FALSE; + break; + + case EFFECT_GASTRO_ACID: + if (gAbilitiesInfo[defAbility].cantBeSuppressed) + return FALSE; + break; + + case EFFECT_ENTRAINMENT: + if (hasSameAbility || gAbilitiesInfo[defAbility].cantBeOverwritten || gAbilitiesInfo[atkAbility].cantBeCopied) + return FALSE; + break; + + case EFFECT_SIMPLE_BEAM: + if (defAbility == ABILITY_SIMPLE || gAbilitiesInfo[defAbility].cantBeOverwritten) + return FALSE; + break; + + case EFFECT_WORRY_SEED: + if (defAbility == ABILITY_INSOMNIA || gAbilitiesInfo[defAbility].cantBeOverwritten) + return FALSE; + break; + + default: + return FALSE; + } + + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) + { + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + return FALSE; + default: + break; + } + } + + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD) + { + switch (effect) + { + case EFFECT_DOODLE: + case EFFECT_ROLE_PLAY: + case EFFECT_SKILL_SWAP: + return FALSE; + default: + break; + } + } + + return TRUE; +} + +bool32 DoesEffectReplaceTargetAbility(u32 effect) +{ + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + return TRUE; + default: + return FALSE; + } +} + +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData) +{ + bool32 isTargetingPartner = IsTargetingPartner(battlerAtk, battlerDef); + enum Ability abilityAtk = aiData->abilities[battlerAtk]; + enum Ability abilityDef = aiData->abilities[battlerDef]; + bool32 partnerHasBadAbility = FALSE; + u32 partnerAbility = ABILITY_NONE; + bool32 attackerHasBadAbility = (gAbilitiesInfo[abilityAtk].aiRating < 0); + s32 currentAbilityScore, transferredAbilityScore = 0; + + if (HasPartner(battlerAtk)) + { + partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; + if (!(gAbilitiesInfo[partnerAbility].cantBeSuppressed) && (gAbilitiesInfo[partnerAbility].aiRating < 0)) + partnerHasBadAbility = TRUE; + } + + if (effect == EFFECT_GASTRO_ACID) + abilityAtk = ABILITY_NONE; + else if (effect == EFFECT_SIMPLE_BEAM) + abilityAtk = ABILITY_SIMPLE; + else if (effect == EFFECT_WORRY_SEED) + abilityAtk = ABILITY_INSOMNIA; + + if (effect == EFFECT_DOODLE || effect == EFFECT_ROLE_PLAY || effect == EFFECT_SKILL_SWAP) + { + if (partnerHasBadAbility && effect == EFFECT_DOODLE) + ADJUST_SCORE_PTR(DECENT_EFFECT); + + if (attackerHasBadAbility) + ADJUST_SCORE_PTR(DECENT_EFFECT); + + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerAtk, abilityAtk, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerAtk, abilityDef, aiData); + ADJUST_SCORE_PTR(transferredAbilityScore - currentAbilityScore); + } + + if (isTargetingPartner) + { + if (DoesEffectReplaceTargetAbility(effect)) + { + if (partnerHasBadAbility) + ADJUST_SCORE_PTR(BEST_EFFECT); + + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityDef, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityAtk, aiData); + ADJUST_SCORE_PTR(transferredAbilityScore - currentAbilityScore); + } + else // This is only Role Play as Doodle can't target the partner + { + ADJUST_SCORE_PTR(-20); + } + + // Trigger Plus or Minus in modern gens. This is not in the overarching function because Skill Swap is rarely beneficial here. + if (B_PLUS_MINUS_INTERACTION >= GEN_5) + { + if (((effect == EFFECT_ENTRAINMENT) && (abilityAtk == ABILITY_PLUS || abilityAtk == ABILITY_MINUS)) || ((effect == EFFECT_ROLE_PLAY) && (abilityDef == ABILITY_PLUS || abilityDef == ABILITY_MINUS))) + ADJUST_SCORE_PTR(DECENT_EFFECT); + } + + } + // Targeting an opponent. + else + { + // We already checked if we want their ability, so now we look to see if we want them to lose their ability. + if (DoesEffectReplaceTargetAbility(effect)) + { + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityDef, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityAtk, aiData); + ADJUST_SCORE_PTR(currentAbilityScore - transferredAbilityScore); + } + } +} + +s32 BattlerBenefitsFromAbilityScore(u32 battler, enum Ability ability, struct AiLogicData *aiData) +{ + if (gAbilitiesInfo[ability].aiRating < 0) + return WORST_EFFECT; + + switch (ability) + { + // Transferrable abilities that can be assumed to be always beneficial. + case ABILITY_CLEAR_BODY: + case ABILITY_GOOD_AS_GOLD: + case ABILITY_MAGIC_GUARD: + case ABILITY_MOODY: + case ABILITY_PURIFYING_SALT: + case ABILITY_SPEED_BOOST: + case ABILITY_WHITE_SMOKE: + return GOOD_EFFECT; + // Conditional ability logic goes here. + case ABILITY_COMPOUND_EYES: + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), 90, FALSE) + || HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), 90, FALSE)) + return GOOD_EFFECT; + break; + case ABILITY_CONTRARY: + if (HasMoveThatLowersOwnStats(battler)) + return BEST_EFFECT; + if (HasMoveThatRaisesOwnStats(battler)) + return AWFUL_EFFECT; + break; + case ABILITY_FRIEND_GUARD: + case ABILITY_POWER_SPOT: + case ABILITY_VICTORY_STAR: + if (HasPartner(battler) && aiData->abilities[BATTLE_PARTNER(battler)] != ability) + return BEST_EFFECT; + break; + case ABILITY_GUTS: + if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_CAN_MOVE)) + return GOOD_EFFECT; + break; + case ABILITY_HUGE_POWER: + case ABILITY_PURE_POWER: + if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL)) + return BEST_EFFECT; + break; + // Also used to Worry Seed WORRY_SEED + case ABILITY_INSOMNIA: + case ABILITY_VITAL_SPIRIT: + if (HasMoveWithEffect(battler, EFFECT_REST)) + return WORST_EFFECT; + break; + case ABILITY_INTIMIDATE: + { + enum Ability abilityDef = aiData->abilities[LEFT_FOE(battler)]; + if (DoesIntimidateRaiseStats(abilityDef)) + { + return AWFUL_EFFECT; + } + else + { + if (HasTwoOpponents(battler)) + { + abilityDef = aiData->abilities[RIGHT_FOE(battler)]; + if (DoesIntimidateRaiseStats(abilityDef)) + { + return AWFUL_EFFECT; + } + else + { + s32 score1 = IncreaseStatDownScore(battler, LEFT_FOE(battler), STAT_ATK); + s32 score2 = IncreaseStatDownScore(battler, RIGHT_FOE(battler), STAT_ATK); + if (score1 > score2) + return score1; + else + return score2; + } + } + return IncreaseStatDownScore(battler, LEFT_FOE(battler), STAT_ATK); + } + } + case ABILITY_NO_GUARD: + if (HasMoveWithLowAccuracy(battler, LEFT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE) + || HasMoveWithLowAccuracy(battler, RIGHT_FOE(battler), LOW_ACCURACY_THRESHOLD, FALSE)) + return GOOD_EFFECT; + break; + // Toxic counter ticks upward while Poison Healed; losing Poison Heal while Toxiced can KO. + case ABILITY_POISON_HEAL: + if (gBattleMons[battler].status1 & (STATUS1_POISON)) + return WEAK_EFFECT; + if (gBattleMons[battler].status1 & (STATUS1_TOXIC_POISON)) + return BEST_EFFECT; + if (gBattleMons[battler].status1 & STATUS1_ANY) + return NO_INCREASE; + break; + // Also used to Simple Beam SIMPLE_BEAM. + case ABILITY_SIMPLE: + // Prioritize moves like Metal Claw, Charge Beam, or Power up Punch + if (HasMoveThatRaisesOwnStats(battler)) + return GOOD_EFFECT; + return NO_INCREASE; + case ABILITY_BEADS_OF_RUIN: + case ABILITY_SWORD_OF_RUIN: + case ABILITY_TABLETS_OF_RUIN: + case ABILITY_VESSEL_OF_RUIN: + if (HasPartner(battler)) + { + if (aiData->abilities[BATTLE_PARTNER(battler)] != ability) + return GOOD_EFFECT; + else + return NO_INCREASE; + } + return GOOD_EFFECT; + case ABILITY_NONE: + return NO_INCREASE; + default: + break; + } + + return WEAK_EFFECT; +} + +bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget) +{ + if (B_WILD_NATURAL_ENEMIES != TRUE) + return FALSE; + + switch (speciesAttacker) + { + case SPECIES_ZANGOOSE: + return (speciesTarget == SPECIES_SEVIPER); + case SPECIES_SEVIPER: + return (speciesTarget == SPECIES_ZANGOOSE); + case SPECIES_HEATMOR: + return (speciesTarget == SPECIES_DURANT); + case SPECIES_DURANT: + return (speciesTarget == SPECIES_HEATMOR); + case SPECIES_SABLEYE: + return (speciesTarget == SPECIES_CARBINK); + case SPECIES_MAREANIE: + return (speciesTarget == SPECIES_CORSOLA); + default: + return FALSE; + } + return FALSE; } diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index d7dbfa36b..05b0b9ee3 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -154,7 +154,6 @@ static void AnimDoubleTeam(struct Sprite *); static void AnimNightSlash(struct Sprite *); static void AnimRockPolishStreak(struct Sprite *); static void AnimRockPolishSparkle(struct Sprite *); -static void AnimPoisonJabProjectile(struct Sprite *); static void AnimNightSlash(struct Sprite *); static void AnimPluck(struct Sprite *); static void AnimAcrobaticsSlashes(struct Sprite *); @@ -4595,20 +4594,18 @@ static void AnimPresent(struct Sprite *sprite) static void AnimKnockOffOpponentsItem(struct Sprite *sprite) { - int zero; sprite->data[0] += ((sprite->data[3] * 128) / sprite->data[4]); - zero = 0; if (sprite->data[0] > 0x7F) { sprite->data[1]++; - sprite->data[0] = zero; + sprite->data[0] = 0; } sprite->y2 = Sin(sprite->data[0] + 0x80, 30 - sprite->data[1] * 8); if (moveAlongLinearPath(sprite)) { - sprite->y2 = zero; - sprite->data[0] = zero; + sprite->y2 = 0; + sprite->data[0] = 0; DestroyAnimSprite(sprite); } } @@ -4686,13 +4683,11 @@ static void AnimItemSteal(struct Sprite *sprite) static void AnimItemSteal_Step3(struct Sprite *sprite) { - int zero; sprite->data[0] += ((sprite->data[3] * 128) / sprite->data[4]); - zero = 0; if (sprite->data[0] > 127) { sprite->data[1]++; - sprite->data[0] = zero; + sprite->data[0] = 0; } sprite->y2 = Sin(sprite->data[0] + 0x80, 30 - sprite->data[1] * 8); @@ -5194,7 +5189,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) { if (gBattleAnimArgs[0] == 0) { - if (IsDoubleBattle()) + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimAttacker, TRUE, &a, &b); } @@ -5206,7 +5201,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) } else { - if (IsDoubleBattle()) + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &a, &b); } @@ -6868,6 +6863,51 @@ static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp); } +static void TrySwapAttractBattlerIds(u32 battlerAtk, u32 battlerPartner) +{ + u32 attractedTo; + + // our own infatuation handled with gBattleMons struct data swapping + + // if another battler is infatuated with one of us, change to other battler + for (u32 i = 0; i < gBattlersCount; i++) + { + if (i == battlerAtk || i == battlerPartner || !gBattleMons[i].volatiles.infatuation) + continue; + + attractedTo = INFATUATED_WITH(i); + if (attractedTo == battlerAtk) + { + gBattleMons[i].volatiles.infatuation = INFATUATED_WITH(battlerPartner); + break; + } + else if (attractedTo == battlerPartner) + { + gBattleMons[i].volatiles.infatuation = INFATUATED_WITH(battlerAtk); + break; + } + } +} + +static void SwapBattlerMoveData(u32 battler1, u32 battler2) +{ + u32 temp; + SWAP(gBattleStruct->chosenMovePositions[battler1], gBattleStruct->chosenMovePositions[battler2], temp); + SWAP(gChosenMoveByBattler[battler1], gChosenMoveByBattler[battler2], temp); + SWAP(gBattleStruct->moveTarget[battler1], gBattleStruct->moveTarget[battler2], temp); + SWAP(gMoveSelectionCursor[battler1], gMoveSelectionCursor[battler2], temp); + SWAP(gLockedMoves[battler1], gLockedMoves[battler2], temp); + + // update last moves + SWAP(gLastPrintedMoves[battler1], gLastPrintedMoves[battler2], temp); + SWAP(gLastMoves[battler1], gLastMoves[battler2], temp); + SWAP(gLastLandedMoves[battler1], gLastLandedMoves[battler2], temp); + SWAP(gLastHitByType[battler1], gLastHitByType[battler2], temp); + SWAP(gLastUsedMoveType[battler1], gLastUsedMoveType[battler2], temp); + SWAP(gLastResultingMoves[battler1], gLastResultingMoves[battler2], temp); + SWAP(gLastHitBy[battler1], gLastHitBy[battler2], temp); +} + static void AnimTask_AllySwitchDataSwap(u8 taskId) { s32 i, j; @@ -6892,13 +6932,9 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp); SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); - SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); - SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp); - SWAP(gBattleStruct->chosenMovePositions[battlerAtk], gBattleStruct->chosenMovePositions[battlerPartner], temp); - SWAP(gChosenMoveByBattler[battlerAtk], gChosenMoveByBattler[battlerPartner], temp); - SWAP(gLockedMoves[battlerAtk], gLockedMoves[battlerPartner], temp); - SWAP(gBattleStruct->moveTarget[battlerAtk], gBattleStruct->moveTarget[battlerPartner], temp); - SWAP(gMoveSelectionCursor[battlerAtk], gMoveSelectionCursor[battlerPartner], temp); + + SwapBattlerMoveData(battlerAtk, battlerPartner); + // Swap turn order, so that all the battlers take action SWAP(gChosenActionByBattler[battlerAtk], gChosenActionByBattler[battlerPartner], temp); for (i = 0; i < gBattlersCount; i++) @@ -6923,11 +6959,12 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) TrySwapSkyDropTargets(battlerAtk, battlerPartner); TrySwapStickyWebBattlerId(battlerAtk, battlerPartner); TrySwapWishBattlerIds(battlerAtk, battlerPartner); + TrySwapAttractBattlerIds(battlerAtk, battlerPartner); // For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target. for (i = 0; i < gBattlersCount; i++) { - u16 ability = GetBattlerAbility(i); + enum Ability ability = GetBattlerAbility(i); // if not targeting a slot that got switched, continue if (!IsBattlerAlly(gBattleStruct->moveTarget[i], battlerAtk)) continue; @@ -7454,7 +7491,7 @@ static void AnimRockPolishSparkle(struct Sprite *sprite) // arg 0: initial x pixel offset // arg 1: initial y pixel offset // arg 2: duration -static void AnimPoisonJabProjectile(struct Sprite *sprite) +void AnimPoisonJabProjectile(struct Sprite *sprite) { s16 targetXPos; s16 targetYPos; diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 9ffc91b17..89d114ea8 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -1325,6 +1325,41 @@ const struct SpriteTemplate gTeraCrystalSpreadSpriteTemplate = .callback = AnimTask_TeraCrystalShatter, }; +// See AnimSpriteOnMonPos in battle_anim_mons.c for more specifics +// Reuses the Mega Symbol affine animation seen in Mega Evolution +// gBattleAnimArgs 0-3 used +// 0, 1 used for position +// 2, 3 as some control variables +const struct SpriteTemplate gTeraSymbolSpriteTemplate = +{ + .tileTag = ANIM_TAG_TERA_SYMBOL, + .paletteTag = ANIM_TAG_TERA_SYMBOL, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_MegaSymbol, + .callback = AnimSpriteOnMonPos, +}; + +// Swirls particle in vortex. Used for moves like Fire Spin or Sand Tomb +// args[0] - initial x offset +// args[1] - initial y offset +// args[2] - y increment +// args[3] - duration +// args[4] - increments some sin parameter +// args[5] - fixed sin parameter +// args[6] - attacker or target +const struct SpriteTemplate gTeraSmokeSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_6, + .paletteTag = ANIM_TAG_SPARKLE_6, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimParticleInVortex, +}; + const struct SpriteTemplate gPinkPetalVortexTemplate = { .tileTag = ANIM_TAG_PINK_PETAL, @@ -2515,6 +2550,31 @@ void AnimTask_HideSwapSprite(u8 taskId) } } +void AnimTask_HideOpponentShadows(u8 taskId) +{ + u32 battlerLeft = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerLeft].shadowSpriteIdPrimary].callback = SpriteCB_SetInvisible; + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerLeft].shadowSpriteIdSecondary].callback = SpriteCB_SetInvisible; + if (IsDoubleBattle()) + { + u32 battlerRight = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerRight].shadowSpriteIdPrimary].callback = SpriteCB_SetInvisible; + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerRight].shadowSpriteIdSecondary].callback = SpriteCB_SetInvisible; + } + DestroyAnimVisualTask(taskId); +} + +void AnimTask_SetOpponentShadowCallbacks(u8 taskId) +{ + u32 battlerLeft = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + SetBattlerShadowSpriteCallback(battlerLeft, gBattleMons[battlerLeft].species); + if (IsDoubleBattle()) + { + u32 battlerRight = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + SetBattlerShadowSpriteCallback(battlerRight, gBattleMons[battlerRight].species); + } + DestroyAnimVisualTask(taskId); +} #define megaEvo data[10] #define trackEnemyPersonality data[11] @@ -5735,7 +5795,7 @@ static void AnimRecycle_Step(struct Sprite *sprite) void AnimTask_GetWeather(u8 taskId) { - bool32 utilityUmbrellaAffected = GetBattlerHoldEffect(gBattleAnimAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA; + bool32 utilityUmbrellaAffected = GetBattlerHoldEffect(gBattleAnimAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA; gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_NONE; if (gWeatherMoveAnim & B_WEATHER_SUN && !utilityUmbrellaAffected) diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c index bd010797a..269d582f3 100644 --- a/src/battle_anim_electric.c +++ b/src/battle_anim_electric.c @@ -10,7 +10,7 @@ static void AnimLightning(struct Sprite *); static void AnimLightning_Step(struct Sprite *); static void AnimUnusedSpinningFist(struct Sprite *); static void AnimUnusedSpinningFist_Step(struct Sprite *); -static void AnimUnusedCirclingShock(struct Sprite *); +static void AnimCirclingElectricShock(struct Sprite *); static void AnimZapCannonSpark_Step(struct Sprite *); static void AnimThunderboltOrb(struct Sprite *); static void AnimThunderboltOrb_Step(struct Sprite *); @@ -83,7 +83,9 @@ static const struct SpriteTemplate sUnusedSpinningFistSpriteTemplate = .callback = AnimUnusedSpinningFist, }; -static const union AnimCmd sAnim_UnusedCirclingShock[] = +// Previously an unused function named sAnim_CirclingElectricShock +// Now used for Tera Blast Electric +static const union AnimCmd sAnim_CirclingElectricShock[] = { ANIMCMD_FRAME(0, 5), ANIMCMD_FRAME(16, 5), @@ -94,21 +96,24 @@ static const union AnimCmd sAnim_UnusedCirclingShock[] = ANIMCMD_JUMP(0), }; -static const union AnimCmd *const sAnims_UnusedCirclingShock[] = +// Previously an unused function named sAnims_UnusedCirclingShock +// Now used for Tera Blast Electric +const union AnimCmd *const sAnims_CirclingElectricShock[] = { - sAnim_UnusedCirclingShock, + sAnim_CirclingElectricShock, }; -// Unused -static const struct SpriteTemplate sUnusedCirclingShockSpriteTemplate = +// Previously named sUnusedCirclingShockSpriteTemplate +// Still unused, but renamed for consistency +static const struct SpriteTemplate sCirclingElectricShockSpriteTemplate = { .tileTag = ANIM_TAG_SHOCK, .paletteTag = ANIM_TAG_SHOCK, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_UnusedCirclingShock, + .anims = sAnims_CirclingElectricShock, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimUnusedCirclingShock, + .callback = AnimCirclingElectricShock, }; const struct SpriteTemplate gSparkElectricitySpriteTemplate = @@ -343,6 +348,19 @@ static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_2[] = AFFINEANIMCMD_END, }; +static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_3[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 60), + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(0xFFFC, 0xFFFC, 0, 5), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), + AFFINEANIMCMD_LOOP(10), + AFFINEANIMCMD_FRAME(-4, -4, 0, 60), + AFFINEANIMCMD_END, +}; + static const union AffineAnimCmd sAffineAnim_GrowingElectricOrb_4[] = { AFFINEANIMCMD_FRAME(5, 5, 0, 0), @@ -368,6 +386,11 @@ const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb2[] = sAffineAnim_GrowingElectricOrb_4, }; +const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb3[] = +{ + sAffineAnim_GrowingElectricOrb_3, +}; + const struct SpriteTemplate gGrowingChargeOrbSpriteTemplate = { .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, @@ -391,6 +414,18 @@ const struct SpriteTemplate gGrowingChargeOrb2SpriteTemplate = .callback = AnimGrowingChargeOrb, }; +// For Dynamax Cannon - orb gets smaller at the end +const struct SpriteTemplate gGrowingChargeOrb3SpriteTemplate = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_AffineNormal_ObjBlend_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_GrowingElectricOrb3, + .callback = AnimGrowingChargeOrb, +}; + static const union AnimCmd sAnim_ElectricPuff[] = { ANIMCMD_FRAME(0, 3), @@ -492,6 +527,17 @@ const struct SpriteTemplate gFairyLockChainsSpriteTemplate = .callback = AnimVoltTackleBolt, }; +const struct SpriteTemplate gCollisionCourseSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_64x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimVoltTackleBolt, +}; + const struct SpriteTemplate gGrowingShockWaveOrbSpriteTemplate = { .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, @@ -603,7 +649,7 @@ const struct SpriteTemplate gVoltSwitchSpriteTemplate = // functions static void AnimLightning(struct Sprite *sprite) { - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; @@ -620,7 +666,7 @@ static void AnimLightning_Step(struct Sprite *sprite) static void AnimUnusedSpinningFist(struct Sprite *sprite) { - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; @@ -634,12 +680,12 @@ static void AnimUnusedSpinningFist_Step(struct Sprite *sprite) DestroySpriteAndMatrix(sprite); } -static void AnimUnusedCirclingShock(struct Sprite *sprite) +static void AnimCirclingElectricShock(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) { sprite->x -= gBattleAnimArgs[0]; sprite->y -= gBattleAnimArgs[1]; @@ -767,7 +813,7 @@ static void AnimThunderboltOrb_Step(struct Sprite *sprite) static void AnimThunderboltOrb(struct Sprite *sprite) { - if (IsContest() || GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + if (IsContest() || IsOnPlayerSide(gBattleAnimTarget)) gBattleAnimArgs[1] = -gBattleAnimArgs[1]; sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; @@ -788,7 +834,7 @@ void AnimSparkElectricityFlashing(struct Sprite *sprite) else battler = gBattleAnimAttacker; - if (IsContest() || GetBattlerSide(battler) == B_SIDE_PLAYER) + if (IsContest() || IsOnPlayerSide(battler)) gBattleAnimArgs[0] = -gBattleAnimArgs[0]; sprite->x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[0]; @@ -1099,7 +1145,7 @@ static void AnimVoltTackleOrbSlide(struct Sprite *sprite) sprite->data[6] = GetAnimBattlerSpriteId(ANIM_ATTACKER); sprite->data[7] = 16; - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->data[7] *= -1; sprite->callback = AnimVoltTackleOrbSlide_Step; @@ -1130,7 +1176,7 @@ void AnimTask_VoltTackleAttackerReappear(u8 taskId) case 0: task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + if (IsOnPlayerSide(gBattleAnimAttacker)) { task->data[14] = -32; task->data[13] = 2; @@ -1186,7 +1232,7 @@ void AnimTask_VoltTackleBolt(u8 taskId) switch(task->data[0]) { case 0: - task->data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1; + task->data[1] = IsOnPlayerSide(gBattleAnimAttacker) ? 1 : -1; switch (gBattleAnimArgs[0]) { @@ -1256,19 +1302,25 @@ void AnimTask_VoltTackleBolt(u8 taskId) static bool8 CreateVoltTackleBolt(struct Task *task, u8 taskId) { u32 spriteId; - bool32 isFairyLock = (gAnimMoveIndex == MOVE_FAIRY_LOCK); - - if (isFairyLock) - spriteId = CreateSprite(&gFairyLockChainsSpriteTemplate, task->data[3], task->data[5] + 10, 35); - else - spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35); + switch(gAnimMoveIndex) + { + case MOVE_FAIRY_LOCK: + spriteId = CreateSprite(&gFairyLockChainsSpriteTemplate, task->data[3], task->data[5] + 10, 35); + break; + case MOVE_COLLISION_COURSE: + spriteId = CreateSprite(&gCollisionCourseSpriteTemplate, task->data[3], task->data[5], 35); + break; + default: + spriteId = CreateSprite(&gVoltTackleBoltSpriteTemplate, task->data[3], task->data[5], 35); + } + bool32 doDestroyOamMatrix = (gAnimMoveIndex == MOVE_FAIRY_LOCK) || (gAnimMoveIndex == MOVE_COLLISION_COURSE); if (spriteId != MAX_SPRITES) { gSprites[spriteId].data[6] = taskId; gSprites[spriteId].data[7] = 7; - gSprites[spriteId].data[1] = isFairyLock ? 25 : 12; // How long the chains / bolts stay on screen. - gSprites[spriteId].data[2] = isFairyLock; // Whether to destroy the Oam Matrix. + gSprites[spriteId].data[1] = (gAnimMoveIndex == MOVE_FAIRY_LOCK) ? 25 : 12; // How long the chains / bolts stay on screen. + gSprites[spriteId].data[2] = doDestroyOamMatrix; // Whether to destroy the Oam Matrix. task->data[7]++; } @@ -1581,9 +1633,9 @@ static void VoltSwitch_Step(struct Sprite* sprite) void AnimTask_VoltSwitch(struct Sprite* sprite) { - InitSpritePosToAnimAttacker(sprite, 0); + InitSpritePosToAnimAttacker(sprite, FALSE); - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; else sprite->y += 10; //Move slightly down diff --git a/src/battle_anim_ground.c b/src/battle_anim_ground.c index 10303ffe2..1ba6fc0b6 100644 --- a/src/battle_anim_ground.c +++ b/src/battle_anim_ground.c @@ -7,7 +7,6 @@ #include "constants/rgb.h" static void AnimBonemerangProjectile(struct Sprite *); -static void AnimBoneHitProjectile(struct Sprite *); static void AnimDirtPlumeParticle_Step(struct Sprite *); static void AnimDigDirtMound(struct Sprite *); static void AnimBonemerangProjectile_Step(struct Sprite *); @@ -84,7 +83,7 @@ static const union AnimCmd sAnim_MudSlapMud[] = ANIMCMD_END, }; -static const union AnimCmd *const sAnims_MudSlapMud[] = +const union AnimCmd *const sAnims_MudSlapMud[] = { sAnim_MudSlapMud, }; @@ -199,10 +198,10 @@ static void AnimBonemerangProjectile_End(struct Sprite *sprite) // arg 2: target x pixel offset // arg 3: target y pixel offset // arg 4: duration -static void AnimBoneHitProjectile(struct Sprite *sprite) +void AnimBoneHitProjectile(struct Sprite *sprite) { InitSpritePosToAnimTarget(sprite, TRUE); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[0] = gBattleAnimArgs[4]; @@ -524,7 +523,7 @@ void AnimDirtPlumeParticle(struct Sprite *sprite) s8 battler; s16 xOffset; - if (gBattleAnimArgs[0] == 0) + if (gBattleAnimArgs[0] == ANIM_ATTACKER) battler = gBattleAnimAttacker; else battler = gBattleAnimTarget; diff --git a/src/battle_anim_ice.c b/src/battle_anim_ice.c index 7cc2395bf..5b8c599c8 100644 --- a/src/battle_anim_ice.c +++ b/src/battle_anim_ice.c @@ -13,17 +13,21 @@ #include "constants/battle_anim.h" #include "constants/rgb.h" +enum { + HAILSTRUCTTYPE_NEGATIVE_POS_MOD = 0, + HAILSTRUCTTYPE_POSITIVE_POS_MOD = 1, + HAILSTRUCTTYPE_FIXED_POSITION = 2, +}; struct HailStruct { s32 x:10; s32 y:10; s32 bPosition:8; - s32 unk3:4; + s32 type:4; }; static void AnimUnusedIceCrystalThrow(struct Sprite *); static void AnimUnusedIceCrystalThrow_Step(struct Sprite *); static void AnimIcePunchSwirlingParticle(struct Sprite *); -static void AnimIceBeamParticle(struct Sprite *); static void AnimFlickerIceEffectParticle(struct Sprite *); static void AnimSwirlingSnowball(struct Sprite *); static void AnimSwirlingSnowball_Step2(struct Sprite *); @@ -382,16 +386,16 @@ const struct SpriteTemplate gPoisonGasCloudSpriteTemplate = static const struct HailStruct sHailCoordData[] = { - {.x = 100, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, - {.x = 85, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 0}, - {.x = 242, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 1}, - {.x = 66, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 1}, - {.x = 182, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 0}, - {.x = 60, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 2}, - {.x = 214, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .unk3 = 0}, - {.x = 113, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .unk3 = 1}, - {.x = 210, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .unk3 = 1}, - {.x = 38, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .unk3 = 0}, + {.x = 100, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .type = HAILSTRUCTTYPE_FIXED_POSITION}, + {.x = 85, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .type = HAILSTRUCTTYPE_NEGATIVE_POS_MOD}, + {.x = 242, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .type = HAILSTRUCTTYPE_POSITIVE_POS_MOD}, + {.x = 66, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .type = HAILSTRUCTTYPE_POSITIVE_POS_MOD}, + {.x = 182, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .type = HAILSTRUCTTYPE_NEGATIVE_POS_MOD}, + {.x = 60, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .type = HAILSTRUCTTYPE_FIXED_POSITION}, + {.x = 214, .y = 120, .bPosition = B_POSITION_OPPONENT_LEFT, .type = HAILSTRUCTTYPE_NEGATIVE_POS_MOD}, + {.x = 113, .y = 120, .bPosition = B_POSITION_PLAYER_LEFT, .type = HAILSTRUCTTYPE_POSITIVE_POS_MOD}, + {.x = 210, .y = 120, .bPosition = B_POSITION_OPPONENT_RIGHT, .type = HAILSTRUCTTYPE_POSITIVE_POS_MOD}, + {.x = 38, .y = 120, .bPosition = B_POSITION_PLAYER_RIGHT, .type = HAILSTRUCTTYPE_NEGATIVE_POS_MOD}, }; static const union AffineAnimCmd sAffineAnim_HailParticle_0[] = @@ -698,12 +702,12 @@ static void AnimIcePunchSwirlingParticle(struct Sprite *sprite) // arg 2: target x offset // arg 3: target y offset // arg 4: duration -static void AnimIceBeamParticle(struct Sprite *sprite) +void AnimIceBeamParticle(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->data[2] -= gBattleAnimArgs[2]; else sprite->data[2] += gBattleAnimArgs[2]; @@ -728,7 +732,7 @@ void AnimIceEffectParticle(struct Sprite *sprite) else { SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[0] = -gBattleAnimArgs[0]; sprite->x += gBattleAnimArgs[0]; @@ -775,7 +779,7 @@ static void AnimSwirlingSnowball(struct Sprite *sprite) SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->data[2], &sprite->data[4]); } - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->data[2] -= gBattleAnimArgs[2]; else sprite->data[2] += gBattleAnimArgs[2]; @@ -821,7 +825,7 @@ void AnimSwirlingSnowball_Step1(struct Sprite *sprite) sprite->x2 = 0; sprite->data[0] = 128; - tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + tempVar = !IsOnPlayerSide(gBattleAnimAttacker) ? 20 : -20; sprite->data[3] = Sin(sprite->data[0], tempVar); sprite->data[4] = Cos(sprite->data[0], 0xF); @@ -833,7 +837,7 @@ void AnimSwirlingSnowball_Step1(struct Sprite *sprite) static void AnimSwirlingSnowball_Step2(struct Sprite *sprite) { s16 tempVar; - tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + tempVar = !IsOnPlayerSide(gBattleAnimAttacker) ? 20 : -20; if (sprite->data[5] <= 31) { @@ -897,7 +901,7 @@ void AnimMoveParticleBeyondTarget(struct Sprite *sprite) SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->data[2], &sprite->data[4]); } - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->data[2] -= gBattleAnimArgs[2]; else sprite->data[2] += gBattleAnimArgs[2]; @@ -969,7 +973,7 @@ static void AnimWaveFromCenterOfTarget(struct Sprite *sprite) { SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &sprite->x, &sprite->y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[0] = -gBattleAnimArgs[0]; sprite->x += gBattleAnimArgs[0]; @@ -1006,7 +1010,7 @@ static void InitSwirlingFogAnim(struct Sprite *sprite) else { SetAverageBattlerPositions(gBattleAnimAttacker, FALSE, &sprite->x, &sprite->y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; @@ -1025,7 +1029,7 @@ static void InitSwirlingFogAnim(struct Sprite *sprite) else { SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &sprite->x, &sprite->y); - if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimTarget)) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; @@ -1043,7 +1047,7 @@ static void InitSwirlingFogAnim(struct Sprite *sprite) tempVar = 0x40; sprite->data[6] = tempVar; - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + if (IsOnPlayerSide(gBattleAnimTarget)) sprite->y += 8; sprite->data[0] = gBattleAnimArgs[3]; @@ -1289,12 +1293,12 @@ static void InitPoisonGasCloudAnim(struct Sprite *sprite) if (GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2)) sprite->data[7] = 0x8000; - if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + if (IsOnPlayerSide(gBattleAnimTarget)) { gBattleAnimArgs[1] = -gBattleAnimArgs[1]; gBattleAnimArgs[3] = -gBattleAnimArgs[3]; - if ((sprite->data[7] & 0x8000) && GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + if ((sprite->data[7] & 0x8000) && IsOnPlayerSide(gBattleAnimAttacker)) sprite->subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1; sprite->data[6] = 1; @@ -1373,7 +1377,7 @@ static void MovePoisonGasCloud(struct Sprite *sprite) sprite->data[7]++; if (IsContest()) sprite->data[5] = 80; - else if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) + else if (!IsOnPlayerSide(gBattleAnimTarget)) sprite->data[5] = 204; else sprite->data[5] = 80; @@ -1419,7 +1423,7 @@ static void MovePoisonGasCloud(struct Sprite *sprite) sprite->data[4] = sprite->y + 4; if (IsContest()) sprite->data[2] = -16; - else if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) + else if (!IsOnPlayerSide(gBattleAnimTarget)) sprite->data[2] = DISPLAY_WIDTH + 16; else sprite->data[2] = -16; @@ -1445,6 +1449,13 @@ static void MovePoisonGasCloud(struct Sprite *sprite) } } +#define tState data[0] +#define tSpriteCount data[1] +#define tHailAffineAnimNum data[2] +#define tHailStructId data[3] +#define tInitialDelayTimer data[4] +#define tHailSpawnTimer data[5] + void AnimTask_Hail(u8 taskId) { struct Task *task = &gTasks[taskId]; @@ -1455,71 +1466,86 @@ void AnimTask_Hail(u8 taskId) static void AnimTask_Hail2(u8 taskId) { struct Task *task = &gTasks[taskId]; - switch (task->data[0]) + switch (task->tState) { case 0: - if (++task->data[4] > 2) + if (++task->tInitialDelayTimer > 2) { - task->data[4] = 0; - task->data[5] = 0; - task->data[2] = 0; - task->data[0]++; + task->tInitialDelayTimer = 0; + task->tHailSpawnTimer = 0; + task->tHailAffineAnimNum = 0; + task->tState++; } break; case 1: - if (task->data[5] == 0) + if (task->tHailSpawnTimer == 0) { - if (GenerateHailParticle(task->data[3], task->data[2], taskId, 1)) - task->data[1]++; + if (GenerateHailParticle(task->tHailStructId, task->tHailAffineAnimNum, taskId, 1)) + task->tSpriteCount++; - if (++task->data[2] == 3) + if (++task->tHailAffineAnimNum == (int)ARRAY_COUNT(sAffineAnims_HailParticle)) { - if (++task->data[3] == 10) - task->data[0]++; + if (++task->tHailStructId == (int)ARRAY_COUNT(sHailCoordData)) + task->tState++; else - task->data[0]--; + task->tState--; } else { - task->data[5] = 1; + task->tHailSpawnTimer = 1; } } else { - task->data[5]--; + task->tHailSpawnTimer--; } break; case 2: - if (task->data[1] == 0) + if (task->tSpriteCount == 0) DestroyAnimVisualTask(taskId); break; } } +#undef tState +#undef tSpriteCount +#undef tHailAffineAnimNum +#undef tHailStructId +#undef tInitialDelayTimer +#undef tHailSpawnTimer + +// Hail falling particle sprite vars +#define sSpawnImpactEffect data[0] +#define sTargetX data[3] +#define sTargetY data[4] +#define sAffineAnimNum data[5] +#define sOwnerTaskId data[6] +#define sOwnerTaskSpriteCountField data[7] + static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c) { u8 id; s16 battlerX, battlerY; s16 spriteX; - bool8 possibleBool = FALSE; - s8 unk = sHailCoordData[hailStructId].unk3; + bool8 shouldSpawnImpactEffect = FALSE; + s8 type = sHailCoordData[hailStructId].type; - if (unk != 2) + if (type != HAILSTRUCTTYPE_FIXED_POSITION) { id = GetBattlerAtPosition(sHailCoordData[hailStructId].bPosition); if (IsBattlerSpriteVisible(id)) { - possibleBool = TRUE; + shouldSpawnImpactEffect = TRUE; battlerX = GetBattlerSpriteCoord(id, BATTLER_COORD_X_2); battlerY = GetBattlerSpriteCoord(id, BATTLER_COORD_Y_PIC_OFFSET); - switch (unk) + switch (type) { - case 0: + case HAILSTRUCTTYPE_NEGATIVE_POS_MOD: battlerX -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; battlerY -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; break; - case 1: + case HAILSTRUCTTYPE_POSITIVE_POS_MOD: battlerX += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; battlerY += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; break; @@ -1545,12 +1571,12 @@ static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, else { StartSpriteAffineAnim(&gSprites[id], affineAnimNum); - gSprites[id].data[0] = possibleBool; - gSprites[id].data[3] = battlerX; - gSprites[id].data[4] = battlerY; - gSprites[id].data[5] = affineAnimNum; - gSprites[id].data[6] = taskId; - gSprites[id].data[7] = c; + gSprites[id].sSpawnImpactEffect = shouldSpawnImpactEffect; + gSprites[id].sTargetX = battlerX; + gSprites[id].sTargetY = battlerY; + gSprites[id].sAffineAnimNum = affineAnimNum; + gSprites[id].sOwnerTaskId = taskId; + gSprites[id].sOwnerTaskSpriteCountField = c; return TRUE; } } @@ -1562,20 +1588,23 @@ static void AnimHailBegin(struct Sprite *sprite) sprite->x += 4; sprite->y += 8; - if (sprite->x < sprite->data[3] && sprite->y < sprite->data[4]) + if (sprite->x < sprite->sTargetX && sprite->y < sprite->sTargetY) return; - if (sprite->data[0] == 1 && sprite->data[5] == 0) + if (sprite->sSpawnImpactEffect == 1 && sprite->sAffineAnimNum == 0) { spriteId = CreateSprite(&gIceCrystalHitLargeSpriteTemplate, - sprite->data[3], sprite->data[4], sprite->subpriority); + sprite->sTargetX, sprite->sTargetY, sprite->subpriority); sprite->data[0] = spriteId; if (spriteId != MAX_SPRITES) { + // The sprite template we're using is shared amongst a few other + // places, which make the sprite flicker. That's not what we want + // here, though. Override the callback. gSprites[sprite->data[0]].callback = AnimHailContinue; - gSprites[sprite->data[0]].data[6] = sprite->data[6]; - gSprites[sprite->data[0]].data[7] = sprite->data[7]; + gSprites[sprite->data[0]].sOwnerTaskId = sprite->sOwnerTaskId; + gSprites[sprite->data[0]].sOwnerTaskSpriteCountField = sprite->sOwnerTaskSpriteCountField; } FreeOamMatrix(sprite->oam.matrixNum); @@ -1583,22 +1612,34 @@ static void AnimHailBegin(struct Sprite *sprite) } else { - gTasks[sprite->data[6]].data[sprite->data[7]]--; + gTasks[sprite->sOwnerTaskId].data[sprite->sOwnerTaskSpriteCountField]--; FreeOamMatrix(sprite->oam.matrixNum); DestroySprite(sprite); } } +#undef sSpawnImpactEffect +#undef sTargetX +#undef sTargetY +#undef sAffineAnimNum + +// Hail impact VFX sprite vars +#define sTimer data[0] + static void AnimHailContinue(struct Sprite *sprite) { - if (++sprite->data[0] == 20) + if (++sprite->sTimer == 20) { - gTasks[sprite->data[6]].data[sprite->data[7]]--; + gTasks[sprite->sOwnerTaskId].data[sprite->sOwnerTaskSpriteCountField]--; FreeOamMatrix(sprite->oam.matrixNum); DestroySprite(sprite); } } +#undef sTimer +#undef sOwnerTaskId +#undef sOwnerTaskSpriteCountField + // Initializes the animation for Ice Ball. // arg 0: initial x pixel offset // arg 1: initial y pixel offset @@ -1618,7 +1659,7 @@ static void InitIceBallAnim(struct Sprite *sprite) sprite->data[0] = gBattleAnimArgs[4]; - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 40d3602e6..58e6a17dc 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -4403,6 +4403,17 @@ const struct SpriteTemplate gUTurnBallBackSpriteTemplate = .callback = AnimAbsorptionOrb, }; +// dynamax cannon +const struct SpriteTemplate gSpriteTemplate_DynamaxCannonOrb = { + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_HydroCannonBall, + .callback = AnimShadowBall +}; + // wicked blow static const union AffineAnimCmd sSpriteAffineAnim_DrainPunchFist[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 1), //Double sprite size @@ -4729,7 +4740,7 @@ static const union AffineAnimCmd* const sSpriteAffineAnimTable_Flutterby[] = { const struct SpriteTemplate gSpriteTemplate_InfernalParadeFlame = { .tileTag = ANIM_TAG_PURPLE_FLAME, .paletteTag = ANIM_TAG_PURPLE_FLAME, - .oam = &gOamData_AffineDouble_ObjBlend_32x16, + .oam = &gOamData_AffineDouble_ObjNormal_16x32, .anims = gAnims_GrudgeFlame, .images = NULL, .affineAnims = sSpriteAffineAnimTable_Flutterby, @@ -5684,7 +5695,7 @@ const struct SpriteTemplate gBlackHoleEclipseBlueRingSpriteTemplate = const struct SpriteTemplate gBlackHoleEclipseBlackRingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_SHADOW_BALL, .oam = &gOamData_AffineDouble_ObjNormal_64x64, .anims = gDummySpriteAnimTable, .images = NULL, @@ -7301,6 +7312,287 @@ const struct SpriteTemplate gOmegaGeyserSpriteTemplate = .callback = SpriteCB_Geyser, }; +// Moves objects (ice crystals) in a wave-like behavior. Seen in Max Flutterby +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: wave amplitude +const struct SpriteTemplate gIceShardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineDouble_ObjBlend_8x8, + .anims = gAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_Flutterby, + .callback = SpriteCB_MaxFlutterby +}; + +const struct SpriteTemplate gSpinningVineSpriteTemplate = +{ + .tileTag = ANIM_TAG_PUNISHMENT_BLADES, + .paletteTag = ANIM_TAG_LEAF, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_SpinningBone, + .callback = AnimBoneHitProjectile, +}; + +const struct SpriteTemplate gMaxFlutterbyButterflySpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_6, + .paletteTag = ANIM_TAG_SPARKLE_6, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_Flutterby, + .callback = SpriteCB_MaxFlutterby +}; + +const struct SpriteTemplate gReallyBigRockBlastRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_REALLY_BIG_ROCK, + .paletteTag = ANIM_TAG_REALLY_BIG_ROCK, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockBlastRock, +}; + +const struct SpriteTemplate gOrderUpTatsugiriCurlySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_CURLY, + .paletteTag = ANIM_TAG_TATSUGIRI_CURLY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +const struct SpriteTemplate gOrderUpTatsugiriDroopySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_DROOPY, + .paletteTag = ANIM_TAG_TATSUGIRI_DROOPY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +const struct SpriteTemplate gOrderUpTatsugiriStretchySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_STRETCHY, + .paletteTag = ANIM_TAG_TATSUGIRI_STRETCHY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +// Start of Tera Blast sprite templates +const struct SpriteTemplate gFireSpreadBlastSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIceBeamParticle, +}; + +const struct SpriteTemplate gPurpleFlameSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_FLAME, + .paletteTag = ANIM_TAG_PURPLE_FLAME, + .oam = &gOamData_AffineOff_ObjBlend_16x32, + .anims = gAnims_GrudgeFlame, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gAirWaveSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_AIR_WAVE_2, + .paletteTag = ANIM_TAG_AIR_WAVE_2, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = gAffineAnims_AirWaveCrescent, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gPinkVioletOrbSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PINKVIO_ORB, + .paletteTag = ANIM_TAG_PINKVIO_ORB, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gHydroPumpSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sCirclingShockSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHOCK, + .paletteTag = ANIM_TAG_SHOCK, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_CirclingElectricShock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sIceCrystalSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineDouble_ObjBlend_8x16, + .anims = gAnims_IceCrystalLarge, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sMudSandSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_MudSlapMud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sPoisonSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = &gAnims_PoisonProjectile[0], + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sRockSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_FlyingRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sMetalBallSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_METAL_BALL, + .paletteTag = ANIM_TAG_METAL_BALL, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sPinkHeartSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PINK_HEART, + .paletteTag = ANIM_TAG_PINK_HEART, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gDragonDanceOrbSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gYellowStarSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_YELLOW_STAR, + .paletteTag = ANIM_TAG_YELLOW_STAR, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gTeraBlastFlyingSpriteTemplate = +{ + .tileTag = ANIM_TAG_METAL_SOUND_WAVES, + .paletteTag = ANIM_TAG_METAL_SOUND_WAVES, + .oam = &gOamData_AffineDouble_ObjNormal_32x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_SpinningBone, + .callback = AnimShadowBall, +}; + +const struct SpriteTemplate gTeraBlastWaterSpriteTemplate = +{ + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDracoMeteorRock, +}; + +const struct SpriteTemplate gTeraBlastRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDracoMeteorRock, +}; + +const struct SpriteTemplate gGhostProjectileSpriteTemplate = +{ + .tileTag = ANIM_TAG_GHOSTLY_SPIRIT, + .paletteTag = ANIM_TAG_GHOSTLY_SPIRIT, + .oam = &gOamData_AffineOff_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimPoisonJabProjectile, +}; +// End of Tera Blast sprite templates + const union AnimCmd gSproutAnimCmds[] = { ANIMCMD_FRAME(96, 5), @@ -7965,7 +8257,7 @@ void SpriteCB_RandomCentredHits(struct Sprite *sprite) StartSpriteAffineAnim(sprite, gBattleAnimArgs[1]); - if (gBattleAnimArgs[0] == 0) + if (gBattleAnimArgs[0] == ANIM_ATTACKER) { if (IsDoubleBattle()) InitSpritePosToAnimAttackersCentre(sprite, FALSE); @@ -8766,7 +9058,7 @@ void AnimTask_ShellSideArm(u8 taskId) void AnimTask_TerrainPulse(u8 taskId) { - if (IsBattlerTerrainAffected(gBattleAnimAttacker, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(gBattleAnimAttacker, GetBattlerAbility(gBattleAnimAttacker), GetBattlerHoldEffect(gBattleAnimAttacker), STATUS_FIELD_TERRAIN_ANY)) { if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) gBattleAnimArgs[0] = TYPE_ELECTRIC; @@ -9137,6 +9429,18 @@ static void SpriteCB_DragonEnergyShot(struct Sprite* sprite) //arg 2: wave amplitude static void SpriteCB_MaxFlutterby(struct Sprite* sprite) { + s16 target_x; + s16 target_y; + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) + { + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &target_x, &target_y); + } + else + { + target_x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + target_y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + InitSpritePosToAnimAttacker(sprite, FALSE); sprite->data[0] = 0x10; //Speed delay @@ -9152,7 +9456,8 @@ static void SpriteCB_MaxFlutterbyStep1(struct Sprite* sprite) { if (!FuncIsActiveTask(AnimTask_DynamaxGrowthStep)) { - if (gAnimMoveIndex != MOVE_INFERNAL_PARADE) + if (gAnimMoveIndex != MOVE_INFERNAL_PARADE + && gAnimMoveIndex != MOVE_ASTRAL_BARRAGE) PlaySE(SE_M_SAND_ATTACK); StartSpriteAffineAnim(sprite, 1); @@ -9327,7 +9632,7 @@ void AnimTask_RandomBool(u8 taskId) // Credit to Skeli #define PRIMAL_PULSE_SCALE_SIZE 16 #define PRIMAL_PULSE_FRAME_COUNT 4 -static const union AffineAnimCmd sSpriteAffineAnim_PrimalSymbol[] = +static const union AffineAnimCmd sSpriteAffineAnim_PrimalSymbol[] = { AFFINEANIMCMD_FRAME(16, 16, 0, 0), AFFINEANIMCMD_FRAME(32, 32, 0, 15), @@ -9370,3 +9675,25 @@ const union AffineAnimCmd* const gSpriteAffineAnimTable_MegaSymbol[] = { sSpriteAffineAnim_MegaSymbol, }; + +// Used for determining which animation to use for Order Up +void AnimTask_GetCommanderType(u8 taskId) +{ + switch (gBattleStruct->battlerState[gEffectBattler].commanderSpecies) + { + case SPECIES_TATSUGIRI_CURLY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_CURLY; + break; + case SPECIES_TATSUGIRI_DROOPY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_DROOPY; + break; + case SPECIES_TATSUGIRI_STRETCHY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_STRETCHY; + break; + default: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_NONE; + break; + } + + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_rock.c b/src/battle_anim_rock.c index 4856a8273..23b244957 100644 --- a/src/battle_anim_rock.c +++ b/src/battle_anim_rock.c @@ -11,7 +11,6 @@ static void AnimTask_Rollout_Step(u8 taskId); static void AnimRolloutParticle(struct Sprite *); -static void AnimRockTomb(struct Sprite *); static void AnimRockTomb_Step(struct Sprite *sprite); static void AnimRockScatter(struct Sprite *); static void AnimRockScatter_Step(struct Sprite *sprite); @@ -174,7 +173,7 @@ static const union AnimCmd sAnim_Rock_Smallest[] = ANIMCMD_END, }; -static const union AnimCmd *const sAnims_BasicRock[] = +const union AnimCmd *const sAnims_BasicRock[] = { sAnim_Rock_Biggest, sAnim_Rock_Bigger, @@ -378,7 +377,7 @@ static void AnimStealthRock(struct Sprite *sprite) InitSpritePosToAnimAttacker(sprite, TRUE); SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &x, &y); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[0] = gBattleAnimArgs[4]; @@ -454,7 +453,7 @@ void AnimRockFragment(struct Sprite *sprite) StartSpriteAnim(sprite, gBattleAnimArgs[5]); AnimateSprite(sprite); - if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (!IsOnPlayerSide(gBattleAnimAttacker)) sprite->x -= gBattleAnimArgs[0]; else sprite->x += gBattleAnimArgs[0]; @@ -485,11 +484,7 @@ void AnimRockFragment(struct Sprite *sprite) // args[6] - attacker or target void AnimParticleInVortex(struct Sprite *sprite) { - if (IsDoubleBattle() - && (gAnimMoveIndex == MOVE_BLEAKWIND_STORM - || gAnimMoveIndex == MOVE_SANDSEAR_STORM - || gAnimMoveIndex == MOVE_SPRINGTIDE_STORM - || gAnimMoveIndex == MOVE_WILDBOLT_STORM)) + if (IsDoubleBattle() && GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH) InitSpritePosToAnimTargetsCentre(sprite, FALSE); else InitSpritePosToAnimBattler(gBattleAnimArgs[6], sprite, FALSE); @@ -515,6 +510,11 @@ static void AnimParticleInVortex_Step(struct Sprite *sprite) } } +#define tBlendTimer data[10] +#define tBlend data[11] +#define tFullAlphaTimer data[11] // not a typo; this data field is used for multiple purposes +#define tState data[12] + void AnimTask_LoadSandstormBackground(u8 taskId) { int var0; @@ -539,7 +539,7 @@ void AnimTask_LoadSandstormBackground(u8 taskId) AnimLoadCompressedBgTilemapHandleContest(&animBg, gBattleAnimBgTilemap_Sandstorm, FALSE); LoadPalette(gBattleAnimSpritePal_FlyingDirt, BG_PLTT_ID(animBg.paletteId), PLTT_SIZE_4BPP); - if (gBattleAnimArgs[0] && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (gBattleAnimArgs[0] && !IsOnPlayerSide(gBattleAnimAttacker)) var0 = 1; gTasks[taskId].data[0] = var0; @@ -557,45 +557,45 @@ static void AnimTask_LoadSandstormBackground_Step(u8 taskId) gBattle_BG1_Y += -1; - switch (gTasks[taskId].data[12]) + switch (gTasks[taskId].tState) { case 0: - if (++gTasks[taskId].data[10] == 4) + if (++gTasks[taskId].tBlendTimer == 4) { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11]++; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 7) + gTasks[taskId].tBlendTimer = 0; + gTasks[taskId].tBlend++; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlend, 16 - gTasks[taskId].tBlend)); + if (gTasks[taskId].tBlend == 7) { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; + gTasks[taskId].tState++; + gTasks[taskId].tFullAlphaTimer = 0; } } break; case 1: - if (++gTasks[taskId].data[11] == 101) + if (++gTasks[taskId].tFullAlphaTimer == 101) { - gTasks[taskId].data[11] = 7; - gTasks[taskId].data[12]++; + gTasks[taskId].tBlend = 7; + gTasks[taskId].tState++; } break; case 2: - if (++gTasks[taskId].data[10] == 4) + if (++gTasks[taskId].tBlendTimer == 4) { - gTasks[taskId].data[10] = 0; - gTasks[taskId].data[11]--; - SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); - if (gTasks[taskId].data[11] == 0) + gTasks[taskId].tBlendTimer = 0; + gTasks[taskId].tBlend--; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].tBlend, 16 - gTasks[taskId].tBlend)); + if (gTasks[taskId].tBlend == 0) { - gTasks[taskId].data[12]++; - gTasks[taskId].data[11] = 0; + gTasks[taskId].tState++; + gTasks[taskId].tFullAlphaTimer = 0; } } break; case 3: GetBattleAnimBg1Data(&animBg); ClearBattleAnimBg(animBg.bgId); - gTasks[taskId].data[12]++; + gTasks[taskId].tState++; break; case 4: if (!IsContest()) @@ -611,21 +611,36 @@ static void AnimTask_LoadSandstormBackground_Step(u8 taskId) } } +#undef tBlendTimer +#undef tBlend +#undef tFullAlphaTimer +#undef tState + // Animates the sprites that fly diagonally across the screen // in Sandstorm and Heat Wave. -// arg 0: initial y pixel offset -// arg 1: projectile speed -// arg 2: y pixel drop -// arg 3: ??? unknown (possibly a color bit) + +#define sState data[0] +#define sVelocityX data[1] // 256ths of a pixel // init'd from gBattleAnimArgs[1] +#define sVelocityY data[2] // 256ths of a pixel // init'd from gBattleAnimArgs[2] +#define sFractionalX data[3] // 256ths of a pixel +#define sFractionalY data[4] // 256ths of a pixel +#define sMirroredX data[5] // init'd from gBattleAnimArgs[3] + +// The fields named "velocity" are arguably more like "acceleration," +// and the fields named "fractional" are arguably more like "velocity." +// +// ...is what I WOULD say if the "fractional" fields weren't AND'd with +// 0xFF after every frame. + void AnimFlyingSandCrescent(struct Sprite *sprite) { - if (sprite->data[0] == 0) + if (sprite->sState == 0) { - if (gBattleAnimArgs[3] != 0 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + if (gBattleAnimArgs[3] != 0 && !IsOnPlayerSide(gBattleAnimAttacker)) { sprite->x = DISPLAY_WIDTH + 64; gBattleAnimArgs[1] = -gBattleAnimArgs[1]; - sprite->data[5] = 1; + sprite->sMirroredX = 1; sprite->oam.matrixNum = ST_OAM_HFLIP; } else @@ -635,18 +650,18 @@ void AnimFlyingSandCrescent(struct Sprite *sprite) sprite->y = gBattleAnimArgs[0]; SetSubspriteTables(sprite, sFlyingSandSubspriteTable); - sprite->data[1] = gBattleAnimArgs[1]; - sprite->data[2] = gBattleAnimArgs[2]; - sprite->data[0]++; + sprite->sVelocityX = gBattleAnimArgs[1]; + sprite->sVelocityY = gBattleAnimArgs[2]; + sprite->sState++; } else { - sprite->data[3] += sprite->data[1]; - sprite->data[4] += sprite->data[2]; - sprite->x2 += (sprite->data[3] >> 8); - sprite->y2 += (sprite->data[4] >> 8); - sprite->data[3] &= 0xFF; - sprite->data[4] &= 0xFF; + sprite->sFractionalX += sprite->sVelocityX; + sprite->sFractionalY += sprite->sVelocityY; + sprite->x2 += (sprite->sFractionalX >> 8); + sprite->y2 += (sprite->sFractionalY >> 8); + sprite->sFractionalX &= 0xFF; + sprite->sFractionalY &= 0xFF; if (sprite->data[5] == 0) { @@ -662,6 +677,13 @@ void AnimFlyingSandCrescent(struct Sprite *sprite) } } +#undef sState +#undef sVelocityX +#undef sVelocityY +#undef sFractionalX +#undef sFractionalY +#undef sMirroredX + // Animates the rising rocks in Ancient Power. // arg 0: initial x pixel offset // arg 1: initial y pixel offset @@ -737,10 +759,10 @@ void AnimTask_TectonicRageRollout(u8 taskId) task = &gTasks[taskId]; - var0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); - var1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + 24; - var2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); - var3 = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + 24; + var0 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + var1 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y) + 24; + var2 = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + var3 = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 24; if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget) var3 = var1; @@ -912,7 +934,7 @@ static u8 GetRolloutCounter(void) return retVal; } -static void AnimRockTomb(struct Sprite *sprite) +void AnimRockTomb(struct Sprite *sprite) { StartSpriteAnim(sprite, gBattleAnimArgs[4]); @@ -947,7 +969,7 @@ static void AnimRockTomb_Step(struct Sprite *sprite) void AnimRockBlastRock(struct Sprite *sprite) { - if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + if (!IsOnPlayerSide(gBattleAnimAttacker)) StartSpriteAffineAnim(sprite, 1); TranslateAnimSpriteToTargetMonLocation(sprite); @@ -1055,3 +1077,14 @@ const struct SpriteTemplate gSaltCureSwirlSpriteTemplate = .affineAnims = gAffineAnims_Whirlpool, .callback = AnimParticleInVortex, }; + +const struct SpriteTemplate gRockPlumeSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_FlyingRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDirtPlumeParticle, +}; diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index 87afa5ab0..ba6bffc43 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -697,7 +697,7 @@ static void OakOldManHandlePrintString(u32 battler) gBattle_BG0_X = 0; gBattle_BG0_Y = 0; stringId = (u16 *)(&gBattleResources->bufferA[battler][2]); - if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && *stringId == 1) + if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && *stringId == STRINGID_INTROSENDOUT) { OakOldManBufferExecCompleted(battler); } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 774313278..32323639e 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -456,31 +456,15 @@ static void OpponentHandleChooseMove(u32 battler) target = GetBattlerAtPosition(Random() & 2); } while (!CanTargetBattler(battler, target, move)); - // Don't bother to loop through table if the move can't attack ally + // Don't bother to check if they're enemies if the move can't attack ally if (B_WILD_NATURAL_ENEMIES == TRUE && !(GetBattlerMoveTargetType(battler, move) & MOVE_TARGET_BOTH)) { - u16 i, speciesAttacker, speciesTarget, isPartnerEnemy = FALSE; - static const u16 naturalEnemies[][2] = - { - // Attacker Target - {SPECIES_ZANGOOSE, SPECIES_SEVIPER}, - {SPECIES_SEVIPER, SPECIES_ZANGOOSE}, - {SPECIES_HEATMOR, SPECIES_DURANT}, - {SPECIES_DURANT, SPECIES_HEATMOR}, - {SPECIES_SABLEYE, SPECIES_CARBINK}, - {SPECIES_MAREANIE, SPECIES_CORSOLA}, - }; + u32 speciesAttacker, speciesTarget; speciesAttacker = gBattleMons[battler].species; speciesTarget = gBattleMons[GetBattlerAtPosition(BATTLE_PARTNER(battler))].species; - for (i = 0; i < ARRAY_COUNT(naturalEnemies); i++) - { - if (speciesAttacker == naturalEnemies[i][0] && speciesTarget == naturalEnemies[i][1]) - { - isPartnerEnemy = TRUE; - break; - } - } + bool32 isPartnerEnemy = IsNaturalEnemy(speciesAttacker, speciesTarget); + if (isPartnerEnemy && CanTargetBattler(battler, target, move)) BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (GetBattlerAtPosition(BATTLE_PARTNER(battler)) << 8)); else @@ -524,6 +508,7 @@ static void OpponentHandleChoosePokemon(u32 battler) { s32 chosenMonId; s32 pokemonInBattle = 1; + enum SwitchType switchType = SWITCH_AFTER_KO; // Choosing Revival Blessing target if (gBattleResources->bufferA[battler][1] == PARTY_ACTION_CHOOSE_FAINTED_MON) @@ -533,7 +518,9 @@ static void OpponentHandleChoosePokemon(u32 battler) // Switching out else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { - chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO); + if (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch) + switchType = SWITCH_MID_BATTLE; + chosenMonId = GetMostSuitableMonToSwitchInto(battler, switchType); if (chosenMonId == PARTY_SIZE) { s32 battler1, battler2, firstId, lastId; diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 358015767..0895f4568 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -892,7 +892,10 @@ void HandleInputChooseMove(u32 battler) } else if (JOY_NEW(START_BUTTON)) { - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler])) + if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE + && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler]) + && !(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE + && GetUsableZMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]]) == MOVE_NONE)) { gBattleStruct->gimmick.playerSelect ^= 1; ReloadMoveNames(battler); @@ -1028,7 +1031,7 @@ void HandleMoveSwitching(u32 battler) gBattleMons[battler].pp[i] = moveInfo->currentPp[i]; } - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battler].volatiles.transformed)) { for (i = 0; i < MAX_MON_MOVES; i++) { @@ -1085,10 +1088,12 @@ void HandleMoveSwitching(u32 battler) PlaySE(SE_SELECT); MoveSelectionDestroyCursorAt(gMultiUsePlayerCursor); MoveSelectionCreateCursorAt(gMoveSelectionCursor[battler], 0); + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) gBattlerControllerFuncs[battler] = OakOldManHandleInputChooseMove; else gBattlerControllerFuncs[battler] = HandleInputChooseMove; + if (B_SHOW_EFFECTIVENESS) MoveSelectionDisplayMoveEffectiveness(CheckTargetTypeEffectiveness(battler), battler); else @@ -2084,7 +2089,7 @@ static void PlayerHandleChooseAction(u32 battler) if (B_SHOW_PARTNER_TARGET && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) { StringCopy(gStringVar1, COMPOUND_STRING("Partner will use:\n")); - u32 move = gBattleMons[B_POSITION_PLAYER_RIGHT].moves[gBattleStruct->chosenMovePositions[B_POSITION_PLAYER_RIGHT]]; + u32 move = GetChosenMoveFromPosition(B_POSITION_PLAYER_RIGHT); StringAppend(gStringVar1, GetMoveName(move)); u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move); if (moveTarget == MOVE_TARGET_SELECTED) @@ -2430,7 +2435,7 @@ enum static bool32 ShouldShowTypeEffectiveness(u32 targetId) { - if (IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)) + if (IsGhostBattleWithoutScope()) return FALSE; if (B_SHOW_EFFECTIVENESS == SHOW_EFFECTIVENESS_CAUGHT) @@ -2453,8 +2458,8 @@ static u32 CheckTypeEffectiveness(u32 battlerAtk, u32 battlerDef) ctx.updateFlags = FALSE; ctx.abilityAtk = GetBattlerAbility(battlerAtk); ctx.abilityDef = GetBattlerAbility(battlerDef); - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); uq4_12_t modifier = CalcTypeEffectivenessMultiplier(&ctx); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 8503d8f25..8e91993ec 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -12,9 +12,11 @@ // #include "battle_tv.h" #include "cable_club.h" #include "event_object_movement.h" +#include "item.h" #include "link.h" #include "link_rfu.h" #include "m4a.h" +#include "overworld.h" #include "palette.h" #include "party_menu.h" #include "recorded_battle.h" @@ -26,6 +28,7 @@ #include "text.h" #include "constants/abilities.h" #include "constants/battle_string_ids.h" +#include "constants/item_effects.h" #include "constants/songs.h" #include "constants/sound.h" #include "pokemon_animation.h" @@ -1057,24 +1060,20 @@ void BtlController_EmitExpUpdate(u32 battler, u32 bufferId, u8 partyId, s32 expP PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 6); } -void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status1, u32 status2) +void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status) { gBattleResources->transferBuffer[0] = CONTROLLER_STATUSICONUPDATE; - gBattleResources->transferBuffer[1] = status1; - gBattleResources->transferBuffer[2] = (status1 & 0x0000FF00) >> 8; - gBattleResources->transferBuffer[3] = (status1 & 0x00FF0000) >> 16; - gBattleResources->transferBuffer[4] = (status1 & 0xFF000000) >> 24; - gBattleResources->transferBuffer[5] = status2; - gBattleResources->transferBuffer[6] = (status2 & 0x0000FF00) >> 8; - gBattleResources->transferBuffer[7] = (status2 & 0x00FF0000) >> 16; - gBattleResources->transferBuffer[8] = (status2 & 0xFF000000) >> 24; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 9); + gBattleResources->transferBuffer[1] = status; + gBattleResources->transferBuffer[2] = (status & 0x0000FF00) >> 8; + gBattleResources->transferBuffer[3] = (status & 0x00FF0000) >> 16; + gBattleResources->transferBuffer[4] = (status & 0xFF000000) >> 24; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 5); } -void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 status2, u32 status) +void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 isVolatile, u32 status) { gBattleResources->transferBuffer[0] = CONTROLLER_STATUSANIMATION; - gBattleResources->transferBuffer[1] = status2; + gBattleResources->transferBuffer[1] = isVolatile; gBattleResources->transferBuffer[2] = status; gBattleResources->transferBuffer[3] = (status & 0x0000FF00) >> 8; gBattleResources->transferBuffer[4] = (status & 0x00FF0000) >> 16; @@ -1399,7 +1398,7 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 * u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif break; @@ -1919,9 +1918,7 @@ void StartSendOutAnim(u32 battler, bool32 dontClearTransform, bool32 dontClearSu ClearTemporarySpeciesSpriteData(battler, dontClearTransform, dontClearSubstituteBit); gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1]; - species = GetIllusionMonSpecies(battler); - if (species == SPECIES_NONE) - species = GetMonData(mon, MON_DATA_SPECIES); + species = GetBattlerVisualSpecies(battler); gBattleControllerData[battler] = CreateInvisibleSpriteWithCallback(SpriteCB_WaitForBattlerBallReleaseAnim); // Load sprite for opponent only, player sprite is expected to be already loaded. if (!IsOnPlayerSide(battler)) @@ -2081,6 +2078,7 @@ void Controller_WaitForHealthBar(u32 battler) { if (IsOnPlayerSide(battler)) HandleLowHpMusicChange(GetBattlerMon(battler), battler); + if (GetBattlerSide(battler) == B_SIDE_OPPONENT && !BtlCtrl_OakOldMan_TestState2Flag(1) && (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)) { BtlCtrl_OakOldMan_SetState2Flag(1); @@ -2266,11 +2264,11 @@ void BtlController_HandleLoadMonSprite(u32 battler) { u32 y; struct Pokemon *mon = GetBattlerMon(battler); - u16 species = GetMonData(mon, MON_DATA_SPECIES); + u16 species = GetBattlerVisualSpecies(battler); if (gBattleTypeFlags & BATTLE_TYPE_GHOST && GetBattlerSide(battler) == B_SIDE_OPPONENT) { - DecompressGhostFrontPic(mon, battler); + DecompressGhostFrontPic(battler); y = GetGhostSpriteDefault_Y(battler); gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = TRUE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = TRUE; @@ -2296,9 +2294,7 @@ void BtlController_HandleLoadMonSprite(u32 battler) if (!(gBattleTypeFlags & BATTLE_TYPE_GHOST)) SetBattlerShadowSpriteCallback(battler, species); - if (IsControllerOpponent(battler) - && IsControllerLinkOpponent(battler) - && IsControllerRecordedOpponent(battler)) + if (IsControllerOpponent(battler) || IsControllerLinkOpponent(battler) || IsControllerRecordedOpponent(battler)) gBattlerControllerFuncs[battler] = TryShinyAnimAfterMonAnim; else if (IsControllerPokedude(battler)) gBattlerControllerFuncs[battler] = CompleteOnBattlerSpritePosX_0; @@ -2314,7 +2310,7 @@ void BtlController_HandleSwitchInAnim(u32 battler) || IsControllerLinkPartner(battler) || (IsControllerPokedude(battler) && GetBattlerSide(battler) == B_SIDE_PLAYER)); - if (IsControllerPlayer(battler) || IsControllerPokedude(battler)) + if (IsControllerPlayer(battler)) { gActionSelectionCursor[battler] = 0; gMoveSelectionCursor[battler] = 0; @@ -2566,7 +2562,7 @@ void BtlController_HandlePrintString(u32 battler) BattlePutTextOnWindow(gDisplayedStringBattle, (B_WIN_MSG | B_TEXT_FLAG_NPC_CONTEXT_FONT)); else BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MSG); - + if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE && GetBattlerSide(battler) == B_SIDE_OPPONENT) { switch (*stringId) @@ -2579,6 +2575,7 @@ void BtlController_HandlePrintString(u32 battler) return; } } + gBattlerControllerFuncs[battler] = Controller_WaitForString; } @@ -2936,6 +2933,15 @@ void BtlController_HandleBattleAnimation(u32 battler) } } +void AnimateMonAfterPokeBallFail(u32 battler) +{ + if (B_ANIMATE_MON_AFTER_FAILED_POKEBALL == FALSE) + return; + + LaunchKOAnimation(battler, ReturnAnimIdForBattler(TRUE, battler), TRUE); + TryShinyAnimation(gBattlerTarget, GetBattlerMon(gBattlerTarget)); +} + static void AnimateMonAfterKnockout(u32 battler) { if (B_ANIMATE_MON_AFTER_KO == FALSE) @@ -2957,6 +2963,8 @@ static void LaunchKOAnimation(u32 battlerId, u16 animId, bool32 isFront) u32 species = GetBattlerVisualSpecies(battlerId); u32 spriteId = gBattlerSpriteIds[battlerId]; + gBattleStruct->battlerKOAnimsRunning++; + if (isFront) { LaunchAnimationTaskForFrontSprite(&gSprites[spriteId], animId); @@ -2986,19 +2994,19 @@ void TrySetBattlerShadowSpriteCallback(u32 battler) if (gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary].callback == SpriteCallbackDummy && (B_ENEMY_MON_SHADOW_STYLE <= GEN_3 || P_GBA_STYLE_SPECIES_GFX == TRUE || gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdSecondary].callback == SpriteCallbackDummy)) - SetBattlerShadowSpriteCallback(battler, GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)); + SetBattlerShadowSpriteCallback(battler, GetBattlerVisualSpecies(battler)); } void TryShinyAnimAfterMonAnim(u32 battler) { - if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy - && gSprites[gBattlerSpriteIds[battler]].x2 == 0) + if (gSprites[gBattlerSpriteIds[battler]].x2 == 0) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) { TryShinyAnimation(battler, GetBattlerMon(battler)); } - else if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) + + if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; @@ -3143,3 +3151,51 @@ void BtlController_HandleSwitchInTryShinyAnim(u32 battler) } } } + +void UpdateFriendshipFromXItem(u32 battler) +{ + struct Pokemon *party = GetBattlerParty(battler); + + u8 friendship; + gBattleResources->bufferA[battler][1] = REQUEST_FRIENDSHIP_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &friendship); + + u16 heldItem; + gBattleResources->bufferA[battler][1] = REQUEST_HELDITEM_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], (u8*)&heldItem); + + if (friendship < X_ITEM_MAX_FRIENDSHIP) + { + if (GetItemHoldEffect(heldItem) == HOLD_EFFECT_FRIENDSHIP_UP) + friendship += 150 * X_ITEM_FRIENDSHIP_INCREASE / 100; + else + friendship += X_ITEM_FRIENDSHIP_INCREASE; + + u8 pokeball; + gBattleResources->bufferA[battler][1] = REQUEST_POKEBALL_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &pokeball); + + if (pokeball == BALL_LUXURY) + friendship++; + + u8 metLocation; + gBattleResources->bufferA[battler][1] = REQUEST_MET_LOCATION_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &metLocation); + + if (metLocation == GetCurrentRegionMapSectionId()) + friendship++; + + if (friendship > MAX_FRIENDSHIP) + friendship = MAX_FRIENDSHIP; + + gBattleMons[battler].friendship = friendship; + gBattleResources->bufferA[battler][3] = friendship; + gBattleResources->bufferA[battler][1] = REQUEST_FRIENDSHIP_BATTLE; + SetBattlerMonData(battler, GetBattlerParty(battler), gBattlerPartyIndexes[battler]); + } +} + +bool32 ShouldBattleRestrictionsApply(u32 battler) +{ + return IsControllerPlayer(battler); +} diff --git a/src/battle_debug.c b/src/battle_debug.c index 523ebd959..5c2e0735a 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -104,15 +104,15 @@ enum LIST_ITEM_STATS, LIST_ITEM_STAT_STAGES, LIST_ITEM_STATUS1, - LIST_ITEM_STATUS2, - LIST_ITEM_STATUS3, - LIST_ITEM_STATUS4, + LIST_ITEM_VOLATILE, + LIST_ITEM_HAZARDS, LIST_ITEM_SIDE_STATUS, LIST_ITEM_AI, LIST_ITEM_AI_MOVES_PTS, LIST_ITEM_AI_INFO, LIST_ITEM_AI_PARTY, LIST_ITEM_VARIOUS, + LIST_ITEM_INSTANT_WIN, LIST_ITEM_COUNT }; @@ -141,72 +141,22 @@ enum enum { - LIST_STATUS2_CONFUSION, - LIST_STATUS2_FLINCHED, - LIST_STATUS2_TORMENT, - LIST_STATUS2_POWDER, - LIST_STATUS2_DEFENSE_CURL, - LIST_STATUS2_RECHARGE, - LIST_STATUS2_RAGE, - LIST_STATUS2_DESTINY_BOND, - LIST_STATUS2_ESCAPE_PREVENTION, - LIST_STATUS2_CURSED, - LIST_STATUS2_FORESIGHT, - LIST_STATUS2_DRAGON_CHEER, - LIST_STATUS2_FOCUS_ENERGY -}; - -enum -{ - LIST_STATUS3_LEECH_SEED_HEALER, - LIST_STATUS3_LEECH_SEEDED, - LIST_STATUS3_ALWAYS_HITS, - LIST_STATUS3_PERISH_SONG, - LIST_STATUS3_ON_AIR, - LIST_STATUS3_UNDERGROUND, - LIST_STATUS3_MINIMIZED, - LIST_STATUS3_CHARGED_UP, - LIST_STATUS3_ROOTED, - LIST_STATUS3_YAWN, - LIST_STATUS3_IMPRISONED_OTHERS, - LIST_STATUS3_GRUDGE, - LIST_STATUS3_GASTRO_ACID, - LIST_STATUS3_EMBARGO, - LIST_STATUS3_UNDERWATER, - LIST_STATUS3_SMACKED_DOWN, - LIST_STATUS3_TELEKINESIS, - LIST_STATUS3_MIRACLE_EYED, - LIST_STATUS3_MAGNET_RISE, - LIST_STATUS3_HEAL_BLOCK, - LIST_STATUS3_AQUA_RING, - LIST_STATUS3_LASER_FOCUS, - LIST_STATUS3_POWER_TRICK, -}; - -enum -{ - LIST_STATUS4_ELECTRIFIED, - LIST_STATUS4_MUD_SPORT, - LIST_STATUS4_WATER_SPORT, - LIST_STATUS4_SALT_CURE, - LIST_STATUS4_SYRUP_BOMB, - LIST_STATUS4_GLAIVE_RUSH, + LIST_SIDE_STICKY_WEB, + LIST_SIDE_SPIKES, + LIST_SIDE_TOXIC_SPIKES, + LIST_SIDE_STEALTH_ROCK, + LIST_SIDE_STEELSURGE, }; enum { LIST_SIDE_REFLECT, LIST_SIDE_LIGHTSCREEN, - LIST_SIDE_STICKY_WEB, - LIST_SIDE_SPIKES, LIST_SIDE_SAFEGUARD, LIST_SIDE_MIST, LIST_SIDE_TAILWIND, LIST_SIDE_AURORA_VEIL, LIST_SIDE_LUCKY_CHANT, - LIST_SIDE_TOXIC_SPIKES, - LIST_SIDE_STEALTH_ROCK, - LIST_SIDE_STEELSURGE, LIST_SIDE_DAMAGE_NON_TYPES, LIST_SIDE_RAINBOW, LIST_SIDE_SEA_OF_FIRE, @@ -268,6 +218,8 @@ enum VAL_BITFIELD_8, VAL_BITFIELD_16, VAL_BITFIELD_32, + VAL_VOLATILE, + VAL_HAZARDS, VAR_SIDE_STATUS, VAR_SHOW_HP, VAR_SUBSTITUTE, @@ -281,147 +233,10 @@ enum static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect); // const rom data -static const u8 sText_Moves[] = _("Moves"); static const u8 sText_Ability[] = _("Ability"); static const u8 sText_HeldItem[] = _("Held Item"); static const u8 sText_HoldEffect[] = _("Hold Effect"); -static const u8 sText_PP[] = _("PP"); -static const u8 sText_Types[] = _("Types"); -static const u8 sText_Stats[] = _("Stats"); -static const u8 sText_StatStages[] = _("Stat Stages"); -static const u8 sText_Status1[] = _("Status1"); -static const u8 sText_Status2[] = _("Status2"); -static const u8 sText_Status3[] = _("Status3"); -static const u8 sText_Status4[] = _("Status4"); -static const u8 sText_SideStatus[] = _("Side Status"); -static const u8 sText_AI[] = _("AI"); -static const u8 sText_AIMovePts[] = _("AI Pts/Dmg"); -static const u8 sText_AiKnowledge[] = _("AI Info"); -static const u8 sText_AiParty[] = _("AI Party"); -static const u8 sText_Various[] = _("Various"); -static const u8 sText_CurrHp[] = _("HP Current"); -static const u8 sText_MaxHp[] = _("HP Max"); -static const u8 sText_Attack[] = _("Attack"); -static const u8 sText_Defense[] = _("Defense"); -static const u8 sText_Speed[] = _("Speed"); -static const u8 sText_SpAtk[] = _("Sp. Atk"); -static const u8 sText_SpDef[] = _("Sp. Def"); -static const u8 sText_Sleep[] = _("Sleep"); -static const u8 sText_Poison[] = _("Poison"); -static const u8 sText_Burn[] = _("Burn"); -static const u8 sText_Freeze[] = _("Freeze"); -static const u8 sText_Paralysis[] = _("Paralysis"); -static const u8 sText_ToxicPoison[] = _("Toxic Poison"); -static const u8 sText_ToxicCounter[] = _("Toxic Counter"); -static const u8 sText_Frostbite[] = _("Frostbite"); -static const u8 sText_Confusion[] = _("Confusion"); -static const u8 sText_Flinched[] = _("Flinched"); -static const u8 sText_Uproar[] = _("Uproar"); -static const u8 sText_Torment[] = _("Torment"); -static const u8 sText_Bide[] = _("Bide"); -static const u8 sText_LockConfuse[] = _("Lock Confuse"); -static const u8 sText_MultipleTurns[] = _("Multiple Turns"); -static const u8 sText_Wrapped[] = _("Wrapped"); -static const u8 sText_Powder[] = _("Powder"); -static const u8 sText_Infatuation[] = _("Infatuation"); -static const u8 sText_DefenseCurl[] = _("Defense Curl"); -static const u8 sText_Transformed[] = _("Transformed"); -static const u8 sText_Recharge[] = _("Recharge"); -static const u8 sText_Rage[] = _("Rage"); -static const u8 sText_Substitute[] = _("Substitute"); -static const u8 sText_DestinyBond[] = _("Destiny Bond"); -static const u8 sText_EscapePrevention[] = _("Escape Prevention"); -static const u8 sText_Nightmare[] = _("Nightmare"); -static const u8 sText_Cursed[] = _("Cursed"); -static const u8 sText_Foresight[] = _("Foresight"); -static const u8 sText_DragonCheer[] = _("Dragon Cheer"); -static const u8 sText_FocusEnergy[] = _("Focus Energy"); -static const u8 sText_LeechSeedHealer[] = _("Leech Seed Healer"); -static const u8 sText_LeechSeeded[] = _("Leech Seeded"); -static const u8 sText_AlwaysHits[] = _("Always Hits"); -static const u8 sText_PerishSong[] = _("Perish Song"); -static const u8 sText_OnAir[] = _("On Air"); -static const u8 sText_Underground[] = _("Underground"); -static const u8 sText_Minimized[] = _("Minimized"); -static const u8 sText_ChargedUp[] = _("Charged Up"); -static const u8 sText_Rooted[] = _("Rooted"); -static const u8 sText_Yawn[] = _("Yawn"); -static const u8 sText_ImprisonedOthers[] = _("Imprisoned Others"); -static const u8 sText_Grudge[] = _("Grudge"); -static const u8 sText_GastroAcid[] = _("Gastro Acid"); -static const u8 sText_Embargo[] = _("Embargo"); -static const u8 sText_Underwater[] = _("Underwater"); -static const u8 sText_Trace[] = _("Trace"); -static const u8 sText_SmackedDown[] = _("Smacked Down"); -static const u8 sText_MeFirst[] = _("Me First"); -static const u8 sText_Telekinesis[] = _("Telekinesis"); -static const u8 sText_PhantomForce[] = _("Phantom Force"); -static const u8 sText_MiracleEyed[] = _("Miracle Eyed"); -static const u8 sText_MagnetRise[] = _("Magnet Rise"); -static const u8 sText_HealBlock[] = _("Heal Block"); -static const u8 sText_AquaRing[] = _("Aqua Ring"); -static const u8 sText_LaserFocus[] = _("Laser Focus"); -static const u8 sText_PowerTrick[] = _("Power Trick"); -static const u8 sText_SkyDropped[] = _("Sky Dropped"); -static const u8 sText_Electrified[] = _("Electrified"); -static const u8 sText_MudSport[] = _("Mud Sport"); -static const u8 sText_WaterSport[] = _("Water Sport"); -static const u8 sText_InfiniteConfusion[] = _("Infinite Confusion"); -static const u8 sText_SaltCure[] = _("Salt Cure"); -static const u8 sText_SyrupBomb[] = _("Syrup Bomb"); -static const u8 sText_GlaiveRush[] = _("Glaive Rush"); -static const u8 sText_Reflect[] = _("Reflect"); -static const u8 sText_LightScreen[] = _("Light Screen"); -static const u8 sText_StickyWeb[] = _("Sticky Web"); -static const u8 sText_Spikes[] = _("Spikes"); -static const u8 sText_Safeguard[] = _("Safeguard"); -static const u8 sText_FutureAttack[] = _("Future Attack"); -static const u8 sText_Mist[] = _("Mist"); -static const u8 sText_Tailwind[] = _("Tailwind"); -static const u8 sText_AuroraVeil[] = _("Aurora Veil"); -static const u8 sText_LuckyChant[] = _("Lucky Chant"); -static const u8 sText_ToxicSpikes[] = _("Toxic Spikes"); -static const u8 sText_StealthRock[] = _("Stealth Rock"); -static const u8 sText_Steelsurge[] = _("Steelsurge"); -static const u8 sText_DamageNonTypes[] = _("Damage Non-Types"); -static const u8 sText_Rainbow[] = _("Rainbow"); -static const u8 sText_SeaOfFire[] = _("Sea of Fire"); -static const u8 sText_Swamp[] = _("Swamp"); -static const u8 sText_CheckBadMove[] = _("Check Bad Move"); -static const u8 sText_TryToFaint[] = _("Try to Faint"); -static const u8 sText_CheckViability[] = _("Check Viability"); -static const u8 sText_ForceSetupFirstTurn[] = _("Force Setup First Turn"); -static const u8 sText_Risky[] = _("Risky"); -static const u8 sText_TryTo2HKO[] = _("Try to 2HKO"); -static const u8 sText_PreferBatonPass[] = _("Prefer Baton Pass"); -static const u8 sText_DoubleBattle[] = _("Double Battle"); -static const u8 sText_HpAware[] = _("HP Aware"); -static const u8 sText_PowerfulStatus[] = _("Powerful Status"); -static const u8 sText_NegateUnaware[] = _("Negate Unaware"); -static const u8 sText_WillSuicide[] = _("Will Suicide"); -static const u8 sText_PreferStatusMoves[] = _("Prefer Status Moves"); -static const u8 sText_Stall[] = _("Stall"); -static const u8 sText_SmartSwitching[] = _("Smart Switching"); -static const u8 sText_AcePokemon[] = _("Ace Pokémon"); -static const u8 sText_Omniscient[] = _("Omniscient"); -static const u8 sText_SmartMonChoices[] = _("Smart Mon Choices"); -static const u8 sText_Conservative[] = _("Conservative"); -static const u8 sText_SequenceSwitching[] = _("Sequence Switching"); -static const u8 sText_DoubleAcePokemon[] = _("Double Ace Pokémon"); -static const u8 sText_WeighAbilityPrediction[] = _("Weigh Ability Prediction"); -static const u8 sText_PreferHighestDamageMove[] = _("Prefer Highest Damage Move"); -static const u8 sText_PredictSwitch[] = _("Predict Switch"); -static const u8 sText_PredictIncomingMon[] = _("Predict Incoming Mon"); -static const u8 sText_DynamicFunc[] = _("Dynamic Func"); -static const u8 sText_Roaming[] = _("Roaming"); -static const u8 sText_Safari[] = _("Safari"); -static const u8 sText_FirstBattle[] = _("First Battle"); -static const u8 sText_ShowHP[] = _("Show HP"); -static const u8 sText_SubstituteHp[] = _("Substitute HP"); -static const u8 sText_InLove[] = _("In Love"); -static const u8 sText_Unknown[] = _("Unknown"); static const u8 sText_EmptyString[] = _(""); -static const u8 sText_IsSwitching[] = _("Switching to "); static const struct BitfieldInfo sStatus1Bitfield[] = { @@ -435,23 +250,6 @@ static const struct BitfieldInfo sStatus1Bitfield[] = {/*Frostbite*/ 1, 12}, }; -static const struct BitfieldInfo sStatus2Bitfield[] = -{ - {/*Confusion*/ 3, 0}, - {/*Flinched*/ 1, 3}, - {/*Torment*/ 1, 7}, - {/*Powder*/ 1, 14}, - {/*Defense Curl*/ 1, 20}, - {/*Recharge*/ 1, 22}, - {/*Rage*/ 1, 23}, - {/*Destiny Bond*/ 1, 25}, - {/*Escape Prevention*/ 1, 26}, - {/*Cursed*/ 1, 28}, - {/*Foresight*/ 1, 29}, - {/*Dragon Cheer*/ 1, 30}, - {/*Focus Energy*/ 1, 31}, -}; - static const struct BitfieldInfo sStatus3Bitfield[] = { {/*Leech Seed Battler*/ 2, 0}, @@ -479,16 +277,6 @@ static const struct BitfieldInfo sStatus3Bitfield[] = {/*Power Trick*/ 1, 30}, }; -static const struct BitfieldInfo sStatus4Bitfield[] = -{ - {/*Electrified*/ 1, 0}, - {/*Mud Sport*/ 1, 1}, - {/*Water Sport*/ 1, 2}, - {/*Salt Cure*/ 1, 4}, - {/*Syrup Bomb*/ 1, 5}, - {/*Glaive Rush*/ 1, 6}, -}; - static const struct BitfieldInfo sAIBitfield[] = { {/*Check Bad Move*/ 1, 0}, @@ -524,160 +312,153 @@ static const struct BitfieldInfo sAIBitfield[] = static const struct ListMenuItem sMainListItems[] = { - {sText_Moves, LIST_ITEM_MOVES}, - {sText_Ability, LIST_ITEM_ABILITY}, - {sText_HeldItem, LIST_ITEM_HELD_ITEM}, - {sText_PP, LIST_ITEM_PP}, - {sText_Types, LIST_ITEM_TYPES}, - {sText_Stats, LIST_ITEM_STATS}, - {sText_StatStages, LIST_ITEM_STAT_STAGES}, - {sText_Status1, LIST_ITEM_STATUS1}, - {sText_Status2, LIST_ITEM_STATUS2}, - {sText_Status3, LIST_ITEM_STATUS3}, - {sText_Status4, LIST_ITEM_STATUS4}, - {sText_SideStatus, LIST_ITEM_SIDE_STATUS}, - {sText_AI, LIST_ITEM_AI}, - {sText_AIMovePts, LIST_ITEM_AI_MOVES_PTS}, - {sText_AiKnowledge, LIST_ITEM_AI_INFO}, - {sText_AiParty, LIST_ITEM_AI_PARTY}, - {sText_Various, LIST_ITEM_VARIOUS}, + {COMPOUND_STRING("Moves"), LIST_ITEM_MOVES}, + {sText_Ability, LIST_ITEM_ABILITY}, + {sText_HeldItem, LIST_ITEM_HELD_ITEM}, + {COMPOUND_STRING("PP"), LIST_ITEM_PP}, + {COMPOUND_STRING("Types"), LIST_ITEM_TYPES}, + {COMPOUND_STRING("Stats"), LIST_ITEM_STATS}, + {COMPOUND_STRING("Stat Stages"), LIST_ITEM_STAT_STAGES}, + {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, + {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, + {COMPOUND_STRING("Hazards"), LIST_ITEM_HAZARDS}, + {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, + {COMPOUND_STRING("AI"), LIST_ITEM_AI}, + {COMPOUND_STRING("AI Pts/Dmg"), LIST_ITEM_AI_MOVES_PTS}, + {COMPOUND_STRING("AI Info"), LIST_ITEM_AI_INFO}, + {COMPOUND_STRING("AI Party"), LIST_ITEM_AI_PARTY}, + {COMPOUND_STRING("Various"), LIST_ITEM_VARIOUS}, + {COMPOUND_STRING("Instant Win"), LIST_ITEM_INSTANT_WIN}, }; static const struct ListMenuItem sStatsListItems[] = { - {sText_CurrHp, LIST_STAT_HP_CURRENT}, - {sText_MaxHp, LIST_STAT_HP_MAX}, - {sText_Attack, LIST_STAT_ATTACK}, - {sText_Defense, LIST_STAT_DEFENSE}, - {sText_Speed, LIST_STAT_SPEED}, - {sText_SpAtk, LIST_STAT_SP_ATK}, - {sText_SpDef, LIST_STAT_SP_DEF}, + {COMPOUND_STRING("HP Current"), LIST_STAT_HP_CURRENT}, + {COMPOUND_STRING("HP Max"), LIST_STAT_HP_MAX}, + {COMPOUND_STRING("Attack"), LIST_STAT_ATTACK}, + {COMPOUND_STRING("Defense"), LIST_STAT_DEFENSE}, + {COMPOUND_STRING("Speed"), LIST_STAT_SPEED}, + {COMPOUND_STRING("Sp. Atk"), LIST_STAT_SP_ATK}, + {COMPOUND_STRING("Sp. Def"), LIST_STAT_SP_DEF}, }; static const struct ListMenuItem sStatus1ListItems[] = { - {sText_Sleep, LIST_STATUS1_SLEEP}, - {sText_Poison, LIST_STATUS1_POISON}, - {sText_Burn, LIST_STATUS1_BURN}, - {sText_Freeze, LIST_STATUS1_FREEZE}, - {sText_Paralysis, LIST_STATUS1_PARALYSIS}, - {sText_ToxicPoison, LIST_STATUS1_TOXIC_POISON}, - {sText_ToxicCounter, LIST_STATUS1_TOXIC_COUNTER}, - {sText_Frostbite, LIST_STATUS1_FROSTBITE}, + {COMPOUND_STRING("Sleep"), LIST_STATUS1_SLEEP}, + {COMPOUND_STRING("Poison"), LIST_STATUS1_POISON}, + {COMPOUND_STRING("Burn"), LIST_STATUS1_BURN}, + {COMPOUND_STRING("Freeze"), LIST_STATUS1_FREEZE}, + {COMPOUND_STRING("Paralysis"), LIST_STATUS1_PARALYSIS}, + {COMPOUND_STRING("Toxic Poison"), LIST_STATUS1_TOXIC_POISON}, + {COMPOUND_STRING("Toxic Counter"), LIST_STATUS1_TOXIC_COUNTER}, + {COMPOUND_STRING("Frostbite"), LIST_STATUS1_FROSTBITE}, }; -static const struct ListMenuItem sStatus2ListItems[] = +static const struct ListMenuItem sVolatileStatusListItems[] = { - {sText_Confusion, LIST_STATUS2_CONFUSION}, - {sText_Flinched, LIST_STATUS2_FLINCHED}, - {sText_Torment, LIST_STATUS2_TORMENT}, - {sText_Powder, LIST_STATUS2_POWDER}, - {sText_DefenseCurl, LIST_STATUS2_DEFENSE_CURL}, - {sText_Recharge, LIST_STATUS2_RECHARGE}, - {sText_Rage, LIST_STATUS2_RAGE}, - {sText_DestinyBond, LIST_STATUS2_DESTINY_BOND}, - {sText_EscapePrevention, LIST_STATUS2_ESCAPE_PREVENTION}, - {sText_Cursed, LIST_STATUS2_CURSED}, - {sText_Foresight, LIST_STATUS2_FORESIGHT}, - {sText_DragonCheer, LIST_STATUS2_DRAGON_CHEER}, - {sText_FocusEnergy, LIST_STATUS2_FOCUS_ENERGY}, + {COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION}, + {COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED}, + {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, + {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, + {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, + {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, + {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, + {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, + {COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION}, + {COMPOUND_STRING("Cursed"), VOLATILE_CURSED}, + {COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT}, + {COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER}, + {COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY}, + {COMPOUND_STRING("Electrified"), VOLATILE_ELECTRIFIED}, + {COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT}, + {COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT}, + {COMPOUND_STRING("Infinite Confusion"), VOLATILE_INFINITE_CONFUSION}, + {COMPOUND_STRING("Salt Cure"), VOLATILE_SALT_CURE}, + {COMPOUND_STRING("Syrup Bomb"), VOLATILE_SYRUP_BOMB}, + {COMPOUND_STRING("Glaive Rush"), VOLATILE_GLAIVE_RUSH}, + {COMPOUND_STRING("Leech Seed"), VOLATILE_LEECH_SEED}, + {COMPOUND_STRING("Lock On"), VOLATILE_LOCK_ON}, + {COMPOUND_STRING("Perish Song"), VOLATILE_PERISH_SONG}, + {COMPOUND_STRING("Minimize"), VOLATILE_MINIMIZE}, + {COMPOUND_STRING("Charge"), VOLATILE_CHARGE}, + {COMPOUND_STRING("Root"), VOLATILE_ROOT}, + {COMPOUND_STRING("Yawn"), VOLATILE_YAWN}, + {COMPOUND_STRING("Imprison"), VOLATILE_IMPRISON}, + {COMPOUND_STRING("Grudge"), VOLATILE_GRUDGE}, + {COMPOUND_STRING("Gastro Acid"), VOLATILE_GASTRO_ACID}, + {COMPOUND_STRING("Embargo"), VOLATILE_EMBARGO}, + {COMPOUND_STRING("Smack Down"), VOLATILE_SMACK_DOWN}, + {COMPOUND_STRING("Telekinesis"), VOLATILE_TELEKINESIS}, + {COMPOUND_STRING("Miracle Eye"), VOLATILE_MIRACLE_EYE}, + {COMPOUND_STRING("Magnet Rise"), VOLATILE_MAGNET_RISE}, + {COMPOUND_STRING("Heal Block"), VOLATILE_HEAL_BLOCK}, + {COMPOUND_STRING("Aqua Ring"), VOLATILE_AQUA_RING}, + {COMPOUND_STRING("Laser Focus"), VOLATILE_LASER_FOCUS}, + {COMPOUND_STRING("Power Trick"), VOLATILE_POWER_TRICK}, }; -static const struct ListMenuItem sStatus3ListItems[] = +static const struct ListMenuItem sHazardsListItems[] = { - {sText_LeechSeedHealer, LIST_STATUS3_LEECH_SEED_HEALER}, - {sText_LeechSeeded, LIST_STATUS3_LEECH_SEEDED}, - {sText_AlwaysHits, LIST_STATUS3_ALWAYS_HITS}, - {sText_PerishSong, LIST_STATUS3_PERISH_SONG}, - {sText_OnAir, LIST_STATUS3_ON_AIR}, - {sText_Underground, LIST_STATUS3_UNDERGROUND}, - {sText_Minimized, LIST_STATUS3_MINIMIZED}, - {sText_ChargedUp, LIST_STATUS3_CHARGED_UP}, - {sText_Rooted, LIST_STATUS3_ROOTED}, - {sText_Yawn, LIST_STATUS3_YAWN}, - {sText_ImprisonedOthers, LIST_STATUS3_IMPRISONED_OTHERS}, - {sText_Grudge, LIST_STATUS3_GRUDGE}, - {sText_GastroAcid, LIST_STATUS3_GASTRO_ACID}, - {sText_Embargo, LIST_STATUS3_EMBARGO}, - {sText_Underwater, LIST_STATUS3_UNDERWATER}, - {sText_SmackedDown, LIST_STATUS3_SMACKED_DOWN}, - {sText_Telekinesis, LIST_STATUS3_TELEKINESIS}, - {sText_MiracleEyed, LIST_STATUS3_MIRACLE_EYED}, - {sText_MagnetRise, LIST_STATUS3_MAGNET_RISE}, - {sText_HealBlock, LIST_STATUS3_HEAL_BLOCK}, - {sText_AquaRing, LIST_STATUS3_AQUA_RING}, - {sText_LaserFocus, LIST_STATUS3_LASER_FOCUS}, - {sText_PowerTrick, LIST_STATUS3_POWER_TRICK}, -}; - -static const struct ListMenuItem sStatus4ListItems[] = -{ - {sText_Electrified, LIST_STATUS4_ELECTRIFIED}, - {sText_MudSport, LIST_STATUS4_MUD_SPORT}, - {sText_WaterSport, LIST_STATUS4_WATER_SPORT}, - {sText_SaltCure, LIST_STATUS4_SALT_CURE}, - {sText_SyrupBomb, LIST_STATUS4_SYRUP_BOMB}, - {sText_GlaiveRush, LIST_STATUS4_GLAIVE_RUSH}, + {COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES}, + {COMPOUND_STRING("Sticky Web"), LIST_SIDE_STICKY_WEB}, + {COMPOUND_STRING("Toxic Spikes"), LIST_SIDE_TOXIC_SPIKES}, + {COMPOUND_STRING("Stealth Rock"), LIST_SIDE_STEALTH_ROCK}, + {COMPOUND_STRING("Steelsurge"), LIST_SIDE_STEELSURGE}, }; static const struct ListMenuItem sSideStatusListItems[] = { - {sText_Reflect, LIST_SIDE_REFLECT}, - {sText_LightScreen, LIST_SIDE_LIGHTSCREEN}, - {sText_StickyWeb, LIST_SIDE_STICKY_WEB}, - {sText_Spikes, LIST_SIDE_SPIKES}, - {sText_Safeguard, LIST_SIDE_SAFEGUARD}, - {sText_Mist, LIST_SIDE_MIST}, - {sText_Tailwind, LIST_SIDE_TAILWIND}, - {sText_AuroraVeil, LIST_SIDE_AURORA_VEIL}, - {sText_LuckyChant, LIST_SIDE_LUCKY_CHANT}, - {sText_ToxicSpikes, LIST_SIDE_TOXIC_SPIKES}, - {sText_StealthRock, LIST_SIDE_STEALTH_ROCK}, - {sText_Steelsurge, LIST_SIDE_STEELSURGE}, - {sText_DamageNonTypes, LIST_SIDE_DAMAGE_NON_TYPES}, - {sText_Rainbow, LIST_SIDE_RAINBOW}, - {sText_SeaOfFire, LIST_SIDE_SEA_OF_FIRE}, - {sText_Swamp, LIST_SIDE_SWAMP}, + {COMPOUND_STRING("Reflect"), LIST_SIDE_REFLECT}, + {COMPOUND_STRING("Light Screen"), LIST_SIDE_LIGHTSCREEN}, + {COMPOUND_STRING("Safeguard"), LIST_SIDE_SAFEGUARD}, + {COMPOUND_STRING("Mist"), LIST_SIDE_MIST}, + {COMPOUND_STRING("Tailwind"), LIST_SIDE_TAILWIND}, + {COMPOUND_STRING("Aurora Veil"), LIST_SIDE_AURORA_VEIL}, + {COMPOUND_STRING("Lucky Chant"), LIST_SIDE_LUCKY_CHANT}, + {COMPOUND_STRING("Damage Non-Types"), LIST_SIDE_DAMAGE_NON_TYPES}, + {COMPOUND_STRING("Rainbow"), LIST_SIDE_RAINBOW}, + {COMPOUND_STRING("Sea of Fire"), LIST_SIDE_SEA_OF_FIRE}, + {COMPOUND_STRING("Swamp"), LIST_SIDE_SWAMP}, }; static const struct ListMenuItem sAIListItems[] = { - {sText_CheckBadMove, LIST_AI_CHECK_BAD_MOVE}, - {sText_TryToFaint, LIST_AI_TRY_TO_FAINT}, - {sText_CheckViability, LIST_AI_CHECK_VIABILITY}, - {sText_ForceSetupFirstTurn, LIST_AI_FORCE_SETUP_FIRST_TURN}, - {sText_Risky, LIST_AI_RISKY}, - {sText_TryTo2HKO, LIST_AI_TRY_TO_2HKO}, - {sText_PreferBatonPass, LIST_AI_PREFER_BATON_PASS}, - {sText_DoubleBattle, LIST_AI_DOUBLE_BATTLE}, - {sText_HpAware, LIST_AI_HP_AWARE}, - {sText_PowerfulStatus, LIST_AI_POWERFUL_STATUS}, - {sText_NegateUnaware, LIST_AI_NEGATE_UNAWARE}, - {sText_WillSuicide, LIST_AI_WILL_SUICIDE}, - {sText_PreferStatusMoves, LIST_AI_PREFER_STATUS_MOVES}, - {sText_Stall, LIST_AI_STALL}, - {sText_SmartSwitching, LIST_AI_SMART_SWITCHING}, - {sText_AcePokemon, LIST_AI_ACE_POKEMON}, - {sText_Omniscient, LIST_AI_OMNISCIENT}, - {sText_SmartMonChoices, LIST_AI_SMART_MON_CHOICES}, - {sText_Conservative, LIST_AI_CONSERVATIVE}, - {sText_SequenceSwitching, LIST_AI_SEQUENCE_SWITCHING}, - {sText_DoubleAcePokemon, LIST_AI_DOUBLE_ACE_POKEMON}, - {sText_WeighAbilityPrediction, LIST_AI_WEIGH_ABILITY_PREDICTION}, - {sText_PreferHighestDamageMove, LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE}, - {sText_PredictSwitch, LIST_AI_PREDICT_SWITCH}, - {sText_PredictIncomingMon, LIST_AI_PREDICT_INCOMING_MON}, - {sText_DynamicFunc, LIST_AI_DYNAMIC_FUNC}, - {sText_Roaming, LIST_AI_ROAMING}, - {sText_Safari, LIST_AI_SAFARI}, - {sText_FirstBattle, LIST_AI_FIRST_BATTLE}, + {COMPOUND_STRING("Check Bad Move"), LIST_AI_CHECK_BAD_MOVE}, + {COMPOUND_STRING("Try to Faint"), LIST_AI_TRY_TO_FAINT}, + {COMPOUND_STRING("Check Viability"), LIST_AI_CHECK_VIABILITY}, + {COMPOUND_STRING("Force Setup First Turn"), LIST_AI_FORCE_SETUP_FIRST_TURN}, + {COMPOUND_STRING("Risky"), LIST_AI_RISKY}, + {COMPOUND_STRING("Try to 2HKO"), LIST_AI_TRY_TO_2HKO}, + {COMPOUND_STRING("Prefer Baton Pass"), LIST_AI_PREFER_BATON_PASS}, + {COMPOUND_STRING("Double Battle"), LIST_AI_DOUBLE_BATTLE}, + {COMPOUND_STRING("HP Aware"), LIST_AI_HP_AWARE}, + {COMPOUND_STRING("Powerful Status"), LIST_AI_POWERFUL_STATUS}, + {COMPOUND_STRING("Negate Unaware"), LIST_AI_NEGATE_UNAWARE}, + {COMPOUND_STRING("Will Suicide"), LIST_AI_WILL_SUICIDE}, + {COMPOUND_STRING("Prefer Status Moves"), LIST_AI_PREFER_STATUS_MOVES}, + {COMPOUND_STRING("Stall"), LIST_AI_STALL}, + {COMPOUND_STRING("Smart Switching"), LIST_AI_SMART_SWITCHING}, + {COMPOUND_STRING("Ace Pokémon"), LIST_AI_ACE_POKEMON}, + {COMPOUND_STRING("Omniscient"), LIST_AI_OMNISCIENT}, + {COMPOUND_STRING("Smart Mon Choices"), LIST_AI_SMART_MON_CHOICES}, + {COMPOUND_STRING("Conservative"), LIST_AI_CONSERVATIVE}, + {COMPOUND_STRING("Sequence Switching"), LIST_AI_SEQUENCE_SWITCHING}, + {COMPOUND_STRING("Double Ace Pokémon"), LIST_AI_DOUBLE_ACE_POKEMON}, + {COMPOUND_STRING("Weigh Ability Prediction"), LIST_AI_WEIGH_ABILITY_PREDICTION}, + {COMPOUND_STRING("Prefer Highest Damage Move"), LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE}, + {COMPOUND_STRING("Predict Switch"), LIST_AI_PREDICT_SWITCH}, + {COMPOUND_STRING("Predict Incoming Mon"), LIST_AI_PREDICT_INCOMING_MON}, + {COMPOUND_STRING("Dynamic Func"), LIST_AI_DYNAMIC_FUNC}, + {COMPOUND_STRING("Roaming"), LIST_AI_ROAMING}, + {COMPOUND_STRING("Safari"), LIST_AI_SAFARI}, + {COMPOUND_STRING("First Battle"), LIST_AI_FIRST_BATTLE}, }; static const struct ListMenuItem sVariousListItems[] = { - {sText_ShowHP, VARIOUS_SHOW_HP}, - {sText_SubstituteHp, VARIOUS_SUBSTITUTE_HP}, - {sText_InLove, VARIOUS_IN_LOVE}, + {COMPOUND_STRING("Show HP"), VARIOUS_SHOW_HP}, + {COMPOUND_STRING("Substitute HP"), VARIOUS_SUBSTITUTE_HP}, + {COMPOUND_STRING("In Love"), VARIOUS_IN_LOVE}, }; static const struct ListMenuItem sSecondaryListItems[] = @@ -805,19 +586,6 @@ static const struct BgTemplate sBgTemplates[] = } }; -static const u8 sBitsToMaxDigit[] = -{ - [0] = 0, - [1] = 1, // max 1 - [2] = 1, // max 3 - [3] = 1, // max 7 - [4] = 2, // max 15 - [5] = 2, // max 31 - [6] = 2, // max 63 - [7] = 3, // max 127 - [8] = 3, // max 255 -}; - static const bool8 sHasChangeableEntries[LIST_ITEM_COUNT] = { [LIST_ITEM_MOVES] = TRUE, @@ -844,6 +612,8 @@ static void PrintDigitChars(struct BattleDebugMenu *data); static void SetUpModifyArrows(struct BattleDebugMenu *data); static void UpdateBattlerValue(struct BattleDebugMenu *data); static void UpdateMonData(struct BattleDebugMenu *data); +static void ChangeHazardsValue(struct BattleDebugMenu *data); +static u32 GetHazardsValue(struct BattleDebugMenu *data); static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue); static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp); static void SwitchToDebugView(u8 taskId); @@ -917,7 +687,7 @@ void CB2_BattleDebugMenu(void) break; case 3: LoadPalette(sBgColor, 0, 2); - LoadPalette(GetTextWindowPalette(2), 0xf0, 16); + LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 16); gMain.state++; break; case 4: @@ -950,17 +720,27 @@ void CB2_BattleDebugMenu(void) } } +enum { + COLORID_RED, +}; + +static const u8 sTextColorTable[][3] = +{ + [COLORID_RED] = {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, +}; + static void PutMovesPointsText(struct BattleDebugMenu *data) { - u32 i, j, count, battlerDef; + u32 i, j, count, battlerDef, chosenMoveIndex = gAiBattleData->chosenMoveIndex[data->aiBattlerId]; u8 *text = Alloc(0x50); FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Score/Dmg"), 3, 0, 0, NULL); for (i = 0; i < MAX_MON_MOVES; i++) { text[0] = CHAR_SPACE; StringCopy(text + 1, GetMoveName(gBattleMons[data->aiBattlerId].moves[i])); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, i * 15, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, (i * 15) + 15, 0, NULL); for (count = 0, j = 0; j < MAX_BATTLERS_COUNT; j++) { if (data->spriteIds.aiIconSpriteIds[j] == 0xFF) @@ -969,12 +749,24 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) ConvertIntToDecimalStringN(text, gAiBattleData->finalScore[data->aiBattlerId][battlerDef][i], STR_CONV_MODE_RIGHT_ALIGN, 3); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 83 + count * 54, i * 15, 0, NULL); + // If chosen move and chosen target + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 84 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, text); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 84 + count * 54, (i * 15) + 15, 0, NULL); + + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 103 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, COMPOUND_STRING("/")); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("/"), 103 + count * 54, (i * 15) + 15, 0, NULL); ConvertIntToDecimalStringN(text, AI_GetDamage(data->aiBattlerId, battlerDef, i, AI_ATTACKING, gAiLogicData), - STR_CONV_MODE_RIGHT_ALIGN, 3); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, i * 15, 0, NULL); + STR_CONV_MODE_LEADING_ZEROS, 3); + if ((chosenMoveIndex == i) && (gAiBattleData->chosenTarget[data->aiBattlerId] == j) && !(gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))) + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 110 + count * 54, (i * 15) + 15, sTextColorTable[COLORID_RED], 0, text); + else + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, (i * 15) + 15, 0, NULL); count++; } @@ -982,10 +774,10 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) if (gAiLogicData->shouldSwitch & (1u << data->aiBattlerId)) { - u32 switchMon = GetMonData(&gEnemyParty[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); - - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, sText_IsSwitching, 74, 64, 0, NULL); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, gSpeciesInfo[switchMon].speciesName, 74 + 68, 64, 0, NULL); + struct Pokemon *party = GetBattlerParty(data->aiBattlerId); + u32 switchMon = GetMonData(&party[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 74, 79, sTextColorTable[COLORID_RED], 0, COMPOUND_STRING("Switching to ")); + AddTextPrinterParameterized3(data->aiMovesWindowId, FONT_NORMAL, 74 + 68, 79, sTextColorTable[COLORID_RED], 0, gSpeciesInfo[switchMon].speciesName); } CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); @@ -1037,7 +829,7 @@ static void Task_ShowAiPoints(u8 taskId) { data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species, SpriteCallbackDummy, - 95 + (count * 60), 17, 0, 0); + 106 + (count * 54), 17, 0, 0); gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id count++; } @@ -1052,7 +844,7 @@ static void Task_ShowAiPoints(u8 taskId) GetMonData(mon, MON_DATA_IS_SHINY), gBattleMons[data->aiBattlerId].personality, TRUE, - 39, 130, 15, TAG_NONE); + 39, 135, 15, TAG_NONE); data->aiViewState++; break; // Put text @@ -1128,7 +920,7 @@ static void PutAiInfoText(struct BattleDebugMenu *data) { if (IsOnPlayerSide(i) && IsBattlerAlive(i)) { - u16 ability = gAiLogicData->abilities[i]; + enum Ability ability = gAiLogicData->abilities[i]; enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[i]; u16 item = gAiLogicData->items[i]; u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75; @@ -1415,6 +1207,13 @@ static void Task_DebugMenuProcessInput(u8 taskId) SwitchToAiPartyView(taskId); return; } + else if (listItemId == LIST_ITEM_INSTANT_WIN && JOY_NEW(A_BUTTON)) + { + BattleDebug_WonBattle(); + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_DebugMenuFadeOut; + return; + } data->currentMainListItemId = listItemId; // Create the secondary menu list. @@ -1586,20 +1385,9 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) itemsCount = ARRAY_COUNT(sStatus1ListItems); data->bitfield = sStatus1Bitfield; break; - case LIST_ITEM_STATUS2: - listTemplate.items = sStatus2ListItems; - itemsCount = ARRAY_COUNT(sStatus2ListItems); - data->bitfield = sStatus2Bitfield; - break; - case LIST_ITEM_STATUS3: - listTemplate.items = sStatus3ListItems; - itemsCount = ARRAY_COUNT(sStatus3ListItems); - data->bitfield = sStatus3Bitfield; - break; - case LIST_ITEM_STATUS4: - listTemplate.items = sStatus4ListItems; - itemsCount = ARRAY_COUNT(sStatus4ListItems); - data->bitfield = sStatus4Bitfield; + case LIST_ITEM_VOLATILE: + listTemplate.items = sVolatileStatusListItems; + itemsCount = ARRAY_COUNT(sVolatileStatusListItems); break; case LIST_ITEM_AI: listTemplate.items = sAIListItems; @@ -1610,10 +1398,15 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) listTemplate.items = sVariousListItems; itemsCount = ARRAY_COUNT(sVariousListItems); break; + case LIST_ITEM_HAZARDS: + listTemplate.items = sHazardsListItems; + itemsCount = ARRAY_COUNT(sHazardsListItems); + break; case LIST_ITEM_SIDE_STATUS: listTemplate.items = sSideStatusListItems; itemsCount = ARRAY_COUNT(sSideStatusListItems); break; + case LIST_ITEM_INSTANT_WIN: case LIST_ITEM_AI_MOVES_PTS: case LIST_ITEM_AI_INFO: return; @@ -1808,6 +1601,12 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data) *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~(GetBitfieldToAndValue(data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount)); *(u32 *)(data->modifyArrows.modifiedValPtr) |= (data->modifyArrows.currValue << data->bitfield[data->currentSecondaryListItemId].currBit); break; + case VAL_VOLATILE: + SetMonVolatile(data->battlerId, data->currentSecondaryListItemId, data->modifyArrows.currValue); + break; + case VAL_HAZARDS: + ChangeHazardsValue(data); + break; case VAR_SIDE_STATUS: *GetSideStatusValue(data, TRUE, data->modifyArrows.currValue != 0) = data->modifyArrows.currValue; break; @@ -1818,12 +1617,12 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data) *(u8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; if (*(u8 *)(data->modifyArrows.modifiedValPtr) == 0) { - gBattleMons[data->battlerId].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[data->battlerId].volatiles.substitute = FALSE; gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 0; } else { - gBattleMons[data->battlerId].status2 |= STATUS2_SUBSTITUTE; + gBattleMons[data->battlerId].volatiles.substitute = TRUE; gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 1; } break; @@ -1831,13 +1630,13 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data) if (data->modifyArrows.currValue) { if (IsBattlerAlive(BATTLE_OPPOSITE(data->battlerId))) - gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId)); + gBattleMons[data->battlerId].volatiles.infatuation = INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId)); else - gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId))); + gBattleMons[data->battlerId].volatiles.infatuation = INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId))); } else { - gBattleMons[data->battlerId].status2 &= ~STATUS2_INFATUATION; + gBattleMons[data->battlerId].volatiles.infatuation = 0; } break; } @@ -1885,6 +1684,83 @@ static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits) charDigits[i] = valueDigits[i] + CHAR_0; } +static void ChangeHazardsValue(struct BattleDebugMenu *data) +{ + u32 side = GetBattlerSide(data->battlerId); + + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: + if (data->modifyArrows.currValue > 0) + { + if (gSideTimers[side].spikesAmount == 0) + PushHazardTypeToQueue(side, HAZARDS_SPIKES); + gSideTimers[side].spikesAmount = data->modifyArrows.currValue; + } + else if (data->modifyArrows.currValue == 0) + { + gSideTimers[side].spikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_SPIKES); + } + break; + case LIST_SIDE_TOXIC_SPIKES: + if (data->modifyArrows.currValue > 0) + { + if (gSideTimers[side].toxicSpikesAmount == 0) + PushHazardTypeToQueue(side, HAZARDS_TOXIC_SPIKES); + gSideTimers[side].toxicSpikesAmount = data->modifyArrows.currValue; + } + else if (data->modifyArrows.currValue == 0) + { + gSideTimers[side].toxicSpikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES); + } + break; + case LIST_SIDE_STICKY_WEB: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STICKY_WEB); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STICKY_WEB); + break; + case LIST_SIDE_STEALTH_ROCK: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STEALTH_ROCK); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STEALTH_ROCK); + break; + case LIST_SIDE_STEELSURGE: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STEELSURGE); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STEELSURGE); + break; + } +} + +static u32 GetHazardsValue(struct BattleDebugMenu *data) +{ + u32 hazardsLayers = 0; + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: + hazardsLayers = gSideTimers[GetBattlerSide(data->battlerId)].spikesAmount; + break; + case LIST_SIDE_TOXIC_SPIKES: + hazardsLayers = gSideTimers[GetBattlerSide(data->battlerId)].toxicSpikesAmount; + break; + case LIST_SIDE_STICKY_WEB: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STICKY_WEB); + break; + case LIST_SIDE_STEALTH_ROCK: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STEALTH_ROCK); + break; + case LIST_SIDE_STEELSURGE: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STEELSURGE); + break; + } + return hazardsLayers; +} + static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue) { struct SideTimer *sideTimer = &gSideTimers[GetBattlerSide(data->battlerId)]; @@ -1909,26 +1785,6 @@ static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LIGHTSCREEN; } return &sideTimer->lightscreenTimer; - case LIST_SIDE_STICKY_WEB: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STICKY_WEB; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STICKY_WEB; - sideTimer->stickyWebBattlerId = data->battlerId; - sideTimer->stickyWebBattlerSide = GetBattlerSide(data->battlerId); - } - return &sideTimer->stickyWebAmount; - case LIST_SIDE_SPIKES: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SPIKES; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SPIKES; - } - return &sideTimer->spikesAmount; case LIST_SIDE_SAFEGUARD: if (changeStatus) { @@ -1974,33 +1830,6 @@ static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LUCKY_CHANT; } return &sideTimer->luckyChantTimer; - case LIST_SIDE_TOXIC_SPIKES: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TOXIC_SPIKES; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TOXIC_SPIKES; - } - return &sideTimer->toxicSpikesAmount; - case LIST_SIDE_STEALTH_ROCK: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEALTH_ROCK; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEALTH_ROCK; - } - return &sideTimer->stealthRockAmount; - case LIST_SIDE_STEELSURGE: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEELSURGE; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEELSURGE; - } - return &sideTimer->steelsurgeAmount; case LIST_SIDE_DAMAGE_NON_TYPES: if (changeStatus) { @@ -2167,7 +1996,7 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.maxDigits = 1; data->modifyArrows.modifiedValPtr = NULL; data->modifyArrows.typeOfVal = VAR_IN_LOVE; - data->modifyArrows.currValue = (gBattleMons[data->battlerId].status2 & STATUS2_INFATUATION) != 0; + data->modifyArrows.currValue = gBattleMons[data->battlerId].volatiles.infatuation; } break; case LIST_ITEM_STATUS1: @@ -2175,21 +2004,28 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status1, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); data->modifyArrows.typeOfVal = VAL_BITFIELD_32; goto CASE_ITEM_STATUS; - case LIST_ITEM_STATUS2: - data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].status2; - data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status2, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); - data->modifyArrows.typeOfVal = VAL_BITFIELD_32; - goto CASE_ITEM_STATUS; - case LIST_ITEM_STATUS3: - data->modifyArrows.modifiedValPtr = &gStatuses3[data->battlerId]; - data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); - data->modifyArrows.typeOfVal = VAL_BITFIELD_32; - goto CASE_ITEM_STATUS; - case LIST_ITEM_STATUS4: - data->modifyArrows.modifiedValPtr = &gStatuses4[data->battlerId]; - data->modifyArrows.currValue = GetBitfieldValue(gStatuses4[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); - data->modifyArrows.typeOfVal = VAL_BITFIELD_32; - goto CASE_ITEM_STATUS; + case LIST_ITEM_VOLATILE: + data->modifyArrows.currValue = GetBattlerVolatile(data->battlerId, data->currentSecondaryListItemId); + data->modifyArrows.typeOfVal = VAL_VOLATILE; + data->modifyArrows.minValue = 0; +#define UNPACK_VOLATILE_MAX_SIZE(_enum, _fieldName, _typeMaxValue, ...) case _enum: data->modifyArrows.maxValue = min(MAX_u16, GET_VOLATILE_MAXIMUM(_typeMaxValue)); break; + switch (data->currentSecondaryListItemId) + { + VOLATILE_DEFINITIONS(UNPACK_VOLATILE_MAX_SIZE) + /* Expands to the following: + * case VOLATILE_CONFUSION: + data->modifyArrows.maxValue = MAX_BITS(3); // Max value 7 + break; + * case VOLATILE_FLINCHED: + data->modifyArrows.maxValue = MAX_BITS(1); // Max value 1 + break; + * ...etc. + */ + default: + data->modifyArrows.maxValue = 0; + } + data->modifyArrows.maxDigits = MAX_DIGITS(data->modifyArrows.maxValue); + break; case LIST_ITEM_AI: data->modifyArrows.modifiedValPtr = &gAiThinkingStruct->aiFlags[data->battlerId]; data->modifyArrows.currValue = GetBitfieldValue(gAiThinkingStruct->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); @@ -2198,18 +2034,31 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) CASE_ITEM_STATUS: data->modifyArrows.minValue = 0; data->modifyArrows.maxValue = (1 << data->bitfield[data->currentSecondaryListItemId].bitsCount) - 1; - data->modifyArrows.maxDigits = sBitsToMaxDigit[data->bitfield[data->currentSecondaryListItemId].bitsCount]; + data->modifyArrows.maxDigits = MAX_DIGITS(data->modifyArrows.maxValue); + break; + case LIST_ITEM_HAZARDS: + data->modifyArrows.minValue = 0; + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: + data->modifyArrows.maxValue = 3; + break; + case LIST_SIDE_TOXIC_SPIKES: + data->modifyArrows.maxValue = 2; + break; + case LIST_SIDE_STICKY_WEB: + case LIST_SIDE_STEALTH_ROCK: + case LIST_SIDE_STEELSURGE: + data->modifyArrows.maxValue = 1; + break; + } + data->modifyArrows.maxDigits = 2; + data->modifyArrows.typeOfVal = VAL_HAZARDS; + data->modifyArrows.currValue = GetHazardsValue(data); break; case LIST_ITEM_SIDE_STATUS: data->modifyArrows.minValue = 0; - - if (data->currentSecondaryListItemId == LIST_SIDE_SPIKES) - data->modifyArrows.maxValue = 3; - else if (data->currentSecondaryListItemId == LIST_SIDE_STEALTH_ROCK || data->currentSecondaryListItemId == LIST_SIDE_STICKY_WEB) - data->modifyArrows.maxValue = 1; - else - data->modifyArrows.maxValue = 9; - + data->modifyArrows.maxValue = 9; data->modifyArrows.maxDigits = 2; data->modifyArrows.modifiedValPtr = &gSideStatuses[GetBattlerSide(data->battlerId)]; data->modifyArrows.typeOfVal = VAR_SIDE_STATUS; @@ -2308,276 +2157,144 @@ static void UpdateMonData(struct BattleDebugMenu *data) } } -static const u8 sText_HoldEffectNone[] = _("????????"); -static const u8 sText_HoldEffectRestoreHp[] = _("Restore Hp"); -static const u8 sText_HoldEffectCurePar[] = _("Cure Par"); -static const u8 sText_HoldEffectCureSlp[] = _("Cure Slp"); -static const u8 sText_HoldEffectCurePsn[] = _("Cure Psn"); -static const u8 sText_HoldEffectCureBrn[] = _("Cure Brn"); -static const u8 sText_HoldEffectCureFrz[] = _("Cure Frz"); -static const u8 sText_HoldEffectRestorePp[] = _("Restore Pp"); -static const u8 sText_HoldEffectCureConfusion[] = _("Cure Confusion"); -static const u8 sText_HoldEffectCureStatus[] = _("Cure Status"); -static const u8 sText_HoldEffectConfuseSpicy[] = _("Confuse Spicy"); -static const u8 sText_HoldEffectConfuseDry[] = _("Confuse Dry"); -static const u8 sText_HoldEffectConfuseSweet[] = _("Confuse Sweet"); -static const u8 sText_HoldEffectConfuseBitter[] = _("Confuse Bitter"); -static const u8 sText_HoldEffectConfuseSour[] = _("Confuse Sour"); -static const u8 sText_HoldEffectAttackUp[] = _("Attack Up"); -static const u8 sText_HoldEffectDefenseUp[] = _("Defense Up"); -static const u8 sText_HoldEffectSpeedUp[] = _("Speed Up"); -static const u8 sText_HoldEffectSpAttackUp[] = _("Sp Attack Up"); -static const u8 sText_HoldEffectSpDefenseUp[] = _("Sp Defense Up"); -static const u8 sText_HoldEffectCriticalUp[] = _("Critical Up"); -static const u8 sText_HoldEffectRandomStatUp[] = _("Random Stat Up"); -static const u8 sText_HoldEffectEvasionUp[] = _("Evasion Up"); -static const u8 sText_HoldEffectRestoreStats[] = _("Restore Stats"); -static const u8 sText_HoldEffectMachoBrace[] = _("Macho Brace"); -static const u8 sText_HoldEffectExpShare[] = _("Exp Share"); -static const u8 sText_HoldEffectQuickClaw[] = _("Quick Claw"); -static const u8 sText_HoldEffectFriendshipUp[] = _("Friendship Up"); -static const u8 sText_HoldEffectMentalHerb[] = _("Mental Herb"); -static const u8 sText_HoldEffectChoiceBand[] = _("Choice Band"); -static const u8 sText_HoldEffectFlinch[] = _("Flinch"); -static const u8 sText_HoldEffectDoublePrize[] = _("Double Prize"); -static const u8 sText_HoldEffectRepel[] = _("Repel"); -static const u8 sText_HoldEffectSoulDew[] = _("Soul Dew"); -static const u8 sText_HoldEffectDeepSeaTooth[] = _("Deep Sea Tooth"); -static const u8 sText_HoldEffectDeepSeaScale[] = _("Deep Sea Scale"); -static const u8 sText_HoldEffectCanAlwaysRun[] = _("Can Always Run"); -static const u8 sText_HoldEffectPreventEvolve[] = _("Prevent Evolve"); -static const u8 sText_HoldEffectFocusBand[] = _("Focus Band"); -static const u8 sText_HoldEffectLuckyEgg[] = _("Lucky Egg"); -static const u8 sText_HoldEffectScopeLens[] = _("Scope Lens"); -static const u8 sText_HoldEffectLeftovers[] = _("Leftovers"); -static const u8 sText_HoldEffectDragonScale[] = _("Dragon Scale"); -static const u8 sText_HoldEffectLightBall[] = _("Light Ball"); -static const u8 sText_HoldEffectTypePower[] = _("Type Power"); -static const u8 sText_HoldEffectUpgrade[] = _("Upgrade"); -static const u8 sText_HoldEffectShellBell[] = _("Shell Bell"); -static const u8 sText_HoldEffectLuckyPunch[] = _("Lucky Punch"); -static const u8 sText_HoldEffectMetalPowder[] = _("Metal Powder"); -static const u8 sText_HoldEffectThickClub[] = _("Thick Club"); -static const u8 sText_HoldEffectLeek[] = _("Leek"); -static const u8 sText_HoldEffectChoiceScarf[] = _("Choice Scarf"); -static const u8 sText_HoldEffectChoiceSpecs[] = _("Choice Specs"); -static const u8 sText_HoldEffectDampRock[] = _("Damp Rock"); -static const u8 sText_HoldEffectGripClaw[] = _("Grip Claw"); -static const u8 sText_HoldEffectHeatRock[] = _("Heat Rock"); -static const u8 sText_HoldEffectIcyRock[] = _("Icy Rock"); -static const u8 sText_HoldEffectLightClay[] = _("Light Clay"); -static const u8 sText_HoldEffectSmoothRock[] = _("Smooth Rock"); -static const u8 sText_HoldEffectPowerHerb[] = _("Power Herb"); -static const u8 sText_HoldEffectBigRoot[] = _("Big Root"); -static const u8 sText_HoldEffectExpertBelt[] = _("Expert Belt"); -static const u8 sText_HoldEffectLifeOrb[] = _("Life Orb"); -static const u8 sText_HoldEffectMetronome[] = _("Metronome"); -static const u8 sText_HoldEffectMuscleBand[] = _("Muscle Band"); -static const u8 sText_HoldEffectWideLens[] = _("Wide Lens"); -static const u8 sText_HoldEffectWiseGlasses[] = _("Wise Glasses"); -static const u8 sText_HoldEffectZoomLens[] = _("Zoom Lens"); -static const u8 sText_HoldEffectLaggingTail[] = _("Lagging Tail"); -static const u8 sText_HoldEffectFocusSash[] = _("Focus Sash"); -static const u8 sText_HoldEffectFlameOrb[] = _("Flame Orb"); -static const u8 sText_HoldEffectToxicOrb[] = _("Toxic Orb"); -static const u8 sText_HoldEffectStickyBarb[] = _("Sticky Barb"); -static const u8 sText_HoldEffectIronBall[] = _("Iron Ball"); -static const u8 sText_HoldEffectBlackSludge[] = _("Black Sludge"); -static const u8 sText_HoldEffectDestinyKnot[] = _("Destiny Knot"); -static const u8 sText_HoldEffectShedShell[] = _("Shed Shell"); -static const u8 sText_HoldEffectQuickPowder[] = _("Quick Powder"); -static const u8 sText_HoldEffectAdamantOrb[] = _("Adamant Orb"); -static const u8 sText_HoldEffectLustrousOrb[] = _("Lustrous Orb"); -static const u8 sText_HoldEffectGriseousOrb[] = _("Griseous Orb"); -static const u8 sText_HoldEffectEnigmaBerry[] = _("Enigma Berry"); -static const u8 sText_HoldEffectResistBerry[] = _("Resist Berry"); -static const u8 sText_HoldEffectPowerItem[] = _("Power Item"); -static const u8 sText_HoldEffectRestorePctHp[] = _("Restore Pct Hp"); -static const u8 sText_HoldEffectMicleBerry[] = _("Micle Berry"); -static const u8 sText_HoldEffectCustapBerry[] = _("Custap Berry"); -static const u8 sText_HoldEffectJabocaBerry[] = _("Jaboca Berry"); -static const u8 sText_HoldEffectRowapBerry[] = _("Rowap Berry"); -static const u8 sText_HoldEffectKeeBerry[] = _("Kee Berry"); -static const u8 sText_HoldEffectMarangaBerry[] = _("Maranga Berry"); -static const u8 sText_HoldEffectFloatStone[] = _("Float Stone"); -static const u8 sText_HoldEffectEviolite[] = _("Eviolite"); -static const u8 sText_HoldEffectAssaultVest[] = _("Assault Vest"); -static const u8 sText_HoldEffectDrive[] = _("Drive"); -static const u8 sText_HoldEffectGems[] = _("Gems"); -static const u8 sText_HoldEffectRockyHelmet[] = _("Rocky Helmet"); -static const u8 sText_HoldEffectAirBalloon[] = _("Air Balloon"); -static const u8 sText_HoldEffectRedCard[] = _("Red Card"); -static const u8 sText_HoldEffectRingTarget[] = _("Ring Target"); -static const u8 sText_HoldEffectBindingBand[] = _("Binding Band"); -static const u8 sText_HoldEffectEjectButton[] = _("Eject Button"); -static const u8 sText_HoldEffectAbsorbBulb[] = _("Absorb Bulb"); -static const u8 sText_HoldEffectCellBattery[] = _("Cell Battery"); -static const u8 sText_HoldEffectMegaStone[] = _("Mega Stone"); -static const u8 sText_HoldEffectSafetyGoggles[] = _("Safety Goggles"); -static const u8 sText_HoldEffectLuminousMoss[] = _("Luminous Moss"); -static const u8 sText_HoldEffectSnowball[] = _("Snowball"); -static const u8 sText_HoldEffectWeaknessPolicy[] = _("Weakness Policy"); -static const u8 sText_HoldEffectPrimalOrb[] = _("Primal Orb"); -static const u8 sText_HoldEffectProtectivePads[] = _("Protective Pads"); -static const u8 sText_HoldEffectTerrainExtender[] = _("Terrain Extender"); -static const u8 sText_HoldEffectSeeds[] = _("Seeds"); -static const u8 sText_HoldEffectAdrenalineOrb[] = _("Adrenaline Orb"); -static const u8 sText_HoldEffectMemory[] = _("Memory"); -static const u8 sText_HoldEffectZCrystal[] = _("Z-Crystal"); -static const u8 sText_HoldEffectPlate[] = _("Plate"); -static const u8 sText_HoldEffectUtilityUmbrella[] = _("Utility Umbrella"); -static const u8 sText_HoldEffectEjectPack[] = _("Eject Pack"); -static const u8 sText_HoldEffectRoomService[] = _("Room Service"); -static const u8 sText_HoldEffectBlunderPolicy[] = _("Blunder Policy"); -static const u8 sText_HoldEffectHeavyDutyBoots[] = _("Heavy Duty Boots"); -static const u8 sText_HoldEffectThroatSpray[] = _("Throat Spray"); -static const u8 sText_HoldEffectAbilityShield[] = _("Ability Shield"); -static const u8 sText_HoldEffectClearAmulet[] = _("Clear Amulet"); -static const u8 sText_HoldEffectMirrorHerb[] = _("Mirror Herb"); -static const u8 sText_HoldEffectPunchingGlove[] = _("Punching Glove"); -static const u8 sText_HoldEffectCovertCloak[] = _("Covert Cloak"); -static const u8 sText_HoldEffectLoadedDice[] = _("Loaded Dice"); -static const u8 sText_HoldEffectBoosterEnergy[] = _("Booster Energy"); -static const u8 sText_HoldEffectBerserkGene[] = _("Berserk Gene"); -static const u8 sText_HoldEffectOgerponMask[] = _("Ogerpon Mask"); -static const u8 *const sHoldEffectNames[] = +static const u8 *const sHoldEffectNames[HOLD_EFFECT_COUNT] = { - [HOLD_EFFECT_NONE] = sText_HoldEffectNone, - [HOLD_EFFECT_RESTORE_HP] = sText_HoldEffectRestoreHp, - [HOLD_EFFECT_CURE_PAR] = sText_HoldEffectCurePar, - [HOLD_EFFECT_CURE_SLP] = sText_HoldEffectCureSlp, - [HOLD_EFFECT_CURE_PSN] = sText_HoldEffectCurePsn, - [HOLD_EFFECT_CURE_BRN] = sText_HoldEffectCureBrn, - [HOLD_EFFECT_CURE_FRZ] = sText_HoldEffectCureFrz, - [HOLD_EFFECT_RESTORE_PP] = sText_HoldEffectRestorePp, - [HOLD_EFFECT_CURE_CONFUSION] = sText_HoldEffectCureConfusion, - [HOLD_EFFECT_CURE_STATUS] = sText_HoldEffectCureStatus, - [HOLD_EFFECT_CONFUSE_SPICY] = sText_HoldEffectConfuseSpicy, - [HOLD_EFFECT_CONFUSE_DRY] = sText_HoldEffectConfuseDry, - [HOLD_EFFECT_CONFUSE_SWEET] = sText_HoldEffectConfuseSweet, - [HOLD_EFFECT_CONFUSE_BITTER] = sText_HoldEffectConfuseBitter, - [HOLD_EFFECT_CONFUSE_SOUR] = sText_HoldEffectConfuseSour, - [HOLD_EFFECT_ATTACK_UP] = sText_HoldEffectAttackUp, - [HOLD_EFFECT_DEFENSE_UP] = sText_HoldEffectDefenseUp, - [HOLD_EFFECT_SPEED_UP] = sText_HoldEffectSpeedUp, - [HOLD_EFFECT_SP_ATTACK_UP] = sText_HoldEffectSpAttackUp, - [HOLD_EFFECT_SP_DEFENSE_UP] = sText_HoldEffectSpDefenseUp, - [HOLD_EFFECT_CRITICAL_UP] = sText_HoldEffectCriticalUp, - [HOLD_EFFECT_RANDOM_STAT_UP] = sText_HoldEffectRandomStatUp, - [HOLD_EFFECT_EVASION_UP] = sText_HoldEffectEvasionUp, - [HOLD_EFFECT_WHITE_HERB] = sText_HoldEffectRestoreStats, - [HOLD_EFFECT_MACHO_BRACE] = sText_HoldEffectMachoBrace, - [HOLD_EFFECT_EXP_SHARE] = sText_HoldEffectExpShare, - [HOLD_EFFECT_QUICK_CLAW] = sText_HoldEffectQuickClaw, - [HOLD_EFFECT_FRIENDSHIP_UP] = sText_HoldEffectFriendshipUp, - [HOLD_EFFECT_MENTAL_HERB] = sText_HoldEffectMentalHerb, - [HOLD_EFFECT_CHOICE_BAND] = sText_HoldEffectChoiceBand, - [HOLD_EFFECT_FLINCH] = sText_HoldEffectFlinch, - [HOLD_EFFECT_DOUBLE_PRIZE] = sText_HoldEffectDoublePrize, - [HOLD_EFFECT_REPEL] = sText_HoldEffectRepel, - [HOLD_EFFECT_SOUL_DEW] = sText_HoldEffectSoulDew, - [HOLD_EFFECT_DEEP_SEA_TOOTH] = sText_HoldEffectDeepSeaTooth, - [HOLD_EFFECT_DEEP_SEA_SCALE] = sText_HoldEffectDeepSeaScale, - [HOLD_EFFECT_CAN_ALWAYS_RUN] = sText_HoldEffectCanAlwaysRun, - [HOLD_EFFECT_PREVENT_EVOLVE] = sText_HoldEffectPreventEvolve, - [HOLD_EFFECT_FOCUS_BAND] = sText_HoldEffectFocusBand, - [HOLD_EFFECT_LUCKY_EGG] = sText_HoldEffectLuckyEgg, - [HOLD_EFFECT_SCOPE_LENS] = sText_HoldEffectScopeLens, - [HOLD_EFFECT_LEFTOVERS] = sText_HoldEffectLeftovers, - [HOLD_EFFECT_DRAGON_SCALE] = sText_HoldEffectDragonScale, - [HOLD_EFFECT_LIGHT_BALL] = sText_HoldEffectLightBall, - [HOLD_EFFECT_TYPE_POWER] = sText_HoldEffectTypePower, - [HOLD_EFFECT_UPGRADE] = sText_HoldEffectUpgrade, - [HOLD_EFFECT_SHELL_BELL] = sText_HoldEffectShellBell, - [HOLD_EFFECT_LUCKY_PUNCH] = sText_HoldEffectLuckyPunch, - [HOLD_EFFECT_METAL_POWDER] = sText_HoldEffectMetalPowder, - [HOLD_EFFECT_THICK_CLUB] = sText_HoldEffectThickClub, - [HOLD_EFFECT_LEEK] = sText_HoldEffectLeek, - [HOLD_EFFECT_CHOICE_SCARF] = sText_HoldEffectChoiceScarf, - [HOLD_EFFECT_CHOICE_SPECS] = sText_HoldEffectChoiceSpecs, - [HOLD_EFFECT_DAMP_ROCK] = sText_HoldEffectDampRock, - [HOLD_EFFECT_GRIP_CLAW] = sText_HoldEffectGripClaw, - [HOLD_EFFECT_HEAT_ROCK] = sText_HoldEffectHeatRock, - [HOLD_EFFECT_ICY_ROCK] = sText_HoldEffectIcyRock, - [HOLD_EFFECT_LIGHT_CLAY] = sText_HoldEffectLightClay, - [HOLD_EFFECT_SMOOTH_ROCK] = sText_HoldEffectSmoothRock, - [HOLD_EFFECT_POWER_HERB] = sText_HoldEffectPowerHerb, - [HOLD_EFFECT_BIG_ROOT] = sText_HoldEffectBigRoot, - [HOLD_EFFECT_EXPERT_BELT] = sText_HoldEffectExpertBelt, - [HOLD_EFFECT_LIFE_ORB] = sText_HoldEffectLifeOrb, - [HOLD_EFFECT_METRONOME] = sText_HoldEffectMetronome, - [HOLD_EFFECT_MUSCLE_BAND] = sText_HoldEffectMuscleBand, - [HOLD_EFFECT_WIDE_LENS] = sText_HoldEffectWideLens, - [HOLD_EFFECT_WISE_GLASSES] = sText_HoldEffectWiseGlasses, - [HOLD_EFFECT_ZOOM_LENS] = sText_HoldEffectZoomLens, - [HOLD_EFFECT_LAGGING_TAIL] = sText_HoldEffectLaggingTail, - [HOLD_EFFECT_FOCUS_SASH] = sText_HoldEffectFocusSash, - [HOLD_EFFECT_FLAME_ORB] = sText_HoldEffectFlameOrb, - [HOLD_EFFECT_TOXIC_ORB] = sText_HoldEffectToxicOrb, - [HOLD_EFFECT_STICKY_BARB] = sText_HoldEffectStickyBarb, - [HOLD_EFFECT_IRON_BALL] = sText_HoldEffectIronBall, - [HOLD_EFFECT_BLACK_SLUDGE] = sText_HoldEffectBlackSludge, - [HOLD_EFFECT_DESTINY_KNOT] = sText_HoldEffectDestinyKnot, - [HOLD_EFFECT_SHED_SHELL] = sText_HoldEffectShedShell, - [HOLD_EFFECT_QUICK_POWDER] = sText_HoldEffectQuickPowder, - [HOLD_EFFECT_ADAMANT_ORB] = sText_HoldEffectAdamantOrb, - [HOLD_EFFECT_LUSTROUS_ORB] = sText_HoldEffectLustrousOrb, - [HOLD_EFFECT_GRISEOUS_ORB] = sText_HoldEffectGriseousOrb, - [HOLD_EFFECT_ENIGMA_BERRY] = sText_HoldEffectEnigmaBerry, - [HOLD_EFFECT_RESIST_BERRY] = sText_HoldEffectResistBerry, - [HOLD_EFFECT_POWER_ITEM] = sText_HoldEffectPowerItem, - [HOLD_EFFECT_RESTORE_PCT_HP] = sText_HoldEffectRestorePctHp, - [HOLD_EFFECT_MICLE_BERRY] = sText_HoldEffectMicleBerry, - [HOLD_EFFECT_CUSTAP_BERRY] = sText_HoldEffectCustapBerry, - [HOLD_EFFECT_JABOCA_BERRY] = sText_HoldEffectJabocaBerry, - [HOLD_EFFECT_ROWAP_BERRY] = sText_HoldEffectRowapBerry, - [HOLD_EFFECT_KEE_BERRY] = sText_HoldEffectKeeBerry, - [HOLD_EFFECT_MARANGA_BERRY] = sText_HoldEffectMarangaBerry, - [HOLD_EFFECT_PLATE] = sText_HoldEffectPlate, - [HOLD_EFFECT_FLOAT_STONE] = sText_HoldEffectFloatStone, - [HOLD_EFFECT_EVIOLITE] = sText_HoldEffectEviolite, - [HOLD_EFFECT_ASSAULT_VEST] = sText_HoldEffectAssaultVest, - [HOLD_EFFECT_DRIVE] = sText_HoldEffectDrive, - [HOLD_EFFECT_GEMS] = sText_HoldEffectGems, - [HOLD_EFFECT_ROCKY_HELMET] = sText_HoldEffectRockyHelmet, - [HOLD_EFFECT_AIR_BALLOON] = sText_HoldEffectAirBalloon, - [HOLD_EFFECT_RED_CARD] = sText_HoldEffectRedCard, - [HOLD_EFFECT_RING_TARGET] = sText_HoldEffectRingTarget, - [HOLD_EFFECT_BINDING_BAND] = sText_HoldEffectBindingBand, - [HOLD_EFFECT_EJECT_BUTTON] = sText_HoldEffectEjectButton, - [HOLD_EFFECT_ABSORB_BULB] = sText_HoldEffectAbsorbBulb, - [HOLD_EFFECT_CELL_BATTERY] = sText_HoldEffectCellBattery, - [HOLD_EFFECT_MEGA_STONE] = sText_HoldEffectMegaStone, - [HOLD_EFFECT_SAFETY_GOGGLES] = sText_HoldEffectSafetyGoggles, - [HOLD_EFFECT_LUMINOUS_MOSS] = sText_HoldEffectLuminousMoss, - [HOLD_EFFECT_SNOWBALL] = sText_HoldEffectSnowball, - [HOLD_EFFECT_WEAKNESS_POLICY] = sText_HoldEffectWeaknessPolicy, - [HOLD_EFFECT_PRIMAL_ORB] = sText_HoldEffectPrimalOrb, - [HOLD_EFFECT_PROTECTIVE_PADS] = sText_HoldEffectProtectivePads, - [HOLD_EFFECT_TERRAIN_EXTENDER] = sText_HoldEffectTerrainExtender, - [HOLD_EFFECT_SEEDS] = sText_HoldEffectSeeds, - [HOLD_EFFECT_ADRENALINE_ORB] = sText_HoldEffectAdrenalineOrb, - [HOLD_EFFECT_MEMORY] = sText_HoldEffectMemory, - [HOLD_EFFECT_Z_CRYSTAL] = sText_HoldEffectZCrystal, - [HOLD_EFFECT_UTILITY_UMBRELLA] = sText_HoldEffectUtilityUmbrella, - [HOLD_EFFECT_EJECT_PACK] = sText_HoldEffectEjectPack, - [HOLD_EFFECT_ROOM_SERVICE] = sText_HoldEffectRoomService, - [HOLD_EFFECT_BLUNDER_POLICY] = sText_HoldEffectBlunderPolicy, - [HOLD_EFFECT_HEAVY_DUTY_BOOTS] = sText_HoldEffectHeavyDutyBoots, - [HOLD_EFFECT_THROAT_SPRAY] = sText_HoldEffectThroatSpray, - [HOLD_EFFECT_ABILITY_SHIELD] = sText_HoldEffectAbilityShield, - [HOLD_EFFECT_CLEAR_AMULET] = sText_HoldEffectClearAmulet, - [HOLD_EFFECT_MIRROR_HERB] = sText_HoldEffectMirrorHerb, - [HOLD_EFFECT_PUNCHING_GLOVE] = sText_HoldEffectPunchingGlove, - [HOLD_EFFECT_COVERT_CLOAK] = sText_HoldEffectCovertCloak, - [HOLD_EFFECT_LOADED_DICE] = sText_HoldEffectLoadedDice, - [HOLD_EFFECT_BOOSTER_ENERGY] = sText_HoldEffectBoosterEnergy, - [HOLD_EFFECT_OGERPON_MASK] = sText_HoldEffectOgerponMask, - [HOLD_EFFECT_BERSERK_GENE] = sText_HoldEffectBerserkGene, + [HOLD_EFFECT_NONE] = COMPOUND_STRING("????????"), + [HOLD_EFFECT_RESTORE_HP] = COMPOUND_STRING("Restore Hp"), + [HOLD_EFFECT_CURE_PAR] = COMPOUND_STRING("Cure Par"), + [HOLD_EFFECT_CURE_SLP] = COMPOUND_STRING("Cure Slp"), + [HOLD_EFFECT_CURE_PSN] = COMPOUND_STRING("Cure Psn"), + [HOLD_EFFECT_CURE_BRN] = COMPOUND_STRING("Cure Brn"), + [HOLD_EFFECT_CURE_FRZ] = COMPOUND_STRING("Cure Frz"), + [HOLD_EFFECT_RESTORE_PP] = COMPOUND_STRING("Restore Pp"), + [HOLD_EFFECT_CURE_CONFUSION] = COMPOUND_STRING("Cure Confusion"), + [HOLD_EFFECT_CURE_STATUS] = COMPOUND_STRING("Cure Status"), + [HOLD_EFFECT_CONFUSE_SPICY] = COMPOUND_STRING("Confuse Spicy"), + [HOLD_EFFECT_CONFUSE_DRY] = COMPOUND_STRING("Confuse Dry"), + [HOLD_EFFECT_CONFUSE_SWEET] = COMPOUND_STRING("Confuse Sweet"), + [HOLD_EFFECT_CONFUSE_BITTER] = COMPOUND_STRING("Confuse Bitter"), + [HOLD_EFFECT_CONFUSE_SOUR] = COMPOUND_STRING("Confuse Sour"), + [HOLD_EFFECT_ATTACK_UP] = COMPOUND_STRING("Attack Up"), + [HOLD_EFFECT_DEFENSE_UP] = COMPOUND_STRING("Defense Up"), + [HOLD_EFFECT_SPEED_UP] = COMPOUND_STRING("Speed Up"), + [HOLD_EFFECT_SP_ATTACK_UP] = COMPOUND_STRING("Sp Attack Up"), + [HOLD_EFFECT_SP_DEFENSE_UP] = COMPOUND_STRING("Sp Defense Up"), + [HOLD_EFFECT_CRITICAL_UP] = COMPOUND_STRING("Critical Up"), + [HOLD_EFFECT_RANDOM_STAT_UP] = COMPOUND_STRING("Random Stat Up"), + [HOLD_EFFECT_EVASION_UP] = COMPOUND_STRING("Evasion Up"), + [HOLD_EFFECT_WHITE_HERB] = COMPOUND_STRING("Restore Stats"), + [HOLD_EFFECT_MACHO_BRACE] = COMPOUND_STRING("Macho Brace"), + [HOLD_EFFECT_EXP_SHARE] = COMPOUND_STRING("Exp Share"), + [HOLD_EFFECT_QUICK_CLAW] = COMPOUND_STRING("Quick Claw"), + [HOLD_EFFECT_FRIENDSHIP_UP] = COMPOUND_STRING("Friendship Up"), + [HOLD_EFFECT_MENTAL_HERB] = COMPOUND_STRING("Mental Herb"), + [HOLD_EFFECT_CHOICE_BAND] = COMPOUND_STRING("Choice Band"), + [HOLD_EFFECT_FLINCH] = COMPOUND_STRING("Flinch"), + [HOLD_EFFECT_DOUBLE_PRIZE] = COMPOUND_STRING("Double Prize"), + [HOLD_EFFECT_REPEL] = COMPOUND_STRING("Repel"), + [HOLD_EFFECT_SOUL_DEW] = COMPOUND_STRING("Soul Dew"), + [HOLD_EFFECT_DEEP_SEA_TOOTH] = COMPOUND_STRING("Deep Sea Tooth"), + [HOLD_EFFECT_DEEP_SEA_SCALE] = COMPOUND_STRING("Deep Sea Scale"), + [HOLD_EFFECT_CAN_ALWAYS_RUN] = COMPOUND_STRING("Can Always Run"), + [HOLD_EFFECT_PREVENT_EVOLVE] = COMPOUND_STRING("Prevent Evolve"), + [HOLD_EFFECT_FOCUS_BAND] = COMPOUND_STRING("Focus Band"), + [HOLD_EFFECT_LUCKY_EGG] = COMPOUND_STRING("Lucky Egg"), + [HOLD_EFFECT_SCOPE_LENS] = COMPOUND_STRING("Scope Lens"), + [HOLD_EFFECT_LEFTOVERS] = COMPOUND_STRING("Leftovers"), + [HOLD_EFFECT_DRAGON_SCALE] = COMPOUND_STRING("Dragon Scale"), + [HOLD_EFFECT_LIGHT_BALL] = COMPOUND_STRING("Light Ball"), + [HOLD_EFFECT_TYPE_POWER] = COMPOUND_STRING("Type Power"), + [HOLD_EFFECT_UPGRADE] = COMPOUND_STRING("Upgrade"), + [HOLD_EFFECT_SHELL_BELL] = COMPOUND_STRING("Shell Bell"), + [HOLD_EFFECT_LUCKY_PUNCH] = COMPOUND_STRING("Lucky Punch"), + [HOLD_EFFECT_METAL_POWDER] = COMPOUND_STRING("Metal Powder"), + [HOLD_EFFECT_THICK_CLUB] = COMPOUND_STRING("Thick Club"), + [HOLD_EFFECT_LEEK] = COMPOUND_STRING("Leek"), + [HOLD_EFFECT_CHOICE_SCARF] = COMPOUND_STRING("Choice Scarf"), + [HOLD_EFFECT_CHOICE_SPECS] = COMPOUND_STRING("Choice Specs"), + [HOLD_EFFECT_DAMP_ROCK] = COMPOUND_STRING("Damp Rock"), + [HOLD_EFFECT_GRIP_CLAW] = COMPOUND_STRING("Grip Claw"), + [HOLD_EFFECT_HEAT_ROCK] = COMPOUND_STRING("Heat Rock"), + [HOLD_EFFECT_ICY_ROCK] = COMPOUND_STRING("Icy Rock"), + [HOLD_EFFECT_LIGHT_CLAY] = COMPOUND_STRING("Light Clay"), + [HOLD_EFFECT_SMOOTH_ROCK] = COMPOUND_STRING("Smooth Rock"), + [HOLD_EFFECT_POWER_HERB] = COMPOUND_STRING("Power Herb"), + [HOLD_EFFECT_BIG_ROOT] = COMPOUND_STRING("Big Root"), + [HOLD_EFFECT_EXPERT_BELT] = COMPOUND_STRING("Expert Belt"), + [HOLD_EFFECT_LIFE_ORB] = COMPOUND_STRING("Life Orb"), + [HOLD_EFFECT_METRONOME] = COMPOUND_STRING("Metronome"), + [HOLD_EFFECT_MUSCLE_BAND] = COMPOUND_STRING("Muscle Band"), + [HOLD_EFFECT_WIDE_LENS] = COMPOUND_STRING("Wide Lens"), + [HOLD_EFFECT_WISE_GLASSES] = COMPOUND_STRING("Wise Glasses"), + [HOLD_EFFECT_ZOOM_LENS] = COMPOUND_STRING("Zoom Lens"), + [HOLD_EFFECT_LAGGING_TAIL] = COMPOUND_STRING("Lagging Tail"), + [HOLD_EFFECT_FOCUS_SASH] = COMPOUND_STRING("Focus Sash"), + [HOLD_EFFECT_FLAME_ORB] = COMPOUND_STRING("Flame Orb"), + [HOLD_EFFECT_TOXIC_ORB] = COMPOUND_STRING("Toxic Orb"), + [HOLD_EFFECT_STICKY_BARB] = COMPOUND_STRING("Sticky Barb"), + [HOLD_EFFECT_IRON_BALL] = COMPOUND_STRING("Iron Ball"), + [HOLD_EFFECT_BLACK_SLUDGE] = COMPOUND_STRING("Black Sludge"), + [HOLD_EFFECT_DESTINY_KNOT] = COMPOUND_STRING("Destiny Knot"), + [HOLD_EFFECT_SHED_SHELL] = COMPOUND_STRING("Shed Shell"), + [HOLD_EFFECT_QUICK_POWDER] = COMPOUND_STRING("Quick Powder"), + [HOLD_EFFECT_ADAMANT_ORB] = COMPOUND_STRING("Adamant Orb"), + [HOLD_EFFECT_LUSTROUS_ORB] = COMPOUND_STRING("Lustrous Orb"), + [HOLD_EFFECT_GRISEOUS_ORB] = COMPOUND_STRING("Griseous Orb"), + [HOLD_EFFECT_ENIGMA_BERRY] = COMPOUND_STRING("Enigma Berry"), + [HOLD_EFFECT_RESIST_BERRY] = COMPOUND_STRING("Resist Berry"), + [HOLD_EFFECT_POWER_ITEM] = COMPOUND_STRING("Power Item"), + [HOLD_EFFECT_RESTORE_PCT_HP] = COMPOUND_STRING("Restore Pct Hp"), + [HOLD_EFFECT_MICLE_BERRY] = COMPOUND_STRING("Micle Berry"), + [HOLD_EFFECT_CUSTAP_BERRY] = COMPOUND_STRING("Custap Berry"), + [HOLD_EFFECT_JABOCA_BERRY] = COMPOUND_STRING("Jaboca Berry"), + [HOLD_EFFECT_ROWAP_BERRY] = COMPOUND_STRING("Rowap Berry"), + [HOLD_EFFECT_KEE_BERRY] = COMPOUND_STRING("Kee Berry"), + [HOLD_EFFECT_MARANGA_BERRY] = COMPOUND_STRING("Maranga Berry"), + [HOLD_EFFECT_PLATE] = COMPOUND_STRING("Plate"), + [HOLD_EFFECT_FLOAT_STONE] = COMPOUND_STRING("Float Stone"), + [HOLD_EFFECT_EVIOLITE] = COMPOUND_STRING("Eviolite"), + [HOLD_EFFECT_ASSAULT_VEST] = COMPOUND_STRING("Assault Vest"), + [HOLD_EFFECT_DRIVE] = COMPOUND_STRING("Drive"), + [HOLD_EFFECT_GEMS] = COMPOUND_STRING("Gems"), + [HOLD_EFFECT_ROCKY_HELMET] = COMPOUND_STRING("Rocky Helmet"), + [HOLD_EFFECT_AIR_BALLOON] = COMPOUND_STRING("Air Balloon"), + [HOLD_EFFECT_RED_CARD] = COMPOUND_STRING("Red Card"), + [HOLD_EFFECT_RING_TARGET] = COMPOUND_STRING("Ring Target"), + [HOLD_EFFECT_BINDING_BAND] = COMPOUND_STRING("Binding Band"), + [HOLD_EFFECT_EJECT_BUTTON] = COMPOUND_STRING("Eject Button"), + [HOLD_EFFECT_ABSORB_BULB] = COMPOUND_STRING("Absorb Bulb"), + [HOLD_EFFECT_CELL_BATTERY] = COMPOUND_STRING("Cell Battery"), + [HOLD_EFFECT_MEGA_STONE] = COMPOUND_STRING("Mega Stone"), + [HOLD_EFFECT_SAFETY_GOGGLES] = COMPOUND_STRING("Safety Goggles"), + [HOLD_EFFECT_LUMINOUS_MOSS] = COMPOUND_STRING("Luminous Moss"), + [HOLD_EFFECT_SNOWBALL] = COMPOUND_STRING("Snowball"), + [HOLD_EFFECT_WEAKNESS_POLICY] = COMPOUND_STRING("Weakness Policy"), + [HOLD_EFFECT_PRIMAL_ORB] = COMPOUND_STRING("Primal Orb"), + [HOLD_EFFECT_PROTECTIVE_PADS] = COMPOUND_STRING("Protective Pads"), + [HOLD_EFFECT_TERRAIN_EXTENDER] = COMPOUND_STRING("Terrain Extender"), + [HOLD_EFFECT_SEEDS] = COMPOUND_STRING("Seeds"), + [HOLD_EFFECT_ADRENALINE_ORB] = COMPOUND_STRING("Adrenaline Orb"), + [HOLD_EFFECT_MEMORY] = COMPOUND_STRING("Memory"), + [HOLD_EFFECT_Z_CRYSTAL] = COMPOUND_STRING("Z-Crystal"), + [HOLD_EFFECT_UTILITY_UMBRELLA] = COMPOUND_STRING("Utility Umbrella"), + [HOLD_EFFECT_EJECT_PACK] = COMPOUND_STRING("Eject Pack"), + [HOLD_EFFECT_ROOM_SERVICE] = COMPOUND_STRING("Room Service"), + [HOLD_EFFECT_BLUNDER_POLICY] = COMPOUND_STRING("Blunder Policy"), + [HOLD_EFFECT_HEAVY_DUTY_BOOTS] = COMPOUND_STRING("Heavy Duty Boots"), + [HOLD_EFFECT_THROAT_SPRAY] = COMPOUND_STRING("Throat Spray"), + [HOLD_EFFECT_ABILITY_SHIELD] = COMPOUND_STRING("Ability Shield"), + [HOLD_EFFECT_CLEAR_AMULET] = COMPOUND_STRING("Clear Amulet"), + [HOLD_EFFECT_MIRROR_HERB] = COMPOUND_STRING("Mirror Herb"), + [HOLD_EFFECT_PUNCHING_GLOVE] = COMPOUND_STRING("Punching Glove"), + [HOLD_EFFECT_COVERT_CLOAK] = COMPOUND_STRING("Covert Cloak"), + [HOLD_EFFECT_LOADED_DICE] = COMPOUND_STRING("Loaded Dice"), + [HOLD_EFFECT_BOOSTER_ENERGY] = COMPOUND_STRING("Booster Energy"), + [HOLD_EFFECT_OGERPON_MASK] = COMPOUND_STRING("Ogerpon Mask"), + [HOLD_EFFECT_BERSERK_GENE] = COMPOUND_STRING("Berserk Gene"), }; static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect) { - if (holdEffect > ARRAY_COUNT(sHoldEffectNames)) + if (sHoldEffectNames[holdEffect] == NULL) return sHoldEffectNames[0]; return sHoldEffectNames[holdEffect]; } diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index a34ecc21b..1ddc2b2b0 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -74,7 +74,7 @@ static const struct GMaxMove sGMaxMoveTable[] = bool32 CanDynamax(u32 battler) { u16 species = GetBattlerVisualSpecies(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Prevents Zigzagoon from dynamaxing in vanilla. if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE && !IsOnPlayerSide(battler)) @@ -181,14 +181,14 @@ void ActivateDynamax(u32 battler) gBattleStruct->dynamax.dynamaxTurns[battler] = gBattleTurnCounter + DYNAMAX_TURNS_COUNT; // Substitute is removed upon Dynamaxing. - gBattleMons[battler].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[battler].volatiles.substitute = FALSE; ClearBehindSubstituteBit(battler); // Choiced Moves are reset upon Dynamaxing. gBattleStruct->choicedMove[battler] = MOVE_NONE; // Try Gigantamax form change. - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) // Ditto cannot Gigantamax. + if (!gBattleMons[battler].volatiles.transformed) // Ditto cannot Gigantamax. TryBattleFormChange(battler, FORM_CHANGE_BATTLE_GIGANTAMAX); BattleScriptExecute(BattleScript_DynamaxBegins); @@ -234,21 +234,6 @@ bool32 IsMoveBlockedByMaxGuard(u32 move) return FALSE; } -// Weight-based moves (and some other moves in Raids) are blocked by Dynamax. -bool32 IsMoveBlockedByDynamax(u32 move) -{ - // TODO: Certain moves are banned in raids. - switch (GetMoveEffect(move)) - { - case EFFECT_HEAT_CRASH: - case EFFECT_LOW_KICK: - return TRUE; - default: - break; - } - return FALSE; -} - static u16 GetTypeBasedMaxMove(u32 battler, u32 type) { // Gigantamax check diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index b63fd3938..3b2c0f8cf 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -163,14 +163,14 @@ static bool32 HandleEndTurnVarious(u32 battler) for (i = 0; i < gBattlersCount; i++) { - if (gStatuses3[i] & STATUS3_ALWAYS_HITS) - gStatuses3[i] -= STATUS3_ALWAYS_HITS_TURN(1); + if (gBattleMons[i].volatiles.lockOn > 0) + gBattleMons[i].volatiles.lockOn--; if (gDisableStructs[i].chargeTimer && --gDisableStructs[i].chargeTimer == 0) - gStatuses3[i] &= ~STATUS3_CHARGED_UP; + gBattleMons[i].volatiles.charge = FALSE; - if (gStatuses3[i] & STATUS3_LASER_FOCUS && gDisableStructs[i].laserFocusTimer == gBattleTurnCounter) - gStatuses3[i] &= ~STATUS3_LASER_FOCUS; + if (gBattleMons[i].volatiles.laserFocus && gDisableStructs[i].laserFocusTimer == gBattleTurnCounter) + gBattleMons[i].volatiles.laserFocus = FALSE; gBattleStruct->hpBefore[i] = gBattleMons[i].hp; } @@ -188,7 +188,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); u32 currBattleWeather = GetCurrentBattleWeather(); if (currBattleWeather == 0xFF) @@ -232,9 +232,10 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && ability != ABILITY_SAND_FORCE && ability != ABILITY_SAND_RUSH && ability != ABILITY_OVERCOAT - && !IS_BATTLER_ANY_TYPE(gBattlerAttacker, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) - && !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES + && !IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; @@ -257,8 +258,9 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) if (ability != ABILITY_SNOW_CLOAK && ability != ABILITY_OVERCOAT && !IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; @@ -292,7 +294,7 @@ static bool32 HandleEndTurnGenThreeBerryActivation(u32 battler) static bool32 HandleEndTurnEmergencyExit(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattleStruct->turnEffectsBattlerId++; @@ -306,7 +308,7 @@ static bool32 HandleEndTurnEmergencyExit(u32 battler) && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) && CountUsablePartyMons(battler) > 0 - && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) // Not currently held by Sky Drop + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) // Not currently held by Sky Drop { gBattlerAbility = battler; gLastUsedAbility = ability; @@ -407,7 +409,7 @@ static bool32 HandleEndTurnWish(u32 battler) } gBattleStruct->moveDamage[battler] *= -1; - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.healBlock) BattleScriptExecute(BattleScript_WishButHealBlocked); else if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) BattleScriptExecute(BattleScript_WishButFullHp); @@ -423,17 +425,22 @@ static bool32 HandleEndTurnWish(u32 battler) static bool32 HandleEndTurnFirstEventBlock(u32 battler) { bool32 effect = FALSE; - u32 side; + if (!IsBattlerAlive(battler)) + { + gBattleStruct->eventBlockCounter = 0; + gBattleStruct->turnEffectsBattlerId++; + return effect; + } + switch (gBattleStruct->eventBlockCounter) { case FIRST_EVENT_BLOCK_GMAX_MOVE_RESIDUAL: // TODO: Has to be split into 3 statuses and needs a queue side = GetBattlerSide(battler); if (gSideStatuses[side] & SIDE_STATUS_DAMAGE_NON_TYPES) { - if (IsBattlerAlive(battler) - && !IS_BATTLER_OF_TYPE(battler, gSideTimers[side].damageNonTypesType) + if (!IS_BATTLER_OF_TYPE(battler, gSideTimers[side].damageNonTypesType) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattlerAttacker = battler; @@ -446,7 +453,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_SEA_OF_FIRE_DAMAGE: - if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SEA_OF_FIRE && IsBattlerAlive(battler)) + if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SEA_OF_FIRE) { gBattlerAttacker = battler; gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; @@ -458,21 +465,21 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_THRASH: - if (gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + if (gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) { - gBattleMons[battler].status2 -= STATUS2_LOCK_CONFUSE_TURN(1); + gBattleMons[battler].volatiles.lockConfusionTurns--; if (WasUnableToUseMove(battler)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); } - else if (!(gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) && (gBattleMons[battler].status2 & STATUS2_MULTIPLETURNS)) + else if (!gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.multipleTurns) { - gBattleMons[battler].status2 &= ~STATUS2_MULTIPLETURNS; - if (!(gBattleMons[battler].status2 & STATUS2_CONFUSION)) + gBattleMons[battler].volatiles.multipleTurns = FALSE; + if (!gBattleMons[battler].volatiles.confusionTurns) { gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; SetMoveEffect(battler, battler, TRUE, FALSE); - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns) BattleScriptExecute(BattleScript_ThrashConfuses); effect = TRUE; } @@ -481,10 +488,16 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL: - if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && IsBattlerGrounded(battler)) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN + && !IsBattlerAtMaxHp(battler) + && !gBattleMons[battler].volatiles.healBlock + && !IsSemiInvulnerable(battler, CHECK_ALL) + && IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) { gBattlerAttacker = battler; gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16); + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = -1; BattleScriptExecute(BattleScript_GrassyTerrainHeals); effect = TRUE; } @@ -492,7 +505,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) break; case FIRST_EVENT_BLOCK_ABILITIES: { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_HEALER: @@ -501,28 +514,19 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; break; + default: + break; } gBattleStruct->eventBlockCounter++; break; } case FIRST_EVENT_BLOCK_HEAL_ITEMS: - { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); - switch (holdEffect) - { - case HOLD_EFFECT_LEFTOVERS: - case HOLD_EFFECT_BLACK_SLUDGE: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) - effect = TRUE; - break; - default: - break; - } + if (ItemBattleEffects(ITEMEFFECT_LEFTOVERS, battler)) + effect = TRUE; gBattleStruct->eventBlockCounter = 0; gBattleStruct->turnEffectsBattlerId++; break; } - } return effect; } @@ -533,8 +537,8 @@ static bool32 HandleEndTurnAquaRing(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_AQUA_RING - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.aquaRing + && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { @@ -552,8 +556,8 @@ static bool32 HandleEndTurnIngrain(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_ROOTED - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.root + && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { @@ -571,24 +575,24 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_LEECHSEED - && IsBattlerAlive(gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER) + if (gBattleMons[battler].volatiles.leechSeed + && IsBattlerAlive(gBattleMons[battler].volatiles.leechSeed - 1) && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { - gBattlerTarget = gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER; // Notice gBattlerTarget is actually the HP receiver. + gBattlerTarget = gBattleMons[battler].volatiles.leechSeed - 1; // leech seed receiver gBattleScripting.animArg1 = gBattlerTarget; gBattleScripting.animArg2 = gBattlerAttacker; gBattleStruct->moveDamage[gBattlerAttacker] = max(1, GetNonDynamaxMaxHP(battler) / 8); gBattleStruct->moveDamage[gBattlerTarget] = GetDrainedBigRootHp(gBattlerTarget, gBattleStruct->moveDamage[gBattlerAttacker]); - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE; + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE; if (GetBattlerAbility(battler) == ABILITY_LIQUID_OOZE) { gBattleStruct->moveDamage[gBattlerTarget] = gBattleStruct->moveDamage[gBattlerTarget] * -1; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_OOZE; BattleScriptExecute(BattleScript_LeechSeedTurnDrainLiquidOoze); } - else if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + else if (gBattleMons[gBattlerTarget].volatiles.healBlock) { BattleScriptExecute(BattleScript_LeechSeedTurnDrainHealBlock); } @@ -607,7 +611,7 @@ static bool32 HandleEndTurnPoison(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattleStruct->turnEffectsBattlerId++; @@ -617,7 +621,7 @@ static bool32 HandleEndTurnPoison(u32 battler) { if (ability == ABILITY_POISON_HEAL) { - if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!IsBattlerAtMaxHp(battler) && !gBattleMons[battler].volatiles.healBlock) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) @@ -655,7 +659,7 @@ static bool32 HandleEndTurnBurn(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattleStruct->turnEffectsBattlerId++; @@ -705,7 +709,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE + if (gBattleMons[battler].volatiles.nightmare && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -719,7 +723,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) } else { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; } } @@ -732,7 +736,7 @@ static bool32 HandleEndTurnCurse(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_CURSED + if (gBattleMons[battler].volatiles.cursed && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -752,10 +756,11 @@ static bool32 HandleEndTurnWrap(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_WRAPPED && IsBattlerAlive(battler)) + if (gBattleMons[battler].volatiles.wrapped && IsBattlerAlive(battler)) { - if (--gDisableStructs[battler].wrapTurns != 0) + if (gDisableStructs[battler].wrapTurns != 0) { + gDisableStructs[battler].wrapTurns--; if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) return effect; @@ -763,7 +768,7 @@ static bool32 HandleEndTurnWrap(u32 battler) gBattleScripting.animArg2 = gBattleStruct->wrappedMove[battler] >> 8; PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); BattleScriptExecute(BattleScript_WrapTurnDmg); - if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[battler], TRUE) == HOLD_EFFECT_BINDING_BAND) + if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[battler]) == HOLD_EFFECT_BINDING_BAND) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); @@ -773,7 +778,7 @@ static bool32 HandleEndTurnWrap(u32 battler) } else // broke free { - gBattleMons[battler].status2 &= ~STATUS2_WRAPPED; + gBattleMons[battler].volatiles.wrapped = FALSE; PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); BattleScriptExecute(BattleScript_WrapEnds); } @@ -789,7 +794,7 @@ static bool32 HandleEndTurnSaltCure(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses4[battler] & STATUS4_SALT_CURE + if (gBattleMons[battler].volatiles.saltCure && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -830,10 +835,10 @@ static bool32 HandleEndTurnSyrupBomb(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (IsBattlerAlive(battler))) + if (gBattleMons[battler].volatiles.syrupBomb && (IsBattlerAlive(battler))) { if (gDisableStructs[battler].syrupBombTimer > 0 && --gDisableStructs[battler].syrupBombTimer == 0) - gStatuses4[battler] &= ~STATUS4_SYRUP_BOMB; + gBattleMons[battler].volatiles.syrupBomb = FALSE; PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn; BattleScriptExecute(gBattlescriptCurrInstr); @@ -867,7 +872,7 @@ static bool32 HandleEndTurnTorment(u32 battler) if (gDisableStructs[battler].tormentTimer == gBattleTurnCounter) { - gBattleMons[battler].status2 &= ~STATUS2_TORMENT; + gBattleMons[battler].volatiles.torment = FALSE; BattleScriptExecute(BattleScript_TormentEnds); effect = TRUE; } @@ -937,9 +942,9 @@ static bool32 HandleEndTurnMagnetRise(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_MAGNET_RISE && gDisableStructs[battler].magnetRiseTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.magnetRise && gDisableStructs[battler].magnetRiseTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_MAGNET_RISE; + gBattleMons[battler].volatiles.magnetRise = FALSE; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_STRING_BUFFER(gBattleTextBuff1, STRINGID_ELECTROMAGNETISM); effect = TRUE; @@ -954,9 +959,9 @@ static bool32 HandleEndTurnTelekinesis(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_TELEKINESIS && gDisableStructs[battler].telekinesisTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.telekinesis && gDisableStructs[battler].telekinesisTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_TELEKINESIS; + gBattleMons[battler].volatiles.telekinesis = FALSE; BattleScriptExecute(BattleScript_TelekinesisEndTurn); effect = TRUE; } @@ -970,9 +975,9 @@ static bool32 HandleEndTurnHealBlock(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK && gDisableStructs[battler].healBlockTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.healBlock && gDisableStructs[battler].healBlockTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; + gBattleMons[battler].volatiles.healBlock = FALSE; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_HEAL_BLOCK); effect = TRUE; @@ -987,9 +992,9 @@ static bool32 HandleEndTurnEmbargo(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_EMBARGO && gDisableStructs[battler].embargoTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.embargo && gDisableStructs[battler].embargoTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_EMBARGO; + gBattleMons[battler].volatiles.embargo = FALSE; BattleScriptExecute(BattleScript_EmbargoEndTurn); effect = TRUE; } @@ -1001,34 +1006,43 @@ static bool32 HandleEndTurnYawn(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_YAWN) + if (gBattleMons[battler].volatiles.yawn > 0) { - gStatuses3[battler] -= STATUS3_YAWN_TURN(1); - if (!(gStatuses3[battler] & STATUS3_YAWN) && !(gBattleMons[battler].status1 & STATUS1_ANY) + gBattleMons[battler].volatiles.yawn--; + if (!gBattleMons[battler].volatiles.yawn + && !(gBattleMons[battler].status1 & STATUS1_ANY) && ability != ABILITY_VITAL_SPIRIT && ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(battler) && !IsLeafGuardProtected(battler, ability)) { - CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN); gEffectBattler = gBattlerTarget = battler; - if (IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN)) + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (IsBattlerTerrainAffected(battler, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } - else if (IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(battler, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY; BattleScriptExecute(BattleScript_TerrainPreventsEnd2); } else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) { - BattleScriptExecute(BattleScript_SleepClausePreventsEnd); + BattleScriptExecute(BattleScript_SleepClausePreventsEnd2); + } + else if ((gBattleScripting.battler = IsAbilityOnSide(battler, ABILITY_SWEET_VEIL))) + { + gBattleScripting.battler--; + gLastUsedAbility = ABILITY_SWEET_VEIL; + gBattlerAbility = gBattleScripting.battler; + RecordAbilityBattle(gBattleScripting.battler, ABILITY_SWEET_VEIL); + BattleScriptExecute(BattleScript_ImmunityProtectedEnd2); } else { @@ -1037,10 +1051,11 @@ static bool32 HandleEndTurnYawn(u32 battler) else gBattleMons[battler].status1 |= ((Random() % 4) + 3); + CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN); TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); - BattleScriptExecute(BattleScript_YawnMakesAsleep); + BattleScriptExecute(BattleScript_YawnMakesAsleepEnd2); } effect = TRUE; } @@ -1055,12 +1070,12 @@ static bool32 HandleEndTurnPerishSong(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (IsBattlerAlive(battler) && gStatuses3[battler] & STATUS3_PERISH_SONG) + if (IsBattlerAlive(battler) && gBattleMons[battler].volatiles.perishSong) { PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[battler].perishSongTimer); if (gDisableStructs[battler].perishSongTimer == 0) { - gStatuses3[battler] &= ~STATUS3_PERISH_SONG; + gBattleMons[battler].volatiles.perishSong = FALSE; gBattleStruct->moveDamage[battler] = gBattleMons[battler].hp; BattleScriptExecute(BattleScript_PerishSongTakesLife); } @@ -1349,39 +1364,36 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) switch (gBattleStruct->eventBlockCounter) { case THIRD_EVENT_BLOCK_UPROAR: - if (gBattleMons[battler].status2 & STATUS2_UPROAR) + if (gBattleMons[battler].volatiles.uproarTurns) { - for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) + for (gEffectBattler = 0; gEffectBattler < gBattlersCount; gEffectBattler++) { - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) + if ((gBattleMons[gEffectBattler].status1 & STATUS1_SLEEP) + && GetBattlerAbility(gEffectBattler) != ABILITY_SOUNDPROOF) { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gEffectBattler].status1 &= ~STATUS1_SLEEP; + gBattleMons[gEffectBattler].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = 1; BattleScriptExecute(BattleScript_MonWokeUpInUproar); - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); - MarkBattlerForControllerExec(gBattlerAttacker); + BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(gEffectBattler); + effect = TRUE; break; } } - if (gBattlerAttacker != gBattlersCount) - { - break; - } - else + if (effect == FALSE) { gBattlerAttacker = battler; - gBattleMons[battler].status2 -= STATUS2_UPROAR_TURN(1); // uproar timer goes down + gBattleMons[battler].volatiles.uproarTurns--; // uproar timer goes down if (WasUnableToUseMove(battler)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_ENDS; } - else if (gBattleMons[battler].status2 & STATUS2_UPROAR) + else if (gBattleMons[battler].volatiles.uproarTurns) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_CONTINUES; - gBattleMons[battler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[battler].volatiles.multipleTurns = TRUE; } else { @@ -1396,7 +1408,7 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) break; case THIRD_EVENT_BLOCK_ABILITIES: { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_TRUANT: // Not fully accurate but it has to be handled somehow. TODO: Find a better way. @@ -1411,13 +1423,15 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; break; + default: + break; } gBattleStruct->eventBlockCounter++; break; } case THIRD_EVENT_BLOCK_ITEMS: { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); switch (holdEffect) { case HOLD_EFFECT_FLAME_ORB: @@ -1427,7 +1441,7 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) effect = TRUE; break; case HOLD_EFFECT_WHITE_HERB: - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) + if (ItemBattleEffects(ITEMEFFECT_WHITE_HERB_ENDTURN, battler)) effect = TRUE; break; default: @@ -1446,7 +1460,7 @@ static bool32 HandleEndTurnAbilities(u32 battler) { bool32 effect = FALSE; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); gBattleStruct->turnEffectsBattlerId++; @@ -1458,6 +1472,8 @@ static bool32 HandleEndTurnAbilities(u32 battler) case ABILITY_ZEN_MODE: if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) effect = TRUE; + default: + break; } return effect; @@ -1471,7 +1487,7 @@ static bool32 HandleEndTurnFourthEventBlock(u32 battler) { case FOURTH_EVENT_BLOCK_HUNGER_SWITCH: { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (ability == ABILITY_HUNGER_SWITCH) { if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) @@ -1482,7 +1498,7 @@ static bool32 HandleEndTurnFourthEventBlock(u32 battler) } case FOURTH_EVENT_BLOCK_EJECT_PACK: { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); if (holdEffect == HOLD_EFFECT_EJECT_PACK) { if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) @@ -1514,6 +1530,19 @@ static bool32 HandleEndTurnDynamax(u32 battler) return effect; } +/* + * Various end turn effects that happen after all battlers moved. + * Each Case will apply the effects for each battler. Moving to the next case when all battlers are done. + * If an effect is going to be applied on a better, the bool effect will be set to TRUE and a script set. + * The script is set with `BattleScriptExecute` and should have the ending `end2` + Example: + BattleScriptExecute(BattleScript_X); + + (in battle_scripts_1.s) + BattleScript_X: + some commands + end2 + */ static bool32 (*const sEndTurnEffectHandlers[])(u32 battler) = { [ENDTURN_ORDER] = HandleEndTurnOrder, diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index ed4cd2fcb..6054324b7 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -23,6 +23,7 @@ #include "data.h" #include "palette.h" // #include "contest.h" +#include "trainer_pokemon_sprites.h" #include "constants/songs.h" #include "constants/rgb.h" // #include "constants/battle_palace.h" @@ -259,13 +260,15 @@ static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite) #undef sSpeedX -void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 status) +void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isVolatile, u32 status) { gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 1; - if (!isStatus2) + if (!isVolatile) { - if (status == STATUS1_FREEZE || status == STATUS1_FROSTBITE) + if (status == STATUS1_FREEZE) LaunchStatusAnimation(battler, B_ANIM_STATUS_FRZ); + else if (status == STATUS1_FROSTBITE) + LaunchStatusAnimation(battler, B_ANIM_STATUS_FRB); else if (status == STATUS1_POISON || status & STATUS1_TOXIC_POISON) LaunchStatusAnimation(battler, B_ANIM_STATUS_PSN); else if (status == STATUS1_BURN) @@ -279,13 +282,13 @@ void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 statu } else { - if (status & STATUS2_INFATUATION) + if (status == VOLATILE_INFATUATION) LaunchStatusAnimation(battler, B_ANIM_STATUS_INFATUATION); - else if (status & STATUS2_CONFUSION) + else if (status == VOLATILE_CONFUSION) LaunchStatusAnimation(battler, B_ANIM_STATUS_CONFUSION); - else if (status & STATUS2_CURSED) + else if (status == VOLATILE_CURSED) LaunchStatusAnimation(battler, B_ANIM_STATUS_CURSED); - else if (status & STATUS2_NIGHTMARE) + else if (status == VOLATILE_NIGHTMARE) LaunchStatusAnimation(battler, B_ANIM_STATUS_NIGHTMARE); else // no animation gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 0; @@ -483,17 +486,6 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) } } -void DecompressGhostFrontPic(struct Pokemon *unused, u8 battlerId) -{ - u16 palOffset; - u8 position = GetBattlerPosition(battlerId); - - DecompressDataWithHeaderWram(gGhostFrontPic, gMonSpritesGfxPtr->spritesGfx[position]); - palOffset = OBJ_PLTT_ID(battlerId); - LoadPalette(gGhostPalette, palOffset, PLTT_SIZE_4BPP); - LoadPalette(gGhostPalette, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP); -} - void BattleGfxSfxDummy2(u16 species) { } @@ -509,17 +501,11 @@ void DecompressTrainerFrontPic(u16 frontPicId, u8 battler) void DecompressTrainerBackPic(u16 backPicId, u8 battler) { u8 position = GetBattlerPosition(battler); - DecompressPicFromTable(&gTrainerBacksprites[backPicId].backPic, - gMonSpritesGfxPtr->spritesGfx[position]); + CopyTrainerBackspriteFramesToDest(backPicId, gMonSpritesGfxPtr->spritesGfx[position]); LoadPalette(gTrainerBacksprites[backPicId].palette.data, OBJ_PLTT_ID(battler), PLTT_SIZE_4BPP); } -void DecompressTrainerBackPalette(u16 index, u8 palette) -{ - LoadPalette(gTrainerBacksprites[index].palette.data, OBJ_PLTT_ID2(palette), PLTT_SIZE_4BPP); -} - void FreeTrainerFrontPicPalette(u16 frontPicId) { FreeSpritePaletteByTag(gTrainerSprites[frontPicId].palette.tag); @@ -683,15 +669,8 @@ bool8 BattleInitAllSprites(u8 *state1, u8 *battler) } break; case 5: - if (IsOnPlayerSide(*battler)) - { - if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) - UpdateHealthboxAttribute(gHealthboxSpriteIds[*battler], GetBattlerMon(*battler), HEALTHBOX_ALL); - } - else - { + if (!IsOnPlayerSide(*battler) || !(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) UpdateHealthboxAttribute(gHealthboxSpriteIds[*battler], GetBattlerMon(*battler), HEALTHBOX_ALL); - } SetHealthboxSpriteInvisible(gHealthboxSpriteIds[*battler]); (*battler)++; if (*battler == gBattlersCount) @@ -764,7 +743,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo { // Get base form if its currently Gigantamax if (IsGigantamaxed(battlerDef)) - targetSpecies = gBattleStruct->changedSpecies[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]]; + targetSpecies = GetBattlerPartyState(battlerDef)->changedSpecies; else if (gBattleStruct->illusion[battlerDef].state == ILLUSION_ON) targetSpecies = GetIllusionMonSpecies(battlerDef); else @@ -826,13 +805,6 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); } - // Terastallization's tint - if (GetActiveGimmick(battlerAtk) == GIMMICK_TERA) - { - BlendPalette(paletteOffset, 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battlerAtk))); - CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); - } - gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk); StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], 0); } @@ -991,7 +963,7 @@ void CreateEnemyShadowSprite(u32 battler) { if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) { - u16 species = SanitizeSpeciesId(gBattleMons[battler].species); + u16 species = GetBattlerVisualSpecies(battler); u8 size = gSpeciesInfo[species].enemyShadowSize; gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow, @@ -1095,8 +1067,8 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite) } else if (transformSpecies != SPECIES_NONE) { - xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset; - yOffset = gSpeciesInfo[transformSpecies].enemyShadowYOffset; + xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16); + yOffset = gSpeciesInfo[transformSpecies].enemyShadowYOffset + 16; size = gSpeciesInfo[transformSpecies].enemyShadowSize; invisible = (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) @@ -1105,7 +1077,7 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite) } else if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) { - u16 species = SanitizeSpeciesId(gBattleMons[battler].species); + u16 species = GetBattlerVisualSpecies(battler); xOffset = gSpeciesInfo[species].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16); yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16; size = gSpeciesInfo[species].enemyShadowSize; @@ -1297,3 +1269,14 @@ bool32 ShouldPlayNormalMonCry(struct Pokemon *mon) return TRUE; } + +void DecompressGhostFrontPic(u32 battlerId) +{ + u16 palOffset; + u8 position = GetBattlerPosition(battlerId); + + DecompressDataWithHeaderWram(gGhostFrontPic, gMonSpritesGfxPtr->spritesGfx[position]); + palOffset = OBJ_PLTT_ID(battlerId); + LoadPalette(gGhostPalette, palOffset, PLTT_SIZE_4BPP); + LoadPalette(gGhostPalette, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP); +} diff --git a/src/battle_interface.c b/src/battle_interface.c index f538543e1..43bea37f2 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -2197,30 +2197,71 @@ static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 wi CpuCopy32(windowTileData + 256, dest + 256, windowWidth * TILE_SIZE_4BPP); } -#define ABILITY_POP_UP_TAG 0xD720 +#undef sBattlerId -// for sprite -#define tOriginalX data[0] -#define tHide data[1] -#define tFrames data[2] -#define tRightToLeft data[3] -#define tBattlerId data[4] -#define tIsMain data[5] +#define ABILITY_POP_UP_POS_X_DIFF 64 +#define ABILITY_POP_UP_POS_X_SLIDE 128 +#define ABILITY_POP_UP_POS_X_SPEED 4 -// for task -#define tSpriteId1 data[6] -#define tSpriteId2 data[7] +#define ABILITY_POP_UP_WIN_WIDTH 10 +#define ABILITY_POP_UP_STR_WIDTH (ABILITY_POP_UP_WIN_WIDTH * 8) -static const u8 ALIGNED(4) sAbilityPopUpGfx[] = INCBIN_U8("graphics/battle_interface/ability_pop_up.4bpp"); +#define ABILITY_POP_UP_PLAYER_LEFT_WIN_W 6 +#define ABILITY_POP_UP_PLAYER_RIGHT_WIN_W 4 +#define ABILITY_POP_UP_OPPONENT_LEFT_WIN_W 7 +#define ABILITY_POP_UP_OPPONENT_RIGHT_WIN_W 3 + +#define ABILITY_POP_UP_WAIT_FRAMES 48 + +/* + * BG = BackGround + * FG = ForeGround + * SH = SHadow + */ +#define ABILITY_POP_UP_BATTLER_BG_TXTCLR 2 +#define ABILITY_POP_UP_BATTLER_FG_TXTCLR 7 +#define ABILITY_POP_UP_BATTLER_SH_TXTCLR 1 + +#define ABILITY_POP_UP_ABILITY_BG_TXTCLR 7 +#define ABILITY_POP_UP_ABILITY_FG_TXTCLR 9 +#define ABILITY_POP_UP_ABILITY_SH_TXTCLR 1 + +#define sState data[0] +#define sAutoDestroy data[1] +#define sTimer data[2] +#define sIsPlayerSide data[3] +#define sBattlerId data[4] +#define sIsMain data[5] + +enum +{ + APU_STATE_SLIDE_IN = 0, + APU_STATE_IDLE, + APU_STATE_SLIDE_OUT, + APU_STATE_END +}; + +enum +{ + TAG_ABILITY_POP_UP = 0xD720, // Only used for the SpritePalette, the rest below is for the SpriteSheets. + TAG_ABILITY_POP_UP_PLAYER1 = TAG_ABILITY_POP_UP, + TAG_ABILITY_POP_UP_OPPONENT1, + TAG_ABILITY_POP_UP_PLAYER2, + TAG_ABILITY_POP_UP_OPPONENT2, + TAG_LAST_BALL_WINDOW, +}; + +static const u32 sAbilityPopUpGfx[] = INCBIN_U32("graphics/battle_interface/ability_pop_up.4bpp"); static const u16 sAbilityPopUpPalette[] = INCBIN_U16("graphics/battle_interface/ability_pop_up.gbapal"); static const struct SpriteSheet sSpriteSheet_AbilityPopUp = { - sAbilityPopUpGfx, sizeof(sAbilityPopUpGfx), ABILITY_POP_UP_TAG + sAbilityPopUpGfx, sizeof(sAbilityPopUpGfx), TAG_ABILITY_POP_UP }; + static const struct SpritePalette sSpritePalette_AbilityPopUp = { - sAbilityPopUpPalette, ABILITY_POP_UP_TAG + sAbilityPopUpPalette, TAG_ABILITY_POP_UP }; static const struct OamData sOamData_AbilityPopUp = @@ -2234,8 +2275,8 @@ static const struct OamData sOamData_AbilityPopUp = static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp = { - .tileTag = ABILITY_POP_UP_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .tileTag = TAG_NONE, // Changed on the fly. + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_AbilityPopUp, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2243,279 +2284,150 @@ static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp = .callback = SpriteCb_AbilityPopUp }; -#define ABILITY_POP_UP_POS_X_DIFF (64 - 7) // Hide second sprite underneath to gain proper letter spacing -#define ABILITY_POP_UP_POS_X_SLIDE 68 - static const s16 sAbilityPopUpCoordsDoubles[MAX_BATTLERS_COUNT][2] = { - {29, 80}, // player left - {186, 19}, // opponent left - {29, 97}, // player right - {186, 36}, // opponent right + { 24, 80}, // Player left + {178, 19}, // Opponent left + { 24, 97}, // Player right + {178, 36}, // Opponent right }; static const s16 sAbilityPopUpCoordsSingles[MAX_BATTLERS_COUNT][2] = { - {29, 97}, // player - {186, 57}, // opponent + { 24, 97}, // Player + {178, 57}, // Opponent }; -#define POPUP_WINDOW_WIDTH 8 -#define MAX_POPUP_STRING_WIDTH (POPUP_WINDOW_WIDTH * 8) - -static u8* AddTextPrinterAndCreateWindowOnAbilityPopUp(const u8 *str, u32 x, u32 y, u32 color1, u32 color2, u32 color3, u32 *windowId) +static u8 *AddTextPrinterAndCreateWindowOnAbilityPopUp(const u8 *str, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 *windowId) { u32 fontId; - u8 color[3] = {color1, color2, color3}; + u8 color[3] = {bgColor, fgColor, shadowColor}; struct WindowTemplate winTemplate = {0}; - winTemplate.width = POPUP_WINDOW_WIDTH; + winTemplate.width = ABILITY_POP_UP_WIN_WIDTH; winTemplate.height = 2; *windowId = AddWindow(&winTemplate); - FillWindowPixelBuffer(*windowId, PIXEL_FILL(color1)); + FillWindowPixelBuffer(*windowId, PIXEL_FILL(bgColor)); - fontId = GetFontIdToFit(str, FONT_SMALL, 0, 76); + fontId = GetFontIdToFit(str, FONT_SMALL, 0, ABILITY_POP_UP_STR_WIDTH); AddTextPrinterParameterized4(*windowId, fontId, x, y, 0, 0, color, TEXT_SKIP_DRAW, str); + return (u8 *)(GetWindowAttribute(*windowId, WINDOW_TILE_DATA)); } -static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 xTileAmount, bool32 arg3) +static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 windowWidth, bool32 printNickname) { - CpuCopy32(windowTileData + 256, dest + 256, xTileAmount * 32); - if (xTileAmount > 0) + #define PIXELS(n) (n * 4) + if (windowWidth > 0) { do { - if (arg3) - CpuCopy32(windowTileData + 16, dest + 16, 16); + if (printNickname) + { + CpuCopy32(windowTileData + PIXELS(3), dest + PIXELS(3), PIXELS(5)); + CpuCopy32(windowTileData + TILE_OFFSET_4BPP(ABILITY_POP_UP_WIN_WIDTH), dest + TILE_OFFSET_4BPP(8), PIXELS(5)); + } else - CpuCopy32(windowTileData + 20, dest + 20, 12); - dest += 32, windowTileData += 32; - xTileAmount--; - } while (xTileAmount != 0); + { + CpuCopy32(windowTileData + PIXELS(7), dest + PIXELS(7), PIXELS(1)); + CpuCopy32(windowTileData + TILE_OFFSET_4BPP(ABILITY_POP_UP_WIN_WIDTH), dest + TILE_OFFSET_4BPP(8), TILE_SIZE_4BPP); + } + + dest += TILE_SIZE_4BPP, windowTileData += TILE_SIZE_4BPP; + windowWidth--; + } while (windowWidth != 0); } + #undef PIXELS } -static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x1, u32 x2, u32 y, u32 color1, u32 color2, u32 color3) +static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 printNickname, u32 battler) { - u32 windowId; - u8 *windowTileData; - u16 width; + u32 windowId, fontId; + u8 *windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x, y, bgColor, fgColor, shadowColor, &windowId); + u32 size1 = ABILITY_POP_UP_OPPONENT_LEFT_WIN_W, size2 = ABILITY_POP_UP_OPPONENT_RIGHT_WIN_W; - windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x1, y, color1, color2, color3, &windowId); - TextIntoAbilityPopUp(spriteTileData1, windowTileData, 8, (y == 0)); - RemoveWindow(windowId); - - width = GetStringWidth(FONT_SMALL, str, 0); - - if (width > MAX_POPUP_STRING_WIDTH - 5) + spriteTileData1 += TILE_OFFSET_4BPP(1); + if (IsOnPlayerSide(battler)) { - windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x2 - MAX_POPUP_STRING_WIDTH, y, color1, color2, color3, &windowId); - TextIntoAbilityPopUp(spriteTileData2, windowTileData, 3, (y == 0)); - RemoveWindow(windowId); + size1 = ABILITY_POP_UP_PLAYER_LEFT_WIN_W, size2 = ABILITY_POP_UP_PLAYER_RIGHT_WIN_W; + // Increment again as the *first* column of the sprite + // is not shown for player's pop up when sliding in. + spriteTileData1 += TILE_OFFSET_4BPP(1); } -} -static const u8 sText_Spaces20[]= _(" "); -static void ClearAbilityName(u8 spriteId1, u8 spriteId2) -{ - PrintOnAbilityPopUp(sText_Spaces20, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, - 5, 12, - 4, - 7, 9, 1); + TextIntoAbilityPopUp(spriteTileData1, windowTileData, size1, printNickname); + fontId = GetFontIdToFit(str, FONT_SMALL, 0, ABILITY_POP_UP_STR_WIDTH); + if (GetStringWidth(fontId, str, 0) > (size1 * 8)) + { + windowTileData += TILE_OFFSET_4BPP(size1); + TextIntoAbilityPopUp(spriteTileData2, windowTileData, size2, printNickname); + } + + RemoveWindow(windowId); } static void PrintBattlerOnAbilityPopUp(u8 battler, u8 spriteId1, u8 spriteId2) { - int i; - u8 lastChar; - u8* textPtr; - u8 monName[POKEMON_NAME_LENGTH + 3] = {0}; + u32 totalChar = 0, lastChar; struct Pokemon *illusionMon = GetIllusionMonPtr(battler); - u8 nick[POKEMON_NAME_LENGTH + 1] = {0}; if (illusionMon != NULL) - GetMonData(illusionMon, MON_DATA_NICKNAME, nick); + GetMonData(illusionMon, MON_DATA_NICKNAME, gStringVar1); else - GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, nick); + GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, gStringVar1); - for (i = 0; i < POKEMON_NAME_LENGTH; ++i) - { - if (nick[i] == EOS) // End of string - break; + while (gStringVar1[totalChar] != EOS) + totalChar++; - monName[i] = nick[i]; - } - - textPtr = monName + i; - - lastChar = *(textPtr - 1); - - // Make the string say "[NAME]'s" instead of "[NAME]" - textPtr[0] = CHAR_SGL_QUOTE_RIGHT; // apostraphe - textPtr++; + lastChar = gStringVar1[totalChar - 1]; + StringAppend(gStringVar1, COMPOUND_STRING("'")); if (lastChar != CHAR_S && lastChar != CHAR_s) - { - textPtr[0] = CHAR_s; - textPtr++; - } + StringAppend(gStringVar1, COMPOUND_STRING("s")); - textPtr[0] = EOS; - - PrintOnAbilityPopUp((const u8 *)monName, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32), - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32), - 5, 12, - 0, - 2, 7, 1); + PrintOnAbilityPopUp(gStringVar1, + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum), + 0, 0, + ABILITY_POP_UP_BATTLER_BG_TXTCLR, ABILITY_POP_UP_BATTLER_FG_TXTCLR, ABILITY_POP_UP_BATTLER_SH_TXTCLR, + TRUE, gSprites[spriteId1].sBattlerId); } -static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2) +static void PrintAbilityOnAbilityPopUp(enum Ability ability, u8 spriteId1, u8 spriteId2) { - ClearAbilityName(spriteId1, spriteId2); + PrintOnAbilityPopUp(COMPOUND_STRING(" "), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum) + TILE_OFFSET_4BPP(8), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum) + TILE_OFFSET_4BPP(8), + 0, 4, + ABILITY_POP_UP_ABILITY_BG_TXTCLR, ABILITY_POP_UP_ABILITY_FG_TXTCLR, ABILITY_POP_UP_ABILITY_SH_TXTCLR, + FALSE, gSprites[spriteId1].sBattlerId); PrintOnAbilityPopUp(gAbilitiesInfo[ability].name, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, - 5, 12, - 4, - 7, 9, 1); -} - -#define PIXEL_COORDS_TO_OFFSET(x, y)( \ -/*Add tiles by X*/ \ -((y / 8) * 32 * 8) \ -/*Add tiles by X*/ \ -+ ((x / 8) * 32) \ -/*Add pixels by Y*/ \ -+ ((((y) - ((y / 8) * 8))) * 4) \ -/*Add pixels by X*/ \ -+ ((((x) - ((x / 8) * 8)) / 2))) - -static const u16 sOverwrittenPixelsTable[][2] = -{ - {PIXEL_COORDS_TO_OFFSET(0, 0), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 1), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 2), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 3), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 4), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 5), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 6), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 7), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 8), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 9), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 10), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 11), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 12), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 13), 8}, - - {PIXEL_COORDS_TO_OFFSET(8, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(24, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(32, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(40, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(48, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(56, 13), 8}, - - {PIXEL_COORDS_TO_OFFSET(0, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(24, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(32, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(40, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(48, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(56, 14), 8}, - - {PIXEL_COORDS_TO_OFFSET(0, 15), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 16), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 17), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 18), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 19), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 20), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 21), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 22), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 23), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 24), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 25), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 26), 3}, - -//Second Row Of Image - {PIXEL_COORDS_TO_OFFSET(0, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(0, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(0, 47), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 47), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 47), 8}, -}; - -static inline void CopyPixels(u8 *dest, const u8 *src, u32 pixelCount) -{ - u32 i = 0; - - if (pixelCount & 1) - { - while (pixelCount != 0) - { - dest[i] &= ~(0xF); - dest[i] |= (src[i] & 0xF); - if (--pixelCount != 0) - { - dest[i] &= ~(0xF0); - dest[i] |= (src[i] & 0xF0); - pixelCount--; - } - i++; - } - } - else - { - for (i = 0; i < pixelCount / 2; i++) - dest[i] = src[i]; - } -} - -static void RestoreOverwrittenPixels(u8 *tiles) -{ - u32 i; - u8 *buffer = Alloc(sizeof(sAbilityPopUpGfx) * 2); - - CpuCopy32(tiles, buffer, sizeof(sAbilityPopUpGfx)); - - for (i = 0; i < ARRAY_COUNT(sOverwrittenPixelsTable); i++) - { - CopyPixels(buffer + sOverwrittenPixelsTable[i][0], - sAbilityPopUpGfx + sOverwrittenPixelsTable[i][0], - sOverwrittenPixelsTable[i][1]); - } - - CpuCopy32(buffer, tiles, sizeof(sAbilityPopUpGfx)); - Free(buffer); + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum) + TILE_OFFSET_4BPP(8), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum) + TILE_OFFSET_4BPP(8), + 0, 4, + ABILITY_POP_UP_ABILITY_BG_TXTCLR, ABILITY_POP_UP_ABILITY_FG_TXTCLR, ABILITY_POP_UP_ABILITY_SH_TXTCLR, + FALSE, gSprites[spriteId1].sBattlerId); } static inline bool32 IsAnyAbilityPopUpActive(void) { + u32 activeAbilityPopUps = 0; for (u32 battler = 0; battler < gBattlersCount; battler++) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) - return TRUE; + activeAbilityPopUps++; } - return FALSE; + return activeAbilityPopUps; } -void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) +void CreateAbilityPopUp(u8 battler, enum Ability ability, bool32 isDoubleBattle) { + u8 *spriteIds; + u32 xSlide, tileTag, battlerPosition = GetBattlerPosition(battler); + struct SpriteTemplate template; const s16 (*coords)[2]; - u8 spriteId1, spriteId2, battlerPosition, taskId; - if (B_ABILITY_POP_UP == FALSE) - return; - - if (gBattleScripting.abilityPopupOverwrite != 0) + if (gBattleScripting.abilityPopupOverwrite) ability = gBattleScripting.abilityPopupOverwrite; if (gTestRunnerEnabled) @@ -2526,111 +2438,122 @@ void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) } if (!IsAnyAbilityPopUpActive()) - { - LoadSpriteSheet(&sSpriteSheet_AbilityPopUp); LoadSpritePalette(&sSpritePalette_AbilityPopUp); + + tileTag = (TAG_ABILITY_POP_UP_PLAYER1 + battler); + if (IndexOfSpriteTileTag(tileTag) == 0xFF) + { + struct SpriteSheet sheet = sSpriteSheet_AbilityPopUp; + sheet.tag = tileTag; + LoadSpriteSheet(&sheet); } + coords = isDoubleBattle ? sAbilityPopUpCoordsDoubles : sAbilityPopUpCoordsSingles; + xSlide = IsOnPlayerSide(battler) ? -ABILITY_POP_UP_POS_X_SLIDE : ABILITY_POP_UP_POS_X_SLIDE; + + template = sSpriteTemplate_AbilityPopUp; + template.tileTag = tileTag; + spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; + spriteIds[0] = CreateSprite(&template, coords[battlerPosition][0] + xSlide, + coords[battlerPosition][1], 0); + spriteIds[1] = CreateSprite(&template, coords[battlerPosition][0] + xSlide + ABILITY_POP_UP_POS_X_DIFF, + coords[battlerPosition][1], 0); + + if (IsOnPlayerSide(battler)) + { + gSprites[spriteIds[0]].sIsPlayerSide = TRUE; + gSprites[spriteIds[1]].sIsPlayerSide = TRUE; + } + + gSprites[spriteIds[1]].oam.tileNum += 32; // Second half of the pop up tiles. + + // Create only one instance, as it's only used for + // tracking the SpriteSheet(s) and SpritePalette. + if (!IsAnyAbilityPopUpActive()) + CreateTask(Task_FreeAbilityPopUpGfx, 5); + gBattleStruct->battlerState[battler].activeAbilityPopUps = TRUE; - battlerPosition = GetBattlerPosition(battler); - if (isDoubleBattle) - coords = sAbilityPopUpCoordsDoubles; - else - coords = sAbilityPopUpCoordsSingles; + gSprites[spriteIds[0]].sIsMain = TRUE; + gSprites[spriteIds[0]].sBattlerId = battler; + gSprites[spriteIds[1]].sBattlerId = battler; - if ((battlerPosition & BIT_SIDE) == B_SIDE_PLAYER) - { - spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE, - coords[battlerPosition][1], 0); - spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF, - coords[battlerPosition][1], 1); //Appears below - - gSprites[spriteId1].tRightToLeft = TRUE; - gSprites[spriteId2].tRightToLeft = TRUE; - } - else - { - spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE, - coords[battlerPosition][1], 0); - spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF, - coords[battlerPosition][1], 1); //Appears below - - gSprites[spriteId1].tRightToLeft = FALSE; - gSprites[spriteId2].tRightToLeft = FALSE; - } - - gSprites[spriteId1].tOriginalX = coords[battlerPosition][0]; - gSprites[spriteId2].tOriginalX = coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_DIFF; - gSprites[spriteId2].oam.tileNum += (8 * 4); //Second half of pop up - - gBattleStruct->abilityPopUpSpriteIds[battler][0] = spriteId1; - gBattleStruct->abilityPopUpSpriteIds[battler][1] = spriteId2; - - taskId = CreateTask(Task_FreeAbilityPopUpGfx, 5); - gTasks[taskId].tSpriteId1 = spriteId1; - gTasks[taskId].tSpriteId2 = spriteId2; - - gSprites[spriteId1].tIsMain = TRUE; - gSprites[spriteId1].tBattlerId = battler; - gSprites[spriteId2].tBattlerId = battler; - - StartSpriteAnim(&gSprites[spriteId1], 0); - StartSpriteAnim(&gSprites[spriteId2], 0); - - PrintBattlerOnAbilityPopUp(battler, spriteId1, spriteId2); - PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); - RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); + PrintBattlerOnAbilityPopUp(battler, spriteIds[0], spriteIds[1]); + PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } void UpdateAbilityPopup(u8 battler) { - u8 spriteId1 = gBattleStruct->abilityPopUpSpriteIds[battler][0]; - u8 spriteId2 = gBattleStruct->abilityPopUpSpriteIds[battler][1]; - u16 ability = (gBattleScripting.abilityPopupOverwrite != 0) ? gBattleScripting.abilityPopupOverwrite : gBattleMons[battler].ability; - - PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); - RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); + u8 *spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; + enum Ability ability = (gBattleScripting.abilityPopupOverwrite) ? gBattleScripting.abilityPopupOverwrite + : gBattleMons[battler].ability; + PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } -#define FRAMES_TO_WAIT 48 - static void SpriteCb_AbilityPopUp(struct Sprite *sprite) { - if (!sprite->tHide) // Show + s16 *data = sprite->data; + u32 battlerPosition = GetBattlerPosition(sBattlerId); + u32 fullX = sprite->x + sprite->x2; + u32 speed; + + switch (sState) { - if (sprite->tIsMain && ++sprite->tFrames == 4) + case APU_STATE_SLIDE_IN: + { + const s16 (*coords)[2] = IsDoubleBattle() ? sAbilityPopUpCoordsDoubles : sAbilityPopUpCoordsSingles; + u32 xCoord = coords[battlerPosition][0]; + + if (sIsMain && ++sTimer == 4) PlaySE(SE_BALL_TRAY_ENTER); - if ((!sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX) - || (sprite->tRightToLeft && (sprite->x += 4) >= sprite->tOriginalX) - ) - { - sprite->x = sprite->tOriginalX; - sprite->tHide = TRUE; - sprite->tFrames = FRAMES_TO_WAIT; - } + + if (!sIsMain) + xCoord += ABILITY_POP_UP_POS_X_DIFF; + + if (fullX == xCoord) + { + sTimer = ABILITY_POP_UP_WAIT_FRAMES; + sState = APU_STATE_IDLE; + break; + } + + speed = sIsPlayerSide ? ABILITY_POP_UP_POS_X_SPEED : -ABILITY_POP_UP_POS_X_SPEED; + sprite->x2 += speed; + break; } - else // Hide + case APU_STATE_IDLE: { - if (sprite->tFrames == 0) + if (!sTimer || sAutoDestroy) { - if ((!sprite->tRightToLeft && (sprite->x += 4) >= sprite->tOriginalX + ABILITY_POP_UP_POS_X_SLIDE) - ||(sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE) - ) - { - gBattleStruct->battlerState[sprite->tBattlerId].activeAbilityPopUps = FALSE; - DestroySprite(sprite); - } - } - else - { - if (!gBattleScripting.fixedPopup) - sprite->tFrames--; + sState = APU_STATE_SLIDE_OUT; + break; } + + if (!gBattleScripting.fixedPopup) + sTimer--; + + break; + } + case APU_STATE_SLIDE_OUT: + { + if (fullX == sprite->x) + { + sState = APU_STATE_END; + break; + } + + speed = sIsPlayerSide ? -ABILITY_POP_UP_POS_X_SPEED : ABILITY_POP_UP_POS_X_SPEED; + sprite->x2 += speed; + break; + } + case APU_STATE_END: + { + if (sIsMain) + gBattleStruct->battlerState[sBattlerId].activeAbilityPopUps = FALSE; + + DestroySprite(sprite); + break; + } } } @@ -2638,26 +2561,33 @@ void DestroyAbilityPopUp(u8 battler) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) { - gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][0]].tFrames = 0; - gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][1]].tFrames = 0; + gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][0]].sAutoDestroy = TRUE; + gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][1]].sAutoDestroy = TRUE; } - gBattleScripting.fixedPopup = FALSE; } static void Task_FreeAbilityPopUpGfx(u8 taskId) { - if (!gSprites[gTasks[taskId].tSpriteId1].inUse - && !gSprites[gTasks[taskId].tSpriteId2].inUse - && !IsAnyAbilityPopUpActive()) + if (!IsAnyAbilityPopUpActive()) { - FreeSpriteTilesByTag(ABILITY_POP_UP_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (IndexOfSpriteTileTag(TAG_ABILITY_POP_UP_PLAYER1 + battler) != 0xFF) + FreeSpriteTilesByTag(TAG_ABILITY_POP_UP_PLAYER1 + battler); + } + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroyTask(taskId); } } +#undef sState +#undef sAutoDestroy +#undef sTimer +#undef sIsPlayerSide +#undef sBattlerId +#undef sIsMain + // last used ball -#define LAST_BALL_WINDOW_TAG 0xD721 static const struct OamData sOamData_LastUsedBall = { @@ -2678,8 +2608,8 @@ static const struct OamData sOamData_LastUsedBall = static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = { - .tileTag = LAST_BALL_WINDOW_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .tileTag = TAG_LAST_BALL_WINDOW, + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_LastUsedBall, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2709,7 +2639,7 @@ static const struct OamData sOamData_MoveInfoWindow = static const struct SpriteTemplate sSpriteTemplate_MoveInfoWindow = { .tileTag = MOVE_INFO_WINDOW_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_MoveInfoWindow, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2728,7 +2658,7 @@ static const struct SpriteTemplate sSpriteTemplate_MoveInfoWindow = #endif static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = { - sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), LAST_BALL_WINDOW_TAG + sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), TAG_LAST_BALL_WINDOW }; #if B_MOVE_DESCRIPTION_BUTTON == R_BUTTON @@ -2786,7 +2716,7 @@ void TryAddLastUsedBallItemSprites(void) // we have to compact the bag first bc it is typically only compacted when you open it CompactItemsInBagPocket(POCKET_POKE_BALLS); - firstBall = gBagPockets[POCKET_POKE_BALLS].itemSlots[0].itemId; + firstBall = GetBagItemId(POCKET_POKE_BALLS, 0); if (firstBall > ITEM_NONE) gBallToDisplay = firstBall; } @@ -2807,7 +2737,7 @@ void TryAddLastUsedBallItemSprites(void) // window LoadSpritePalette(&sSpritePalette_AbilityPopUp); - if (GetSpriteTileStartByTag(LAST_BALL_WINDOW_TAG) == 0xFFFF) + if (GetSpriteTileStartByTag(TAG_LAST_BALL_WINDOW) == 0xFFFF) LoadSpriteSheet(&sSpriteSheet_LastUsedBallWindow); if (gBattleStruct->ballSpriteIds[1] == MAX_SPRITES) @@ -2825,8 +2755,8 @@ void TryAddLastUsedBallItemSprites(void) static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) { - FreeSpriteTilesByTag(LAST_BALL_WINDOW_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + FreeSpriteTilesByTag(TAG_LAST_BALL_WINDOW); + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; } @@ -2863,7 +2793,7 @@ void TryToHideMoveInfoWindow(void) static void DestroyMoveInfoWinGfx(struct Sprite *sprite) { FreeSpriteTilesByTag(MOVE_INFO_WINDOW_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->moveInfoSpriteId = MAX_SPRITES; } diff --git a/src/battle_main.c b/src/battle_main.c index 839fcf8fa..e03ad5503 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -67,9 +67,9 @@ #include "constants/abilities.h" #include "constants/battle_ai.h" #include "constants/battle_move_effects.h" -#include "constants/battle_setup.h" #include "constants/battle_string_ids.h" #include "constants/battle_partner.h" +#include "constants/battle_setup.h" #include "constants/hold_effects.h" #include "constants/items.h" #include "constants/moves.h" @@ -95,6 +95,9 @@ static void BattleMainCB1(void); static void CB2_QuitPokedudeBattle(void); static void CB2_EndLinkBattle(void); static void EndLinkBattleInSteps(void); +// static void CB2_InitAskRecordBattle(void); +// static void CB2_AskRecordBattle(void); +// static void AskRecordBattle(void); static void SpriteCB_MoveWildMonToRight(struct Sprite *sprite); static void SpriteCB_WildMonShowHealthbox(struct Sprite *sprite); static void SpriteCB_WildMonAnimate(struct Sprite *sprite); @@ -168,7 +171,7 @@ EWRAM_DATA u16 gChosenMove = 0; EWRAM_DATA u16 gCalledMove = 0; EWRAM_DATA s32 gBideDmg[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gLastUsedItem = 0; -EWRAM_DATA u16 gLastUsedAbility = 0; +EWRAM_DATA enum Ability gLastUsedAbility = 0; EWRAM_DATA u8 gBattlerAttacker = 0; EWRAM_DATA u8 gBattlerTarget = 0; EWRAM_DATA u8 gBattlerFainted = 0; @@ -194,8 +197,6 @@ EWRAM_DATA u32 gHitMarker = 0; EWRAM_DATA u8 gBideTarget[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u32 gSideStatuses[NUM_BATTLE_SIDES] = {0}; EWRAM_DATA struct SideTimer gSideTimers[NUM_BATTLE_SIDES] = {0}; -EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0}; -EWRAM_DATA u32 gStatuses4[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gPauseCounterBattle = 0; EWRAM_DATA u16 gPaydayMoney = 0; @@ -239,7 +240,7 @@ EWRAM_DATA u16 gBattleTurnCounter = 0; EWRAM_DATA u8 gBattlerAbility = 0; EWRAM_DATA struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA bool8 gHasFetchedBall = FALSE; -EWRAM_DATA u8 gLastUsedBall = 0; +EWRAM_DATA u16 gLastUsedBall = 0; EWRAM_DATA u16 gLastThrownBall = 0; EWRAM_DATA u16 gBallToDisplay = 0; EWRAM_DATA bool8 gLastUsedBallMenuPresent = FALSE; @@ -541,10 +542,9 @@ static void CB2_InitBattleInternal(void) else { gBattle_WIN0V = WIN_RANGE(DISPLAY_HEIGHT / 2, DISPLAY_HEIGHT / 2 + 1); + ScanlineEffect_Clear(); if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless) { - ScanlineEffect_Clear(); - for (i = 0; i < DISPLAY_HEIGHT / 2; i++) { gScanlineEffectRegBuffers[0][i] = 0xF0; @@ -1481,7 +1481,7 @@ static void CB2_PreInitIngamePlayerPartnerBattle(void) *savedBattleTypeFlags = gBattleTypeFlags; gMain.savedCallback = CB2_PreInitIngamePlayerPartnerBattle; // if (!PlayerHasFollowerNPC() || !FollowerNPCIsBattlePartner() || (FNPC_NPC_FOLLOWER_PARTY_PREVIEW && FollowerNPCIsBattlePartner())) - ShowPartyMenuToShowcaseMultiBattleParty(); + ShowPartyMenuToShowcaseMultiBattleParty(); break; case 1: @@ -2106,7 +2106,24 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir u8 retVal; if (trainerNum == TRAINER_SECRET_BASE) return 0; - retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); + if (GetTrainerStructFromId(trainerNum)->overrideTrainer) + { + struct Trainer tempTrainer; + memcpy(&tempTrainer, GetTrainerStructFromId(trainerNum), sizeof(struct Trainer)); + const struct Trainer *origTrainer = GetTrainerStructFromId(tempTrainer.overrideTrainer); + + tempTrainer.party = origTrainer->party; + + tempTrainer.poolSize = origTrainer->poolSize; + if (tempTrainer.partySize == 0) + tempTrainer.partySize = origTrainer->partySize; + + retVal = CreateNPCTrainerPartyFromTrainer(party, (const struct Trainer *)(&tempTrainer), firstTrainer, gBattleTypeFlags); + } + else + { + retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); + } return retVal; } @@ -2767,8 +2784,6 @@ static void BattleStartClearSetData(void) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - gStatuses3[i] = 0; - gStatuses4[i] = 0; gDisableStructs[i].isFirstTurn = 2; gLastMoves[i] = MOVE_NONE; gLastLandedMoves[i] = MOVE_NONE; @@ -2874,14 +2889,13 @@ static void BattleStartClearSetData(void) } } -#define UNPACK_VOLATILE_BATON_PASSABLES(_enum, _fieldName, _typeBitSize, ...) __VA_OPT__(if ((FIRST(__VA_ARGS__)) & V_BATON_PASSABLE) gBattleMons[battler].volatiles._fieldName = volatilesCopy._fieldName;) +#define UNPACK_VOLATILE_BATON_PASSABLES(_enum, _fieldName, _typeMaxValue, ...) __VA_OPT__(if ((FIRST(__VA_ARGS__)) & V_BATON_PASSABLE) gBattleMons[battler].volatiles._fieldName = volatilesCopy->_fieldName;) -void SwitchInClearSetData(u32 battler) +void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) { s32 i; enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); struct DisableStruct disableStructCopy = gDisableStructs[battler]; - struct Volatiles volatilesCopy = gBattleMons[battler].volatiles; ClearIllusionMon(battler); if (effect != EFFECT_BATON_PASS) @@ -2890,58 +2904,52 @@ void SwitchInClearSetData(u32 battler) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == battler) - gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION; - if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].battlerWithSureHit == battler) + if (gBattleMons[i].volatiles.escapePrevention && gDisableStructs[i].battlerPreventingEscape == battler) + gBattleMons[i].volatiles.escapePrevention = FALSE; + if (gBattleMons[i].volatiles.lockOn && gDisableStructs[i].battlerWithSureHit == battler) { - gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; + gBattleMons[i].volatiles.lockOn = 0; gDisableStructs[i].battlerWithSureHit = 0; } } } + + // Clear volatiles - reapply some if Baton Pass was used + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); if (effect == EFFECT_BATON_PASS) { // Transfer Baton Passable volatile statuses - memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); VOLATILE_DEFINITIONS(UNPACK_VOLATILE_BATON_PASSABLES) /* Expands to the following (compiler removes `if` statements): - * gBattleMons[battler].volatiles.confusionTurns = volatilesCopy.confusionTurns; - * gBattleMons[battler].volatiles.substitute = volatilesCopy.substitute; - * gBattleMons[battler].volatiles.escapePrevention = volatilesCopy.escapePrevention; + * gBattleMons[battler].volatiles.confusionTurns = volatilesCopy->confusionTurns; + * gBattleMons[battler].volatiles.substitute = volatilesCopy->substitute; + * gBattleMons[battler].volatiles.escapePrevention = volatilesCopy->escapePrevention; * ...etc */ - gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED - | STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK - | STATUS3_AQUA_RING | STATUS3_POWER_TRICK); - gStatuses4[battler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT | STATUS4_INFINITE_CONFUSION); + for (i = 0; i < gBattlersCount; i++) { if (!IsBattlerAlly(battler, i) - && (gStatuses3[i] & STATUS3_ALWAYS_HITS) != 0 + && gBattleMons[i].volatiles.lockOn != 0 && (gDisableStructs[i].battlerWithSureHit == battler)) { - gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; - gStatuses3[i] |= STATUS3_ALWAYS_HITS_TURN(2); + gBattleMons[i].volatiles.lockOn = 0; } } - if (gStatuses3[battler] & STATUS3_POWER_TRICK) + if (gBattleMons[battler].volatiles.powerTrick) SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, i); } - else - { - gBattleMons[battler].status2 = 0; - gStatuses3[battler] = 0; - gStatuses4[battler] = 0; - } for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler)) - gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler); - if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler) - gBattleMons[i].status2 &= ~STATUS2_WRAPPED; - if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) - gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) + gBattleMons[i].volatiles.infatuation = 0; + if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + gBattleMons[i].volatiles.wrapped = FALSE; + if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + gBattleMons[i].volatiles.syrupBomb = FALSE; + if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) + gDisableStructs[i].octolock = FALSE; } gActionSelectionCursor[battler] = 0; @@ -2949,6 +2957,9 @@ void SwitchInClearSetData(u32 battler) memset(&gDisableStructs[battler], 0, sizeof(struct DisableStruct)); + if (GetProtectType(gProtectStructs[battler].protected) == PROTECT_TYPE_SINGLE) // Side type protects expire at the end of the turn + gProtectStructs[battler].protected = PROTECT_NONE; + if (effect == EFFECT_BATON_PASS) { gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP; @@ -2956,10 +2967,11 @@ void SwitchInClearSetData(u32 battler) gDisableStructs[battler].perishSongTimer = disableStructCopy.perishSongTimer; gDisableStructs[battler].battlerPreventingEscape = disableStructCopy.battlerPreventingEscape; gDisableStructs[battler].embargoTimer = disableStructCopy.embargoTimer; + gDisableStructs[battler].healBlockTimer = disableStructCopy.healBlockTimer; } else if (effect == EFFECT_SHED_TAIL) { - gBattleMons[battler].status2 |= STATUS2_SUBSTITUTE; + gBattleMons[battler].volatiles.substitute = TRUE; gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP; } @@ -3030,7 +3042,7 @@ void SwitchInClearSetData(u32 battler) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif // TESTING @@ -3045,20 +3057,22 @@ const u8* FaintClearSetData(u32 battler) for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - gBattleMons[battler].status2 = 0; - gStatuses3[battler] &= STATUS3_GASTRO_ACID; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. - gStatuses4[battler] = 0; + bool32 keepGastroAcid = gBattleMons[battler].volatiles.gastroAcid; + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); + gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == battler) - gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION; - if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler)) - gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler); - if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler) - gBattleMons[i].status2 &= ~STATUS2_WRAPPED; - if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) - gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gBattleMons[i].volatiles.escapePrevention && gDisableStructs[i].battlerPreventingEscape == battler) + gBattleMons[i].volatiles.escapePrevention = FALSE; + if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) + gBattleMons[i].volatiles.infatuation = 0; + if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + gBattleMons[i].volatiles.wrapped = FALSE; + if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + gBattleMons[i].volatiles.syrupBomb = FALSE; + if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) + gDisableStructs[i].octolock = FALSE; } gActionSelectionCursor[battler] = 0; @@ -3070,9 +3084,8 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].protected = PROTECT_NONE; gProtectStructs[battler].quash = FALSE; - gProtectStructs[battler].endured = FALSE; gProtectStructs[battler].noValidMoves = FALSE; - gProtectStructs[battler].helpingHand = FALSE; + gProtectStructs[battler].helpingHand = 0; gProtectStructs[battler].bounceMove = FALSE; gProtectStructs[battler].stealMove = FALSE; gProtectStructs[battler].nonVolatileStatusImmobility = FALSE; @@ -3080,9 +3093,7 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].confusionSelfDmg = FALSE; gProtectStructs[battler].chargingTurn = FALSE; gProtectStructs[battler].fleeType = 0; - gProtectStructs[battler].notFirstStrike = FALSE; gProtectStructs[battler].statRaised = FALSE; - gProtectStructs[battler].tryEjectPack = FALSE; gProtectStructs[battler].pranksterElevated = FALSE; gDisableStructs[battler].isFirstTurn = 2; @@ -3106,7 +3117,7 @@ const u8* FaintClearSetData(u32 battler) ClearPursuitValuesIfSet(battler); - if (gBattleStruct->commanderActive[battler] != SPECIES_NONE) + if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE) { u32 partner = BATTLE_PARTNER(battler); if (IsBattlerAlive(partner)) @@ -3149,27 +3160,28 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->skyDropTargets[otherSkyDropper] = SKY_DROP_NO_TARGET; // If the other Pokemon involved in this Sky Drop was the target, not the attacker - if (gStatuses3[otherSkyDropper] & STATUS3_SKY_DROPPED) + if (gBattleMons[otherSkyDropper].volatiles.semiInvulnerable == STATE_SKY_DROP) { // Release the target and take them out of the semi-invulnerable state - gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_NONE; // Make the target's sprite visible gSprites[gBattlerSpriteIds[otherSkyDropper]].invisible = FALSE; // If the target was sky dropped in the middle of using Outrage/Petal Dance/Thrash, // confuse them upon release and print "confused via fatigue" message and animation. - if (gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) + if (gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns) { - gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns = 0; // If the released mon can be confused, do so. // Don't use CanBeConfused here, since it can cause issues in edge cases. - if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO - || gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION - || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) + enum Ability ability = GetBattlerAbility(otherSkyDropper); + if (!(ability == ABILITY_OWN_TEMPO + || gBattleMons[otherSkyDropper].volatiles.confusionTurns + || IsBattlerTerrainAffected(otherSkyDropper, ability, GetBattlerHoldEffect(otherSkyDropper), STATUS_FIELD_MISTY_TERRAIN))) { - gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattlerAttacker = otherSkyDropper; result = BattleScript_ThrashConfuses; } @@ -3232,7 +3244,7 @@ static void DoBattleIntro(void) gBattleMons[battler].types[2] = TYPE_MYSTERY; gBattleMons[battler].ability = GetAbilityBySpecies(gBattleMons[battler].species, gBattleMons[battler].abilityNum); gBattleStruct->hpOnSwitchout[GetBattlerSide(battler)] = gBattleMons[battler].hp; - gBattleMons[battler].status2 = 0; + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; #if TESTING @@ -3241,7 +3253,7 @@ static void DoBattleIntro(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif } @@ -3418,7 +3430,7 @@ static void DoBattleIntro(void) case BATTLE_INTRO_STATE_WAIT_FOR_WILD_BATTLE_TEXT: if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { - if (IS_BATTLE_TYPE_GHOST_WITH_SCOPE(gBattleTypeFlags)) + if (gBattleTypeFlags & BATTLE_TYPE_GHOST && CheckBagHasItem(ITEM_SILPH_SCOPE, 1)) { gBattleScripting.battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); BattleScriptExecute(BattleScript_SilphScopeUnveiled); @@ -3495,7 +3507,7 @@ static void DoBattleIntro(void) | BATTLE_TYPE_GHOST | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_LEGENDARY)) - || ((gBattleTypeFlags & (BATTLE_TYPE_GHOST | BATTLE_TYPE_GHOST_UNVEILED)) && !IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)))) + || ((gBattleTypeFlags & (BATTLE_TYPE_GHOST | BATTLE_TYPE_GHOST_UNVEILED)) && !IsGhostBattleWithoutScope()))) { HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[battler].species), FLAG_SET_SEEN, gBattleMons[battler].personality); } @@ -3560,7 +3572,7 @@ static void TryDoEventsBeforeFirstTurn(void) u32 side = GetBattlerSide(i); u32 partyIndex = gBattlerPartyIndexes[i]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } } #endif // TESTING @@ -3622,28 +3634,28 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_NEUTRALIZING_GAS: - if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) - return; - gBattleStruct->eventsBeforeFirstTurnState++; - break; - case FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES: while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest { i = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; - - if (TryPrimalReversion(i)) - return; - if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0) != 0) - return; - if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN)) + if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, i, gBattleMons[i].ability, 0, 0) != 0) return; } gBattleStruct->switchInBattlerCounter = 0; gBattleStruct->eventsBeforeFirstTurnState++; break; - case FIRST_TURN_EVENTS_OPPORTUNIST_1: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - return; + case FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + + if (TryPrimalReversion(battler)) + return; + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0)) + return; + if (TryClearIllusion(battler, ABILITYEFFECT_ON_SWITCHIN)) + return; + } + gBattleStruct->switchInBattlerCounter = 0; gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_ITEM_EFFECTS: @@ -3655,9 +3667,32 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleStruct->switchInBattlerCounter = 0; gBattleStruct->eventsBeforeFirstTurnState++; break; - case FIRST_TURN_EVENTS_OPPORTUNIST_2: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - return; + case FIRST_TURN_EVENTS_WHITE_HERB: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + if (ItemBattleEffects(ITEMEFFECT_WHITE_HERB_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++])) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventsBeforeFirstTurnState++; + break; + case FIRST_TURN_EVENTS_OPPORTUNIST: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST_FIRST_TURN, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->switchInBattlerCounter = 0; + gBattleStruct->eventsBeforeFirstTurnState++; + break; + case FIRST_TURN_EVENTS_MIRROR_HERB: + while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest + { + if (ItemBattleEffects(ITEMEFFECT_MIRROR_HERB_FIRST_TURN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++])) + return; + } + gBattleStruct->switchInBattlerCounter = 0; gBattleStruct->eventsBeforeFirstTurnState++; break; case FIRST_TURN_EVENTS_EJECT_PACK: @@ -3684,14 +3719,14 @@ static void TryDoEventsBeforeFirstTurn(void) for (i = 0; i < gBattlersCount; i++) { - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; + gBattleMons[i].volatiles.flinched = FALSE; // Record party slots of player's mons that appeared in battle if (!BattlerHasAi(i)) gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[i]; } - *(&gBattleStruct->eventBlockCounter) = 0; - *(&gBattleStruct->turnEffectsBattlerId) = 0; + gBattleStruct->eventBlockCounter = 0; + gBattleStruct->turnEffectsBattlerId = 0; gBattleScripting.moveendState = 0; gBattleStruct->faintedActionsState = 0; gBattleStruct->endTurnEventsCounter = 0; @@ -3724,8 +3759,8 @@ static void HandleEndTurn_ContinueBattle(void) gBattleCommunication[i] = 0; for (i = 0; i < gBattlersCount; i++) { - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; - if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].status2 & STATUS2_MULTIPLETURNS)) + gBattleMons[i].volatiles.flinched = FALSE; + if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].volatiles.multipleTurns)) CancelMultiTurnMoves(i, SKY_DROP_IGNORE); } gBattleStruct->eventBlockCounter = 0; @@ -3752,10 +3787,10 @@ void BattleTurnPassed(void) gBattleStruct->faintedActionsState = 0; TurnValuesCleanUp(FALSE); - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; gHitMarker &= ~HITMARKER_UNABLE_TO_USE_MOVE; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; gHitMarker &= ~HITMARKER_PLAYER_FAINTED; - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; @@ -3781,9 +3816,9 @@ void BattleTurnPassed(void) gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; - gStatuses4[i] &= ~STATUS4_ELECTRIFIED; - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; - gBattleMons[i].status2 &= ~STATUS2_POWDER; + gBattleMons[i].volatiles.electrified = FALSE; + gBattleMons[i].volatiles.flinched = FALSE; + gBattleMons[i].volatiles.powder = FALSE; if (gBattleStruct->battlerState[i].stompingTantrumTimer > 0) gBattleStruct->battlerState[i].stompingTantrumTimer--; @@ -3967,8 +4002,8 @@ static void HandleTurnActionSelectionState(void) } else { - if (gBattleMons[battler].status2 & STATUS2_MULTIPLETURNS - || gBattleMons[battler].status2 & STATUS2_RECHARGE) + if (gBattleMons[battler].volatiles.multipleTurns + || gBattleMons[battler].volatiles.recharge) { gChosenActionByBattler[battler] = B_ACTION_USE_MOVE; gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; @@ -4050,7 +4085,7 @@ static void HandleTurnActionSelectionState(void) } break; case B_ACTION_USE_ITEM: - if (FlagGet(B_FLAG_NO_BAG_USE)) + if (ShouldBattleRestrictionsApply(battler) && !IsAllowedToUseBag()) { RecordedBattle_ClearBattlerAction(battler, 1); gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed; @@ -4066,7 +4101,7 @@ static void HandleTurnActionSelectionState(void) | BATTLE_TYPE_RECORDED_LINK)) && !gTestRunnerEnabled) // Or if currently held by Sky Drop - || gStatuses3[battler] & STATUS3_SKY_DROPPED) + || gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) { RecordedBattle_ClearBattlerAction(battler, 1); gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed; @@ -4118,8 +4153,8 @@ static void HandleTurnActionSelectionState(void) gBattleCommunication[battler] = STATE_WAIT_SET_BEFORE_ACTION; gBattleCommunication[GetPartnerBattler(battler)] = STATE_BEFORE_ACTION_CHOSEN; RecordedBattle_ClearBattlerAction(battler, 1); - if (gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_MULTIPLETURNS - || gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_RECHARGE) + if (gBattleMons[GetPartnerBattler(battler)].volatiles.multipleTurns + || gBattleMons[GetPartnerBattler(battler)].volatiles.recharge) { BtlController_EmitEndBounceEffect(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); @@ -4248,8 +4283,12 @@ static void HandleTurnActionSelectionState(void) // Get the chosen move position (and thus the chosen move) and target from the returned buffer. gBattleStruct->chosenMovePositions[battler] = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK; - gChosenMoveByBattler[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + gChosenMoveByBattler[battler] = GetChosenMoveFromPosition(battler); gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3]; + if (IsBattleMoveStatus(gChosenMoveByBattler[battler]) && GetBattlerAbility(battler) == ABILITY_MYCELIUM_MIGHT) + gProtectStructs[battler].myceliumMight = TRUE; + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LAGGING_TAIL) + gProtectStructs[battler].laggingTail = TRUE; // Check to see if any gimmicks need to be prepared. if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) @@ -4258,13 +4297,16 @@ static void HandleTurnActionSelectionState(void) // Max Move check if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX)) { - gBattleStruct->dynamax.baseMoves[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + gBattleStruct->dynamax.baseMoves[battler] = GetChosenMoveFromPosition(battler); } gBattleCommunication[battler]++; if (gTestRunnerEnabled) { - TestRunner_Battle_CheckChosenMove(battler, gChosenMoveByBattler[battler], gBattleStruct->moveTarget[battler]); + UNUSED enum Gimmick gimmick = GIMMICK_NONE; + if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) + gimmick = gBattleStruct->gimmick.usableGimmick[battler]; + TestRunner_Battle_CheckChosenMove(battler, gChosenMoveByBattler[battler], gBattleStruct->moveTarget[battler], gimmick); } } break; @@ -4478,7 +4520,7 @@ void SwapTurnOrder(u8 id1, u8 id2) } // For AI, so it doesn't 'cheat' by knowing player's ability -u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +u32 GetBattlerTotalSpeedStatArgs(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect) { u32 speed = gBattleMons[battler].speed; @@ -4506,9 +4548,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h speed *= 2; else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; - else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) + else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].volatiles.transformed) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; - else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) + else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].volatiles.transformed) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive) speed *= 2; @@ -4528,7 +4570,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h speed /= 2; else if (holdEffect == HOLD_EFFECT_CHOICE_SCARF && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) speed = (speed * 150) / 100; - else if (holdEffect == HOLD_EFFECT_QUICK_POWDER && gBattleMons[battler].species == SPECIES_DITTO && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + else if (holdEffect == HOLD_EFFECT_QUICK_POWDER && gBattleMons[battler].species == SPECIES_DITTO && !(gBattleMons[battler].volatiles.transformed)) speed *= 2; // various effects @@ -4547,12 +4589,12 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h u32 GetBattlerTotalSpeedStat(u32 battler) { - u32 ability = GetBattlerAbility(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum Ability ability = GetBattlerAbility(battler); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); return GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); } -s32 GetChosenMovePriority(u32 battler, u32 ability) +s32 GetChosenMovePriority(u32 battler, enum Ability ability) { u16 move; @@ -4560,12 +4602,12 @@ s32 GetChosenMovePriority(u32 battler, u32 ability) if (gProtectStructs[battler].noValidMoves) move = MOVE_STRUGGLE; else - move = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; + move = GetChosenMoveFromPosition(battler); return GetBattleMovePriority(battler, ability, move); } -s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) +s32 GetBattleMovePriority(u32 battler, enum Ability ability, u32 move) { s32 priority = 0; @@ -4578,9 +4620,13 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS) return GetMovePriority(MOVE_MAX_GUARD); - if (ability == ABILITY_GALE_WINGS - && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) - && GetMoveType(move) == TYPE_FLYING) + if (gProtectStructs[battler].quash) + { + priority = -8; + } + else if (ability == ABILITY_GALE_WINGS + && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) + && GetMoveType(move) == TYPE_FLYING) { priority++; } @@ -4589,20 +4635,19 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) gProtectStructs[battler].pranksterElevated = 1; priority++; } - else if (GetMoveEffect(move) == EFFECT_GRASSY_GLIDE && IsBattlerTerrainAffected(battler, STATUS_FIELD_GRASSY_TERRAIN) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX && !IsGimmickSelected(battler, GIMMICK_DYNAMAX)) + else if (GetMoveEffect(move) == EFFECT_GRASSY_GLIDE && IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_GRASSY_TERRAIN) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX && !IsGimmickSelected(battler, GIMMICK_DYNAMAX)) { priority++; } else if (ability == ABILITY_TRIAGE && IsHealingMove(move)) + { priority += 3; - - if (gProtectStructs[battler].quash) - priority = -8; + } return priority; } -s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, +s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, enum Ability ability1, enum Ability ability2, enum ItemHoldEffect holdEffectBattler1, enum ItemHoldEffect holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) { u32 strikesFirst = 0; @@ -4614,16 +4659,16 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Lagging Tail - always last bool32 battler1HasQuickEffect = gProtectStructs[battler1].quickDraw || gProtectStructs[battler1].usedCustapBerry; bool32 battler2HasQuickEffect = gProtectStructs[battler2].quickDraw || gProtectStructs[battler2].usedCustapBerry; - bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || (ability1 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler1])); - bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || (ability2 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler2])); + bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || gProtectStructs[battler1].myceliumMight; + bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || gProtectStructs[battler2].myceliumMight; if (battler1HasQuickEffect && !battler2HasQuickEffect) strikesFirst = 1; else if (battler2HasQuickEffect && !battler1HasQuickEffect) strikesFirst = -1; - else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL) + else if (gProtectStructs[battler1].laggingTail && !gProtectStructs[battler2].laggingTail) strikesFirst = -1; - else if (holdEffectBattler2 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler1 != HOLD_EFFECT_LAGGING_TAIL) + else if (gProtectStructs[battler2].laggingTail && !gProtectStructs[battler1].laggingTail) strikesFirst = 1; else if (battler1HasStallingAbility && !battler2HasStallingAbility) strikesFirst = -1; @@ -4668,12 +4713,12 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) { s32 priority1 = 0, priority2 = 0; - u32 ability1 = GetBattlerAbility(battler1); + enum Ability ability1 = GetBattlerAbility(battler1); u32 speedBattler1 = GetBattlerTotalSpeedStat(battler1); - enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); + enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1); u32 speedBattler2 = GetBattlerTotalSpeedStat(battler2); - enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); - u32 ability2 = GetBattlerAbility(battler2); + enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2); + enum Ability ability2 = GetBattlerAbility(battler2); if (!ignoreChosenMoves) { @@ -4874,15 +4919,15 @@ static void TurnValuesCleanUp(bool8 var0) { gDisableStructs[i].rechargeTimer--; if (gDisableStructs[i].rechargeTimer == 0) - gBattleMons[i].status2 &= ~STATUS2_RECHARGE; + gBattleMons[i].volatiles.recharge = FALSE; } gBattleStruct->battlerState[i].canPickupItem = FALSE; } if (gDisableStructs[i].substituteHP == 0) - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; - if (!(gStatuses3[i] & STATUS3_COMMANDER)) + if (gBattleMons[i].volatiles.semiInvulnerable != STATE_COMMANDER) gBattleStruct->battlerState[i].commandingDondozo = FALSE; gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF; @@ -4942,7 +4987,7 @@ static bool32 TryDoGimmicksBeforeMoves(void) } } - if (B_MEGA_EVO_TURN_ORDER >= GEN_7) + if (GetGenConfig(GEN_CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7) TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved. return FALSE; } @@ -5009,10 +5054,10 @@ static void TryChangeTurnOrder(void) static void TryChangingTurnOrderEffects(u32 battler1, u32 battler2, u32 *quickClawRandom, u32 *quickDrawRandom) { - u32 ability1 = GetBattlerAbility(battler1); - enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1, TRUE); - enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2, TRUE); - u32 ability2 = GetBattlerAbility(battler2); + enum Ability ability1 = GetBattlerAbility(battler1); + enum ItemHoldEffect holdEffectBattler1 = GetBattlerHoldEffect(battler1); + enum ItemHoldEffect holdEffectBattler2 = GetBattlerHoldEffect(battler2); + enum Ability ability2 = GetBattlerAbility(battler2); // Battler 1 // Quick Draw @@ -5056,14 +5101,14 @@ static void CheckChangingTurnOrderEffects(void) { gLastUsedItem = gBattleMons[battler].item; PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_CUSTAP_BERRY) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_CUSTAP_BERRY) { // don't record berry since its gone now BattleScriptExecute(BattleScript_CustapBerryActivation); } else { - RecordItemEffectBattle(battler, GetBattlerHoldEffect(battler, FALSE)); + RecordItemEffectBattle(battler, GetBattlerHoldEffect(battler)); BattleScriptExecute(BattleScript_QuickClawActivation); } } @@ -5089,14 +5134,13 @@ static void CheckChangingTurnOrderEffects(void) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { gBattleStruct->battlerState[i].focusPunchBattlers = FALSE; - gBattleStruct->ateBoost[i] = FALSE; + gBattleStruct->battlerState[i].ateBoost = FALSE; gSpecialStatuses[i].gemBoost = FALSE; } gBattleMainFunc = RunTurnActionsFunctions; gBattleCommunication[3] = 0; gBattleCommunication[4] = 0; - gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; } @@ -5128,14 +5172,14 @@ static void RunTurnActionsFunctions(void) if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished { - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; } else { if (gBattleStruct->savedTurnActionNumber != gCurrentTurnActionNumber) // action turn has been done, clear hitmarker bits for another battler { - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; gHitMarker &= ~HITMARKER_UNABLE_TO_USE_MOVE; } } @@ -5261,7 +5305,8 @@ static void HandleEndTurn_FinishBattle(void) | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_SAFARI | BATTLE_TYPE_FIRST_BATTLE - | BATTLE_TYPE_LINK))) + | BATTLE_TYPE_LINK)) + && !(gBattleTypeFlags & BATTLE_TYPE_GHOST && IsGhostBattleWithoutScope())) { for (battler = 0; battler < gBattlersCount; battler++) { @@ -5278,11 +5323,16 @@ static void HandleEndTurn_FinishBattle(void) GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, gBattleResults.playerMon2Name); } } + else if (!IsOnPlayerSide(battler)) + { + HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[battler].species), FLAG_SET_SEEN, gBattleMons[battler].personality); + } } } TrySetQuestLogBattleEvent(); if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) ClearRematchStateByTrainerId(); + RecordedBattle_SetPlaybackFinished(); if (gTestRunnerEnabled) TestRunner_Battle_AfterLastTurn(); @@ -5310,8 +5360,8 @@ static void HandleEndTurn_FinishBattle(void) changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); // Clear original species field - gBattleStruct->changedSpecies[B_SIDE_PLAYER][i] = SPECIES_NONE; - gBattleStruct->changedSpecies[B_SIDE_OPPONENT][i] = SPECIES_NONE; + gBattleStruct->partyState[B_SIDE_PLAYER][i].changedSpecies = SPECIES_NONE; + gBattleStruct->partyState[B_SIDE_OPPONENT][i].changedSpecies = SPECIES_NONE; // Recalculate the stats of every party member before the end if (!changedForm && B_RECALCULATE_STATS >= GEN_5) @@ -5482,7 +5532,7 @@ void RunBattleScriptCommands(void) gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } -u32 TrySetAteType(u32 move, u32 battlerAtk, u32 attackerAbility) +u32 TrySetAteType(u32 move, u32 battlerAtk, enum Ability attackerAbility) { u32 ateType = TYPE_NONE; @@ -5534,7 +5584,8 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState { u32 moveType = GetMoveType(move); enum BattleMoveEffects moveEffect = GetMoveEffect(move); - u32 species, heldItem, ability, type1, type2, type3; + u32 species, heldItem, type1, type2, type3; + enum Ability ability; enum ItemHoldEffect holdEffect; enum Gimmick gimmick = GetActiveGimmick(battler); @@ -5545,7 +5596,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState { species = gBattleMons[battler].species; heldItem = gBattleMons[battler].item; - holdEffect = GetBattlerHoldEffect(battler, TRUE); + holdEffect = GetBattlerHoldEffect(battler); ability = GetBattlerAbility(battler); type1 = gBattleMons[battler].types[0]; type2 = gBattleMons[battler].types[1]; @@ -5687,7 +5738,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState case EFFECT_TERRAIN_PULSE: if (state == MON_IN_BATTLE) { - if (IsBattlerTerrainAffected(battler, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), STATUS_FIELD_TERRAIN_ANY)) { if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) return TYPE_ELECTRIC; @@ -5747,7 +5798,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState { u32 ateType = TrySetAteType(move, battler, ability); if (ateType != TYPE_NONE && state == MON_IN_BATTLE) - gBattleStruct->ateBoost[battler] = TRUE; + gBattleStruct->battlerState[battler].ateBoost = TRUE; return ateType; } else if (moveEffect != EFFECT_CHANGE_TYPE_ON_ITEM @@ -5759,7 +5810,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState && gimmick != GIMMICK_Z_MOVE) { if (state == MON_IN_BATTLE && gimmick != GIMMICK_DYNAMAX) - gBattleStruct->ateBoost[battler] = TRUE; + gBattleStruct->battlerState[battler].ateBoost = TRUE; return TYPE_NORMAL; } @@ -5770,10 +5821,10 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler) { u32 moveType; u32 heldItem = gBattleMons[battler].item; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); gBattleStruct->dynamicMoveType = 0; - gBattleStruct->ateBoost[battler] = FALSE; + gBattleStruct->battlerState[battler].ateBoost = FALSE; gSpecialStatuses[battler].gemBoost = FALSE; moveType = GetDynamicMoveType(GetBattlerMon(battler), @@ -5785,7 +5836,8 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler) gBattleStruct->dynamicMoveType = moveType | F_DYNAMIC_TYPE_SET; moveType = GetBattleMoveType(move); - if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL) || gStatuses4[battler] & STATUS4_ELECTRIFIED) + if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL) + || gBattleMons[battler].volatiles.electrified) gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_SET; // Check if a gem should activate. @@ -5861,3 +5913,10 @@ static s32 Factorial(s32 n) // return (gBattleOutcome == B_OUTCOME_FORFEITED); // } + +// Wins the battle instantly. Used in the battle debug with LIST_ITEM_INSTANT_WIN +void BattleDebug_WonBattle(void) +{ + gBattleOutcome |= B_OUTCOME_WON; + gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; +} diff --git a/src/battle_message.c b/src/battle_message.c index 2b65e0689..1affb72a0 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -301,13 +301,12 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PLAYERWHITEOUT2_WILD] = COMPOUND_STRING("You panicked and dropped ¥{B_BUFF1}…"), [STRINGID_PLAYERWHITEOUT2_TRAINER] = COMPOUND_STRING("You gave ¥{B_BUFF1} to the winner…"), [STRINGID_PLAYERWHITEOUT3] = COMPOUND_STRING("You were overwhelmed by your defeat!"), - [STRINGID_PREVENTSESCAPE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} prevents escape with {B_SCR_ACTIVE_ABILITY}!\p"), + [STRINGID_PREVENTSESCAPE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} prevents escape with {B_SCR_ABILITY}!\p"), [STRINGID_HITXTIMES] = COMPOUND_STRING("The Pokémon was hit {B_BUFF1} time(s)!"), //SV has dynamic plural here [STRINGID_PKMNFELLASLEEP] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} fell asleep!"), [STRINGID_PKMNMADESLEEP] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} made {B_EFF_NAME_WITH_PREFIX2} sleep!"), //not in gen 5+, ability popup [STRINGID_PKMNALREADYASLEEP] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is already asleep!"), [STRINGID_PKMNALREADYASLEEP2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is already asleep!"), - [STRINGID_PKMNWASNTAFFECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} wasn't affected!"), //not in gen 5+, ability popup [STRINGID_PKMNWASPOISONED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} was poisoned!"), [STRINGID_PKMNPOISONEDBY] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} was poisoned by {B_SCR_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), //not in gen 5+, ability popup [STRINGID_PKMNHURTBYPOISON] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} was hurt by its poisoning!"), @@ -328,11 +327,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNISPARALYZED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} couldn't move because it's paralyzed!"), [STRINGID_PKMNISALREADYPARALYZED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is already paralyzed!"), [STRINGID_PKMNHEALEDPARALYSIS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} was cured of paralysis!"), - [STRINGID_PKMNDREAMEATEN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s dream was eaten!"), //not in gen 5+, expansion doesn't use anymore [STRINGID_STATSWONTINCREASE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any higher!"), [STRINGID_STATSWONTDECREASE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any lower!"), - [STRINGID_TEAMSTOPPEDWORKING] = COMPOUND_STRING("Your team's {B_BUFF1} stopped working!"), //unused - [STRINGID_FOESTOPPEDWORKING] = COMPOUND_STRING("The foe's {B_BUFF1} stopped working!"), //unused [STRINGID_PKMNISCONFUSED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is confused!"), [STRINGID_PKMNHEALEDCONFUSION] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} snapped out of its confusion!"), [STRINGID_PKMNWASCONFUSED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} became confused!"), @@ -340,7 +336,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFELLINLOVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} fell in love!"), [STRINGID_PKMNINLOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is in love with {B_SCR_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNIMMOBILIZEDBYLOVE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is immobilized by love!"), - [STRINGID_PKMNBLOWNAWAY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} was blown away!"), //unused [STRINGID_PKMNCHANGEDTYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} transformed into the {B_BUFF1} type!"), [STRINGID_PKMNFLINCHED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} flinched and couldn't move!"), [STRINGID_PKMNREGAINEDHEALTH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s HP was restored."), @@ -378,13 +373,12 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFASTASLEEP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is fast asleep."), [STRINGID_PKMNWOKEUP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} woke up!"), [STRINGID_PKMNUPROARKEPTAWAKE] = COMPOUND_STRING("But the uproar kept {B_SCR_NAME_WITH_PREFIX2} awake!"), - [STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("The uproar woke {B_ATK_NAME_WITH_PREFIX2}!"), + [STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("The uproar woke {B_EFF_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNCAUSEDUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} caused an uproar!"), [STRINGID_PKMNMAKINGUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is making an uproar!"), [STRINGID_PKMNCALMEDDOWN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} calmed down."), [STRINGID_PKMNCANTSLEEPINUPROAR] = COMPOUND_STRING("But {B_DEF_NAME_WITH_PREFIX2} can't sleep in an uproar!"), [STRINGID_PKMNSTOCKPILED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} stockpiled {B_BUFF1}!"), - [STRINGID_PKMNCANTSTOCKPILE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} can't stockpile any more!"), //I think this was replaced with just "But it failed!" [STRINGID_PKMNCANTSLEEPINUPROAR2] = COMPOUND_STRING("But {B_DEF_NAME_WITH_PREFIX2} can't sleep in an uproar!"), [STRINGID_UPROARKEPTPKMNAWAKE] = COMPOUND_STRING("But the uproar kept {B_DEF_NAME_WITH_PREFIX2} awake!"), [STRINGID_PKMNSTAYEDAWAKEUSING] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} stayed awake using its {B_DEF_ABILITY}!"), //not in gen 5+, ability popup @@ -425,14 +419,14 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNENDUREDHIT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} endured the hit!"), [STRINGID_MAGNITUDESTRENGTH] = COMPOUND_STRING("Magnitude {B_BUFF1}!"), [STRINGID_PKMNCUTHPMAXEDATTACK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} cut its own HP and maximized its Attack!"), - [STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} copied {B_DEF_NAME_WITH_PREFIX2}'s stat changes!"), + [STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} copied {B_EFF_NAME_WITH_PREFIX2}'s stat changes!"), [STRINGID_PKMNGOTFREE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} got free of {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), //not in gen 5+, generic rapid spin? [STRINGID_PKMNSHEDLEECHSEED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} shed Leech Seed!"), //not in gen 5+, generic rapid spin? [STRINGID_PKMNBLEWAWAYSPIKES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} blew away Spikes!"), //not in gen 5+, generic rapid spin? [STRINGID_PKMNFLEDFROMBATTLE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} fled from battle!"), [STRINGID_PKMNFORESAWATTACK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} foresaw an attack!"), [STRINGID_PKMNTOOKATTACK] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} took the {B_BUFF1} attack!"), - [STRINGID_PKMNATTACK] = COMPOUND_STRING("{B_BUFF1}'s attack!"), //not in gen 5+, expansion doesn't use anymore + [STRINGID_PKMNATTACK] = COMPOUND_STRING("{B_BUFF1}'s attack!"), //not in gen 5+ [STRINGID_PKMNCENTERATTENTION] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} became the center of attention!"), [STRINGID_PKMNCHARGINGPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} began charging power!"), [STRINGID_NATUREPOWERTURNEDINTO] = COMPOUND_STRING("Nature Power turned into {B_CURRENT_MOVE}!"), @@ -446,7 +440,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNREADYTOHELP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is ready to help {B_DEF_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNSWITCHEDITEMS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} switched items with its target!"), [STRINGID_PKMNCOPIEDFOE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} copied {B_DEF_NAME_WITH_PREFIX2}'s Ability!"), - [STRINGID_PKMNMADEWISH] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} made a wish!"), //unused [STRINGID_PKMNWISHCAMETRUE] = COMPOUND_STRING("{B_BUFF1}'s wish came true!"), [STRINGID_PKMNPLANTEDROOTS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} planted its roots!"), [STRINGID_PKMNABSORBEDNUTRIENTS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} absorbed nutrients with its roots!"), @@ -462,30 +455,27 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNMOVEBOUNCED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} bounced the {B_CURRENT_MOVE} back!"), [STRINGID_PKMNWAITSFORTARGET] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} waits for a target to make a move!"), [STRINGID_PKMNSNATCHEDMOVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} snatched {B_SCR_NAME_WITH_PREFIX2}'s move!"), - [STRINGID_PKMNMADEITRAIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} made it rain!"), //not in gen 5+, ability popup - [STRINGID_PKMNRAISEDSPEED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} raised its Speed!"), //not in gen 5+, ability popup + [STRINGID_PKMNMADEITRAIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} made it rain!"), //not in gen 5+, ability popup [STRINGID_PKMNPROTECTEDBY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} was protected by {B_DEF_ABILITY}!"), //not in gen 5+, ability popup [STRINGID_PKMNPREVENTSUSAGE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} prevents {B_ATK_NAME_WITH_PREFIX2} from using {B_CURRENT_MOVE}!"), //I don't see this in SV text [STRINGID_PKMNRESTOREDHPUSING] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} restored HP using its {B_DEF_ABILITY}!"), //not in gen 5+, ability popup - [STRINGID_PKMNCHANGEDTYPEWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} made it the {B_BUFF1} type!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSPARALYSISWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ABILITY} prevents paralysis!"), //not in gen 5+, ability popup + [STRINGID_PKMNCHANGEDTYPEWITH] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}'s {B_EFF_ABILITY} made it the {B_BUFF1} type!"), //not in gen 5+, ability popup [STRINGID_PKMNPREVENTSROMANCEWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} prevents romance!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSPOISONINGWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ABILITY} prevents poisoning!"), //not in gen 5+, ability popup [STRINGID_PKMNPREVENTSCONFUSIONWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} prevents confusion!"), //not in gen 5+, ability popup [STRINGID_PKMNRAISEDFIREPOWERWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} raised the power of Fire-type moves!"), //not in gen 5+, ability popup [STRINGID_PKMNANCHORSITSELFWITH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} anchors itself with {B_DEF_ABILITY}!"), //not in gen 5+, ability popup - [STRINGID_PKMNCUTSATTACKWITH] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} cuts {B_DEF_NAME_WITH_PREFIX2}'s Attack!"), //not in gen 5+, ability popup - [STRINGID_PKMNPREVENTSSTATLOSSWITH] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} prevents stat loss!"), //not in gen 5+, ability popup + [STRINGID_PKMNCUTSATTACKWITH] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} cuts {B_DEF_NAME_WITH_PREFIX2}'s Attack!"), //not in gen 5+, ability popup + [STRINGID_PKMNPREVENTSSTATLOSSWITH] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} prevents stat loss!"), //not in gen 5+, ability popup [STRINGID_PKMNHURTSWITH] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} was hurt by {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), [STRINGID_PKMNTRACED] = COMPOUND_STRING("It traced {B_BUFF1}'s {B_BUFF2}!"), [STRINGID_STATSHARPLY] = gText_StatSharply, [STRINGID_STATROSE] = gText_StatRose, [STRINGID_STATHARSHLY] = COMPOUND_STRING("harshly "), [STRINGID_STATFELL] = gText_StatFell, - [STRINGID_ATTACKERSSTATROSE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}"), + [STRINGID_ATTACKERSSTATROSE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}rose!"), [STRINGID_DEFENDERSSTATROSE] = gText_DefendersStatRose, - [STRINGID_ATTACKERSSTATFELL] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}"), - [STRINGID_DEFENDERSSTATFELL] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}"), + [STRINGID_ATTACKERSSTATFELL] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}fell!"), + [STRINGID_DEFENDERSSTATFELL] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} {B_BUFF2}fell!"), [STRINGID_CRITICALHIT] = COMPOUND_STRING("A critical hit!"), [STRINGID_ONEHITKO] = COMPOUND_STRING("It's a one-hit KO!"), [STRINGID_123POOF] = COMPOUND_STRING("One…{PAUSE 10}two…{PAUSE 10}and…{PAUSE 10}{PAUSE 20}{PLAY_SE SE_BALL_BOUNCE_1}ta-da!\p"), @@ -500,7 +490,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_BUTNOTHINGHAPPENED] = COMPOUND_STRING("But nothing happened!"), [STRINGID_BUTITFAILED] = COMPOUND_STRING("But it failed!"), [STRINGID_ITHURTCONFUSION] = COMPOUND_STRING("It hurt itself in its confusion!"), - [STRINGID_MIRRORMOVEFAILED] = COMPOUND_STRING("The Mirror Move failed!"), //not in gen 5+, uses "but it failed" [STRINGID_STARTEDTORAIN] = COMPOUND_STRING("It started to rain!"), [STRINGID_DOWNPOURSTARTED] = COMPOUND_STRING("A downpour started!"), // corresponds to DownpourText in pokegold and pokecrystal and is used by Rain Dance in GSC [STRINGID_RAINCONTINUES] = COMPOUND_STRING("Rain continues to fall."), //not in gen 5+ @@ -515,9 +504,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_STARTEDHAIL] = COMPOUND_STRING("It started to hail!"), [STRINGID_HAILCONTINUES] = COMPOUND_STRING("The hail is crashing down."), [STRINGID_HAILSTOPPED] = COMPOUND_STRING("The hail stopped."), - [STRINGID_FAILEDTOSPITUP] = COMPOUND_STRING("But it failed to spit up a thing!"), //not in gen 5+, uses "but it failed" - [STRINGID_FAILEDTOSWALLOW] = COMPOUND_STRING("But it failed to swallow a thing!"), //not in gen 5+, uses "but it failed" - [STRINGID_WINDBECAMEHEATWAVE] = COMPOUND_STRING("The wind turned into a Heat Wave!"), //unused [STRINGID_STATCHANGESGONE] = COMPOUND_STRING("All stat changes were eliminated!"), [STRINGID_COINSSCATTERED] = COMPOUND_STRING("Coins were scattered everywhere!"), [STRINGID_TOOWEAKFORSUBSTITUTE] = COMPOUND_STRING("But it does not have enough HP left to make a substitute!"), @@ -574,14 +560,13 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_ITEMALLOWSONLYYMOVE] = COMPOUND_STRING("{B_LAST_ITEM} only allows the use of {B_CURRENT_MOVE}!\p"), [STRINGID_PKMNHUNGONWITHX] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} hung on using its {B_LAST_ITEM}!"), [STRINGID_EMPTYSTRING3] = gText_EmptyString3, - [STRINGID_PKMNSXPREVENTSBURNS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ABILITY} prevents burns!"), //not in gen 5+, ability popup [STRINGID_PKMNSXBLOCKSY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} blocks {B_CURRENT_MOVE}!"), //not in gen 5+, ability popup [STRINGID_PKMNSXRESTOREDHPALITTLE2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} restored its HP a little!"), //not in gen 5+, ability popup - [STRINGID_PKMNSXWHIPPEDUPSANDSTORM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} whipped up a sandstorm!"), //not in gen 5+, ability popup - [STRINGID_PKMNSXPREVENTSYLOSS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} prevents {B_BUFF1} loss!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXWHIPPEDUPSANDSTORM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} whipped up a sandstorm!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXPREVENTSYLOSS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} prevents {B_BUFF1} loss!"), //not in gen 5+, ability popup [STRINGID_PKMNSXINFATUATEDY] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} infatuated {B_ATK_NAME_WITH_PREFIX2}!"), //not in gen 5+, ability popup [STRINGID_PKMNSXMADEYINEFFECTIVE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} made {B_CURRENT_MOVE} ineffective!"), //not in gen 5+, ability popup - [STRINGID_PKMNSXCUREDYPROBLEM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} cured its {B_BUFF1} problem!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXCUREDYPROBLEM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} cured its {B_BUFF1} problem!"), //not in gen 5+, ability popup [STRINGID_ITSUCKEDLIQUIDOOZE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} sucked up the liquid ooze!"), [STRINGID_PKMNTRANSFORMED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} transformed!"), [STRINGID_ELECTRICITYWEAKENED] = COMPOUND_STRING("Electricity's power was weakened!"), @@ -593,14 +578,14 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PLAYERDEFEATEDTRAINER1] = sText_PlayerDefeatedLinkTrainerTrainer1, [STRINGID_SOOTHINGAROMA] = COMPOUND_STRING("A soothing aroma wafted through the area!"), [STRINGID_ITEMSCANTBEUSEDNOW] = COMPOUND_STRING("Items can't be used now.{PAUSE 64}"), //not in gen 5+, i think - [STRINGID_FORXCOMMAYZ] = COMPOUND_STRING("For {B_SCR_NAME_WITH_PREFIX2}, {B_LAST_ITEM} {B_BUFF1}"), //not in gen 5+, expansion doesn't use anymore - [STRINGID_USINGITEMSTATOFPKMNROSE] = COMPOUND_STRING("Using {B_LAST_ITEM}, the {B_BUFF1} of {B_SCR_NAME_WITH_PREFIX2} {B_BUFF2}"), //todo: update this, will require code changes + [STRINGID_USINGITEMSTATOFPKMNROSE] = COMPOUND_STRING("Using {B_LAST_ITEM}, the {B_BUFF1} of {B_SCR_NAME_WITH_PREFIX2} {B_BUFF2}rose!"), //todo: update this, will require code changes + [STRINGID_USINGITEMSTATOFPKMNFELL] = COMPOUND_STRING("Using {B_LAST_ITEM}, the {B_BUFF1} of {B_SCR_NAME_WITH_PREFIX2} {B_BUFF2}fell!"), [STRINGID_PKMNUSEDXTOGETPUMPED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} used the {B_LAST_ITEM} to get pumped!"), [STRINGID_PKMNSXMADEYUSELESS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} made {B_CURRENT_MOVE} useless!"), //not in gen 5+, ability popup [STRINGID_PKMNTRAPPEDBYSANDTOMB] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} became trapped by the quicksand!"), [STRINGID_EMPTYSTRING4] = COMPOUND_STRING(""), [STRINGID_ABOOSTED] = COMPOUND_STRING(" a boosted"), - [STRINGID_PKMNSXINTENSIFIEDSUN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} intensified the sun's rays!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXINTENSIFIEDSUN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} intensified the sun's rays!"), //not in gen 5+, ability popup [STRINGID_PKMNMAKESGROUNDMISS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} makes Ground-type moves miss with {B_DEF_ABILITY}!"), //not in gen 5+, ability popup [STRINGID_YOUTHROWABALLNOWRIGHT] = COMPOUND_STRING("You throw a Ball now, right? I… I'll do my best!"), [STRINGID_PKMNSXTOOKATTACK] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} took the attack!"), //In gen 5+ but without naming the ability @@ -610,28 +595,23 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFLEDUSINGITS] = COMPOUND_STRING("{PLAY_SE SE_FLEE}{B_ATK_NAME_WITH_PREFIX} fled using its {B_LAST_ITEM}!\p"), [STRINGID_PKMNFLEDUSING] = COMPOUND_STRING("{PLAY_SE SE_FLEE}{B_ATK_NAME_WITH_PREFIX} fled using {B_ATK_ABILITY}!\p"), //not in gen 5+ [STRINGID_PKMNWASDRAGGEDOUT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} was dragged out!\p"), - [STRINGID_PREVENTEDFROMWORKING] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} prevented {B_SCR_NAME_WITH_PREFIX2}'s {B_BUFF1} from working!"), //unused [STRINGID_PKMNSITEMNORMALIZEDSTATUS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_LAST_ITEM} normalized its status!"), [STRINGID_TRAINER1USEDITEM] = COMPOUND_STRING("{B_ATK_TRAINER_NAME_WITH_CLASS} used {B_LAST_ITEM}!"), [STRINGID_BOXISFULL] = COMPOUND_STRING("The Box is full! You can't catch any more!\p"), [STRINGID_PKMNAVOIDEDATTACK] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} avoided the attack!"), - [STRINGID_PKMNSXMADEITINEFFECTIVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} made it ineffective!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXMADEITINEFFECTIVE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} made it ineffective!"), //not in gen 5+, ability popup [STRINGID_PKMNSXPREVENTSFLINCHING] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}'s {B_EFF_ABILITY} prevents flinching!"), //not in gen 5+, ability popup [STRINGID_PKMNALREADYHASBURN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is already burned!"), [STRINGID_STATSWONTDECREASE2] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s stats won't go any lower!"), - [STRINGID_PKMNSXBLOCKSY2] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} blocks {B_CURRENT_MOVE}!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXBLOCKSY2] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} blocks {B_CURRENT_MOVE}!"), //not in gen 5+, ability popup [STRINGID_PKMNSXWOREOFF] = COMPOUND_STRING("{B_ATK_TEAM1} team's {B_BUFF1} wore off!"), - [STRINGID_PKMNRAISEDDEFALITTLE] = COMPOUND_STRING("{B_ATK_PREFIX1}'s {B_CURRENT_MOVE} raised DEFENSE a little!"), //expansion doesn't use anymore - [STRINGID_PKMNRAISEDSPDEFALITTLE] = COMPOUND_STRING("{B_ATK_PREFIX1}'s {B_CURRENT_MOVE} raised SP. DEF a little!"), //expansion doesn't use anymore [STRINGID_THEWALLSHATTERED] = COMPOUND_STRING("The wall shattered!"), //not in gen5+, uses "your teams light screen wore off!" etc instead - [STRINGID_PKMNSXPREVENTSYSZ] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} prevents {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY} from working!"), - [STRINGID_PKMNSXCUREDITSYPROBLEM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} cured its {B_BUFF1} problem!"), //not in gen 5+, ability popup + [STRINGID_PKMNSXCUREDITSYPROBLEM] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} cured its {B_BUFF1} problem!"), //not in gen 5+, ability popup [STRINGID_ATTACKERCANTESCAPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} can't escape!"), [STRINGID_PKMNOBTAINEDX] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} obtained {B_BUFF1}."), [STRINGID_PKMNOBTAINEDX2] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} obtained {B_BUFF2}."), [STRINGID_PKMNOBTAINEDXYOBTAINEDZ] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} obtained {B_BUFF1}.\p{B_DEF_NAME_WITH_PREFIX} obtained {B_BUFF2}."), [STRINGID_BUTNOEFFECT] = COMPOUND_STRING("But it had no effect!"), - [STRINGID_PKMNSXHADNOEFFECTONY] = COMPOUND_STRING("Target protected by {B_LAST_ABILITY}!"), //not in gen 5+, ability popup [STRINGID_TWOENEMIESDEFEATED] = sText_TwoInGameTrainersDefeated, [STRINGID_TRAINER2LOSETEXT] = COMPOUND_STRING("{B_TRAINER2_LOSE_TEXT}"), [STRINGID_PKMNINCAPABLEOFPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} appears incapable of using its power!"), @@ -690,10 +670,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_FELLSTRAIGHTDOWN] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} fell straight down!"), [STRINGID_TARGETCHANGEDTYPE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} transformed into the {B_BUFF1} type!"), [STRINGID_PKMNACQUIREDSIMPLE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} acquired Simple!"), //shouldn't directly use the name - [STRINGID_EMPTYSTRING5] = sText_EmptyString4, [STRINGID_KINDOFFER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} took the kind offer!"), [STRINGID_RESETSTARGETSSTATLEVELS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s stat changes were removed!"), - [STRINGID_EMPTYSTRING6] = sText_EmptyString4, [STRINGID_ALLYSWITCHPOSITION] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} and {B_SCR_NAME_WITH_PREFIX2} switched places!"), [STRINGID_RESTORETARGETSHEALTH] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s HP was restored!"), [STRINGID_TOOKPJMNINTOTHESKY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} took {B_DEF_NAME_WITH_PREFIX2} into the sky!"), @@ -718,9 +696,9 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_MISTYTERRAINENDS] = COMPOUND_STRING("The mist disappeared from the battlefield."), [STRINGID_PSYCHICTERRAINENDS] = COMPOUND_STRING("The weirdness disappeared from the battlefield!"), [STRINGID_GRASSYTERRAINENDS] = COMPOUND_STRING("The grass disappeared from the battlefield."), - [STRINGID_TARGETABILITYSTATRAISE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} raised its {B_BUFF1}!"), + [STRINGID_TARGETABILITYSTATRAISE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} {B_BUFF2}raised its {B_BUFF1}!"), [STRINGID_TARGETSSTATWASMAXEDOUT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} maxed its {B_BUFF1}!"), - [STRINGID_ATTACKERABILITYSTATRAISE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} raised its {B_BUFF1}!"), + [STRINGID_ATTACKERABILITYSTATRAISE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} {B_BUFF2}raised its {B_BUFF1}!"), [STRINGID_POISONHEALHPUP] = COMPOUND_STRING("The poisoning healed {B_ATK_NAME_WITH_PREFIX2} a little bit!"), //don't think this message is displayed anymore [STRINGID_BADDREAMSDMG] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is tormented!"), [STRINGID_MOLDBREAKERENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} breaks the mold!"), @@ -731,26 +709,26 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SOLARPOWERHPDROP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} takes its toll!"), //don't think this message is displayed anymore [STRINGID_AFTERMATHDMG] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} was hurt!"), [STRINGID_ANTICIPATIONACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} shuddered!"), - [STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("{B_SCR_ACTIVE_ABILITY} alerted {B_SCR_NAME_WITH_PREFIX2} to {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), + [STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("{B_SCR_ABILITY} alerted {B_SCR_NAME_WITH_PREFIX2} to {B_EFF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), [STRINGID_ICEBODYHPGAIN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} healed it a little bit!"), //don't think this message is displayed anymore [STRINGID_SNOWWARNINGHAIL] = COMPOUND_STRING("It started to hail!"), [STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} frisked {B_DEF_NAME_WITH_PREFIX2} and found its {B_LAST_ITEM}!"), - [STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_DEF_TEAM1} team is too nervous to eat Berries!"), + [STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_EFF_TEAM1} team is too nervous to eat Berries!"), [STRINGID_HARVESTBERRY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} harvested its {B_LAST_ITEM}!"), [STRINGID_MAGICBOUNCEACTIVATES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} bounced the {B_ATK_NAME_WITH_PREFIX2} back!"), [STRINGID_PROTEANTYPECHANGE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} transformed it into the {B_BUFF1} type!"), [STRINGID_SYMBIOSISITEMPASS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} passed its {B_LAST_ITEM} to {B_EFF_NAME_WITH_PREFIX2} through {B_LAST_ABILITY}!"), [STRINGID_STEALTHROCKDMG] = COMPOUND_STRING("Pointed stones dug into {B_SCR_NAME_WITH_PREFIX2}!"), - [STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("The poison spikes disappeared from the ground around {B_SCR_TEAM2} team!"), + [STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("The poison spikes disappeared from the ground around {B_EFF_TEAM2} team!"), [STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was poisoned!"), [STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was badly poisoned!"), [STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was caught in a sticky web!"), [STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_ATK_NAME_WITH_PREFIX2}!"), [STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} regained health!"), [STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in mystical moonlight!"), - [STRINGID_CUSEDBODYDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"), + [STRINGID_CURSEDBODYDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"), [STRINGID_ATTACKERACQUIREDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} acquired {B_ATK_ABILITY}!"), - [STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} lowered its {B_BUFF1}!"), + [STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} {B_BUFF2}lowered its {B_BUFF1}!"), [STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any higher!"), [STRINGID_PKMNMOVEBOUNCEDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} was bounced back by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"), [STRINGID_IMPOSTERTRANSFORM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} transformed into {B_DEF_NAME_WITH_PREFIX2} using {B_LAST_ABILITY}!"), @@ -789,7 +767,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_MISTYTERRAINPREVENTS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} surrounds itself with a protective mist!"), [STRINGID_GRASSYTERRAINHEALS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is healed by the grassy terrain!"), [STRINGID_ELECTRICTERRAINPREVENTS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} surrounds itself with electrified terrain!"), - [STRINGID_PSYCHICTERRAINPREVENTS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} surrounds itself with psychic terrain!"), + [STRINGID_PSYCHICTERRAINPREVENTS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is protected by the Psychic Terrain!"), [STRINGID_SAFETYGOGGLESPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is not affected thanks to its {B_LAST_ITEM}!"), [STRINGID_FLOWERVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} surrounded itself with a veil of petals!"), [STRINGID_SWEETVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} can't fall asleep due to a veil of sweetness!"), @@ -809,8 +787,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_ATTACKERCUREDTARGETSTATUS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} cured {B_DEF_NAME_WITH_PREFIX2}'s problem!"), [STRINGID_ATTACKERLOSTFIRETYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} burned itself out!"), [STRINGID_HEALERCURE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_LAST_ABILITY} cured {B_SCR_NAME_WITH_PREFIX2}'s problem!"), - [STRINGID_SCRIPTINGABILITYSTATRAISE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} raised its {B_BUFF1}!"), - [STRINGID_RECEIVERABILITYTAKEOVER] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} was taken over!"), + [STRINGID_SCRIPTINGABILITYSTATRAISE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} {B_BUFF2}raised its {B_BUFF1}!"), + [STRINGID_RECEIVERABILITYTAKEOVER] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} was taken over!"), [STRINGID_PKNMABSORBINGPOWER] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is absorbing power!"), [STRINGID_NOONEWILLBEABLETORUNAWAY] = COMPOUND_STRING("No one will be able to run away during the next turn!"), [STRINGID_DESTINYKNOTACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} fell in love because of the {B_LAST_ITEM}!"), @@ -825,10 +803,8 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_COMATOSEENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} is drowsing!"), [STRINGID_SCREENCLEANERENTERS] = COMPOUND_STRING("All screens on the field were cleansed!"), [STRINGID_FETCHEDPOKEBALL] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} found a {B_LAST_ITEM}!"), - [STRINGID_BATTLERABILITYRAISEDSTAT] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} raised its {B_BUFF1}!"), [STRINGID_ASANDSTORMKICKEDUP] = COMPOUND_STRING("A sandstorm kicked up!"), [STRINGID_PKMNSWILLPERISHIN3TURNS] = COMPOUND_STRING("Both Pokémon will perish in three turns!"), //don't think this message is displayed anymore - [STRINGID_ABILITYRAISEDSTATDRASTICALLY] = COMPOUND_STRING("{B_DEF_ABILITY} raised {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1} drastically!"), [STRINGID_AURAFLAREDTOLIFE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s aura flared to life!"), [STRINGID_ASONEENTERS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} has two Abilities!"), [STRINGID_CURIOUSMEDICINEENTERS] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX}'s stat changes were removed!"), @@ -865,7 +841,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_BROKETHROUGHPROTECTION] = COMPOUND_STRING("It broke through {B_DEF_NAME_WITH_PREFIX2}'s protection!"), [STRINGID_ABILITYALLOWSONLYMOVE] = COMPOUND_STRING("{B_ATK_ABILITY} only allows the use of {B_CURRENT_MOVE}!\p"), [STRINGID_SWAPPEDABILITIES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} swapped Abilities with its target!"), - [STRINGID_PASTELVEILPROTECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is protected by a pastel veil!"), [STRINGID_PASTELVEILENTERS] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} was cured of its poisoning!"), [STRINGID_BATTLERTYPECHANGEDTO] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s type changed to {B_BUFF1}!"), [STRINGID_BOTHCANNOLONGERESCAPE] = COMPOUND_STRING("Neither Pokémon can run away!"), @@ -901,9 +876,9 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SUNLIGHTACTIVATEDABILITY] = COMPOUND_STRING("The harsh sunlight activated {B_SCR_NAME_WITH_PREFIX2}'s Protosynthesis!"), [STRINGID_STATWASHEIGHTENED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!"), [STRINGID_ELECTRICTERRAINACTIVATEDABILITY] = COMPOUND_STRING("The Electric Terrain activated {B_SCR_NAME_WITH_PREFIX2}'s Quark Drive!"), - [STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} weakened the {B_BUFF1} of all surrounding Pokémon!\p"), + [STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} weakened the {B_BUFF1} of all surrounding Pokémon!\p"), [STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} gained strength from the fallen!"), - [STRINGID_PKMNSABILITYPREVENTSABILITY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY} prevents {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY} from working!"), //not in gen 5+, ability popup + [STRINGID_PKMNSABILITYPREVENTSABILITY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_SCR_ABILITY} prevents {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY} from working!"), //not in gen 5+, ability popup [STRINGID_PREPARESHELLTRAP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} set a shell trap!"), [STRINGID_SHELLTRAPDIDNTWORK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!"), [STRINGID_SPIKESDISAPPEAREDFROMTEAM] = COMPOUND_STRING("The spikes disappeared from the ground around {B_ATK_TEAM2} team!"), @@ -935,7 +910,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_TEAMGAINEDEXP] = COMPOUND_STRING("The rest of your team gained Exp. Points thanks to the Exp. Share!\p"), [STRINGID_CURRENTMOVECANTSELECT] = COMPOUND_STRING("{B_BUFF1} cannot be used!\p"), [STRINGID_TARGETISBEINGSALTCURED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is being salt cured!"), - [STRINGID_TARGETISHURTBYSALTCURE] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!"), + [STRINGID_TARGETISHURTBYSALTCURE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!"), [STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} got covered in sticky candy syrup!"), [STRINGID_SHARPSTEELFLOATS] = COMPOUND_STRING("Sharp-pointed pieces of steel started floating around {B_DEF_TEAM2} Pokémon!"), [STRINGID_SHARPSTEELDMG] = COMPOUND_STRING("The sharp steel bit into {B_DEF_NAME_WITH_PREFIX2}!"), @@ -961,7 +936,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SWAMPENVELOPEDSIDE] = COMPOUND_STRING("A swamp enveloped {B_DEF_TEAM2} team!"), [STRINGID_THESWAMPDISAPPEARED] = COMPOUND_STRING("The swamp around {B_ATK_TEAM2} team disappeared!"), [STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is preparing to tell a chillingly bad joke!"), - [STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_ATK_PARTNER_NAME} drank down all the matcha that {B_ATK_NAME_WITH_PREFIX2} made!"), + [STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} drank down all the matcha that {B_SCR_NAME_WITH_PREFIX2} made!"), [STRINGID_ELECTROSHOTCHARGING] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} absorbed electricity!"), [STRINGID_ITEMWASUSEDUP] = COMPOUND_STRING("The {B_LAST_ITEM} was used up…"), [STRINGID_ATTACKERLOSTITSTYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} lost its {B_BUFF1} type!"), @@ -973,7 +948,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_BIZARREAREACREATED] = COMPOUND_STRING("A bizarre area was created in which Defense and Sp. Def stats are swapped!"), [STRINGID_TIDYINGUPCOMPLETE] = COMPOUND_STRING("Tidying up complete!"), [STRINGID_PKMNTERASTALLIZEDINTO] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} terastallized into the {B_BUFF1} type!"), - [STRINGID_BOOSTERENERGYACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} used its {B_LAST_ITEM} to activate {B_SCR_ACTIVE_ABILITY}!"), + [STRINGID_BOOSTERENERGYACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} used its {B_LAST_ITEM} to activate {B_SCR_ABILITY}!"), [STRINGID_FOGCREPTUP] = COMPOUND_STRING("Fog crept up as thick as soup!"), [STRINGID_FOGISDEEP] = COMPOUND_STRING("The fog is deep…"), [STRINGID_FOGLIFTED] = COMPOUND_STRING("The fog lifted."), @@ -1197,10 +1172,10 @@ const u16 gReflectLightScreenSafeguardStringIds[] = { [B_MSG_SIDE_STATUS_FAILED] = STRINGID_BUTITFAILED, [B_MSG_SET_REFLECT_SINGLE] = STRINGID_PKMNRAISEDDEF, - [B_MSG_SET_REFLECT_DOUBLE] = STRINGID_PKMNRAISEDDEFALITTLE, + [B_MSG_SET_REFLECT_DOUBLE] = STRINGID_PKMNRAISEDDEF, [B_MSG_SET_LIGHTSCREEN_SINGLE] = STRINGID_PKMNRAISEDSPDEF, - [B_MSG_SET_LIGHTSCREEN_DOUBLE] = STRINGID_PKMNRAISEDSPDEFALITTLE, - [B_MSG_SET_SAFEGUARD] = STRINGID_PKMNCOVEREDBYVEIL + [B_MSG_SET_LIGHTSCREEN_DOUBLE] = STRINGID_PKMNRAISEDSPDEF, + [B_MSG_SET_SAFEGUARD] = STRINGID_PKMNCOVEREDBYVEIL, }; const u16 gLeechSeedStringIds[] = @@ -1224,24 +1199,12 @@ const u16 gUproarOverTurnStringIds[] = [B_MSG_UPROAR_ENDS] = STRINGID_PKMNCALMEDDOWN }; -const u16 gStockpileUsedStringIds[] = -{ - [B_MSG_STOCKPILED] = STRINGID_PKMNSTOCKPILED, - [B_MSG_CANT_STOCKPILE] = STRINGID_PKMNCANTSTOCKPILE -}; - const u16 gWokeUpStringIds[] = { [B_MSG_WOKE_UP] = STRINGID_PKMNWOKEUP, [B_MSG_WOKE_UP_UPROAR] = STRINGID_PKMNWOKEUPINUPROAR }; -const u16 gSwallowFailStringIds[] = -{ - [B_MSG_SWALLOW_FAILED] = STRINGID_FAILEDTOSWALLOW, - [B_MSG_SWALLOW_FULL_HP] = STRINGID_PKMNHPFULL -}; - const u16 gUproarAwakeStringIds[] = { [B_MSG_CANT_SLEEP_UPROAR] = STRINGID_PKMNCANTSLEEPINUPROAR2, @@ -1250,20 +1213,21 @@ const u16 gUproarAwakeStringIds[] = const u16 gStatUpStringIds[] = { - [B_MSG_ATTACKER_STAT_ROSE] = STRINGID_ATTACKERSSTATROSE, - [B_MSG_DEFENDER_STAT_ROSE] = STRINGID_DEFENDERSSTATROSE, - [B_MSG_STAT_WONT_INCREASE] = STRINGID_STATSWONTINCREASE, - [B_MSG_STAT_ROSE_EMPTY] = STRINGID_EMPTYSTRING3, - [B_MSG_STAT_ROSE_ITEM] = STRINGID_USINGITEMSTATOFPKMNROSE, - [B_MSG_USED_DIRE_HIT] = STRINGID_PKMNUSEDXTOGETPUMPED, + [B_MSG_ATTACKER_STAT_CHANGED] = STRINGID_ATTACKERSSTATROSE, + [B_MSG_DEFENDER_STAT_CHANGED] = STRINGID_DEFENDERSSTATROSE, + [B_MSG_STAT_WONT_CHANGE] = STRINGID_STATSWONTINCREASE, + [B_MSG_STAT_CHANGE_EMPTY] = STRINGID_EMPTYSTRING3, + [B_MSG_STAT_CHANGED_ITEM] = STRINGID_USINGITEMSTATOFPKMNROSE, + [B_MSG_USED_DIRE_HIT] = STRINGID_PKMNUSEDXTOGETPUMPED, }; const u16 gStatDownStringIds[] = { - [B_MSG_ATTACKER_STAT_FELL] = STRINGID_ATTACKERSSTATFELL, - [B_MSG_DEFENDER_STAT_FELL] = STRINGID_DEFENDERSSTATFELL, - [B_MSG_STAT_WONT_DECREASE] = STRINGID_STATSWONTDECREASE, - [B_MSG_STAT_FELL_EMPTY] = STRINGID_EMPTYSTRING3 + [B_MSG_ATTACKER_STAT_CHANGED] = STRINGID_ATTACKERSSTATFELL, + [B_MSG_DEFENDER_STAT_CHANGED] = STRINGID_DEFENDERSSTATFELL, + [B_MSG_STAT_WONT_CHANGE] = STRINGID_STATSWONTDECREASE, + [B_MSG_STAT_CHANGE_EMPTY] = STRINGID_EMPTYSTRING3, + [B_MSG_STAT_CHANGED_ITEM] = STRINGID_USINGITEMSTATOFPKMNFELL, }; // Index copied from move's index in sTrappingMoves @@ -1463,16 +1427,6 @@ const u16 gBerryEffectStringIds[] = [B_MSG_NORMALIZED_STATUS] = STRINGID_PKMNSITEMNORMALIZEDSTATUS }; -const u16 gStatusPreventionStringIds[] = -{ - [B_MSG_ABILITY_PREVENTS_MOVE_BURN] = STRINGID_PKMNSXPREVENTSBURNS, - [B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS] = STRINGID_PKMNPREVENTSPARALYSISWITH, - [B_MSG_ABILITY_PREVENTS_MOVE_POISON] = STRINGID_PKMNPREVENTSPOISONINGWITH, - [B_MSG_ABILITY_PREVENTS_ABILITY_STATUS] = STRINGID_PKMNSXPREVENTSYSZ, - [B_MSG_STATUS_HAD_NO_EFFECT] = STRINGID_PKMNSXHADNOEFFECTONY, - [B_MSG_ABILITY_PASTEL_VEIL] = STRINGID_PASTELVEILPROTECTED -}; - const u16 gItemSwapStringIds[] = { [B_MSG_ITEM_SWAP_TAKEN] = STRINGID_PKMNOBTAINEDX, @@ -1529,6 +1483,24 @@ const u16 gDamageNonTypesDmgStringIds[] = [B_MSG_HURT_BY_ROCKS_THROWN] = STRINGID_PKMNHURTBYROCKSTHROWN, }; +const u16 gDefogHazardsStringIds[] = +{ + [HAZARDS_SPIKES] = STRINGID_SPIKESDISAPPEAREDFROMTEAM, + [HAZARDS_STICKY_WEB] = STRINGID_STICKYWEBDISAPPEAREDFROMTEAM, + [HAZARDS_TOXIC_SPIKES] = STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM, + [HAZARDS_STEALTH_ROCK] = STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM, + [HAZARDS_STEELSURGE] = STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM, +}; + +const u16 gSpinHazardsStringIds[] = +{ + [HAZARDS_SPIKES] = STRINGID_PKMNBLEWAWAYSPIKES, + [HAZARDS_STICKY_WEB] = STRINGID_PKMNBLEWAWAYSTICKYWEB, + [HAZARDS_TOXIC_SPIKES] = STRINGID_PKMNBLEWAWAYTOXICSPIKES, + [HAZARDS_STEALTH_ROCK] = STRINGID_PKMNBLEWAWAYSTEALTHROCK, + [HAZARDS_STEELSURGE] = STRINGID_PKMNBLEWAWAYSHARPSTEEL, +}; + // Index is determined in VARIOUS_GET_BATTLERS_FOR_RECALL by ORing flags for each present battler on the losing side. // No battlers (0) is skipped. const u16 gDoubleBattleRecallStrings[1 << (MAX_BATTLERS_COUNT / 2)] = @@ -1674,7 +1646,7 @@ static const u16 sGrammarMoveUsedTable[] = static const u8 sRecordedBattleTextSpeeds[] = {8, 4, 1, 0}; -void BufferStringBattle(u16 stringId, u32 battler) +void BufferStringBattle(enum StringID stringID, u32 battler) { s32 i; const u8 *stringPtr = NULL; @@ -1699,7 +1671,7 @@ void BufferStringBattle(u16 stringId, u32 battler) gBattleTextBuff3[i] = gBattleMsgDataPtr->textBuffs[2][i]; } - switch (stringId) + switch (stringID) { case STRINGID_INTROMSG: // first battle msg if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) @@ -1737,16 +1709,13 @@ void BufferStringBattle(u16 stringId, u32 battler) } else { - if (gBattleTypeFlags & BATTLE_TYPE_GHOST) - { - if (gBattleTypeFlags & BATTLE_TYPE_GHOST_UNVEILED) - stringPtr = sText_TheGhostAppeared; - else - stringPtr = sText_GhostAppearedCantId; - } + if (gBattleTypeFlags & BATTLE_TYPE_GHOST && IsGhostBattleWithoutScope()) + stringPtr = sText_GhostAppearedCantId; + else if (gBattleTypeFlags & BATTLE_TYPE_GHOST) + stringPtr = sText_TheGhostAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) stringPtr = sText_WildPkmnAppeared2; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)]])) // interesting, looks like they had something planned for wild double battles + else if (IsDoubleBattle() && IsValidForBattle(GetBattlerMon(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)))) stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL) stringPtr = sText_WildPkmnAppearedPause; @@ -1755,9 +1724,9 @@ void BufferStringBattle(u16 stringId, u32 battler) } break; case STRINGID_INTROSENDOUT: // poke first send-out - if (GetBattlerSide(battler) == B_SIDE_PLAYER) + if (IsOnPlayerSide(battler)) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) + if (IsDoubleBattle() && IsValidForBattle(GetBattlerMon(BATTLE_PARTNER(battler)))) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) stringPtr = sText_InGamePartnerSentOutZGoN; @@ -1775,7 +1744,7 @@ void BufferStringBattle(u16 stringId, u32 battler) } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battler)]])) + if (IsDoubleBattle() && IsValidForBattle(GetBattlerMon(BATTLE_PARTNER(battler)))) { if (BATTLE_TWO_VS_ONE_OPPONENT) stringPtr = sText_Trainer1SentOutTwoPkmn; @@ -1802,11 +1771,11 @@ void BufferStringBattle(u16 stringId, u32 battler) } break; case STRINGID_RETURNMON: // sending poke to ball msg - if (GetBattlerSide(battler) == B_SIDE_PLAYER) + if (IsOnPlayerSide(battler)) { if (*(&gBattleStruct->hpScale) == 0) stringPtr = sText_PkmnThatsEnough; - else if (*(&gBattleStruct->hpScale) == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + else if (*(&gBattleStruct->hpScale) == 1 || IsDoubleBattle()) stringPtr = sText_PkmnComeBack; else if (*(&gBattleStruct->hpScale) == 2) stringPtr = sText_PkmnOkComeBack; @@ -1829,9 +1798,9 @@ void BufferStringBattle(u16 stringId, u32 battler) } break; case STRINGID_SWITCHINMON: // switch-in msg - if (GetBattlerSide(gBattleScripting.battler) == B_SIDE_PLAYER) + if (IsOnPlayerSide(gBattleScripting.battler)) { - if (*(&gBattleStruct->hpScale) == 0 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (*(&gBattleStruct->hpScale) == 0 || IsDoubleBattle()) stringPtr = sText_GoPkmn2; else if (*(&gBattleStruct->hpScale) == 1) stringPtr = sText_DoItPkmn; @@ -1844,20 +1813,40 @@ void BufferStringBattle(u16 stringId, u32 battler) { if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) { - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = sText_LinkTrainerMultiSentOutPkmn; - else if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_UNION_ROOM) - stringPtr = sText_Trainer1SentOutPkmn2; + if (gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI) + { + if (gBattleScripting.battler == 1) + stringPtr = sText_Trainer1SentOutPkmn2; + else + stringPtr = sText_Trainer2SentOutPkmn; + } else - stringPtr = sText_LinkTrainerSentOutPkmn2; + { + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + stringPtr = sText_LinkTrainerMultiSentOutPkmn; + else if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_UNION_ROOM) + stringPtr = sText_Trainer1SentOutPkmn2; + else + stringPtr = sText_LinkTrainerSentOutPkmn2; + } } else { - stringPtr = sText_Trainer1SentOutPkmn2; + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + { + if (gBattleScripting.battler == 1) + stringPtr = sText_Trainer1SentOutPkmn2; + else + stringPtr = sText_Trainer2SentOutPkmn; + } + else + { + stringPtr = sText_Trainer1SentOutPkmn2; + } } } break; - case STRINGID_USEDMOVE: // pokemon used a move msg + case STRINGID_USEDMOVE: // Pokémon used a move msg if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT && !IsZMove(gBattleMsgDataPtr->currentMove) && !IsMaxMove(gBattleMsgDataPtr->currentMove)) @@ -1870,21 +1859,19 @@ void BufferStringBattle(u16 stringId, u32 battler) if (gBattleTextBuff1[0] & B_OUTCOME_LINK_BATTLE_RAN) { gBattleTextBuff1[0] &= ~(B_OUTCOME_LINK_BATTLE_RAN); - if (GetBattlerSide(battler) == B_SIDE_OPPONENT && gBattleTextBuff1[0] != B_OUTCOME_DREW) + if (!IsOnPlayerSide(battler) && gBattleTextBuff1[0] != B_OUTCOME_DREW) gBattleTextBuff1[0] ^= (B_OUTCOME_LOST | B_OUTCOME_WON); if (gBattleTextBuff1[0] == B_OUTCOME_LOST || gBattleTextBuff1[0] == B_OUTCOME_DREW) stringPtr = sText_GotAwaySafely; else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) stringPtr = sText_TwoWildFled; - else if (TRAINER_BATTLE_PARAM.opponentA == TRAINER_UNION_ROOM) - stringPtr = sText_Trainer1Fled; else stringPtr = sText_WildFled; } else { - if (GetBattlerSide(battler) == B_SIDE_OPPONENT && gBattleTextBuff1[0] != B_OUTCOME_DREW) + if (!IsOnPlayerSide(battler) && gBattleTextBuff1[0] != B_OUTCOME_DREW) gBattleTextBuff1[0] ^= (B_OUTCOME_LOST | B_OUTCOME_WON); if (gBattleTypeFlags & BATTLE_TYPE_MULTI) @@ -1938,14 +1925,14 @@ void BufferStringBattle(u16 stringId, u32 battler) stringPtr = gBattleStruct->trainerSlideMsg; break; default: // load a string from the table - if (stringId >= STRINGID_COUNT) + if (stringID >= STRINGID_COUNT) { gDisplayedStringBattle[0] = EOS; return; } else { - stringPtr = gBattleStringsTable[stringId]; + stringPtr = gBattleStringsTable[stringID]; } break; } @@ -2700,13 +2687,13 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) else toCpy = sText_Opposing2; break; - case B_TXT_SCR_TEAM1: + case B_TXT_EFF_TEAM1: if (GetBattlerSide(gBattleScripting.battler) == B_SIDE_PLAYER) toCpy = sText_Your1; else toCpy = sText_Opposing1; break; - case B_TXT_SCR_TEAM2: + case B_TXT_EFF_TEAM2: if (GetBattlerSide(gBattleScripting.battler) == B_SIDE_PLAYER) toCpy = sText_Your2; else diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0f2ea063b..4b8397e2b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -41,8 +41,8 @@ #include "party_menu.h" #include "trainer_pokemon_sprites.h" // #include "battle_arena.h" -// #include "battle_pike.h" -// #include "battle_pyramid.h" +// // #include "battle_pike.h" +// // #include "battle_pyramid.h" #include "field_specials.h" #include "pokemon_summary_screen.h" // #include "pokenav.h" @@ -58,17 +58,19 @@ #include "constants/hold_effects.h" #include "constants/items.h" #include "constants/item_effects.h" -#include "constants/map_types.h" #include "constants/moves.h" #include "constants/party_menu.h" #include "constants/rgb.h" #include "constants/songs.h" #include "constants/trainer_slide.h" #include "constants/trainers.h" +#include "test/battle.h" #include "battle_util.h" #include "constants/pokemon.h" #include "config/battle.h" #include "data/battle_move_effects.h" +// #include "follower_npc.h" +#include "load_save.h" // table to avoid ugly powing on gba (courtesy of doesnt) // this returns (i^2.5)/4 @@ -288,20 +290,6 @@ static const s32 sExperienceScalingFactors[] = 159767, }; -static const u16 sTrappingMoves[NUM_TRAPPING_MOVES] = -{ - MOVE_BIND, - MOVE_WRAP, - MOVE_FIRE_SPIN, - MOVE_CLAMP, - MOVE_WHIRLPOOL, - MOVE_SAND_TOMB, - MOVE_MAGMA_STORM, - MOVE_INFESTATION, - MOVE_SNAP_TRAP, - MOVE_THUNDER_CAGE -}; - static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120 }; enum GiveCaughtMonStates @@ -341,17 +329,19 @@ static bool32 SetTargetToNextPursuiter(u32 battlerDef); void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler); static void RemoveAllWeather(void); static void RemoveAllTerrains(void); -static bool32 CanAbilityPreventStatLoss(u32 abilityDef); +static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef); static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent); static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove); static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move); static void ResetValuesForCalledMove(void); static void TryRestoreDamageAfterCheekPouch(u32 battler); +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd); +static bool32 CanAbilityShieldActivateForBattler(u32 battler); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); -static void Cmd_attackstring(void); -static void Cmd_ppreduce(void); +static void Cmd_printattackstring(void); +static void Cmd_unused0x3(void); static void Cmd_critcalc(void); static void Cmd_damagecalc(void); static void Cmd_typecalc(void); @@ -381,7 +371,7 @@ static void Cmd_jumpifvolatile(void); static void Cmd_jumpifability(void); static void Cmd_jumpifsideaffecting(void); static void Cmd_jumpifstat(void); -static void Cmd_jumpifstatus3condition(void); +static void Cmd_unused_0x21(void); static void Cmd_jumpbasedontype(void); static void Cmd_getexp(void); static void Cmd_checkteamslost(void); @@ -419,7 +409,7 @@ static void Cmd_jumpifabilitypresent(void); static void Cmd_endselectionscript(void); static void Cmd_playanimation(void); static void Cmd_playanimation_var(void); -static void Cmd_unused_0x47(void); +static void Cmd_jumpfifsemiinvulnerable(void); static void Cmd_unused_0x48(void); static void Cmd_moveend(void); static void Cmd_sethealblock(void); @@ -449,8 +439,8 @@ static void Cmd_drawpartystatussummary(void); static void Cmd_hidepartystatussummary(void); static void Cmd_jumptocalledmove(void); static void Cmd_statusanimation(void); -static void Cmd_status2animation(void); -static void Cmd_chosenstatusanimation(void); +static void Cmd_unused_0x65(void); +static void Cmd_unused_0x66(void); static void Cmd_yesnobox(void); static void Cmd_cancelallactions(void); static void Cmd_setgravity(void); @@ -472,14 +462,14 @@ static void Cmd_tryexplosion(void); static void Cmd_setatkhptozero(void); static void Cmd_jumpifnexttargetvalid(void); static void Cmd_tryhealhalfhealth(void); -static void Cmd_trymirrormove(void); +static void Cmd_unused_0x7e(void); static void Cmd_setfieldweather(void); static void Cmd_setreflect(void); static void Cmd_setseeded(void); static void Cmd_manipulatedamage(void); static void Cmd_trysetrest(void); -static void Cmd_jumpifnotfirstturn(void); -static void Cmd_setmiracleeye(void); +static void Cmd_unused_0x82(void); +static void Cmd_unused_0x83(void); static void Cmd_jumpifuproarwakes(void); static void Cmd_stockpile(void); static void Cmd_stockpiletobasedamage(void); @@ -496,9 +486,9 @@ static void Cmd_tryconversiontypechange(void); static void Cmd_givepaydaymoney(void); static void Cmd_setlightscreen(void); static void Cmd_tryKO(void); -static void Cmd_unused_0x94(void); +static void Cmd_checknonvolatiletrigger(void); static void Cmd_copybidedmg(void); -static void Cmd_unused_96(void); +static void Cmd_animatewildpokemonafterfailedpokeball(void); static void Cmd_tryinfatuating(void); static void Cmd_updatestatusicon(void); static void Cmd_setmist(void); @@ -506,7 +496,7 @@ static void Cmd_setfocusenergy(void); static void Cmd_transformdataexecution(void); static void Cmd_setsubstitute(void); static void Cmd_mimicattackcopy(void); -static void Cmd_metronome(void); +static void Cmd_setcalledmove(void); static void Cmd_unused_0x9f(void); static void Cmd_unused_0xA0(void); static void Cmd_counterdamagecalculator(void); @@ -517,15 +507,15 @@ static void Cmd_painsplitdmgcalc(void); static void Cmd_settypetorandomresistance(void); static void Cmd_setalwayshitflag(void); static void Cmd_copymovepermanently(void); -static void Cmd_trychoosesleeptalkmove(void); -static void Cmd_trysetdestinybond(void); +static void Cmd_unused_0xA9(void); +static void Cmd_unused_AA(void); static void Cmd_trysetdestinybondtohappen(void); static void Cmd_settailwind(void); static void Cmd_tryspiteppreduce(void); static void Cmd_healpartystatus(void); static void Cmd_cursetarget(void); static void Cmd_trysetspikes(void); -static void Cmd_setforesight(void); +static void Cmd_setvolatile(void); static void Cmd_trysetperishsong(void); static void Cmd_handlerollout(void); static void Cmd_jumpifconfusedandstatmaxed(void); @@ -539,20 +529,20 @@ static void Cmd_tryrestorehpberry(void); static void Cmd_halvehp(void); static void Cmd_copyfoestats(void); static void Cmd_rapidspinfree(void); -static void Cmd_setdefensecurlbit(void); +static void Cmd_unused_0xBF(void); static void Cmd_recoverbasedonsunlight(void); static void Cmd_setstickyweb(void); static void Cmd_selectfirstvalidtarget(void); -static void Cmd_trysetfutureattack(void); +static void Cmd_setfutureattack(void); static void Cmd_trydobeatup(void); static void Cmd_setsemiinvulnerablebit(void); static void Cmd_tryfiretwoturnmovenowbyeffect(void); -static void Cmd_setminimize(void); +static void Cmd_unused_0xC7(void); static void Cmd_unused_c8(void); static void Cmd_trymemento(void); static void Cmd_setforcedtarget(void); static void Cmd_setcharge(void); -static void Cmd_callenvironmentattack(void); +static void Cmd_unused_0xCC(void); static void Cmd_curestatuswithmove(void); static void Cmd_settorment(void); static void Cmd_jumpifnodamage(void); @@ -569,14 +559,14 @@ static void Cmd_setroom(void); static void Cmd_tryswapabilities(void); static void Cmd_tryimprison(void); static void Cmd_setstealthrock(void); -static void Cmd_setuserstatus3(void); -static void Cmd_assistattackselect(void); +static void Cmd_trysetvolatile(void); +static void Cmd_unused_0xde(void); static void Cmd_trysetmagiccoat(void); static void Cmd_trysetsnatch(void); static void Cmd_unused2(void); static void Cmd_switchoutabilities(void); static void Cmd_jumpifhasnohp(void); -static void Cmd_jumpifnotcurrentmoveargtype(void); +static void Cmd_unused_0xE4(void); static void Cmd_pickup(void); static void Cmd_unused_0xE6(void); static void Cmd_unused_0xE7(void); @@ -609,8 +599,8 @@ void (*const gBattleScriptingCommandsTable[])(void) = { Cmd_attackcanceler, //0x0 Cmd_accuracycheck, //0x1 - Cmd_attackstring, //0x2 - Cmd_ppreduce, //0x3 + Cmd_printattackstring, //0x2 + Cmd_unused0x3, //0x3 Cmd_critcalc, //0x4 Cmd_damagecalc, //0x5 Cmd_typecalc, //0x6 @@ -640,7 +630,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_jumpifability, //0x1E Cmd_jumpifsideaffecting, //0x1F Cmd_jumpifstat, //0x20 - Cmd_jumpifstatus3condition, //0x21 + Cmd_unused_0x21, //0x21 Cmd_jumpbasedontype, //0x22 Cmd_getexp, //0x23 Cmd_checkteamslost, //0x24 @@ -678,7 +668,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_endselectionscript, //0x44 Cmd_playanimation, //0x45 Cmd_playanimation_var, //0x46 - Cmd_unused_0x47, //0x47 + Cmd_jumpfifsemiinvulnerable, //0x47 Cmd_unused_0x48, //0x48 Cmd_moveend, //0x49 Cmd_sethealblock, //0x4A @@ -708,8 +698,8 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_hidepartystatussummary, //0x62 Cmd_jumptocalledmove, //0x63 Cmd_statusanimation, //0x64 - Cmd_status2animation, //0x65 - Cmd_chosenstatusanimation, //0x66 + Cmd_unused_0x65, //0x65 + Cmd_unused_0x66, //0x66 Cmd_yesnobox, //0x67 Cmd_cancelallactions, //0x68 Cmd_setgravity, //0x69 @@ -731,14 +721,14 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_setatkhptozero, //0x79 Cmd_jumpifnexttargetvalid, //0x7A Cmd_tryhealhalfhealth, //0x7B - Cmd_trymirrormove, //0x7C + Cmd_unused_0x7e, //0x7C Cmd_setfieldweather, //0x7D Cmd_setreflect, //0x7E Cmd_setseeded, //0x7F Cmd_manipulatedamage, //0x80 Cmd_trysetrest, //0x81 - Cmd_jumpifnotfirstturn, //0x82 - Cmd_setmiracleeye, //0x83 + Cmd_unused_0x82, //0x82 + Cmd_unused_0x83, //0x83 Cmd_jumpifuproarwakes, //0x84 Cmd_stockpile, //0x85 Cmd_stockpiletobasedamage, //0x86 @@ -755,9 +745,9 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_givepaydaymoney, //0x91 Cmd_setlightscreen, //0x92 Cmd_tryKO, //0x93 - Cmd_unused_0x94, //0x94 + Cmd_checknonvolatiletrigger, //0x94 Cmd_copybidedmg, //0x95 - Cmd_unused_96, //0x96 + Cmd_animatewildpokemonafterfailedpokeball, //0x96 Cmd_tryinfatuating, //0x97 Cmd_updatestatusicon, //0x98 Cmd_setmist, //0x99 @@ -765,7 +755,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_transformdataexecution, //0x9B Cmd_setsubstitute, //0x9C Cmd_mimicattackcopy, //0x9D - Cmd_metronome, //0x9E + Cmd_setcalledmove, //0x9E Cmd_unused_0x9f, //0x9F Cmd_unused_0xA0, //0xA0 Cmd_counterdamagecalculator, //0xA1 @@ -776,15 +766,15 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_settypetorandomresistance, //0xA6 Cmd_setalwayshitflag, //0xA7 Cmd_copymovepermanently, //0xA8 - Cmd_trychoosesleeptalkmove, //0xA9 - Cmd_trysetdestinybond, //0xAA + Cmd_unused_0xA9, //0xA9 + Cmd_unused_AA, //0xAA Cmd_trysetdestinybondtohappen, //0xAB Cmd_settailwind, //0xAC Cmd_tryspiteppreduce, //0xAD Cmd_healpartystatus, //0xAE Cmd_cursetarget, //0xAF Cmd_trysetspikes, //0xB0 - Cmd_setforesight, //0xB1 + Cmd_setvolatile, //0xB1 Cmd_trysetperishsong, //0xB2 Cmd_handlerollout, //0xB3 Cmd_jumpifconfusedandstatmaxed, //0xB4 @@ -798,20 +788,20 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_halvehp, //0xBC Cmd_copyfoestats, //0xBD Cmd_rapidspinfree, //0xBE - Cmd_setdefensecurlbit, //0xBF + Cmd_unused_0xBF, //0xBF Cmd_recoverbasedonsunlight, //0xC0 Cmd_setstickyweb, //0xC1 Cmd_selectfirstvalidtarget, //0xC2 - Cmd_trysetfutureattack, //0xC3 + Cmd_setfutureattack, //0xC3 Cmd_trydobeatup, //0xC4 Cmd_setsemiinvulnerablebit, //0xC5 Cmd_tryfiretwoturnmovenowbyeffect, //0xC6 - Cmd_setminimize, //0xC7 + Cmd_unused_0xC7, //0xC7 Cmd_unused_c8, //0xC8 Cmd_trymemento, //0xC9 Cmd_setforcedtarget, //0xCA Cmd_setcharge, //0xCB - Cmd_callenvironmentattack, //0xCC + Cmd_unused_0xCC, //0xCC Cmd_curestatuswithmove, //0xCD Cmd_settorment, //0xCE Cmd_jumpifnodamage, //0xCF @@ -828,14 +818,14 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_tryswapabilities, //0xDA Cmd_tryimprison, //0xDB Cmd_setstealthrock, //0xDC - Cmd_setuserstatus3, //0xDD - Cmd_assistattackselect, //0xDE + Cmd_trysetvolatile, //0xDD + Cmd_unused_0xde, //0xDE Cmd_trysetmagiccoat, //0xDF Cmd_trysetsnatch, //0xE0 Cmd_unused2, //0xE1 Cmd_switchoutabilities, //0xE2 Cmd_jumpifhasnohp, //0xE3 - Cmd_jumpifnotcurrentmoveargtype, //0xE4 + Cmd_unused_0xE4, //0xE4 Cmd_pickup, //0xE5 Cmd_unused_0xE6, //0xE6 Cmd_unused_0xE7, //0xE7 @@ -928,8 +918,6 @@ static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / static const u16 sFinalStrikeOnlyEffects[] = { - MOVE_EFFECT_BUG_BITE, - MOVE_EFFECT_STEAL_ITEM, MOVE_EFFECT_REMOVE_ARG_TYPE, MOVE_EFFECT_REMOVE_STATUS, MOVE_EFFECT_RECOIL_HP_25, @@ -975,6 +963,26 @@ static const struct PickupItem sPickupTable[] = #undef _ +static void ValidateSavedBattlerCounts(void) +{ + if (gBattleStruct->savedAttackerCount > 0) + { + // #if TESTING + // Test_ExitWithResult(TEST_RESULT_ERROR, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); + // #else + DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); + // #endif + } + if (gBattleStruct->savedTargetCount > 0) + { + // #if TESTING + // Test_ExitWithResult(TEST_RESULT_ERROR, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); + // #else + DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); + // #endif + } +} + static bool32 NoTargetPresent(u8 battler, u32 move) { if (!IsBattlerAlive(gBattlerTarget)) @@ -1001,7 +1009,7 @@ static bool32 NoTargetPresent(u8 battler, u32 move) return FALSE; } -bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) +bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, u32 moveType) { if ((ability == ABILITY_PROTEAN || ability == ABILITY_LIBERO) && !gDisableStructs[gBattlerAttacker].usedProteanLibero @@ -1039,9 +1047,9 @@ u32 NumAffectedSpreadMoveTargets(void) u32 NumFaintedBattlersByAttacker(u32 battlerAtk) { - u32 numMonsFainted = 0; + u32 battler, numMonsFainted = 0; - for (u32 battler = 0; battler < gBattlersCount; battler++) + for (battler = 0; battler < gBattlersCount; battler++) { if (battler == battlerAtk) continue; @@ -1053,23 +1061,23 @@ u32 NumFaintedBattlersByAttacker(u32 battlerAtk) return numMonsFainted; } -bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +bool32 IsMovePowderBlocked(struct BattleContext *ctx) { bool32 effect = FALSE; - if (IsPowderMove(move) && (battlerAtk != battlerDef)) + if (IsPowderMove(ctx->currentMove) && (ctx->battlerAtk != ctx->battlerDef)) { if (B_POWDER_GRASS >= GEN_6 - && (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || GetBattlerAbility(battlerDef) == ABILITY_OVERCOAT)) + && (IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GRASS) || ctx->ability[ctx->battlerDef] == ABILITY_OVERCOAT)) { - gBattlerAbility = battlerDef; - RecordAbilityBattle(gBattlerTarget, ABILITY_OVERCOAT); + gBattlerAbility = ctx->battlerDef; + RecordAbilityBattle(ctx->battlerDef, ABILITY_OVERCOAT); effect = TRUE; } - else if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) + else if (GetBattlerHoldEffect(ctx->battlerDef) == HOLD_EFFECT_SAFETY_GOGGLES) { - RecordItemEffectBattle(battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); - gLastUsedItem = gBattleMons[battlerDef].item; + RecordItemEffectBattle(ctx->battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); + gLastUsedItem = gBattleMons[ctx->battlerDef].item; effect = TRUE; } @@ -1082,7 +1090,7 @@ bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) bool32 EmergencyExitCanBeTriggered(u32 battler) { - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (ability != ABILITY_EMERGENCY_EXIT && ability != ABILITY_WIMP_OUT) return FALSE; @@ -1093,7 +1101,7 @@ bool32 EmergencyExitCanBeTriggered(u32 battler) && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) && CountUsablePartyMons(battler) > 0 - && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) return TRUE; return FALSE; @@ -1116,22 +1124,30 @@ static void Cmd_attackcanceler(void) return; } - enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); + struct BattleContext ctx = {0}; + ctx.battlerAtk = gBattlerAttacker; + ctx.battlerDef = gBattlerTarget; + ctx.currentMove = gCurrentMove; + ctx.moveEffect = GetMoveEffect(ctx.currentMove); if (!IsBattlerAlive(gBattlerAttacker) - && effect != EFFECT_EXPLOSION - && effect != EFFECT_MISTY_EXPLOSION - && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + && ctx.moveEffect != EFFECT_EXPLOSION + && ctx.moveEffect != EFFECT_MISTY_EXPLOSION) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (AtkCanceller_MoveSuccessOrder() != MOVE_STEP_SUCCESS) + + // With how attackcanceller works right now we only need attacker and target abilities. Might change in the future + ctx.ability[ctx.battlerAtk] = GetBattlerAbility(ctx.battlerAtk); + ctx.ability[ctx.battlerDef] = GetBattlerAbility(ctx.battlerDef); + + if (AtkCanceller_MoveSuccessOrder(&ctx) != MOVE_STEP_SUCCESS) return; if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF - && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND + && ctx.ability[ctx.battlerAtk] == ABILITY_PARENTAL_BOND && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE) @@ -1142,54 +1158,43 @@ static void Cmd_attackcanceler(void) return; } - - u32 abilityDef = GetBattlerAbility(gBattlerTarget); - if (CanAbilityBlockMove(gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - abilityDef, - gCurrentMove, - ABILITY_RUN_SCRIPT)) + if (CanAbilityBlockMove( + ctx.battlerAtk, + ctx.battlerDef, + ctx.ability[ctx.battlerAtk], + ctx.ability[ctx.battlerDef], + ctx.currentMove, + RUN_SCRIPT)) return; - if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS) + if (GetMoveNonVolatileStatus(ctx.currentMove) == MOVE_EFFECT_PARALYSIS) { - if (CanAbilityAbsorbMove(gBattlerAttacker, - gBattlerTarget, - abilityDef, - gCurrentMove, - GetBattleMoveType(gCurrentMove), - ABILITY_RUN_SCRIPT)) + if (CanAbilityAbsorbMove( + ctx.battlerAtk, + ctx.battlerDef, + ctx.ability[ctx.battlerDef], + ctx.currentMove, + GetBattleMoveType(ctx.currentMove), + RUN_SCRIPT)) return; } - if (IsMovePowderBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + if (IsMovePowderBlocked(&ctx)) return; - if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE - && !(gHitMarker & (HITMARKER_ALLOW_NO_PP | HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT)) - && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) - { - gBattlescriptCurrInstr = BattleScript_NoPPForMove; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return; - } - - gHitMarker &= ~HITMARKER_ALLOW_NO_PP; - // Check if no available target present on the field or if Sky Battles ban the move if ((NoTargetPresent(gBattlerAttacker, gCurrentMove) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) + && (!gBattleMoveEffects[ctx.moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns))) || (IsMoveNotAllowedInSkyBattles(gCurrentMove))) { gBattleStruct->noTargetPresent = TRUE; - if (effect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling. + if (ctx.moveEffect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling. gBattlescriptCurrInstr = BattleScript_FlingFailConsumeItem; else - gBattlescriptCurrInstr = BattleScript_FailedFromAtkString; + gBattlescriptCurrInstr = BattleScript_ButItFailed; - if (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + if (!gBattleMoveEffects[ctx.moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); return; } @@ -1203,7 +1208,6 @@ static void Cmd_attackcanceler(void) // Edge case for bouncing a powder move against a grass type pokemon. ClearDamageCalcResults(); - SetAtkCancellerForCalledMove(); gEffectBattler = gBattlerTarget; if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE)) { @@ -1221,7 +1225,7 @@ static void Cmd_attackcanceler(void) { u32 battler = gBattlerTarget; - if (abilityDef == ABILITY_MAGIC_BOUNCE) + if (ctx.ability[ctx.battlerDef] == ABILITY_MAGIC_BOUNCE) { battler = gBattlerTarget; gBattleStruct->bouncedMoveIsUsed = TRUE; @@ -1237,7 +1241,6 @@ static void Cmd_attackcanceler(void) if (gBattleStruct->bouncedMoveIsUsed) { ClearDamageCalcResults(); - SetAtkCancellerForCalledMove(); // Edge case for bouncing a powder move against a grass type pokemon. BattleScriptCall(BattleScript_MagicBounce); gBattlerAbility = battler; return; @@ -1254,7 +1257,8 @@ static void Cmd_attackcanceler(void) return; } - for (u32 i = 0; i < gBattlersCount; i++) + u32 i; + for (i = 0; i < gBattlersCount; i++) { if ((gProtectStructs[gBattlerByTurnOrder[i]].stealMove) && MoveCanBeSnatched(gCurrentMove)) { @@ -1266,28 +1270,19 @@ static void Cmd_attackcanceler(void) } } - if (gSpecialStatuses[gBattlerTarget].lightningRodRedirected) + if (gSpecialStatuses[gBattlerTarget].abilityRedirected) { - gSpecialStatuses[gBattlerTarget].lightningRodRedirected = FALSE; - gLastUsedAbility = ABILITY_LIGHTNING_ROD; + gSpecialStatuses[gBattlerTarget].abilityRedirected = FALSE; BattleScriptCall(BattleScript_TookAttack); - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); - } - else if (gSpecialStatuses[gBattlerTarget].stormDrainRedirected) - { - gSpecialStatuses[gBattlerTarget].stormDrainRedirected = FALSE; - gLastUsedAbility = ABILITY_STORM_DRAIN; - BattleScriptCall(BattleScript_TookAttack); - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } else if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) - && (effect != EFFECT_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) - && effect != EFFECT_SUCKER_PUNCH - && effect != EFFECT_COUNTER - && effect != EFFECT_UPPER_HAND) + && (ctx.moveEffect != EFFECT_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + && (!gBattleMoveEffects[ctx.moveEffect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) + && ctx.moveEffect != EFFECT_SUCKER_PUNCH + && ctx.moveEffect != EFFECT_COUNTER + && ctx.moveEffect != EFFECT_UPPER_HAND) { - if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)) gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; @@ -1303,7 +1298,7 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr = cmd->nextInstr; } - else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + else if (gProtectStructs[gBattlerTarget].beakBlastCharge && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; @@ -1332,7 +1327,7 @@ static void JumpIfMoveFailed(u32 adder, u32 move, u32 moveType, const u8 *failIn GetBattlerAbility(gBattlerTarget), move, moveType, - ABILITY_RUN_SCRIPT)) + RUN_SCRIPT)) return; } @@ -1364,223 +1359,13 @@ static bool32 JumpIfMoveAffectedByProtect(u32 move, u32 battler, u32 shouldJump, return affected; } -static bool32 AccuracyCalcHelper(u32 move, u32 battler) -{ - bool32 effect = FALSE; - u32 ability = ABILITY_NONE; - enum BattleMoveEffects moveEffect = GetMoveEffect(move); - u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - - if ((gStatuses3[battler] & STATUS3_ALWAYS_HITS && gDisableStructs[battler].battlerWithSureHit == gBattlerAttacker) - || (B_TOXIC_NEVER_MISS >= GEN_6 - && nonVolatileStatus == MOVE_EFFECT_TOXIC - && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)) - || gStatuses4[battler] & STATUS4_GLAIVE_RUSH) - { - effect = TRUE; - } - // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. - else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD - && !(gStatuses3[battler] & STATUS3_COMMANDER) - && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battler] == SKY_DROP_NO_TARGET)) - { - effect = TRUE; - ability = ABILITY_NO_GUARD; - } - // If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits. - else if (GetBattlerAbility(battler) == ABILITY_NO_GUARD - && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battler] == SKY_DROP_NO_TARGET)) - { - effect = TRUE; - ability = ABILITY_NO_GUARD; - } - // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. - else if (gStatuses3[battler] & STATUS3_TELEKINESIS - && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && moveEffect != EFFECT_OHKO - && moveEffect != EFFECT_SHEER_COLD) - { - effect = TRUE; - } - else if (gBattleStruct->battlerState[battler].pursuitTarget) - { - effect = TRUE; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)) - { - effect = TRUE; - } - else if ((gStatuses3[battler] & STATUS3_COMMANDER) - || (gStatuses3[battler] & STATUS3_PHANTOM_FORCE) - || ((gStatuses3[battler] & STATUS3_ON_AIR) && !(MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move))) - || ((gStatuses3[battler] & STATUS3_UNDERGROUND) && !MoveDamagesUnderground(move)) - || ((gStatuses3[battler] & STATUS3_UNDERWATER) && !MoveDamagesUnderWater(move))) - { - gBattleStruct->moveResultFlags[battler] |= MOVE_RESULT_MISSED; - effect = TRUE; - } - else if (B_MINIMIZE_DMG_ACC >= GEN_6 - && (gStatuses3[battler] & STATUS3_MINIMIZED) - && MoveIncreasesPowerToMinimizedTargets(move)) - { - effect = TRUE; - } - else if (GetMoveAccuracy(move) == 0) - { - effect = TRUE; - } - - if (!effect && HasWeatherEffect()) - { - if (MoveAlwaysHitsInRain(move) && IsBattlerWeatherAffected(battler, B_WEATHER_RAIN)) - effect = TRUE; - else if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) - effect = TRUE; - - if (effect) - return effect; - } - - if (ability != ABILITY_NONE) - RecordAbilityBattle(gBattlerAttacker, ABILITY_NO_GUARD); - - return effect; -} - -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) -{ - u32 calc, moveAcc; - s8 buff, accStage, evasionStage; - u32 atkParam = GetBattlerHoldEffectParam(battlerAtk); - u32 defParam = GetBattlerHoldEffectParam(battlerDef); - u32 atkAlly = BATTLE_PARTNER(battlerAtk); - u32 atkAllyAbility = GetBattlerAbility(atkAlly); - - gPotentialItemEffectBattler = battlerDef; - accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; - evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; - if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE - || (B_ILLUMINATE_EFFECT >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) - evasionStage = DEFAULT_STAT_STAGE; - if (MoveIgnoresDefenseEvasionStages(move)) - evasionStage = DEFAULT_STAT_STAGE; - if (defAbility == ABILITY_UNAWARE) - accStage = DEFAULT_STAT_STAGE; - - if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) - buff = accStage; - else - buff = accStage + DEFAULT_STAT_STAGE - evasionStage; - - if (buff < MIN_STAT_STAGE) - buff = MIN_STAT_STAGE; - if (buff > MAX_STAT_STAGE) - buff = MAX_STAT_STAGE; - - moveAcc = GetMoveAccuracy(move); - // Check Thunder and Hurricane on sunny weather. - if (IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) - moveAcc = 50; - // Check Wonder Skin. - if (defAbility == ABILITY_WONDER_SKIN && IsBattleMoveStatus(move) && moveAcc > 50) - moveAcc = 50; - - calc = gAccuracyStageRatios[buff].dividend * moveAcc; - calc /= gAccuracyStageRatios[buff].divisor; - - // Attacker's ability - switch (atkAbility) - { - case ABILITY_COMPOUND_EYES: - calc = (calc * 130) / 100; // 1.3 compound eyes boost - break; - case ABILITY_VICTORY_STAR: - calc = (calc * 110) / 100; // 1.1 victory star boost - break; - case ABILITY_HUSTLE: - if (IsBattleMovePhysical(move)) - calc = (calc * 80) / 100; // 1.2 hustle loss - break; - } - - // Target's ability - switch (defAbility) - { - case ABILITY_SAND_VEIL: - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) - calc = (calc * 80) / 100; // 1.2 sand veil loss - break; - case ABILITY_SNOW_CLOAK: - if (HasWeatherEffect() && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) - calc = (calc * 80) / 100; // 1.2 snow cloak loss - break; - case ABILITY_TANGLED_FEET: - if (gBattleMons[battlerDef].volatiles.confusionTurns) - calc = (calc * 50) / 100; // 1.5 tangled feet loss - break; - } - - // Attacker's ally's ability - switch (atkAllyAbility) - { - case ABILITY_VICTORY_STAR: - if (IsBattlerAlive(atkAlly)) - calc = (calc * 110) / 100; // 1.1 ally's victory star boost - break; - } - - // Attacker's hold effect - switch (atkHoldEffect) - { - case HOLD_EFFECT_WIDE_LENS: - calc = (calc * (100 + atkParam)) / 100; - break; - case HOLD_EFFECT_ZOOM_LENS: - if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)) - calc = (calc * (100 + atkParam)) / 100; - break; - } - - // Target's hold effect - switch (defHoldEffect) - { - case HOLD_EFFECT_EVASION_UP: - calc = (calc * (100 - defParam)) / 100; - break; - } - - if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) - { - if (atkAbility == ABILITY_RIPEN) - calc = (calc * 140) / 100; // ripen gives 40% acc boost - else - calc = (calc * 120) / 100; // 20% acc boost - } - - if (gFieldStatuses & STATUS_FIELD_GRAVITY) - calc = (calc * 5) / 3; // 1.66 Gravity acc boost - - if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerDef) == AFFECTION_FIVE_HEARTS) - calc = (calc * 90) / 100; - - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_FOG) - calc = (calc * 60) / 100; // modified by 3/5 - - return calc; -} - static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move) { - // pokefirered specific - if ((gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE - && !BtlCtrl_OakOldMan_TestState2Flag(1) + if (IS_FRLG && + ((gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE + && (!BtlCtrl_OakOldMan_TestState2Flag(1) || !BtlCtrl_OakOldMan_TestState2Flag(2)) && gMovesInfo[move].power != 0 - && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - || (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE - && !BtlCtrl_OakOldMan_TestState2Flag(2) - && gMovesInfo[move].power == 0 - && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - || (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)) + && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) || (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE))) { JumpIfMoveFailed(7, move, GetBattleMoveType(move), failInstr); return; @@ -1590,14 +1375,14 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u move = gCurrentMove; enum BattleMoveEffects effect = GetMoveEffect(move); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); if (move == NO_ACC_CALC_CHECK_LOCK_ON) { - if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) + if (gBattleMons[gBattlerTarget].volatiles.lockOn && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) gBattlescriptCurrInstr = nextInstr; - else if (gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE)) + else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) gBattlescriptCurrInstr = failInstr; else if (!JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, failInstr)) gBattlescriptCurrInstr = nextInstr; @@ -1611,7 +1396,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u GetBattlerAbility(gBattlerTarget), gCurrentMove, GetBattleMoveType(gCurrentMove), - ABILITY_RUN_SCRIPT); + RUN_SCRIPT); } } else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT @@ -1624,28 +1409,30 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u } else { - u32 numTargets = 0; - u32 numMisses = 0; - u32 moveType = GetBattleMoveType(move); - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); + u32 battlerDef, + numTargets = 0, + numMisses = 0, + moveType = GetBattleMoveType(move), + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); bool32 calcSpreadMove = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(move); - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->calculatedSpreadMoveAccuracy) break; if ((!calcSpreadMove && battlerDef != gBattlerTarget) || IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; numTargets++; - if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE, failInstr) || AccuracyCalcHelper(move, battlerDef)) + enum Ability abilityDef = GetBattlerAbility(battlerDef); + if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE, failInstr) + || CanMoveSkipAccuracyCalc(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, move, RUN_SCRIPT)) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); - u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + u32 holdEffectDef = GetBattlerHoldEffect(battlerDef); u32 accuracy = GetTotalAccuracy(gBattlerAttacker, battlerDef, move, @@ -1717,76 +1504,20 @@ static void Cmd_accuracycheck(void) AccuracyCheck(FALSE, cmd->nextInstr, cmd->failInstr, cmd->move); } -static void Cmd_attackstring(void) +static void Cmd_printattackstring(void) { CMD_ARGS(); if (gBattleControllerExecFlags) return; - if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED))) - { - PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); - gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - } - gBattlescriptCurrInstr = cmd->nextInstr; + PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); gBattleCommunication[MSG_DISPLAY] = 0; + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_ppreduce(void) +static void Cmd_unused0x3(void) { - CMD_ARGS(); - - s32 i, ppToDeduct = 1; - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - - if (gBattleControllerExecFlags) - return; - - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - - if (moveTarget == MOVE_TARGET_BOTH - || moveTarget == MOVE_TARGET_FOES_AND_ALLY - || moveTarget == MOVE_TARGET_ALL_BATTLERS - || MoveForcesPressure(gCurrentMove)) - { - for (i = 0; i < gBattlersCount; i++) - { - if (!IsBattlerAlly(i, gBattlerAttacker) && IsBattlerAlive(i)) - ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE); - } - } - else if (moveTarget != MOVE_TARGET_OPPONENTS_FIELD) - { - if (gBattlerAttacker != gBattlerTarget && GetBattlerAbility(gBattlerTarget) == ABILITY_PRESSURE) - ppToDeduct++; - } - - if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBattlerAttacker].pp[gCurrMovePos]) - { - gProtectStructs[gBattlerAttacker].notFirstStrike = TRUE; - - // For item Metronome, echoed voice - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] || WasUnableToUseMove(gBattlerAttacker)) - gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; - - if (gBattleMons[gBattlerAttacker].pp[gCurrMovePos] > ppToDeduct) - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] -= ppToDeduct; - else - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = 0; - - if (MOVE_IS_PERMANENT(gBattlerAttacker, gCurrMovePos)) - { - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, - sizeof(gBattleMons[gBattlerAttacker].pp[gCurrMovePos]), - &gBattleMons[gBattlerAttacker].pp[gCurrMovePos]); - MarkBattlerForControllerExec(gBattlerAttacker); - } - } - - gHitMarker &= ~HITMARKER_NO_PPDEDUCT; - gBattlescriptCurrInstr = cmd->nextInstr; } // The chance is 1/N for each stage. @@ -1842,7 +1573,7 @@ static inline u32 GetHoldEffectCritChanceIncrease(u32 battler, enum ItemHoldEffe return critStageIncrease; } -s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk) +s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum ItemHoldEffect holdEffectAtk) { s32 critChance = 0; @@ -1850,7 +1581,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA { critChance = CRITICAL_HIT_BLOCKED; } - else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS + else if (gBattleMons[battlerAtk].volatiles.laserFocus || MoveAlwaysCrits(move) || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)) { @@ -1858,12 +1589,12 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA } else { - critChance = 2 * ((gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY) != 0) - + 1 * ((gBattleMons[battlerAtk].status2 & STATUS2_DRAGON_CHEER) != 0) + critChance = (gBattleMons[battlerAtk].volatiles.focusEnergy != 0 ? 2 : 0) + + (gBattleMons[battlerAtk].volatiles.dragonCheer != 0 ? 1 : 0) + GetMoveCriticalHitStage(move) + GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk) - + 2 * (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) - + (abilityAtk == ABILITY_SUPER_LUCK) + + ((B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) ? 2 : 0) + + (abilityAtk == ABILITY_SUPER_LUCK ? 1 : 0) + gBattleStruct->bonusCritStages[gBattlerAttacker]; if (critChance >= ARRAY_COUNT(sCriticalHitOdds)) @@ -1891,7 +1622,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA // Threshold = Base Speed / 2 // High crit move = 8 * (Base Speed / 2) // Focus Energy = 4 * (Base Speed / 2) -s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk) +s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, enum Ability abilityAtk, enum Ability abilityDef, enum ItemHoldEffect holdEffectAtk) { s32 critChance = 0; s32 moveCritStage = GetMoveCriticalHitStage(gCurrentMove); @@ -1908,9 +1639,9 @@ s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec if (bonusCritStage > 0) critChance *= bonusCritStage; - if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY) + if (gBattleMons[battlerAtk].volatiles.focusEnergy) critChance *= 4; - else if (gBattleMons[battlerAtk].status2 & STATUS2_DRAGON_CHEER) + else if (gBattleMons[battlerAtk].volatiles.dragonCheer) critChance *= 2; if (holdEffectCritStage > 0) @@ -1933,7 +1664,7 @@ s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec } // Guaranteed crits - else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS + else if (gBattleMons[battlerAtk].volatiles.laserFocus || MoveAlwaysCrits(move) || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)) { @@ -1955,14 +1686,14 @@ static void Cmd_critcalc(void) { CMD_ARGS(); - u32 partySlot = gBattlerPartyIndexes[gBattlerAttacker]; - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + u32 partySlot = gBattlerPartyIndexes[gBattlerAttacker], + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), + battlerDef; bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); gPotentialItemEffectBattler = gBattlerAttacker; - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->calculatedDamageDone) break; @@ -1971,11 +1702,12 @@ static void Cmd_critcalc(void) continue; if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if (GetGenConfig(GEN_CONFIG_CRIT_CHANCE) == GEN_1) gBattleStruct->critChance[battlerDef] = CalcCritChanceStageGen1(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk); @@ -1983,7 +1715,7 @@ static void Cmd_critcalc(void) gBattleStruct->critChance[battlerDef] = CalcCritChanceStage(gBattlerAttacker, battlerDef, gCurrentMove, TRUE, abilityAtk, abilityDef, holdEffectAtk); if ((gBattleTypeFlags & (BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_POKEDUDE)) - || ((gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) && !BtlCtrl_OakOldMan_TestState2Flag(1))) + || ((gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) && (!IS_FRLG || !BtlCtrl_OakOldMan_TestState2Flag(1)))) gSpecialStatuses[battlerDef].criticalHit = FALSE; else if (gBattleStruct->critChance[battlerDef] == -1) gSpecialStatuses[battlerDef].criticalHit = FALSE; @@ -2048,7 +1780,7 @@ static void Cmd_damagecalc(void) for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) continue; @@ -2079,8 +1811,8 @@ static void Cmd_typecalc(void) ctx.updateFlags = TRUE; ctx.abilityAtk = GetBattlerAbility(gBattlerAttacker); ctx.abilityDef = GetBattlerAbility(gBattlerTarget); - ctx.holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(gBattlerTarget, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker); + ctx.holdEffectDef = GetBattlerHoldEffect(gBattlerTarget); CalcTypeEffectivenessMultiplier(&ctx); } @@ -2096,11 +1828,11 @@ static void Cmd_adjustdamage(void) u8 param; u32 battlerDef; u32 rand = Random() % 100; - u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); + u32 affectionScore; u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); - bool32 enduredHit = FALSE; + u32 enduredHit = 0; for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { @@ -2111,7 +1843,7 @@ static void Cmd_adjustdamage(void) continue; if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef]) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; if (DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)) @@ -2138,37 +1870,38 @@ static void Cmd_adjustdamage(void) if (gBattleMons[gBattlerTarget].hp > gBattleStruct->moveDamage[battlerDef]) continue; - holdEffect = GetBattlerHoldEffect(battlerDef, TRUE); + holdEffect = GetBattlerHoldEffect(battlerDef); param = GetBattlerHoldEffectParam(battlerDef); + affectionScore = GetBattlerAffectionHearts(battlerDef); gPotentialItemEffectBattler = battlerDef; if (moveEffect == EFFECT_FALSE_SWIPE) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; } - else if (gProtectStructs[battlerDef].endured) + else if (gDisableStructs[battlerDef].endured) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED; } else if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordItemEffectBattle(battlerDef, holdEffect); gLastUsedItem = gBattleMons[battlerDef].item; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; } else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordAbilityBattle(battlerDef, ABILITY_STURDY); gLastUsedAbility = ABILITY_STURDY; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED; } else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordItemEffectBattle(battlerDef, holdEffect); gLastUsedItem = gBattleMons[battlerDef].item; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; @@ -2179,16 +1912,17 @@ static void Cmd_adjustdamage(void) || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; } } // Handle reducing the dmg to 1 hp. - if (enduredHit) + if (enduredHit & 1u << battlerDef) { gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; gSpecialStatuses[battlerDef].enduredDamage = TRUE; + gProtectStructs[battlerDef].assuranceDoubled = TRUE; } } @@ -2238,9 +1972,9 @@ static void Cmd_multihitresultmessage(void) static inline bool32 DoesBattlerNegateDamage(u32 battler) { u32 species = gBattleMons[battler].species; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; if (ability == ABILITY_DISGUISE && species == SPECIES_MIMIKYU) return TRUE; @@ -2257,8 +1991,8 @@ static u32 UpdateEffectivenessResultFlagsForDoubleSpreadMoves(u32 resultFlags) { for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { - if ((gBattleStruct->moveResultFlags[battlerDef] & (MOVE_RESULT_MISSED | MOVE_RESULT_NO_EFFECT) - || gBattleStruct->noResultString[battlerDef])) + if (gBattleStruct->moveResultFlags[battlerDef] & (MOVE_RESULT_MISSED | MOVE_RESULT_NO_EFFECT) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; switch (sound) @@ -2316,13 +2050,13 @@ static inline bool32 TryTeraShellDistortTypeMatchups(u32 battlerDef) // According to Gen5 Weakness berry activation happens after the attackanimation. // It doesn't have any impact on gameplay and is only a visual thing which can be adjusted later. -static inline bool32 TryActivateWeakenessBerry(u32 battlerDef) +static inline bool32 TryActivateWeaknessBerry(u32 battlerDef) { if (gSpecialStatuses[battlerDef].berryReduced && gBattleMons[battlerDef].item != ITEM_NONE) { gBattleScripting.battler = battlerDef; gLastUsedItem = gBattleMons[battlerDef].item; - gBattleStruct->partyState[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]].ateBerry = TRUE; + GetBattlerPartyState(battlerDef)->ateBerry = TRUE; BattleScriptCall(BattleScript_BerryReduceDmg); return TRUE; } @@ -2336,13 +2070,14 @@ static bool32 ProcessPreAttackAnimationFuncs(void) if (IsDoubleSpreadMove()) { u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + if (!gBattleStruct->printedStrongWindsWeakenedAttack) { for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) || (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY)) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; if (TryStrongWindsWeakenAttack(battlerDef, moveType)) @@ -2354,12 +2089,12 @@ static bool32 ProcessPreAttackAnimationFuncs(void) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) || (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY)) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; if (TryTeraShellDistortTypeMatchups(battlerDef)) return TRUE; - if (TryActivateWeakenessBerry(battlerDef)) + if (TryActivateWeaknessBerry(battlerDef)) return TRUE; } } @@ -2369,7 +2104,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) return TRUE; if (TryTeraShellDistortTypeMatchups(gBattlerTarget)) return TRUE; - if (TryActivateWeakenessBerry(gBattlerTarget)) + if (TryActivateWeaknessBerry(gBattlerTarget)) return TRUE; } @@ -2426,7 +2161,7 @@ static void Cmd_attackanimation(void) if (!(moveResultFlags & MOVE_RESULT_NO_EFFECT)) { u32 multihit; - if (gBattleMons[gBattlerTarget].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[gBattlerTarget].volatiles.substitute) { multihit = gMultiHitCounter; } @@ -2468,21 +2203,21 @@ static void Cmd_waitanimation(void) { CMD_ARGS(); - if (gBattleControllerExecFlags == 0) + if (gBattleControllerExecFlags == 0 && gBattleStruct->battlerKOAnimsRunning == 0) gBattlescriptCurrInstr = cmd->nextInstr; } static void DoublesHPBarReduction(void) { if (gBattleStruct->doneDoublesSpreadHit - || gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE)) + || gHitMarker & (HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE)) return; for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT || gBattleStruct->moveDamage[battlerDef] == 0 - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove) || DoesDisguiseBlockMove(battlerDef, gCurrentMove)) continue; @@ -2507,7 +2242,7 @@ static void Cmd_healthbarupdate(void) if (gBattleControllerExecFlags) return; - if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) { if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && gDisableStructs[battler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) { @@ -2545,13 +2280,15 @@ static void Cmd_healthbarupdate(void) static void Cmd_datahpupdate(void) { CMD_ARGS(u8 battler); + bool32 isPassiveHpUpdate = gHitMarker & HITMARKER_PASSIVE_HP_UPDATE; + bool32 disguiseActivates = FALSE; if (gBattleControllerExecFlags) return; u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) { if (DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && gDisableStructs[battler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE)) { @@ -2575,19 +2312,18 @@ static void Cmd_datahpupdate(void) else if (DoesDisguiseBlockMove(battler, gCurrentMove)) { // TODO: Convert this to a proper FORM_CHANGE type. - u32 side = GetBattlerSide(battler); gBattleScripting.battler = battler; - if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; + if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; if (gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM; else gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED; - if (B_DISGUISE_HP_LOSS >= GEN_8) + if (GetGenConfig(GEN_CONFIG_DISGUISE_HP_LOSS) >= GEN_8) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_TargetFormChange; - return; + disguiseActivates = TRUE; } else { @@ -2630,7 +2366,7 @@ static void Cmd_datahpupdate(void) // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are // used in combination as general damage trackers for other purposes. specialDmg is additionally used // to help determine if a fire move should defrost the target. - if (IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && effect != EFFECT_PAIN_SPLIT) + if (IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE) && effect != EFFECT_PAIN_SPLIT) { gProtectStructs[battler].physicalDmg = gBattleStruct->moveDamage[battler]; gSpecialStatuses[battler].physicalDmg = gBattleStruct->moveDamage[battler]; @@ -2638,8 +2374,9 @@ static void Cmd_datahpupdate(void) gProtectStructs[battler].physicalBattlerId = gBattlerAttacker; else gProtectStructs[battler].physicalBattlerId = gBattlerTarget; + gProtectStructs[battler].assuranceDoubled = TRUE; } - else if (!IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && effect != EFFECT_PAIN_SPLIT) + else if (!IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE) && effect != EFFECT_PAIN_SPLIT) { // Record special damage/attacker for Mirror Coat gProtectStructs[battler].specialDmg = gBattleStruct->moveDamage[battler]; @@ -2648,18 +2385,32 @@ static void Cmd_datahpupdate(void) gProtectStructs[battler].specialBattlerId = gBattlerAttacker; else gProtectStructs[battler].specialBattlerId = gBattlerTarget; + gProtectStructs[battler].assuranceDoubled = TRUE; } } - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; // Send updated HP BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[battler].hp), &gBattleMons[battler].hp); MarkBattlerForControllerExec(battler); } if (gBattlerAttacker != gBattlerTarget + && !isPassiveHpUpdate && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS && IsBattlerTurnDamaged(gBattlerTarget)) - gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; + GetBattlerPartyState(gBattlerTarget)->timesGotHit++; + + if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF + && !isPassiveHpUpdate + && IsBattlerTurnDamaged(gBattlerTarget) + && gBattleMons[gBattlerTarget].item != ITEM_NONE + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) + && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) + && !NoAliveMonsForEitherParty()) + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE; + + if (disguiseActivates) + return; } TryRestoreDamageAfterCheekPouch(battler); @@ -2754,7 +2505,7 @@ static inline bool32 ShouldPrintTwoFoesMessage(u32 moveResult) { return gBattlerTarget == BATTLE_OPPOSITE(gBattlerAttacker) && gBattleStruct->moveResultFlags[BATTLE_PARTNER(gBattlerTarget)] & moveResult - && !gBattleStruct->noResultString[BATTLE_PARTNER(gBattlerTarget)]; + && gBattleStruct->noResultString[BATTLE_PARTNER(gBattlerTarget)] == CAN_DAMAGE; } static inline bool32 ShouldRelyOnTwoFoesMessage(u32 moveResult) @@ -2762,7 +2513,7 @@ static inline bool32 ShouldRelyOnTwoFoesMessage(u32 moveResult) return gBattlerTarget == BATTLE_PARTNER(BATTLE_OPPOSITE(gBattlerAttacker)) && gBattleStruct->moveResultFlags[BATTLE_OPPOSITE(gBattlerAttacker)] & moveResult && !(gBattleStruct->moveResultFlags[BATTLE_OPPOSITE(gBattlerAttacker)] & MOVE_RESULT_MISSED && gBattleStruct->missStringId[BATTLE_OPPOSITE(gBattlerAttacker)] > B_MSG_AVOIDED_ATK) - && !gBattleStruct->noResultString[BATTLE_OPPOSITE(gBattlerAttacker)]; + && gBattleStruct->noResultString[BATTLE_OPPOSITE(gBattlerAttacker)] == CAN_DAMAGE; } static void Cmd_resultmessage(void) @@ -2780,9 +2531,8 @@ static void Cmd_resultmessage(void) if (gDisableStructs[gBattlerTarget].iceFaceActivationPrevention) { gDisableStructs[gBattlerTarget].iceFaceActivationPrevention = FALSE; - u32 side = GetBattlerSide(gBattlerTarget); - if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + if (GetBattlerPartyState(gBattlerTarget)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(gBattlerTarget)->changedSpecies = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_EISCUE_NOICE; gBattleScripting.battler = gBattlerTarget; // For STRINGID_PKMNTRANSFORMED BattleScriptCall(BattleScript_IceFaceNullsDamage); @@ -3014,9 +2764,20 @@ static void Cmd_printselectionstringfromtable(void) } } -u8 GetBattlerTurnOrderNum(u8 battler) +bool32 HasBattlerActedThisTurn(u32 battler) { - s32 i; + u32 i; + for (i = 0; i < gCurrentTurnActionNumber; i++) + { + if (gBattlerByTurnOrder[i] == battler) + return TRUE; + } + return FALSE; +} + +u32 GetBattlerTurnOrderNum(u32 battler) +{ + u32 i; for (i = 0; i < gBattlersCount; i++) { if (gBattlerByTurnOrder[i] == battler) @@ -3037,9 +2798,9 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) gLastUsedItem = gBattleMons[battlerItem].item; gBattleMons[battlerItem].item = ITEM_NONE; - if (B_STEAL_WILD_ITEMS >= GEN_9 + if (GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) - && MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_STEAL_ITEM) + && GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM && battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this { AddBagItem(gLastUsedItem, 1); @@ -3071,7 +2832,7 @@ static inline bool32 TrySetReflect(u32 battler) if (!(gSideStatuses[side] & SIDE_STATUS_REFLECT)) { gSideStatuses[side] |= SIDE_STATUS_REFLECT; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LIGHT_CLAY) gSideTimers[side].reflectTimer = gBattleTurnCounter + 8; else gSideTimers[side].reflectTimer = gBattleTurnCounter + 5; @@ -3092,7 +2853,7 @@ static inline bool32 TrySetLightScreen(u32 battler) if (!(gSideStatuses[side] & SIDE_STATUS_LIGHTSCREEN)) { gSideStatuses[side] |= SIDE_STATUS_LIGHTSCREEN; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_LIGHT_CLAY) gSideTimers[side].lightscreenTimer = gBattleTurnCounter + 8; else gSideTimers[side].lightscreenTimer = gBattleTurnCounter + 5; @@ -3107,7 +2868,7 @@ static inline bool32 TrySetLightScreen(u32 battler) return FALSE; } -static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffects effect, enum StatusTrigger trigger) +static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger) { gEffectBattler = effectBattler; @@ -3206,10 +2967,8 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai switch (gBattleScripting.moveEffect) // Set move effects which happen later on { case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: case MOVE_EFFECT_PAYDAY: case MOVE_EFFECT_BUG_BITE: - case MOVE_EFFECT_STEAL_ITEM: activateAfterFaint = TRUE; break; } @@ -3224,7 +2983,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattleScripting.moveEffect = MOVE_EFFECT_NONE; else if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) - && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->commanderActive[gBattlerAttacker]) + && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE) && !primary) gBattleScripting.moveEffect = MOVE_EFFECT_NONE; else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint) @@ -3252,25 +3011,25 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai GetBattlerAbility(gBattlerAttacker), battlerAbility, gBattleScripting.moveEffect, - STATUS_CHECK_TRIGGER)) - SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); + CHECK_TRIGGER)) + SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); break; case MOVE_EFFECT_CONFUSION: if (!CanBeConfused(gEffectBattler) - || gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION + || gBattleMons[gEffectBattler].volatiles.confusionTurns || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary)) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); // 2-5 turns + gBattleMons[gEffectBattler].volatiles.confusionTurns = ((Random()) % 4) + 2; // 2-5 turns // If the confusion is activating due to being released from Sky Drop, go to "confused due to fatigue" script. // Otherwise, do normal confusion script. if (GetMoveEffect(gCurrentMove) == EFFECT_SKY_DROP) { - gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; gBattlerAttacker = gEffectBattler; gBattlescriptCurrInstr = BattleScript_ThrashConfuses; } @@ -3291,6 +3050,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gLastUsedAbility = ABILITY_INNER_FOCUS; gBattlerAbility = gEffectBattler; RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); + BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_FlinchPrevention; } else @@ -3298,14 +3058,14 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattlescriptCurrInstr++; } } - else if (gBattleMons[gEffectBattler].status2 & STATUS2_FLINCHED) + else if (gBattleMons[gEffectBattler].volatiles.flinched) { gBattlescriptCurrInstr++; } - else if (GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber - && !(GetActiveGimmick(gEffectBattler) == GIMMICK_DYNAMAX)) + else if (!HasBattlerActedThisTurn(gEffectBattler) + && GetActiveGimmick(gEffectBattler) != GIMMICK_DYNAMAX) { - gBattleMons[gEffectBattler].status2 |= STATUS2_FLINCHED; + gBattleMons[gEffectBattler].volatiles.flinched = TRUE; gBattlescriptCurrInstr++; } else @@ -3314,11 +3074,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_UPROAR: - if (!(gBattleMons[gEffectBattler].status2 & STATUS2_UPROAR)) + if (!gBattleMons[gEffectBattler].volatiles.uproarTurns) { - gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gEffectBattler].volatiles.multipleTurns = TRUE; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN(B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2); + gBattleMons[gEffectBattler].volatiles.uproarTurns = B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectUproar; @@ -3379,29 +3139,23 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_WRAP: - if (gBattleMons[gEffectBattler].status2 & STATUS2_WRAPPED) + if (gBattleMons[gEffectBattler].volatiles.wrapped) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) + gBattleMons[gEffectBattler].volatiles.wrapped = TRUE; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5; else - gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2; + gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5); gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove; gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectWrap; - - for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattleCommunication[MULTISTRING_CHOOSER] < NUM_TRAPPING_MOVES; gBattleCommunication[MULTISTRING_CHOOSER]++) - { - if (sTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) - break; - } } break; case MOVE_EFFECT_ATK_PLUS_1: @@ -3520,54 +3274,25 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (B_SKIP_RECHARGE == GEN_1 && !IsBattlerAlive(gBattlerTarget)) // Skip recharge if gen 1 and foe is KO'd break; - gBattleMons[gEffectBattler].status2 |= STATUS2_RECHARGE; + gBattleMons[gEffectBattler].volatiles.recharge = TRUE; gDisableStructs[gEffectBattler].rechargeTimer = 2; gLockedMoves[gEffectBattler] = gCurrentMove; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_RAGE: - gBattleMons[gBattlerAttacker].status2 |= STATUS2_RAGE; + gBattleMons[gBattlerAttacker].volatiles.rage = TRUE; gBattlescriptCurrInstr++; break; - case MOVE_EFFECT_STEAL_ITEM: - if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) - || gBattleMons[gBattlerAttacker].item != ITEM_NONE - || gBattleMons[gBattlerTarget].item == ITEM_NONE) - { - gBattlescriptCurrInstr++; - } - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) - { - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_NoItemSteal; - - gLastUsedAbility = gBattleMons[gBattlerTarget].ability; - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); - } - else - { - StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item - - if (!(B_STEAL_WILD_ITEMS >= GEN_9 - && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) - { - gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) - gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later - } - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_ItemSteal; - } - break; case MOVE_EFFECT_PREVENT_ESCAPE: - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) // Do we need to check if the status is already set? { - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; } gBattlescriptCurrInstr++; break; case MOVE_EFFECT_NIGHTMARE: - gBattleMons[gBattlerTarget].status2 |= STATUS2_NIGHTMARE; + gBattleMons[gBattlerTarget].volatiles.nightmare = TRUE; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_ALL_STATS_UP: @@ -3603,15 +3328,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_THRASH: // Petal Dance doesn't lock mons that copy the move with Dancer - if (gSpecialStatuses[gEffectBattler].dancerUsedMove || gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE) + if (gSpecialStatuses[gEffectBattler].dancerUsedMove || gBattleMons[gEffectBattler].volatiles.lockConfusionTurns) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gEffectBattler].volatiles.multipleTurns = TRUE; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN(RandomUniform(RNG_RAMPAGE_TURNS, 2, 3)); + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = RandomUniform(RNG_RAMPAGE_TURNS, 2, 3); } break; case MOVE_EFFECT_CLEAR_SMOG: @@ -3620,7 +3345,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (gBattleMons[gEffectBattler].statStages[i] != DEFAULT_STAT_STAGE) break; } - if ((gSpecialStatuses[gEffectBattler].physicalDmg || gSpecialStatuses[gEffectBattler].specialDmg) && i != NUM_BATTLE_STATS) + if (IsBattlerTurnDamaged(gEffectBattler) && i != NUM_BATTLE_STATS) { for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[gEffectBattler].statStages[i] = DEFAULT_STAT_STAGE; @@ -3630,14 +3355,14 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_FLAME_BURST: if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) - && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_SEMI_INVULNERABLE) + && !IsSemiInvulnerable(BATTLE_PARTNER(gBattlerTarget), CHECK_ALL) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) { - i = BATTLE_PARTNER(gBattlerTarget); - gBattleScripting.savedBattler = i; + gBattleScripting.battler = i = BATTLE_PARTNER(gBattlerTarget); gBattleStruct->moveDamage[i] = gBattleMons[i].maxHP / 16; if (gBattleStruct->moveDamage[i] == 0) gBattleStruct->moveDamage[i] = 1; + BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; } break; @@ -3671,7 +3396,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_CORE_ENFORCER: - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) + if (HasBattlerActedThisTurn(gBattlerTarget) && !NoAliveMonsForEitherParty()) { BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -3684,7 +3409,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_INCINERATE: if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX) - || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler, FALSE) == HOLD_EFFECT_GEMS)) + || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_GEMS)) { gLastUsedItem = gBattleMons[gEffectBattler].item; gBattleMons[gEffectBattler].item = 0; @@ -3697,7 +3422,12 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_BUG_BITE: - if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES + if (GetBattlerHoldEffect(gEffectBattler) == HOLD_EFFECT_JABOCA_BERRY) + { + // jaboca berry triggers instead of being stolen + gBattlescriptCurrInstr++; + } + else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES && battlerAbility != ABILITY_STICKY_HOLD) { // target loses their berry @@ -3712,19 +3442,19 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_TRAP_BOTH: - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!(gBattleMons[gBattlerTarget].volatiles.escapePrevention || gBattleMons[gBattlerAttacker].volatiles.escapePrevention)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_BothCanNoLongerEscape; } - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerAttacker].volatiles.escapePrevention) gDisableStructs[gBattlerAttacker].battlerPreventingEscape = gBattlerTarget; - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; + gBattleMons[gBattlerAttacker].volatiles.escapePrevention = TRUE; break; case MOVE_EFFECT_REMOVE_ARG_TYPE: { @@ -3759,31 +3489,19 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_STEALTH_ROCK: - if (!(gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_STEALTH_ROCK)) + if (!IsHazardOnSide(GetBattlerSide(gEffectBattler), HAZARDS_STEALTH_ROCK)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_StealthRockActivates; } break; - case MOVE_EFFECT_SPIKES: - if (gSideTimers[GetBattlerSide(gEffectBattler)].spikesAmount < 3) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; - BattleScriptPush(gBattlescriptCurrInstr + 1); - - if (gBattleStruct->isSkyBattle) - gBattlescriptCurrInstr++; - else - gBattlescriptCurrInstr = BattleScript_SpikesActivates; - } - break; case MOVE_EFFECT_SYRUP_BOMB: - if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) + if (!gBattleMons[gEffectBattler].volatiles.syrupBomb) { struct Pokemon *mon = GetBattlerMon(gBattlerAttacker); - gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB; + gBattleMons[gEffectBattler].volatiles.syrupBomb = TRUE; gDisableStructs[gEffectBattler].syrupBombTimer = 3; gDisableStructs[gEffectBattler].syrupBombIsShiny = IsMonShiny(mon); gBattleStruct->stickySyrupdBy[gEffectBattler] = gBattlerAttacker; @@ -3814,64 +3532,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } } else - { - switch (gBattleEnvironment) - { - case BATTLE_ENVIRONMENT_GRASS: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON); - break; - case BATTLE_ENVIRONMENT_UNDERWATER: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1); - break; - case BATTLE_ENVIRONMENT_POND: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1); - break; - case BATTLE_ENVIRONMENT_MOUNTAIN: - if (B_SECRET_POWER_EFFECT >= GEN_5) - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; - else if (B_SECRET_POWER_EFFECT >= GEN_4) - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - else - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; - break; - case BATTLE_ENVIRONMENT_PUDDLE: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1); - break; - case BATTLE_ENVIRONMENT_LONG_GRASS: - gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; - break; - case BATTLE_ENVIRONMENT_SAND: - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; - break; - case BATTLE_ENVIRONMENT_WATER: - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; - break; - case BATTLE_ENVIRONMENT_CAVE: - case BATTLE_ENVIRONMENT_BURIAL_GROUND: - case BATTLE_ENVIRONMENT_SPACE: - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - break; - case BATTLE_ENVIRONMENT_SOARING: - case BATTLE_ENVIRONMENT_SKY_PILLAR: - case BATTLE_ENVIRONMENT_MARSH: - case BATTLE_ENVIRONMENT_SWAMP: - gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; - break; - case BATTLE_ENVIRONMENT_SNOW: - case BATTLE_ENVIRONMENT_ICE: - gBattleScripting.moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE; - break; - case BATTLE_ENVIRONMENT_VOLCANO: - gBattleScripting.moveEffect = MOVE_EFFECT_BURN; - break; - case BATTLE_ENVIRONMENT_ULTRA_SPACE: - gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_1; - break; - default: - gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; - break; - } - } + gBattleScripting.moveEffect = gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect; SetMoveEffect(battler, effectBattler, primary, certain); break; case MOVE_EFFECT_PSYCHIC_NOISE: @@ -3883,9 +3544,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_AromaVeilProtectsRet; } - else if (!(gStatuses3[gEffectBattler] & STATUS3_HEAL_BLOCK)) + else if (!gBattleMons[gEffectBattler].volatiles.healBlock) { - gStatuses3[gEffectBattler] |= STATUS3_HEAL_BLOCK; + gBattleMons[gEffectBattler].volatiles.healBlock = TRUE; gDisableStructs[gEffectBattler].healBlockTimer = gBattleTurnCounter + 2; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_EffectPsychicNoise; @@ -3904,7 +3565,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { u32 stat = 0; bool32 commanderAffected = TRUE; - switch (gBattleStruct->commanderActive[gEffectBattler]) + switch (gBattleStruct->battlerState[gEffectBattler].commanderSpecies) { case SPECIES_TATSUGIRI_CURLY: stat = STAT_ATK; @@ -3955,10 +3616,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattlescriptCurrInstr = BattleScript_MoveEffectHaze; break; case MOVE_EFFECT_LEECH_SEED: - if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !(gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED)) + if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !gBattleMons[gBattlerTarget].volatiles.leechSeed) { - gStatuses3[gBattlerTarget] |= gBattlerAttacker; - gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + gBattleMons[gBattlerTarget].volatiles.leechSeed = LEECHSEEDED_BY(gBattlerAttacker); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectLeechSeed; } @@ -3978,9 +3638,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_SALT_CURE: - if (!(gStatuses4[gBattlerTarget] & STATUS4_SALT_CURE)) + if (!gBattleMons[gBattlerTarget].volatiles.saltCure) { - gStatuses4[gBattlerTarget] |= STATUS4_SALT_CURE; + gBattleMons[gBattlerTarget].volatiles.saltCure = TRUE; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectSaltCure; } @@ -4008,7 +3668,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) - && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[gBattlerTarget].volatiles.transformed)) { BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); MarkBattlerForControllerExec(gBattlerTarget); @@ -4167,7 +3827,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_TERRAIN_EXTENDER) gFieldTimers.terrainTimer = gBattleTurnCounter + 8; else gFieldTimers.terrainTimer = gBattleTurnCounter + 5; @@ -4195,7 +3855,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; } case MOVE_EFFECT_STEELSURGE: - if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEELSURGE)) + if (!IsHazardOnSide(GetBattlerSide(gBattlerTarget), HAZARDS_STEELSURGE)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS; BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4204,25 +3864,25 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_DEFOG: if (gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_SCREEN_ANY - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_HAZARDS_ANY - || gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_HAZARDS_ANY + || AreAnyHazardsOnSide(GetBattlerSide(gBattlerTarget)) + || AreAnyHazardsOnSide(GetBattlerSide(gBattlerAttacker)) || gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_DefogTryHazards; + gBattlescriptCurrInstr = BattleScript_MoveEffectDefog; } break; case MOVE_EFFECT_AURORA_VEIL: if (!(gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_AURORA_VEIL)) { gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_AURORA_VEIL; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LIGHT_CLAY) gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8; else gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectAuroraVeilSuccess; + gBattlescriptCurrInstr = BattleScript_MoveEffectAuroraVeil; } break; case MOVE_EFFECT_GRAVITY: @@ -4243,10 +3903,10 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { if (!IsBattlerAlly(battler, gBattlerTarget)) continue; - if (!(gBattleMons[battler].status2 & STATUS2_WRAPPED)) + if (!gBattleMons[battler].volatiles.wrapped) { - gBattleMons[battler].status2 |= STATUS2_WRAPPED; - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) + gBattleMons[battler].volatiles.wrapped = TRUE; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[battler].wrapTurns = (B_BINDING_TURNS >= GEN_5) ? 7 : 5; else gDisableStructs[battler].wrapTurns = (Random() % 2) + 4; @@ -4262,13 +3922,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } case MOVE_EFFECT_YAWN_FOE: { - if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN) + if (gBattleMons[gBattlerTarget].volatiles.yawn == 0 && CanBeSlept(gBattlerTarget, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE) && RandomPercentage(RNG_G_MAX_SNOOZE, 50)) { - gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); + gBattleMons[gBattlerTarget].volatiles.yawn = 2; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectYawnSuccess; + gBattlescriptCurrInstr = BattleScript_MoveEffectYawnSide; } break; } @@ -4334,17 +3994,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_AROMATHERAPY: BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectHealBell_FromHeal; + gBattlescriptCurrInstr = BattleScript_MoveEffectAromatherapy; break; case MOVE_EFFECT_RECYCLE_BERRIES: - { if (RandomPercentage(RNG_G_MAX_REPLENISH, 50)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies; } break; - } case MOVE_EFFECT_REMOVE_STATUS: { u32 argStatus = GetMoveEffectArg_Status(gCurrentMove); @@ -4390,6 +4048,10 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additionalEffect) { + // If Toxic Chain will activate it blocks all other non volatile effects + if (gBattleStruct->toxicChainPriority && additionalEffect->moveEffect <= MOVE_EFFECT_FROSTBITE) + return FALSE; + if (additionalEffect->self && NumAffectedSpreadMoveTargets() > 1 && GetNextTarget(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), TRUE) != MAX_BATTLERS_COUNT) @@ -4406,6 +4068,20 @@ static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additional return TRUE; } +static void SetToxicChainPriority(void) +{ + if (gBattleStruct->toxicChainPriority) + return; + + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + if (abilityAtk == ABILITY_TOXIC_CHAIN + && IsBattlerAlive(gBattlerTarget) + && CanBePoisoned(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerAbility(gBattlerTarget)) + && IsBattlerTurnDamaged(gBattlerTarget) + && RandomWeighted(RNG_TOXIC_CHAIN, 7, 3)) + gBattleStruct->toxicChainPriority = TRUE; +} + static void Cmd_setadditionaleffects(void) { CMD_ARGS(); @@ -4413,6 +4089,7 @@ static void Cmd_setadditionaleffects(void) if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { u32 numAdditionalEffects = GetMoveAdditionalEffectCount(gCurrentMove); + SetToxicChainPriority(); if (numAdditionalEffects > gBattleStruct->additionalEffectsCounter) { u32 percentChance; @@ -4428,6 +4105,7 @@ static void Cmd_setadditionaleffects(void) if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance)) { gBattleScripting.moveEffect = additionalEffect->moveEffect; + gBattleCommunication[MULTISTRING_CHOOSER] = *((u8 *) &additionalEffect->multistring); SetMoveEffect( gBattlerAttacker, @@ -4460,8 +4138,6 @@ static void Cmd_setadditionaleffects(void) gBattleScripting.moveEffect = 0; gBattlescriptCurrInstr = cmd->nextInstr; } - - gBattleScripting.multihitMoveEffect = 0; } static void Cmd_seteffectprimary(void) @@ -4495,7 +4171,6 @@ static void Cmd_clearvolatile(void) gProtectStructs[battler].chargingTurn = FALSE; gBattlescriptCurrInstr = cmd->nextInstr; - gBattleScripting.multihitMoveEffect = 0; } static void Cmd_tryfaintmon(void) @@ -4567,7 +4242,7 @@ static void Cmd_tryfaintmon(void) gBattleStruct->moveDamage[destinyBondBattler] = gBattleMons[destinyBondBattler].hp; gBattlescriptCurrInstr = BattleScript_DestinyBondTakesLife; } - if ((gStatuses3[gBattlerTarget] & STATUS3_GRUDGE) + if (gBattleMons[gBattlerTarget].volatiles.grudge && !(gHitMarker & HITMARKER_GRUDGE) && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) @@ -4654,12 +4329,12 @@ static void Cmd_jumpifstatus(void) static void Cmd_jumpifvolatile(void) { - CMD_ARGS(u8 battler, u8 volatileStatus, const u8 *jumpInstr); + CMD_ARGS(u8 battler, u8 _volatile, const u8 *jumpInstr); u8 battler = GetBattlerForBattleScript(cmd->battler); const u8 *jumpInstr = cmd->jumpInstr; - if (GetMonVolatile(battler, cmd->volatileStatus) && IsBattlerAlive(battler)) + if (GetBattlerVolatile(battler, cmd->_volatile) != 0 && IsBattlerAlive(battler)) gBattlescriptCurrInstr = jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -4667,11 +4342,11 @@ static void Cmd_jumpifvolatile(void) static void Cmd_jumpifability(void) { - CMD_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + CMD_ARGS(u8 battler, enum Ability ability, const u8 *jumpInstr); u32 battler; bool32 hasAbility = FALSE; - u32 ability = cmd->ability; + enum Ability ability = cmd->ability; switch (cmd->battler) { @@ -4741,25 +4416,8 @@ static void Cmd_jumpifstat(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifstatus3condition(void) +static void Cmd_unused_0x21(void) { - CMD_ARGS(u8 battler, u32 flags, bool8 jumpIfTrue, const u8 *jumpInstr); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (cmd->jumpIfTrue) - { - if ((gStatuses3[battler] & cmd->flags) != 0) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - if ((gStatuses3[battler] & cmd->flags) != 0) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_jumpbasedontype(void) @@ -5091,7 +4749,7 @@ static void Cmd_getexp(void) if (battler != 0xFF) { CopyMonLevelAndBaseStatsToBattleMon(battler, &gPlayerParty[*expMonId]); - if (gStatuses3[battler] & STATUS3_POWER_TRICK) + if (gBattleMons[battler].volatiles.powerTrick) SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, temp); } @@ -5709,18 +5367,15 @@ static void Cmd_setroost(void) CMD_ARGS(); gDisableStructs[gBattlerAttacker].roostActive = TRUE; - gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].types[0]; - gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].types[1]; - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_jumpifabilitypresent(void) { - CMD_ARGS(u16 ability, const u8 *jumpInstr); + CMD_ARGS(enum Ability ability, const u8 *jumpInstr); - u16 ability = cmd->ability; - u32 abilityBattler = IsAbilityOnField(ability); + enum Ability ability = cmd->ability; + enum Ability abilityBattler = IsAbilityOnField(ability); if (abilityBattler) { gBattlerAbility = abilityBattler - 1; @@ -5779,7 +5434,7 @@ static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *n MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = nextInstr; } - else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + else if (IsSemiInvulnerable(battler, CHECK_ALL)) { gBattlescriptCurrInstr = nextInstr; } @@ -5808,53 +5463,21 @@ static void Cmd_playanimation_var(void) PlayAnimation(battler, *(cmd->animIdPtr), cmd->argPtr, cmd->nextInstr); } -static void Cmd_unused_0x47(void) +static void Cmd_jumpfifsemiinvulnerable(void) { + CMD_ARGS(u8 battler, u8 state, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gBattleMons[battler].volatiles.semiInvulnerable == cmd->state) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_0x48(void) { } -static bool32 TryKnockOffBattleScript(u32 battlerDef) -{ - if (gBattleMons[battlerDef].item != 0 - && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item) - && !NoAliveMonsForEitherParty()) - { - if (GetBattlerAbility(battlerDef) == ABILITY_STICKY_HOLD && IsBattlerAlive(battlerDef)) - { - gBattlerAbility = battlerDef; - BattleScriptCall(BattleScript_StickyHoldActivates); - } - else - { - u32 side = GetBattlerSide(battlerDef); - - gLastUsedItem = gBattleMons[battlerDef].item; - gBattleMons[battlerDef].item = 0; - if (gBattleMons[battlerDef].ability != ABILITY_GORILLA_TACTICS) - gBattleStruct->choicedMove[battlerDef] = 0; - CheckSetUnburden(battlerDef); - - // In Gen 5+, Knock Off removes the target's item rather than rendering it unusable. - if (B_KNOCK_OFF_REMOVAL >= GEN_5) - { - BtlController_EmitSetMonData(battlerDef, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item); - MarkBattlerForControllerExec(battlerDef); - } - else - { - gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[battlerDef]; - } - - BattleScriptCall(BattleScript_KnockedOff); - } - return TRUE; - } - return FALSE; -} - static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally) { return GetBattlerAbility(ally) == ABILITY_SYMBIOSIS @@ -5871,9 +5494,10 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) u32 battler; for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) { - if (battler != gBattlerAttacker - && !(excludeCurrent && battler == gBattlerTarget) - && IsBattlerAlive(battler) + if (battler == gBattlerAttacker || !IsBattlerAlive(battler)) + continue; + + if (!(excludeCurrent && battler == gBattlerTarget) && !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler] && (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) break; @@ -5890,31 +5514,9 @@ static inline bool32 IsProtectivePadsProtected(u32 battler, enum ItemHoldEffect return TRUE; } -static inline bool32 IsProtectEffectAffected(u32 battler, u32 move) -{ - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - if (IsProtectivePadsProtected(battler, holdEffect)) - return TRUE; - - if (holdEffect == HOLD_EFFECT_CLEAR_AMULET) - { - RecordItemEffectBattle(battler, holdEffect); - return TRUE; - } - - u32 ability = GetBattlerAbility(gBattlerAttacker); - if (CanAbilityPreventStatLoss(ability)) - { - RecordAbilityBattle(battler, ability); - return TRUE; - } - - return FALSE; -} - static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { - if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_BUTTON + if (GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_BUTTON && battlerAtk != battlerDef && IsBattlerTurnDamaged(battlerDef) && IsBattlerAlive(battlerDef) @@ -5927,8 +5529,8 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { - if (gProtectStructs[battlerDef].tryEjectPack - && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK + if (gDisableStructs[battlerDef].tryEjectPack + && GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(battlerDef) && CountUsablePartyMons(battlerDef) > 0 && !gProtectStructs[battlerDef].disableEjectPack @@ -5942,7 +5544,7 @@ static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum Ba static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move) { bool32 effect = FALSE; - u32 abilityAtk = GetBattlerAbility(battlerAtk); + enum Ability abilityAtk = GetBattlerAbility(battlerAtk); switch (abilityAtk) { @@ -6006,18 +5608,16 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move || NumFaintedBattlersByAttacker(battlerAtk) == 0) break; - u32 side = GetBattlerSide(battlerAtk); - - if (gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost) + if (GetBattlerPartyState(battlerAtk)->battleBondBoost) break; if (GetGenConfig(GEN_CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND) { // TODO: Convert this to a proper FORM_CHANGE type. gLastUsedAbility = abilityAtk; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost = TRUE; + GetBattlerPartyState(battlerAtk)->battleBondBoost = TRUE; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerAtk].species); - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battlerAtk]] = gBattleMons[battlerAtk].species; + GetBattlerPartyState(battlerAtk)->changedSpecies = gBattleMons[battlerAtk].species; gBattleMons[battlerAtk].species = SPECIES_GRENINJA_ASH; BattleScriptCall(BattleScript_BattleBondActivatesOnMoveEndAttacker); effect = TRUE; @@ -6048,13 +5648,239 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move gLastUsedAbility = abilityAtk; gBattlerAbility = battlerAtk; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost = TRUE; + GetBattlerPartyState(battlerAtk)->battleBondBoost = TRUE; BattleScriptCall(BattleScript_EffectBattleBondStatIncrease); effect = TRUE; } } } break; + default: + break; + } + + return effect; +} + +static bool32 HandleMoveEndMoveBlock(u32 moveEffect) +{ + if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + return FALSE; + + u32 effect = FALSE; + switch (moveEffect) + { + case EFFECT_KNOCK_OFF: + if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff + && gBattleMons[gBattlerTarget].item != ITEM_NONE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker)) + { + u32 side = GetBattlerSide(gBattlerTarget); + gLastUsedItem = gBattleMons[gBattlerTarget].item; + gBattleMons[gBattlerTarget].item = 0; + if (gBattleMons[gBattlerTarget].ability != ABILITY_GORILLA_TACTICS) + gBattleStruct->choicedMove[gBattlerTarget] = 0; + CheckSetUnburden(gBattlerTarget); + + // In Gen 5+, Knock Off removes the target's item rather than rendering it unusable. + if (B_KNOCK_OFF_REMOVAL >= GEN_5) + { + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); + MarkBattlerForControllerExec(gBattlerTarget); + } + else + { + gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; + } + + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; + BattleScriptCall(BattleScript_KnockedOff); + effect = TRUE; + } + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; + break; + case EFFECT_STEAL_ITEM: + if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) + || gBattleMons[gBattlerAttacker].item != ITEM_NONE + || gBattleMons[gBattlerTarget].item == ITEM_NONE + || !IsBattlerAlive(gBattlerAttacker) + || !IsBattlerTurnDamaged(gBattlerTarget)) + { + effect = FALSE; + } + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + { + BattleScriptCall(BattleScript_NoItemSteal); + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + effect = TRUE; + } + else + { + StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item + + if (!(GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 + && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) + { + gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) + gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later + } + BattleScriptCall(BattleScript_ItemSteal); + effect = TRUE; + } + break; + case EFFECT_HIT_SWITCH_TARGET: + if (IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && gBattleMons[BATTLE_PARTNER(gBattlerTarget)].volatiles.semiInvulnerable != STATE_COMMANDER) + { + u32 targetAbility = GetBattlerAbility(gBattlerTarget); + if (targetAbility == ABILITY_GUARD_DOG) + return FALSE; + + if (targetAbility == ABILITY_SUCTION_CUPS) + { + BattleScriptCall(BattleScript_AbilityPreventsPhasingOutRet); + } + else if (gBattleMons[gBattlerTarget].volatiles.root) + { + BattleScriptCall(BattleScript_PrintMonIsRootedRet); + } + else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) + { + BattleScriptCall(BattleScript_HitSwitchTargetDynamaxed); + } + else + { + gBattleScripting.switchCase = B_SWITCH_HIT; + BattleScriptCall(BattleScript_TryHitSwitchTarget); + } + effect = TRUE; + } + break; + case EFFECT_SMACK_DOWN: + if (!IsBattlerGrounded(gBattlerTarget, GetBattlerAbility(gBattlerTarget), GetBattlerHoldEffect(gBattlerTarget)) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + { + gBattleMons[gBattlerTarget].volatiles.smackDown = TRUE; + gBattleMons[gBattlerTarget].volatiles.telekinesis = FALSE; + gBattleMons[gBattlerTarget].volatiles.magnetRise = FALSE; + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; + BattleScriptCall(BattleScript_MoveEffectSmackDown); + effect = TRUE; + } + break; + case EFFECT_RECOIL_IF_MISS: + if (IsBattlerAlive(gBattlerAttacker) + && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + && !gBattleStruct->noTargetPresent) + { + if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE)) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget]) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower. + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + + BattleScriptCall(BattleScript_RecoilIfMiss); + effect = TRUE; + } + break; + case EFFECT_RECOIL: + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleScripting.savedDmg * max(1, GetMoveRecoil(gCurrentMove)) / 100); + BattleScriptCall(BattleScript_MoveEffectRecoil); + effect = TRUE; + } + break; + case EFFECT_EXPLOSION: + if (!IsAbilityOnField(ABILITY_DAMP)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = 0; + BattleScriptCall(BattleScript_FaintAttackerForExplosion); + effect = TRUE; + } + break; + case EFFECT_MAX_HP_50_RECOIL: + if (IsBattlerAlive(gBattlerAttacker) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptCall(BattleScript_MaxHp50Recoil); + effect = TRUE; + } + break; + case EFFECT_CHLOROBLAST: + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptCall(BattleScript_MoveEffectRecoil); + effect = TRUE; + } + break; + case EFFECT_RAPID_SPIN: + if (IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptCall(BattleScript_RapidSpinAway); + effect = TRUE; + } + break; + case EFFECT_FELL_STINGER: + if (IsBattlerAlive(gBattlerAttacker) + && !IsBattlerAlive(gBattlerTarget) + && IsBattlerTurnDamaged(gBattlerTarget) + && !NoAliveMonsForEitherParty() + && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat; + effect = TRUE; + } + break; + case EFFECT_STONE_AXE: + if (!IsHazardOnSide(GetBattlerSide(gBattlerTarget), HAZARDS_STEALTH_ROCK) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StealthRockActivates; + effect = TRUE; + } + break; + case EFFECT_CEASELESS_EDGE: + if (gSideTimers[GetBattlerSide(gBattlerTarget)].spikesAmount < 3 + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; + BattleScriptPush(gBattlescriptCurrInstr + 1); + if (gBattleStruct->isSkyBattle) + { + effect = FALSE; + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SpikesActivates; + effect = TRUE; + } + } + break; + default: + effect = FALSE; + break; } return effect; @@ -6067,7 +5893,6 @@ static void Cmd_moveend(void) s32 i; bool32 effect = FALSE; u32 moveType = 0; - enum ItemHoldEffect holdEffectAtk = HOLD_EFFECT_NONE; u32 endMode, endState; u32 originallyUsedMove; @@ -6079,7 +5904,6 @@ static void Cmd_moveend(void) endMode = cmd->endMode; endState = cmd->endState; - holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); moveType = GetBattleMoveType(gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); @@ -6088,8 +5912,9 @@ static void Cmd_moveend(void) { switch (gBattleScripting.moveendState) { - case MOVEEND_SUM_DAMAGE: // Sum and store damage dealt for multi strike recoil + case MOVEEND_SET_VALUES: gBattleScripting.savedDmg += gBattleStruct->moveDamage[gBattlerTarget]; + gBattleStruct->moveEndBattlerId = 0; gBattleScripting.moveendState++; break; case MOVEEND_PROTECT_LIKE_EFFECT: @@ -6100,7 +5925,7 @@ static void Cmd_moveend(void) { case PROTECT_SPIKY_SHIELD: if (moveEffect != EFFECT_COUNTER - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; @@ -6113,7 +5938,7 @@ static void Cmd_moveend(void) } break; case PROTECT_KINGS_SHIELD: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; i = gBattlerAttacker; @@ -6128,7 +5953,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BANEFUL_BUNKER: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_POISON; @@ -6138,7 +5964,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BURNING_BULWARK: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker)) + && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) { gEffectBattler = gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; @@ -6151,7 +5978,7 @@ static void Cmd_moveend(void) case PROTECT_OBSTRUCT: if (moveEffect != EFFECT_SUCKER_PUNCH // Why??? && moveEffect != EFFECT_UPPER_HAND // Why??? - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; i = gBattlerAttacker; @@ -6163,7 +5990,7 @@ static void Cmd_moveend(void) } break; case PROTECT_SILK_TRAP: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; i = gBattlerAttacker; @@ -6180,7 +6007,7 @@ static void Cmd_moveend(void) // Not strictly a protect effect, but works the same way if (gProtectStructs[gBattlerTarget].beakBlastCharge - && CanBeBurned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker)) + && CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; @@ -6203,24 +6030,28 @@ static void Cmd_moveend(void) switch (moveEffect) { case EFFECT_ABSORB: - if (!(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK) && IsBattlerAlive(gBattlerAttacker)) + case EFFECT_DREAM_EATER: + if (!gBattleMons[gBattlerAttacker].volatiles.healBlock + && gBattleStruct->moveDamage[gBattlerTarget] > 0 + && IsBattlerAlive(gBattlerAttacker)) { gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100)); gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE; + + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_HP_UPDATE; effect = TRUE; - if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIQUID_OOZE) - { - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - gHitMarker |= HITMARKER_PASSIVE_DAMAGE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB_OOZE; - BattleScriptCall(BattleScript_EffectAbsorbLiquidOoze); - } - else + if ((moveEffect == EFFECT_DREAM_EATER && GetGenConfig(GEN_DREAM_EATER_LIQUID_OOZE) < GEN_5) + || GetBattlerAbility(gBattlerTarget) != ABILITY_LIQUID_OOZE) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB; BattleScriptCall(BattleScript_EffectAbsorb); } + else + { + gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB_OOZE; + BattleScriptCall(BattleScript_EffectAbsorbLiquidOoze); + } } break; case EFFECT_FINAL_GAMBIT: @@ -6233,7 +6064,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_RAGE: // rage check - if (gBattleMons[gBattlerTarget].status2 & STATUS2_RAGE + if (gBattleMons[gBattlerTarget].volatiles.rage && IsBattlerAlive(gBattlerTarget) && gBattlerAttacker != gBattlerTarget && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) @@ -6275,102 +6106,27 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.moveendState++; break; - case MOVEEND_CHOICE_MOVE: // update choice band move - { - u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker]; - if (gHitMarker & HITMARKER_OBEYS - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && gChosenMove != MOVE_STRUGGLE - && (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE) - && (HOLD_EFFECT_CHOICE(holdEffectAtk) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)) - { - if ((moveEffect == EFFECT_BATON_PASS || moveEffect == EFFECT_HEALING_WISH) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED)) - { - gBattleScripting.moveendState++; - break; - } - *choicedMoveAtk = gChosenMove; - } - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[gBattlerAttacker].moves[i] == *choicedMoveAtk) - break; - } - if (i == MAX_MON_MOVES) - { - *choicedMoveAtk = MOVE_NONE; - } - gBattleScripting.moveendState++; - break; - } case MOVEEND_ITEM_EFFECTS_TARGET: if (ItemBattleEffects(ITEMEFFECT_TARGET, gBattlerTarget)) effect = TRUE; gBattleScripting.moveendState++; break; - case MOVEEND_FIRST_MOVE_BLOCK: - if ((gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) - || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + case MOVEEND_SYMBIOSIS: + for (i = 0; i < gBattlersCount; i++) { - gBattleScripting.moveendState++; - break; - } - - switch (moveEffect) - { - case EFFECT_KNOCK_OFF: - if (!DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - effect = TryKnockOffBattleScript(gBattlerTarget); - break; - case EFFECT_HIT_SWITCH_TARGET: - if (IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER)) + if ((gSpecialStatuses[i].berryReduced + || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) + && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) { - u32 targetAbility = GetBattlerAbility(gBattlerTarget); - if (targetAbility == ABILITY_GUARD_DOG) - { - gBattleScripting.moveendState++; - break; - } - + BestowItem(BATTLE_PARTNER(i), i); + gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; + gEffectBattler = i; + gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); + gBattlerAttacker = i; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; effect = TRUE; - if (targetAbility == ABILITY_SUCTION_CUPS) - { - BattleScriptCall(BattleScript_AbilityPreventsPhasingOutRet); - } - else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED) - { - BattleScriptCall(BattleScript_PrintMonIsRootedRet); - } - else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) - { - BattleScriptCall(BattleScript_HitSwitchTargetDynamaxed); - } - else - { - gBattleScripting.switchCase = B_SWITCH_HIT; - BattleScriptCall(BattleScript_TryHitSwitchTarget); - } } - break; - case EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - { - gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); - effect = TRUE; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown; - } - break; - default: - break; } gBattleScripting.moveendState++; break; @@ -6380,14 +6136,8 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // King's rock - // These effects will occur at each hit in a multi-strike move - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible - if (gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL) && gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)) { BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, TRUE); @@ -6399,12 +6149,12 @@ static void Cmd_moveend(void) break; case MOVEEND_ATTACKER_VISIBLE: // make attacker sprite visible if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || !(gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE)) + || !IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL) || WasUnableToUseMove(gBattlerAttacker)) { BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, FALSE); MarkBattlerForControllerExec(gBattlerAttacker); - gStatuses3[gBattlerAttacker] &= ~STATUS3_SEMI_INVULNERABLE; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE; gSpecialStatuses[gBattlerAttacker].restoredBattlerSprite = TRUE; gBattleScripting.moveendState++; return; @@ -6413,21 +6163,27 @@ static void Cmd_moveend(void) break; case MOVEEND_TARGET_VISIBLE: // make target sprite visible if (!gSpecialStatuses[gBattlerTarget].restoredBattlerSprite && gBattlerTarget < gBattlersCount - && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE)) + && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) { BtlController_EmitSpriteInvisibility(gBattlerTarget, B_COMM_TO_CONTROLLER, FALSE); MarkBattlerForControllerExec(gBattlerTarget); - gStatuses3[gBattlerTarget] &= ~STATUS3_SEMI_INVULNERABLE; + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; gBattleScripting.moveendState++; return; } gBattleScripting.moveendState++; break; + case MOVEEND_KINGSROCK: // King's rock + // These effects will occur at each hit in a multi-strike move + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0)) + effect = TRUE; + gBattleScripting.moveendState++; + break; case MOVEEND_SUBSTITUTE: for (i = 0; i < gBattlersCount; i++) { if (gDisableStructs[i].substituteHP == 0) - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; } gBattleScripting.moveendState++; break; @@ -6462,7 +6218,8 @@ static void Cmd_moveend(void) if (!IsOnPlayerSide(gBattlerAttacker)) UpdateStallMons(); if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) - || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) + || gBattleMons[gBattlerAttacker].volatiles.flinched + || gBattleStruct->pledgeMove == TRUE // Is the battler that uses the first Pledge move in the combo || gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility) gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2; @@ -6557,6 +6314,35 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_DEFROST: + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptCall(BattleScript_DefrostedViaFireMove); + effect = TRUE; + } + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && MoveThawsUser(originallyUsedMove) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptCall(BattleScript_FrostbiteHealedViaFireMove); + effect = TRUE; + } + gBattleScripting.moveendState++; + break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. { u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); @@ -6566,11 +6352,9 @@ static void Cmd_moveend(void) && IsDoubleBattle() && !gProtectStructs[gBattlerAttacker].chargingTurn && (moveTarget == MOVE_TARGET_BOTH - || moveTarget == MOVE_TARGET_FOES_AND_ALLY) - && !(gHitMarker & HITMARKER_NO_ATTACKSTRING)) + || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) { u32 nextTarget = GetNextTarget(moveTarget, FALSE); - gHitMarker |= HITMARKER_NO_PPDEDUCT; if (nextTarget != MAX_BATTLERS_COUNT) { @@ -6579,8 +6363,12 @@ static void Cmd_moveend(void) MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; - if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION) - BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets + // Edge cases for moves that shouldn't repeat their own script + if (moveEffect == EFFECT_EXPLOSION + || moveEffect == EFFECT_MISTY_EXPLOSION + || moveEffect == EFFECT_MAGNITUDE + || moveEffect == EFFECT_SYNCHRONOISE) + BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); else BattleScriptPush(GetMoveBattleScript(gCurrentMove)); gBattlescriptCurrInstr = BattleScript_FlushMessageBox; @@ -6609,9 +6397,6 @@ static void Cmd_moveend(void) return; } } - - gHitMarker |= HITMARKER_NO_ATTACKSTRING; - gHitMarker &= ~HITMARKER_NO_PPDEDUCT; } RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); gBattleScripting.moveendState++; @@ -6656,7 +6441,6 @@ static void Cmd_moveend(void) if (gSpecialStatuses[gBattlerAttacker].parentalBondState) gSpecialStatuses[gBattlerAttacker].parentalBondState--; - gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING); gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE; @@ -6678,117 +6462,8 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - case MOVEEND_DEFROST: - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove))) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptCall(BattleScript_DefrostedViaFireMove); - effect = TRUE; - } - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && MoveThawsUser(originallyUsedMove)) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptCall(BattleScript_FrostbiteHealedViaFireMove); - effect = TRUE; - } - gBattleScripting.moveendState++; - break; - case MOVEEND_SECOND_MOVE_BLOCK: - if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - { - gBattleScripting.moveendState++; - break; - } - - switch (moveEffect) - { - case EFFECT_RECOIL_IF_MISS: - if (IsBattlerAlive(gBattlerAttacker) - && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && !gBattleStruct->noTargetPresent) - { - if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE)) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget]) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower. - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - - BattleScriptCall(BattleScript_RecoilIfMiss); - effect = TRUE; - } - break; - case EFFECT_RECOIL: - if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleStruct->moveDamage[gBattlerTarget] * max(1, GetMoveRecoil(gCurrentMove)) / 100); - BattleScriptCall(BattleScript_MoveEffectRecoil); - effect = TRUE; - } - break; - case EFFECT_EXPLOSION: - case EFFECT_MISTY_EXPLOSION: - gBattleStruct->moveDamage[gBattlerAttacker] = 0; - BattleScriptCall(BattleScript_FaintAttackerForExplosion); - effect = TRUE; - break; - case EFFECT_MAX_HP_50_RECOIL: - if (IsBattlerAlive(gBattlerAttacker) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP - BattleScriptCall(BattleScript_MaxHp50Recoil); - effect = TRUE; - } - break; - case EFFECT_CHLOROBLAST: - if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; - effect = TRUE; - } - break; - case EFFECT_RAPID_SPIN: - if (IsBattlerTurnDamaged(gBattlerTarget)) - { - BattleScriptCall(BattleScript_RapidSpinAway); - effect = TRUE; - } - break; - case EFFECT_FELL_STINGER: - if (IsBattlerAlive(gBattlerAttacker) - && !IsBattlerAlive(gBattlerTarget) - && IsBattlerTurnDamaged(gBattlerTarget) - && !NoAliveMonsForEitherParty() - && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); - BattleScriptCall(BattleScript_FellStingerRaisesStat); - effect = TRUE; - } - break; - default: - break; - } + case MOVEEND_MOVE_BLOCK: + effect = HandleMoveEndMoveBlock(moveEffect); gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_ATTACKER: @@ -6806,6 +6481,69 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_COLOR_CHANGE: + while (gBattleStruct->moveEndBattlerId < gBattlersCount) + { + u32 battler = gBattleStruct->moveEndBattlerId++; + if (battler == gBattlerAttacker) + continue; + if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->moveEndBattlerId = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_RED_CARD: + { + u32 redCardBattlers = 0, i; + for (i = 0; i < gBattlersCount; i++) + { + if (i == gBattlerAttacker) + continue; + if (GetBattlerHoldEffect(i) == HOLD_EFFECT_RED_CARD) + redCardBattlers |= (1u << i); + } + if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) + { + // Since we check if battler was damaged, we don't need to check move result. + // In fact, doing so actually prevents multi-target moves from activating red card properly + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + // Search for fastest hit pokemon with a red card + // Attacker is the one to be switched out, battler is one with red card + if (redCardBattlers & (1u << battler) + && IsBattlerAlive(battler) + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) + && IsBattlerTurnDamaged(battler) + && CanBattlerSwitch(gBattlerAttacker) + && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) + { + effect = TRUE; + gLastUsedItem = gBattleMons[battler].item; + SaveBattlerTarget(battler); // save battler with red card + SaveBattlerAttacker(gBattlerAttacker); + gBattleScripting.battler = battler; + gEffectBattler = gBattlerAttacker; + BattleScriptPushCursor(); + if (gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE + || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG + || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) + gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; + else + gBattlescriptCurrInstr = BattleScript_RedCardActivates; + break; // Only fastest red card activates + } + } + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_BUTTON: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -6828,7 +6566,7 @@ static void Cmd_moveend(void) } for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; u8 battlers[4] = {0, 1, 2, 3}; if (numEjectButtonBattlers > 1) @@ -6855,168 +6593,11 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_EJECT_PACK: - { - // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. - u32 ejectPackBattlers = 0; - u32 numEjectPackBattlers = 0; - - for (i = 0; i < gBattlersCount; i++) - { - if (CanEjectPackTrigger(gBattlerAttacker, i, moveEffect)) - { - ejectPackBattlers |= 1u << i; - numEjectPackBattlers++; - } - } - - if (numEjectPackBattlers == 0) - { - gBattleScripting.moveendState++; - break; - } - - u8 battlers[4] = {0, 1, 2, 3}; - if (numEjectPackBattlers > 1) - SortBattlersBySpeed(battlers, FALSE); - - for (i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; - - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - - if (!(ejectPackBattlers & 1u << battler)) - continue; - - // Hit escape moves activate before Eject Pack for user - if (moveEffect == EFFECT_HIT_ESCAPE && gBattlerAttacker == battler) - continue; - - gBattleScripting.battler = battler; - gLastUsedItem = gBattleMons[battler].item; - effect = TRUE; - gBattleStruct->battlerState[battler].usedEjectItem = TRUE; - BattleScriptCall(BattleScript_EjectPackActivates); - gAiLogicData->ejectPackSwitch = TRUE; - break; // Only the fastest Eject item activates - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; - else - gBattleScripting.moveendState++; - break; - case MOVEEND_WHITE_HERB: - for (i = 0; i < gBattlersCount; i++) - { - if (!IsBattlerAlive(i)) - continue; - - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB - && RestoreWhiteHerbStats(i)) - { - BattleScriptCall(BattleScript_WhiteHerbRet); - effect = TRUE; - break; - } - } - if (!effect) - gBattleScripting.moveendState++; - break; - case MOVEEND_RED_CARD: - { - u32 redCardBattlers = 0, i; - for (i = 0; i < gBattlersCount; i++) - { - if (i == gBattlerAttacker) - continue; - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) - redCardBattlers |= (1u << i); - } - if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) - { - // Since we check if battler was damaged, we don't need to check move result. - // In fact, doing so actually prevents multi-target moves from activating red card properly - u8 battlers[4] = {0, 1, 2, 3}; - SortBattlersBySpeed(battlers, FALSE); - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - // Search for fastest hit pokemon with a red card - // Attacker is the one to be switched out, battler is one with red card - if (redCardBattlers & (1u << battler) - && IsBattlerAlive(battler) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattlerTurnDamaged(battler) - && CanBattlerSwitch(gBattlerAttacker) - && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) - { - for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; - effect = TRUE; - gLastUsedItem = gBattleMons[battler].item; - SaveBattlerTarget(battler); // save battler with red card - SaveBattlerAttacker(gBattlerAttacker); - gBattleScripting.battler = battler; - gEffectBattler = gBattlerAttacker; - if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE - || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG - || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) - BattleScriptCall(BattleScript_RedCardActivationNoSwitch); - else - BattleScriptCall(BattleScript_RedCardActivates); - break; // Only fastest red card activates - } - } - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; - else - gBattleScripting.moveendState++; - break; case MOVEEND_LIFEORB_SHELLBELL: if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0)) effect = TRUE; gBattleScripting.moveendState++; break; - case MOVEEND_PICKPOCKET: - if (IsBattlerAlive(gBattlerAttacker) - && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item - && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // Pickpocket requires contact - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked - { - u8 battlers[4] = {0, 1, 2, 3}; - SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item - for (i = 0; i < gBattlersCount; i++) - { - u8 battler = battlers[i]; - // Attacker is mon who made contact, battler is mon with pickpocket - if (battler != gBattlerAttacker // Cannot pickpocket yourself - && GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability - && IsBattlerTurnDamaged(battler) // Target needs to have been damaged - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected - && IsBattlerAlive(battler) // Battler must be alive to pickpocket - && gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already - && CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc - { - gBattlerTarget = gBattlerAbility = battler; - // Battle scripting is super brittle so we shall do the item exchange now (if possible) - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD) - StealTargetItem(gBattlerTarget, gBattlerAttacker); // Target takes attacker's item - - gEffectBattler = gBattlerAttacker; - BattleScriptCall(BattleScript_Pickpocket); // Includes sticky hold check to print separate string - effect = TRUE; - break; // Pickpocket activates on fastest mon, so exit loop. - } - } - } - gBattleScripting.moveendState++; - break; case MOVEEND_FORM_CHANGE: if (TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_AFTER_MOVE)) { @@ -7048,7 +6629,7 @@ static void Cmd_moveend(void) } for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; u8 battlers[4] = {0, 1, 2, 3}; if (numEmergencyExitBattlers > 1) @@ -7077,6 +6658,59 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_EJECT_PACK: + { + // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. + u32 ejectPackBattlers = 0; + u32 numEjectPackBattlers = 0; + + for (i = 0; i < gBattlersCount; i++) + { + if (CanEjectPackTrigger(gBattlerAttacker, i, moveEffect)) + { + ejectPackBattlers |= 1u << i; + numEjectPackBattlers++; + } + } + + if (numEjectPackBattlers == 0) + { + gBattleScripting.moveendState++; + break; + } + + u8 battlers[4] = {0, 1, 2, 3}; + if (numEjectPackBattlers > 1) + SortBattlersBySpeed(battlers, FALSE); + + for (i = 0; i < gBattlersCount; i++) + gDisableStructs[i].tryEjectPack = FALSE; + + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + + if (!(ejectPackBattlers & 1u << battler)) + continue; + + // Hit escape moves activate before Eject Pack for user + if (moveEffect == EFFECT_HIT_ESCAPE && gBattlerAttacker == battler) + continue; + + gBattleScripting.battler = battler; + gLastUsedItem = gBattleMons[battler].item; + effect = TRUE; + gBattleStruct->battlerState[battler].usedEjectItem = TRUE; + BattleScriptCall(BattleScript_EjectPackActivates); + gAiLogicData->ejectPackSwitch = TRUE; + break; // Only the fastest Eject item activates + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_HIT_ESCAPE: if (moveEffect == EFFECT_HIT_ESCAPE && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) @@ -7090,35 +6724,120 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_OPPORTUNIST: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers - else - gBattleScripting.moveendState++; - break; - case MOVEEND_SYMBIOSIS: - for (i = 0; i < gBattlersCount; i++) + while (gBattleStruct->moveEndBattlerId < gBattlersCount) { - if ((gSpecialStatuses[i].berryReduced - || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) - && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) + u32 battler = gBattleStruct->moveEndBattlerId++; + if (!IsBattlerAlive(battler)) + continue; + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, 0)) + return; + } + gBattleStruct->moveEndBattlerId = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_MIRROR_HERB: + while (gBattleStruct->moveEndBattlerId < gBattlersCount) + { + u32 battler = gBattleStruct->moveEndBattlerId++; + if (!IsBattlerAlive(battler)) + continue; + if (ItemBattleEffects(ITEMEFFECT_MIRROR_HERB, battler)) + return; + } + gBattleStruct->moveEndBattlerId = 0; + gBattleScripting.moveendState++; + break; + case MOVEEND_PICKPOCKET: + if (IsBattlerAlive(gBattlerAttacker) + && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item + && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off + && IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked + { + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item + for (i = 0; i < gBattlersCount; i++) { - BestowItem(BATTLE_PARTNER(i), i); - gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; - gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); - gBattlerAttacker = i; - BattleScriptCall(BattleScript_SymbiosisActivates); - effect = TRUE; + u8 battler = battlers[i]; + // Attacker is mon who made contact, battler is mon with pickpocket + if (battler != gBattlerAttacker // Cannot pickpocket yourself + && GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability + && IsBattlerTurnDamaged(battler) // Target needs to have been damaged + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected + && IsBattlerAlive(battler) // Battler must be alive to pickpocket + && gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already + && CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc + { + gBattlerTarget = gBattlerAbility = battler; + // Battle scripting is super brittle so we shall do the item exchange now (if possible) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD) + StealTargetItem(gBattlerTarget, gBattlerAttacker); // Target takes attacker's item + + gEffectBattler = gBattlerAttacker; + BattleScriptCall(BattleScript_Pickpocket); // Includes sticky hold check to print separate string + effect = TRUE; + break; // Pickpocket activates on fastest mon, so exit loop. + } } } gBattleScripting.moveendState++; break; - case MOVEEND_SAME_MOVE_TURNS: - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] - || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; - else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) - gBattleStruct->sameMoveTurns[gBattlerAttacker]++; + case MOVEEND_WHITE_HERB: + for (i = 0; i < gBattlersCount; i++) + { + if (!IsBattlerAlive(i)) + continue; + + if (ItemBattleEffects(ITEMEFFECT_WHITE_HERB, i)) + return; + } + gBattleScripting.moveendState++; + break; + case MOVEEND_THIRD_MOVE_BLOCK: + // Special case for Steel Roller since it has to check the chosen move + if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptCall(BattleScript_RemoveTerrain); + effect = TRUE; + gBattleScripting.moveendState++; + break; + } + + switch (moveEffect) + { + case EFFECT_ICE_SPINNER: + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY + && IsBattlerAlive(gBattlerAttacker) + && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptCall(BattleScript_RemoveTerrain); + effect = TRUE; + } + break; + case EFFECT_NATURAL_GIFT: + if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && GetItemPocket(gBattleMons[gBattlerAttacker].item) == POCKET_BERRIES) + { + u32 item = gBattleMons[gBattlerAttacker].item; + gBattleMons[gBattlerAttacker].item = ITEM_NONE; + gBattleStruct->battlerState[gBattlerAttacker].canPickupItem = TRUE; + gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)] = item; + CheckSetUnburden(gBattlerAttacker); + BtlController_EmitSetMonData( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + REQUEST_HELDITEM_BATTLE, + 0, + sizeof(gBattleMons[gBattlerAttacker].item), + &gBattleMons[gBattlerAttacker].item); + MarkBattlerForControllerExec(gBattlerAttacker); + ClearBattlerItemEffectHistory(gBattlerAttacker); + + if (!TrySymbiosis(gBattlerAttacker, item, TRUE)) + effect = TRUE; + } + default: + break; + } gBattleScripting.moveendState++; break; case MOVEEND_CHANGED_ITEMS: @@ -7132,6 +6851,15 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_SAME_MOVE_TURNS: + if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] + || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT + || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; + else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) + gBattleStruct->sameMoveTurns[gBattlerAttacker]++; + gBattleScripting.moveendState++; + break; case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) gBattleStruct->moveTarget[gBattlerAttacker] = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; @@ -7145,32 +6873,16 @@ static void Cmd_moveend(void) if (B_RAMPAGE_CANCELLING >= GEN_5 && MoveHasAdditionalEffectSelf(gCurrentMove, MOVE_EFFECT_THRASH) // If we're rampaging && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT // And it is unusable - && (gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE) != STATUS2_LOCK_CONFUSE_TURN(1)) // And won't end this turn + && gBattleMons[gBattlerAttacker].volatiles.lockConfusionTurns != 1) // And won't end this turn CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_IGNORE); // Cancel it - if (gBattleStruct->savedAttackerCount > 0) - { - // #if TESTING - // Test_ExitWithResult(TEST_RESULT_ERROR, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); - // #else - DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); - // #endif - } - if (gBattleStruct->savedTargetCount > 0) - { - // #if TESTING - // Test_ExitWithResult(TEST_RESULT_ERROR, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); - // #else - DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); - // #endif - } + ValidateSavedBattlerCounts(); gProtectStructs[gBattlerAttacker].shellTrap = FALSE; - gBattleStruct->ateBoost[gBattlerAttacker] = FALSE; + gBattleStruct->battlerState[gBattlerAttacker].ateBoost = FALSE; gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_NONE; - gBattleStruct->isAtkCancelerForCalledMove = FALSE; gBattleStruct->swapDamageCategory = FALSE; gBattleStruct->categoryOverride = FALSE; gBattleStruct->additionalEffectsCounter = 0; @@ -7178,12 +6890,15 @@ static void Cmd_moveend(void) gBattleStruct->fickleBeamBoosted = FALSE; gBattleStruct->battlerState[gBattlerAttacker].usedMicleBerry = FALSE; gBattleStruct->noTargetPresent = FALSE; + gBattleStruct->toxicChainPriority = FALSE; if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) gBattleStruct->pledgeMove = FALSE; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP); + gBattleMons[gBattlerAttacker].volatiles.charge = FALSE; + if (gBattleMons[gBattlerAttacker].volatiles.destinyBond > 0) + gBattleMons[gBattlerAttacker].volatiles.destinyBond--; // check if Stellar type boost should be used up if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA && GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR @@ -7195,14 +6910,14 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE; - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; - if (gBattleStruct->commanderActive[i] != SPECIES_NONE && !IsBattlerAlive(i)) + if (gBattleStruct->battlerState[i].commanderSpecies != SPECIES_NONE && !IsBattlerAlive(i)) { u32 partner = BATTLE_PARTNER(i); - gBattleStruct->commanderActive[i] = SPECIES_NONE; + gBattleStruct->battlerState[i].commanderSpecies = SPECIES_NONE; if (IsBattlerAlive(partner)) - gStatuses3[partner] &= ~STATUS3_COMMANDER; + gBattleMons[partner].volatiles.semiInvulnerable = STATE_NONE; } } @@ -7296,13 +7011,13 @@ static void Cmd_sethealblock(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + if (gBattleMons[gBattlerTarget].volatiles.healBlock) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_HEAL_BLOCK; + gBattleMons[gBattlerTarget].volatiles.healBlock = TRUE; gDisableStructs[gBattlerTarget].healBlockTimer = gBattleTurnCounter + 5; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -7328,6 +7043,11 @@ static void Cmd_getswitchedmondata(void) if (gBattleControllerExecFlags) return; + if (TESTING + && gBattlerPartyIndexes[battler] == gBattleStruct->monToSwitchIntoId[battler] + && gBattleStruct->hpBefore[battler] != 0) // battler is alive + Test_ExitWithResult(TEST_RESULT_ERROR, 0, ":L:%s:%d: battler is trying to switch to themself", __FILE__, __LINE__); + gBattlerPartyIndexes[battler] = gBattleStruct->monToSwitchIntoId[battler]; BtlController_EmitGetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_ALL_BATTLE, 1u << gBattlerPartyIndexes[battler]); @@ -7410,10 +7130,9 @@ static void Cmd_switchindataupdate(void) { gBattleMons[battler].statStages[i] = oldData.statStages[i]; } - gBattleMons[battler].status2 = oldData.status2; } - SwitchInClearSetData(battler); + SwitchInClearSetData(battler, &oldData.volatiles); if (gBattleTypeFlags & BATTLE_TYPE_PALACE && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp @@ -7916,23 +7635,6 @@ static void Cmd_switchhandleorder(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) -{ - gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND; - gHitMarker &= ~HITMARKER_DESTINYBOND; - gBattleScripting.battler = battler; - gBattleCommunication[MULTISTRING_CHOOSER] = multistringId; - - if (gBattlescriptCurrInstr[1] == BS_TARGET) - BattleScriptCall(BattleScript_DmgHazardsOnTarget); - else if (gBattlescriptCurrInstr[1] == BS_ATTACKER) - BattleScriptCall(BattleScript_DmgHazardsOnAttacker); - else if (gBattlescriptCurrInstr[1] == BS_SCRIPTING) - BattleScriptCall(BattleScript_DmgHazardsOnBattlerScripting); - else - BattleScriptCall(BattleScript_DmgHazardsOnFaintedBattler); -} - bool32 DoSwitchInAbilities(u32 battler) { return (TryPrimalReversion(battler) @@ -7952,22 +7654,119 @@ static void UpdateSentMonFlags(u32 battler) gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[battler]; } +static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) +{ + gBattleMons[battler].volatiles.destinyBond = 0; + gHitMarker &= ~HITMARKER_DESTINYBOND; + gBattleScripting.battler = battler; + gBattleCommunication[MULTISTRING_CHOOSER] = multistringId; + + if (gBattlescriptCurrInstr[1] == BS_TARGET) + BattleScriptCall(BattleScript_DmgHazardsOnTarget); + else if (gBattlescriptCurrInstr[1] == BS_ATTACKER) + BattleScriptCall(BattleScript_DmgHazardsOnAttacker); + else if (gBattlescriptCurrInstr[1] == BS_SCRIPTING) + BattleScriptCall(BattleScript_DmgHazardsOnBattlerScripting); + else + BattleScriptCall(BattleScript_DmgHazardsOnFaintedBattler); +} + +void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType) +{ + switch (hazardType) + { + case HAZARDS_NONE: + break; + case HAZARDS_SPIKES: + { + enum Ability ability = GetBattlerAbility(battler); + if (ability != ABILITY_MAGIC_GUARD + && IsBattlerAffectedByHazards(battler, FALSE) + && IsBattlerGrounded(battler, ability, GetBattlerHoldEffect(battler))) + { + u8 spikesDmg = (5 - gSideTimers[side].spikesAmount) * 2; + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (spikesDmg); + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES); + } + break; + } + case HAZARDS_STICKY_WEB: + if (IsBattlerAffectedByHazards(battler, FALSE) && IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) + { + gBattleScripting.battler = battler; + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + BattleScriptCall(BattleScript_StickyWebOnSwitchIn); + } + break; + case HAZARDS_TOXIC_SPIKES: + if (!IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) + break; + + if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes. + { + gBattleStruct->hazardsCounter--; // reduce counter so the next hazard can be applied + gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES); + gEffectBattler = battler; + BattleScriptCall(BattleScript_ToxicSpikesAbsorbed); + } + else if (IsBattlerAffectedByHazards(battler, TRUE) + && CanBePoisoned(battler, battler, GetBattlerAbility(battler), GetBattlerAbility(battler))) + { + gBattleScripting.battler = battler; + BattleScriptPushCursor(); + if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) + { + gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned; + gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON; + } + else + { + gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned; + gBattleMons[battler].status1 |= STATUS1_POISON; + } + + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + } + break; + case HAZARDS_STEALTH_ROCK: + if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); + if (gBattleStruct->moveDamage[battler] != 0) + SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); + } + break; + case HAZARDS_STEELSURGE: + if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); + if (gBattleStruct->moveDamage[battler] != 0) + SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); + } + break; + case HAZARDS_MAX_COUNT: + break; + } +} + static bool32 DoSwitchInEffectsForBattler(u32 battler) { u32 i = 0; + u32 side = GetBattlerSide(battler); // Neutralizing Gas announces itself before hazards - if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS && gSpecialStatuses[battler].announceNeutralizingGas == 0) + if (!gSpecialStatuses[battler].announceNeutralizingGas + && AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, battler, gBattleMons[battler].ability, 0, 0)) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; gSpecialStatuses[battler].announceNeutralizingGas = TRUE; - gDisableStructs[battler].neutralizingGas = TRUE; - gBattlerAbility = battler; - BattleScriptCall(BattleScript_SwitchInAbilityMsgRet); } // Healing Wish activates before hazards. // Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways. else if ((gBattleStruct->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance) - && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || B_HEALING_WISH_SWITCH < GEN_8)) + && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || GetGenConfig(GEN_CONFIG_HEALING_WISH_SWITCH) < GEN_8)) { gBattlerAttacker = battler; if (gBattleStruct->battlerState[battler].storedHealingWish) @@ -7981,85 +7780,17 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->battlerState[battler].storedLunarDance = FALSE; } } - else if (!(gDisableStructs[battler].spikesDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SPIKES) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD - && IsBattlerAffectedByHazards(battler, FALSE) - && IsBattlerGrounded(battler)) + else if (!gDisableStructs[battler].hazardsDone) { - u8 spikesDmg = (5 - gSideTimers[GetBattlerSide(battler)].spikesAmount) * 2; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (spikesDmg); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - - gDisableStructs[battler].spikesDone = TRUE; - SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES); - } - else if (!(gDisableStructs[battler].stealthRockDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEALTH_ROCK) - && IsBattlerAffectedByHazards(battler, FALSE) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) - { - gDisableStructs[battler].stealthRockDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); - - if (gBattleStruct->moveDamage[battler] != 0) - SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); - } - else if (!(gDisableStructs[battler].toxicSpikesDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TOXIC_SPIKES) - && IsBattlerGrounded(battler)) - { - gDisableStructs[battler].toxicSpikesDone = TRUE; - if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes. + TryHazardsOnSwitchIn(battler, side, gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter]); + gBattleStruct->hazardsCounter++; + // Done once we reach the first element without any hazard type or the array is full + if (gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter] == HAZARDS_NONE + || gBattleStruct->hazardsCounter == HAZARDS_MAX_COUNT) { - gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_TOXIC_SPIKES; - gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0; - gBattleScripting.battler = battler; - BattleScriptCall(BattleScript_ToxicSpikesAbsorbed); + gDisableStructs[battler].hazardsDone = TRUE; + gBattleStruct->hazardsCounter = 0; } - else if (IsBattlerAffectedByHazards(battler, TRUE)) - { - if (CanBePoisoned(gBattlerAttacker, battler, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(battler))) - { - gBattleScripting.battler = battler; - BattleScriptPushCursor(); - if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) - { - gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned; - gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON; - } - else - { - gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned; - gBattleMons[battler].status1 |= STATUS1_POISON; - } - - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - } - } - else if (!(gDisableStructs[battler].stickyWebDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STICKY_WEB) - && IsBattlerAffectedByHazards(battler, FALSE) - && IsBattlerGrounded(battler)) - { - gDisableStructs[battler].stickyWebDone = TRUE; - gBattleScripting.battler = battler; - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - BattleScriptCall(BattleScript_StickyWebOnSwitchIn); - } - else if (!(gDisableStructs[battler].steelSurgeDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEELSURGE) - && IsBattlerAffectedByHazards(battler, FALSE) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) - { - gDisableStructs[battler].steelSurgeDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); - - if (gBattleStruct->moveDamage[battler] != 0) - SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); } else if (gBattleMons[battler].hp != gBattleMons[battler].maxHP && gBattleStruct->zmove.healReplacement) { @@ -8072,7 +7803,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) } else { - u32 battlerAbility = GetBattlerAbility(battler); + enum Ability battlerAbility = GetBattlerAbility(battler); // There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts. // The truant counter is not updated in the case where a mon switches in after a lost judgment in the battle arena. if (battlerAbility == ABILITY_TRUANT @@ -8084,37 +7815,48 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) if (DoSwitchInAbilities(battler) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battler)) return TRUE; - else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) - return TRUE; for (i = 0; i < gBattlersCount; i++) { if (i == battler) continue; - switch (GetBattlerAbility(i)) + enum Ability ability = GetBattlerAbility(i); + switch (ability) { case ABILITY_TRACE: case ABILITY_COMMANDER: - if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, 0, 0, 0)) + if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, ability, 0, 0)) return TRUE; break; case ABILITY_FORECAST: case ABILITY_FLOWER_GIFT: case ABILITY_PROTOSYNTHESIS: - if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, ability, 0, 0)) return TRUE; break; + default: + break; } if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN)) return TRUE; } - gDisableStructs[battler].stickyWebDone = FALSE; - gDisableStructs[battler].spikesDone = FALSE; - gDisableStructs[battler].toxicSpikesDone = FALSE; - gDisableStructs[battler].stealthRockDone = FALSE; - gDisableStructs[battler].steelSurgeDone = FALSE; + for (i = 0; i < gBattlersCount; i++) + { + if (ItemBattleEffects(ITEMEFFECT_WHITE_HERB, i)) + return TRUE; + } + for (i = 0; i < gBattlersCount; i++) + { + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, i, GetBattlerAbility(i), 0, 0)) + return TRUE; + } + for (i = 0; i < gBattlersCount; i++) + { + if (ItemBattleEffects(ITEMEFFECT_MIRROR_HERB, i)) + return TRUE; + } for (i = 0; i < gBattlersCount; i++) { @@ -8124,6 +7866,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; } + gDisableStructs[battler].hazardsDone = FALSE; gBattleStruct->battlerState[battler].forcedSwitch = FALSE; return FALSE; } @@ -8307,7 +8050,7 @@ static void Cmd_handlelearnnewmove(void) u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gBattlerPartyIndexes[battler] == monId - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { GiveMoveToBattleMon(&gBattleMons[battler], learnMove); } @@ -8315,7 +8058,7 @@ static void Cmd_handlelearnnewmove(void) { battler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); if (gBattlerPartyIndexes[battler] == monId - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { GiveMoveToBattleMon(&gBattleMons[battler], learnMove); } @@ -8398,7 +8141,7 @@ static void Cmd_yesnoboxlearnmove(void) else { u16 move = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MOVE1 + movePosition); - if (IsMoveHM(move)) + if (CannotForgetMove(move)) { PrepareStringBattle(STRINGID_HMMOVESCANTBEFORGOTTEN, B_POSITION_PLAYER_LEFT); gBattleScripting.learnMoveState = 6; @@ -8515,7 +8258,7 @@ static void Cmd_hitanimation(void) for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT - || gBattleStruct->noResultString[battlerDef]) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) @@ -8706,7 +8449,7 @@ static void ResetValuesForCalledMove(void) if (gBattlerByTurnOrder[gCurrentTurnActionNumber] != gBattlerAttacker) gBattleStruct->atkCancellerTracker = 0; else - SetAtkCancellerForCalledMove(); + gBattleStruct->atkCancellerTracker = CANCELLER_VOLATILE_BLOCKED; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker); @@ -8730,58 +8473,29 @@ static void Cmd_jumptocalledmove(void) static void Cmd_statusanimation(void) { - CMD_ARGS(u8 battler); + CMD_ARGS(u8 battler, u32 status, bool8 isVolatile); if (gBattleControllerExecFlags == 0) { - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + u32 battler = GetBattlerForBattleScript(cmd->battler), + statusFlag = (cmd->isVolatile || cmd->status) ? cmd->status : gBattleMons[battler].status1; + if (!IsSemiInvulnerable(battler, CHECK_ALL) && gDisableStructs[battler].substituteHP == 0 && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, FALSE, gBattleMons[battler].status1); + BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, cmd->isVolatile, statusFlag); MarkBattlerForControllerExec(battler); } gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_status2animation(void) +static void Cmd_unused_0x65(void) { - CMD_ARGS(u8 battler, u32 status2); - - if (gBattleControllerExecFlags == 0) - { - u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 status2ToAnim = cmd->status2; - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && gDisableStructs[battler].substituteHP == 0 - && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) - { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, TRUE, gBattleMons[battler].status2 & status2ToAnim); - MarkBattlerForControllerExec(battler); - } - gBattlescriptCurrInstr = cmd->nextInstr; - } } -static void Cmd_chosenstatusanimation(void) +static void Cmd_unused_0x66(void) { - CMD_ARGS(u8 battler, bool8 isStatus2, u32 status); - - if (gBattleControllerExecFlags == 0) - { - u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 wantedStatus = cmd->status; - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && gDisableStructs[battler].substituteHP == 0 - && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) - { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, cmd->isStatus2, wantedStatus); - MarkBattlerForControllerExec(battler); - } - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_yesnobox(void) @@ -8861,8 +8575,8 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) { if (GetItemPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) - && gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry + && !gBattleMons[battler].volatiles.healBlock + && GetBattlerPartyState(battler)->ateBerry && !IsBattlerAtMaxHp(battler)) { gBattleStruct->cheekPouchActivated = TRUE; @@ -8906,12 +8620,12 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef) } // Called by Cmd_removeitem. itemId represents the item that was removed, not being given. -static bool32 TrySymbiosis(u32 battler, u32 itemId) +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { if (!gBattleStruct->itemLost[B_SIDE_PLAYER][gBattlerPartyIndexes[battler]].stolen && gBattleStruct->changedItems[battler] == ITEM_NONE - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_BUTTON + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_EJECT_PACK && (B_SYMBIOSIS_GEMS < GEN_7 || !(gSpecialStatuses[battler].gemBoost)) && GetMoveEffect(gCurrentMove) != EFFECT_FLING //Fling and damage-reducing berries are handled separately. && !gSpecialStatuses[battler].berryReduced @@ -8919,9 +8633,12 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId) { BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; + gEffectBattler = battler; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); - gBattlerAttacker = battler; - BattleScriptPush(gBattlescriptCurrInstr + 2); + if (moveEnd) + BattleScriptPushCursor(); + else + BattleScriptPush(gBattlescriptCurrInstr + 2); gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; return TRUE; } @@ -8947,7 +8664,7 @@ static void Cmd_removeitem(void) // Popped Air Balloon cannot be restored by any means. // Corroded items cannot be restored either. - if (GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_AIR_BALLOON + if (GetBattlerHoldEffect(battler) != HOLD_EFFECT_AIR_BALLOON && GetMoveEffect(gCurrentMove) != EFFECT_CORROSIVE_GAS) gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = itemId; // Remember if switched out @@ -8959,7 +8676,7 @@ static void Cmd_removeitem(void) MarkBattlerForControllerExec(battler); ClearBattlerItemEffectHistory(battler); - if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId)) + if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId, FALSE)) gBattlescriptCurrInstr = cmd->nextInstr; } @@ -9458,6 +9175,32 @@ static void RemoveAllTerrains(void) } \ } +static bool32 DefogClearHazards(u32 saveBattler, u32 side, bool32 clear) +{ + if (!AreAnyHazardsOnSide(side)) + return FALSE; + + for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) + { + bool32 checkOrClear = clear ? IsHazardOnSideAndClear(side, hazardType) : IsHazardOnSide(side, hazardType); + if (checkOrClear) + { + if (clear) + { + gBattleStruct->numHazards[side]--; + gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; + BattleScriptCall(BattleScript_DefogClearHazards); + } + else + { + gBattlerAttacker = saveBattler; + } + return TRUE; + } + } + return FALSE; +} + static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) { s32 i; @@ -9480,11 +9223,8 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { gBattlerAttacker = i; // For correct battle string. Ally's / Foe's - DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEELSURGE, steelsurgeAmount, BattleScript_SteelsurgeDefog, 0); + if (DefogClearHazards(saveBattler, i, clear)) + return TRUE; } if (gBattleWeather & B_WEATHER_FOG) { @@ -9512,25 +9252,20 @@ static bool32 TryTidyUpClear(u32 battlerAtk, bool32 clear) for (i = 0; i < NUM_BATTLE_SIDES; i++) { - struct SideTimer *sideTimer = &gSideTimers[i]; - u32 *sideStatuses = &gSideStatuses[i]; - gBattlerAttacker = i; // For correct battle string. Ally's / Foe's - DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); + if (DefogClearHazards(saveBattler, i, clear)) + return TRUE; } for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - if (gBattleMons[i].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[i].volatiles.substitute) { if (clear) { gBattlerTarget = i; gDisableStructs[i].substituteHP = 0; - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; BattleScriptCall(BattleScript_SubstituteFade); } gBattlerAttacker = saveBattler; @@ -9550,7 +9285,7 @@ u32 IsFlowerVeilProtected(u32 battler) return 0; } -u32 IsLeafGuardProtected(u32 battler, u32 ability) +u32 IsLeafGuardProtected(u32 battler, enum Ability ability) { if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) return ability == ABILITY_LEAF_GUARD; @@ -9558,13 +9293,13 @@ u32 IsLeafGuardProtected(u32 battler, u32 ability) return 0; } -bool32 IsShieldsDownProtected(u32 battler, u32 ability) +bool32 IsShieldsDownProtected(u32 battler, enum Ability ability) { return (ability == ABILITY_SHIELDS_DOWN && GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form } -u32 IsAbilityStatusProtected(u32 battler, u32 ability) +u32 IsAbilityStatusProtected(u32 battler, enum Ability ability) { return IsLeafGuardProtected(battler, ability) || IsShieldsDownProtected(battler, ability) @@ -9594,18 +9329,18 @@ static bool32 IsRototillerAffected(u32 battler) { if (!IsBattlerAlive(battler)) return FALSE; - if (!IsBattlerGrounded(battler)) + if (!IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler))) return FALSE; // Only grounded battlers affected if (!IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) return FALSE; // Only grass types affected - if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; // Rototiller doesn't affected semi-invulnerable battlers if (BlocksPrankster(MOVE_ROTOTILLER, gBattlerAttacker, battler, FALSE)) return FALSE; return TRUE; } -static bool32 IsElectricAbilityAffected(u32 battler, u32 ability) +static bool32 IsElectricAbilityAffected(u32 battler, enum Ability ability) { u32 moveType; @@ -9628,7 +9363,7 @@ static bool32 IsTeatimeAffected(u32 battler) { if (GetItemPocket(gBattleMons[battler].item) != POCKET_BERRIES) return FALSE; // Only berries - if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; // Teatime doesn't affected semi-invulnerable battlers return TRUE; } @@ -9671,17 +9406,23 @@ void BS_CourtChangeSwapSideStatuses(void) COURTCHANGE_SWAP(SIDE_STATUS_TAILWIND, tailwindTimer, temp); // Lucky Chant doesn't exist in gen 8, but seems like it should be affected by Court Change COURTCHANGE_SWAP(SIDE_STATUS_LUCKY_CHANT, luckyChantTimer, temp); - COURTCHANGE_SWAP(SIDE_STATUS_SPIKES, spikesAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STICKY_WEB, stickyWebAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STEELSURGE, steelsurgeAmount, temp); COURTCHANGE_SWAP(SIDE_STATUS_DAMAGE_NON_TYPES, damageNonTypesTimer, temp); // Track Pledge effect side COURTCHANGE_SWAP(SIDE_STATUS_RAINBOW, rainbowTimer, temp); COURTCHANGE_SWAP(SIDE_STATUS_SEA_OF_FIRE, seaOfFireTimer, temp); COURTCHANGE_SWAP(SIDE_STATUS_SWAMP, swampTimer, temp); + // Hazards + u32 tempQueue[HAZARDS_MAX_COUNT] = {HAZARDS_NONE}; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + tempQueue[i] = gBattleStruct->hazardsQueue[B_SIDE_PLAYER][i]; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[B_SIDE_PLAYER][i] = gBattleStruct->hazardsQueue[B_SIDE_OPPONENT][i]; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[B_SIDE_OPPONENT][i] = tempQueue[i]; + SWAP(sideTimerPlayer->spikesAmount, sideTimerOpp->spikesAmount, temp); + SWAP(sideTimerPlayer->toxicSpikesAmount, sideTimerOpp->toxicSpikesAmount, temp); + // Change battler IDs of swapped effects. Needed for the correct string when they expire UPDATE_COURTCHANGED_BATTLER(stickyWebBattlerId); @@ -9735,25 +9476,27 @@ static bool32 ChangeOrderTargetAfterAttacker(void) u32 i; u8 data[MAX_BATTLERS_COUNT]; u8 actionsData[MAX_BATTLERS_COUNT]; + u32 attackerTurnOrderNum = GetBattlerTurnOrderNum(gBattlerAttacker); + u32 targetTurnOrderNum = GetBattlerTurnOrderNum(gBattlerTarget); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + if (attackerTurnOrderNum > targetTurnOrderNum) return FALSE; - if (GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget)) - return B_AFTER_YOU_TURN_ORDER >= GEN_8; + if (attackerTurnOrderNum + 1 == targetTurnOrderNum) + return GetGenConfig(GEN_CONFIG_AFTER_YOU_TURN_ORDER) >= GEN_8; for (i = 0; i < MAX_BATTLERS_COUNT; i++) { data[i] = gBattlerByTurnOrder[i]; actionsData[i] = gActionsByTurnOrder[i]; } - if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 2) + if (attackerTurnOrderNum == 0 && targetTurnOrderNum == 2) { gBattlerByTurnOrder[1] = gBattlerTarget; gActionsByTurnOrder[1] = actionsData[2]; gBattlerByTurnOrder[2] = data[1]; gActionsByTurnOrder[2] = actionsData[1]; } - else if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 3) + else if (attackerTurnOrderNum == 0 && targetTurnOrderNum == 3) { gBattlerByTurnOrder[1] = gBattlerTarget; gActionsByTurnOrder[1] = actionsData[3]; @@ -9762,7 +9505,7 @@ static bool32 ChangeOrderTargetAfterAttacker(void) gBattlerByTurnOrder[3] = data[2]; gActionsByTurnOrder[3] = actionsData[2]; } - else // Attacker == 1, Target == 3 + else // attackerTurnOrderNum == 1, targetTurnOrderNum == 3 { gBattlerByTurnOrder[2] = gBattlerTarget; gActionsByTurnOrder[2] = actionsData[3]; @@ -9772,1623 +9515,14 @@ static bool32 ChangeOrderTargetAfterAttacker(void) return TRUE; } +// will be deprecated next release cycle static void Cmd_various(void) { CMD_ARGS(u8 battler, u8 id); - struct Pokemon *mon; - s32 i; - u8 data[10]; - u32 battler, bits; - enum CmdVarious variousId = cmd->id; - if (gBattleControllerExecFlags) return; - battler = GetBattlerForBattleScript(cmd->battler); - - switch (variousId) - { - // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. - // Also when an opposing wild mon uses it againt its partner. - // Also when B_FLAG_NO_RUNNING is enabled. - case VARIOUS_JUMP_IF_ROAR_FAILS: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (WILD_DOUBLE_BATTLE - && IsOnPlayerSide(gBattlerAttacker) - && !IsOnPlayerSide(gBattlerTarget) - && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else if (WILD_DOUBLE_BATTLE - && !IsOnPlayerSide(gBattlerAttacker) - && !IsOnPlayerSide(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else if (FlagGet(B_FLAG_NO_RUNNING)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_ABSENT: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlive(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsShieldsDownProtected(battler, GetBattlerAbility(battler))) - { - gBattlerAbility = battler; - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_HOLD_EFFECT: - { - VARIOUS_ARGS(u8 holdEffect, const u8 *jumpInstr, u8 equal); - if ((GetBattlerHoldEffect(battler, TRUE) == cmd->holdEffect) == cmd->equal) - { - if (cmd->equal) - gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - if (!cmd->equal) - gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_NO_ALLY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlive(BATTLE_PARTNER(battler))) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_INFATUATE_WITH_BATTLER: - { - VARIOUS_ARGS(u8 infatuateWith); - gBattleScripting.battler = battler; - gBattleMons[battler].status2 |= STATUS2_INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SET_LAST_USED_ITEM: - { - VARIOUS_ARGS(); - gLastUsedItem = gBattleMons[battler].item; - break; - } - case VARIOUS_TRY_FAIRY_LOCK: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gFieldStatuses |= STATUS_FIELD_FAIRY_LOCK; - gFieldTimers.fairyLockTimer = gBattleTurnCounter + 2; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_GET_STAT_VALUE: - { - VARIOUS_ARGS(u8 stat); - i = cmd->stat; - gBattleStruct->moveDamage[gBattlerAttacker] = *(u16 *)(&gBattleMons[battler].attack) + (i - 1); - gBattleStruct->moveDamage[gBattlerAttacker] *= gStatStageRatios[gBattleMons[battler].statStages[i]][0]; - gBattleStruct->moveDamage[gBattlerAttacker] /= gStatStageRatios[gBattleMons[battler].statStages[i]][1]; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_FULL_HP: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsBattlerAtMaxHp(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_FRISK: - { - VARIOUS_ARGS(); - while (gBattleStruct->friskedBattler < gBattlersCount) - { - gBattlerTarget = gBattleStruct->friskedBattler++; - if (!IsBattlerAlly(battler, gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattleMons[gBattlerTarget].item != ITEM_NONE) - { - gLastUsedItem = gBattleMons[gBattlerTarget].item; - RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffect(gBattlerTarget, FALSE)); - // If Frisk identifies two mons' items, show the pop-up only once. - if (gBattleStruct->friskedAbility) - { - BattleScriptCall(BattleScript_FriskMsg); - } - else - { - gBattleStruct->friskedAbility = TRUE; - BattleScriptCall(BattleScript_FriskMsgWithPopup); - } - return; - } - } - gBattleStruct->friskedBattler = 0; - gBattleStruct->friskedAbility = FALSE; - break; - } - case VARIOUS_TRACE_ABILITY: - { - VARIOUS_ARGS(); - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = gBattleStruct->tracedAbility[battler]; - break; - } - case VARIOUS_TRY_ILLUSION_OFF: - { - VARIOUS_ARGS(); - if (TryClearIllusion(battler, ABILITYEFFECT_MOVE_END)) - return; - break; - } - case VARIOUS_SET_SPRITEIGNORE0HP: - { - VARIOUS_ARGS(bool8 ignore0HP); - gBattleStruct->spriteIgnore0Hp = cmd->ignore0HP; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_UPDATE_NICK: - { - VARIOUS_ARGS(); - mon = GetBattlerMon(battler); - UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_NICK); - break; - } - case VARIOUS_JUMP_IF_NOT_BERRY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; - return; - } - case VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS: - { - VARIOUS_ARGS(const u8 *failInstr); - if ((gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK)) - || IsBattlerAtMaxHp(battler) - || !gBattleMons[battler].hp - || !(IsBattlerGrounded(battler))) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_GRAVITY_ON_AIRBORNE_MONS: - { - VARIOUS_ARGS(); - // Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop. - if (gStatuses3[battler] & STATUS3_ON_AIR && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) - CancelMultiTurnMoves(battler, SKY_DROP_GRAVITY_ON_AIRBORNE); - - gStatuses3[battler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); - break; - } - case VARIOUS_SET_POWDER: - { - VARIOUS_ARGS(); - gBattleMons[battler].status2 |= STATUS2_POWDER; - break; - } - case VARIOUS_ACUPRESSURE: - { - VARIOUS_ARGS(const u8 *failInstr); - bits = 0; - for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) - { - if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - bits |= 1u << i; - } - if (bits) - { - u32 statId; - do - { - statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1; - } while (!(bits & (1u << statId))); - - SET_STATCHANGER(statId, 2, FALSE); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_CANCEL_MULTI_TURN_MOVES: - { - VARIOUS_ARGS(); - const u8 *result; - result = CancelMultiTurnMoves(battler, SKY_DROP_CANCEL_MULTI_TURN_MOVES); - if (result) - { - gBattlescriptCurrInstr = result; - return; - } - break; - } - case VARIOUS_IS_RUNNING_IMPOSSIBLE: - { - VARIOUS_ARGS(); - gBattleCommunication[0] = IsRunningFromBattleImpossible(battler); - break; - } - case VARIOUS_GET_MOVE_TARGET: - { - VARIOUS_ARGS(); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - break; - } - case VARIOUS_GET_BATTLER_FAINTED: - { - VARIOUS_ARGS(); - if (gHitMarker & HITMARKER_FAINTED(battler)) - gBattleCommunication[0] = TRUE; - else - gBattleCommunication[0] = FALSE; - break; - } - case VARIOUS_RESET_SWITCH_IN_ABILITY_BITS: - { - VARIOUS_ARGS(); - gSpecialStatuses[battler].switchInAbilityDone = FALSE; - break; - } - case VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP: - { - VARIOUS_ARGS(); - if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId || gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) - { - if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId) - battler = 0; - else - battler = 2; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[battler].moves[i] == gBattleStruct->choicedMove[battler]) - break; - } - if (i == MAX_MON_MOVES) - gBattleStruct->choicedMove[battler] = MOVE_NONE; - } - break; - } - case VARIOUS_RESET_PLAYER_FAINTED: - { - VARIOUS_ARGS(); - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE)) - && gBattleTypeFlags & BATTLE_TYPE_TRAINER - && IsBattlerAlive(B_POSITION_PLAYER_LEFT) - && IsBattlerAlive(B_POSITION_OPPONENT_LEFT)) - { - gHitMarker &= ~HITMARKER_PLAYER_FAINTED; - } - break; - } - case VARIOUS_PALACE_FLAVOR_TEXT: - { - VARIOUS_ARGS(); - // Try and print end-of-turn Battle Palace flavor text (e.g. "A glint appears in mon's eyes") - // gBattleCommunication[0] = FALSE; // whether or not msg should be printed - // gBattleScripting.battler = battler = gBattleCommunication[1]; - // if (!(gBattleStruct->palaceFlags & (1u << battler)) - // && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp - // && IsBattlerAlive(battler) - // && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) - // { - // gBattleStruct->palaceFlags |= 1u << battler; - // gBattleCommunication[0] = TRUE; - // gBattleCommunication[MULTISTRING_CHOOSER] = gNaturesInfo[GetNatureFromPersonality(gBattleMons[battler].personality)].battlePalaceFlavorText; - // } - break; - } - case VARIOUS_ARENA_JUDGMENT_WINDOW: - { - VARIOUS_ARGS(); - - // i = BattleArena_ShowJudgmentWindow(&gBattleCommunication[0]); - - // // BattleArena_ShowJudgmentWindow's last state was an intermediate step. - // // Return without advancing the current instruction so that it will be called again. - // if (i == ARENA_RESULT_RUNNING) - // return; - - // gBattleCommunication[1] = i; - break; - } - case VARIOUS_ARENA_OPPONENT_MON_LOST: - { - VARIOUS_ARGS(); - // gBattleMons[1].hp = 0; - // gHitMarker |= HITMARKER_FAINTED(1); - // gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; - // gDisableStructs[1].truantSwitchInHack = 1; - break; - } - case VARIOUS_ARENA_PLAYER_MON_LOST: - { - VARIOUS_ARGS(); - // gBattleMons[0].hp = 0; - // gHitMarker |= HITMARKER_FAINTED(0); - // gHitMarker |= HITMARKER_PLAYER_FAINTED; - // gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; - // gDisableStructs[0].truantSwitchInHack = 1; - break; - } - case VARIOUS_ARENA_BOTH_MONS_LOST: - { - VARIOUS_ARGS(); - // gBattleMons[0].hp = 0; - // gBattleMons[1].hp = 0; - // gHitMarker |= HITMARKER_FAINTED(0); - // gHitMarker |= HITMARKER_FAINTED(1); - // gHitMarker |= HITMARKER_PLAYER_FAINTED; - // gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; - // gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; - // gDisableStructs[0].truantSwitchInHack = 1; - // gDisableStructs[1].truantSwitchInHack = 1; - break; - } - case VARIOUS_EMIT_YESNOBOX: - { - VARIOUS_ARGS(); - BtlController_EmitYesNoBox(battler, B_COMM_TO_CONTROLLER); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_DRAW_ARENA_REF_TEXT_BOX: - { - VARIOUS_ARGS(); - // DrawArenaRefereeTextBox(); - break; - } - case VARIOUS_ERASE_ARENA_REF_TEXT_BOX: - { - VARIOUS_ARGS(); - // EraseArenaRefereeTextBox(); - break; - } - case VARIOUS_ARENA_JUDGMENT_STRING: - { - CMD_ARGS(u8 id, u8 _); - // BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[cmd->id]); - // BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGMENT_TEXT); - break; - } - case VARIOUS_ARENA_WAIT_STRING: - { - VARIOUS_ARGS(); - // if (IsTextPrinterActive(ARENA_WIN_JUDGMENT_TEXT)) - // return; - break; - } - case VARIOUS_WAIT_CRY: - { - VARIOUS_ARGS(); - if (!IsCryFinished()) - return; - break; - } - case VARIOUS_RETURN_OPPONENT_MON1: - { - VARIOUS_ARGS(); - battler = 1; - if (IsBattlerAlive(battler)) - { - BtlController_EmitReturnMonToBall(battler, B_COMM_TO_CONTROLLER, FALSE); - MarkBattlerForControllerExec(battler); - } - break; - } - case VARIOUS_RETURN_OPPONENT_MON2: - { - VARIOUS_ARGS(); - if (gBattlersCount > 3) - { - battler = 3; - if (IsBattlerAlive(battler)) - { - BtlController_EmitReturnMonToBall(battler, B_COMM_TO_CONTROLLER, FALSE); - MarkBattlerForControllerExec(battler); - } - } - break; - } - case VARIOUS_VOLUME_DOWN: - { - VARIOUS_ARGS(); - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x55); - break; - } - case VARIOUS_VOLUME_UP: - { - VARIOUS_ARGS(); - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); - break; - } - case VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT: - { - VARIOUS_ARGS(); - gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = TRUE; - break; - } - case VARIOUS_PALACE_TRY_ESCAPE_STATUS: - { - VARIOUS_ARGS(); - // if (BattlePalace_TryEscapeStatus(battler)) - // return; - break; - } - case VARIOUS_SET_TELEPORT_OUTCOME: - { - VARIOUS_ARGS(); - // Don't end the battle if one of the wild mons teleported from the wild double battle - // and its partner is still alive. - if (!IsOnPlayerSide(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))) - { - gAbsentBattlerFlags |= 1u << battler; - gHitMarker |= HITMARKER_FAINTED(battler); - gBattleMons[battler].hp = 0; - SetMonData(GetBattlerMon(battler), MON_DATA_HP, &gBattleMons[battler].hp); - SetHealthboxSpriteInvisible(gHealthboxSpriteIds[battler]); - FaintClearSetData(battler); - } - else if (IsOnPlayerSide(battler)) - { - gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED; - } - else - { - gBattleOutcome = B_OUTCOME_MON_TELEPORTED; - } - break; - } - case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC: - { - VARIOUS_ARGS(); - BtlController_EmitPlayFanfareOrBGM(battler, B_COMM_TO_CONTROLLER, MUS_VICTORY_TRAINER, TRUE); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_STAT_TEXT_BUFFER: - { - VARIOUS_ARGS(); - PREPARE_STAT_BUFFER(gBattleTextBuff1, gBattleCommunication[0]); - break; - } - case VARIOUS_SWITCHIN_ABILITIES: - { - VARIOUS_ARGS(); - gBattlescriptCurrInstr = cmd->nextInstr; - AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); - AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); - AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); - return; - } - case VARIOUS_INSTANT_HP_DROP: - { - VARIOUS_ARGS(); - BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_CLEAR_STATUS: - { - VARIOUS_ARGS(); - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_RESTORE_PP: - { - VARIOUS_ARGS(); - for (i = 0; i < 4; i++) - { - gBattleMons[battler].pp[i] = CalculatePPWithBonus(gBattleMons[battler].moves[i], gBattleMons[battler].ppBonuses, i); - data[i] = gBattleMons[battler].pp[i]; - } - data[i] = gBattleMons[battler].ppBonuses; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_PP_DATA_BATTLE, 0, 5, data); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_TRY_ACTIVATE_RECEIVER: // Partner gets fainted's ally ability - { - VARIOUS_ARGS(); - gBattlerAbility = BATTLE_PARTNER(battler); - i = GetBattlerAbility(gBattlerAbility); - if (IsBattlerAlive(gBattlerAbility) - && (i == ABILITY_RECEIVER || i == ABILITY_POWER_OF_ALCHEMY) - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD - && !gAbilitiesInfo[gBattleMons[battler].ability].cantBeCopied) - { - gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_ReceiverActivates; - return; - } - break; - } - case VARIOUS_TRY_ACTIVATE_SOULHEART: - { - VARIOUS_ARGS(); - while (gBattleStruct->soulheartBattlerId < gBattlersCount) - { - gBattleScripting.battler = gBattleStruct->soulheartBattlerId++; - if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART - && IsBattlerAlive(gBattleScripting.battler) - && !NoAliveMonsForEitherParty() - && CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); - BattleScriptCall(BattleScript_ScriptingAbilityStatRaise); - return; - } - } - gBattleStruct->soulheartBattlerId = 0; - break; - } - case VARIOUS_PLAY_MOVE_ANIMATION: - { - VARIOUS_ARGS(u16 move); - BtlController_EmitMoveAnimation(battler, B_COMM_TO_CONTROLLER, cmd->move, gBattleScripting.animTurn, 0, 0, gBattleMons[battler].friendship, &gDisableStructs[battler], gMultiHitCounter); - MarkBattlerForControllerExec(battler); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SET_LUCKY_CHANT: - { - VARIOUS_ARGS(const u8 *failInstr); - if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_LUCKY_CHANT)) - { - gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_LUCKY_CHANT; - gSideTimers[GetBattlerSide(battler)].luckyChantTimer = gBattleTurnCounter + 5; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_SUCKER_PUNCH_CHECK: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gProtectStructs[gBattlerTarget].protected == PROTECT_OBSTRUCT) - gBattlescriptCurrInstr = cmd->failInstr; - else if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else if (IsBattleMoveStatus(gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]) && !gProtectStructs[gBattlerTarget].noValidMoves) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SET_SIMPLE_BEAM: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten - || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) - gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - - gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_ENTRAINMENT: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeCopied - || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (gBattleMons[gBattlerTarget].ability == gBattleMons[gBattlerAttacker].ability - || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; - gBattlescriptCurrInstr = cmd->nextInstr; - } - } - return; - } - case VARIOUS_SET_LAST_USED_ABILITY: - { - VARIOUS_ARGS(); - gLastUsedAbility = gBattleMons[battler].ability; - break; - } - case VARIOUS_INVERT_STAT_STAGES: - { - VARIOUS_ARGS(); - for (i = 0; i < NUM_BATTLE_STATS; i++) - { - if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) // Negative becomes positive. - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE + (DEFAULT_STAT_STAGE - gBattleMons[battler].statStages[i]); - else if (gBattleMons[battler].statStages[i] > DEFAULT_STAT_STAGE) // Positive becomes negative. - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE - (gBattleMons[battler].statStages[i] - DEFAULT_STAT_STAGE); - } - break; - } - case VARIOUS_TRY_ME_FIRST: - { - VARIOUS_ARGS(const u8 *failInstr); - u16 move = gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]; - if (IsBattleMoveStatus(move) || IsMoveMeFirstBanned(move) - || GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else - { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCalledMove = GetTypeBasedZMove(move); - } - else - { - gCalledMove = move; - } - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_BATTLE_END: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (NoAliveMonsForEitherParty()) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_ELECTRIFY: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gStatuses4[gBattlerTarget] |= STATUS4_ELECTRIFIED; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_SOAK: - { - VARIOUS_ARGS(const u8 *failInstr); - u32 types[3]; - GetBattlerTypes(gBattlerTarget, FALSE, types); - u32 typeToSet = GetMoveArgType(gCurrentMove); - if ((types[0] == typeToSet && types[1] == typeToSet) - || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - SET_BATTLER_TYPE(gBattlerTarget, typeToSet); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, typeToSet); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_HANDLE_FORM_CHANGE: - { - VARIOUS_ARGS(u8 case_); - mon = GetBattlerMon(battler); - - // Change species. - if (cmd->case_ == 0) - { - /* What was the idea here? - if (!gBattleTextBuff1) - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battler].species); - */ - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); - MarkBattlerForControllerExec(battler); - } - // Change stats. - else if (cmd->case_ == 1) - { - RecalcBattlerStats(battler, mon, FALSE); - } - // Update healthbox. - else - { - UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); - } - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_LAST_RESORT: - { - VARIOUS_ARGS(const u8 *failInstr); - if (CanUseLastResort(battler)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->failInstr; - return; - } - case VARIOUS_TRY_AUTOTOMIZE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerWeight(battler) > 1) - { - gDisableStructs[battler].autotomizeCount++; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_TRY_INSTRUCT: - { - VARIOUS_ARGS(const u8 *failInstr); - u16 move = gLastPrintedMoves[gBattlerTarget]; - if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasAdditionalEffectSelf(move, MOVE_EFFECT_RECHARGE) - || IsMoveInstructBanned(move) - || gBattleMoveEffects[GetMoveEffect(move)].twoTurnEffect - || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) - || IsZMove(move) - || IsMaxMove(move)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4; - gCalledMove = move; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[gBattlerTarget].moves[i] == gCalledMove) - { - gCurrMovePos = i; - i = 4; - break; - } - } - if (i != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) - gBattlescriptCurrInstr = cmd->failInstr; - else - { - gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget]; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gBattlerPartyIndexes[battler]); - gBattlescriptCurrInstr = cmd->nextInstr; - } - } - return; - } - case VARIOUS_ABILITY_POPUP: - { - VARIOUS_ARGS(); - CreateAbilityPopUp(battler, gBattleMons[battler].ability, (IsDoubleBattle()) != 0); - break; - } - case VARIOUS_UPDATE_ABILITY_POPUP: - { - VARIOUS_ARGS(); - UpdateAbilityPopup(battler); - break; - } - case VARIOUS_JUMP_IF_TARGET_ALLY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; - return; - } - case VARIOUS_TRY_SYNCHRONOISE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (!DoBattlersShareType(gBattlerAttacker, gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_LOSE_TYPE: - { - VARIOUS_ARGS(u8 type); - RemoveBattlerType(battler, cmd->type); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_PSYCHO_SHIFT: - { - VARIOUS_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr); - u32 targetAbility = GetBattlerAbility(gBattlerTarget); - // Psycho shift works - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_TOXIC_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 1; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_BURN) && CanBeBurned(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 2; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 3; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerAttacker, gBattlerTarget, targetAbility, BLOCKED_BY_SLEEP_CLAUSE)) - gBattleCommunication[MULTISTRING_CHOOSER] = 4; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) - { - gBattlescriptCurrInstr = cmd->sleepClauseFailInstr; - return; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - return; - } - gBattleMons[gBattlerTarget].status1 = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; - battler = gBattlerTarget; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - gBattlescriptCurrInstr = cmd->nextInstr; - TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); - return; - } - case VARIOUS_CURE_STATUS: - { - VARIOUS_ARGS(); - - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_POWER_TRICK: - { - VARIOUS_ARGS(); - gStatuses3[battler] ^= STATUS3_POWER_TRICK; - SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, i); - break; - } - case VARIOUS_AFTER_YOU: - { - VARIOUS_ARGS(const u8 *failInstr); - if (ChangeOrderTargetAfterAttacker()) - { - gSpecialStatuses[gBattlerTarget].afterYou = 1; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_BESTOW: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerAttacker].item == ITEM_NONE - || gBattleMons[gBattlerTarget].item != ITEM_NONE - || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) - || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) - || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - BestowItem(gBattlerAttacker, gBattlerTarget); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_NOT_GROUNDED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerGrounded(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_HANDLE_TRAINER_SLIDE_MSG: - { - VARIOUS_ARGS(u8 case_); - if (cmd->case_ == PRINT_SLIDE_MESSAGE) - { - BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, STRINGID_TRAINERSLIDE); - MarkBattlerForControllerExec(battler); - } - else if (cmd->case_ == RESTORE_BATTLER_SLIDE_CONTROL) - { - if (IsBattlerAlive(battler)) - { - SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species); - BattleLoadMonSpriteGfx(GetBattlerMon(battler), battler); - } - i = BATTLE_PARTNER(battler); - if (IsBattlerAlive(i)) - { - SetBattlerShadowSpriteCallback(i, gBattleMons[i].species); - BattleLoadMonSpriteGfx(GetBattlerMon(i), i); - } - } - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF: - { - VARIOUS_ARGS(); - if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN))) - { - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - return; - } - break; - } - case VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON: - { - VARIOUS_ARGS(); - if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_LAST_SWITCHIN))) - { - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - return; - } - break; - } - case VARIOUS_SET_AURORA_VEIL: - { - VARIOUS_ARGS(); - if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_AURORA_VEIL - || !(HasWeatherEffect() && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - } - else - { - gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_AURORA_VEIL; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[GetBattlerSide(battler)].auroraVeilTimer = gBattleTurnCounter + 8; - else - gSideTimers[GetBattlerSide(battler)].auroraVeilTimer = gBattleTurnCounter + 5; - - if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - else - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - } - break; - } - case VARIOUS_TRY_THIRD_TYPE: - { - VARIOUS_ARGS(const u8 *failInstr); - u32 type = GetMoveArgType(gCurrentMove); - if (IS_BATTLER_OF_TYPE(battler, type) || GetActiveGimmick(battler) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[battler].types[2] = type; - PREPARE_TYPE_BUFFER(gBattleTextBuff1, type); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_DESTROY_ABILITY_POPUP: - { - VARIOUS_ARGS(); - DestroyAbilityPopUp(battler); - break; - } - case VARIOUS_TOTEM_BOOST: - { - VARIOUS_ARGS(const u8 *jumpInstr); - battler = gBattlerAttacker; - if (gQueuedStatBoosts[battler].stats == 0) - { - gBattlescriptCurrInstr = cmd->nextInstr; // stats done, exit - } - else - { - for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) - { - if (gQueuedStatBoosts[battler].stats & (1 << i)) - { - if (gQueuedStatBoosts[battler].statChanges[i] <= -1) - SET_STATCHANGER(i + 1, abs(gQueuedStatBoosts[battler].statChanges[i]), TRUE); - else - SET_STATCHANGER(i + 1, gQueuedStatBoosts[battler].statChanges[i], FALSE); - - gQueuedStatBoosts[battler].stats &= ~(1 << i); - gBattleScripting.battler = battler; - gBattlerTarget = battler; - if (gQueuedStatBoosts[battler].stats & 0x80) - { - gQueuedStatBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag - gBattlescriptCurrInstr = BattleScript_TotemFlaredToLife; - } - else - { - gBattlescriptCurrInstr = cmd->jumpInstr; // do boost - } - return; - } - } - gBattlescriptCurrInstr = cmd->nextInstr; // exit if loop failed (failsafe) - } - return; - } - case VARIOUS_MOVEEND_ITEM_EFFECTS: - { - VARIOUS_ARGS(); - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) - return; - break; - } - case VARIOUS_ROOM_SERVICE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(battler)) - { - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_TERRAIN_SEED: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS) - { - enum ItemEffect effect = ITEM_NO_EFFECT; - u16 item = gBattleMons[battler].item; - switch (GetBattlerHoldEffectParam(battler)) - { - case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_MISTY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - } - - if (effect != ITEM_NO_EFFECT) - return; - } - gBattlescriptCurrInstr = cmd->failInstr; - return; - } - case VARIOUS_MAKE_INVISIBLE: - { - VARIOUS_ARGS(); - if (gBattleControllerExecFlags) - break; - - BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_JUMP_IF_TEAM_HEALTHY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if ((IsDoubleBattle()) && IsBattlerAlive(BATTLE_PARTNER(battler))) - { - u8 partner = BATTLE_PARTNER(battler); - if ((gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) - && (gBattleMons[partner].hp == gBattleMons[partner].maxHP && !(gBattleMons[partner].status1 & STATUS1_ANY))) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } - else // single battle - { - if (gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_HEAL_QUARTER_HP: - { - VARIOUS_ARGS(const u8 *failInstr); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - - if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) - gBattlescriptCurrInstr = cmd->failInstr; // fail - else - gBattlescriptCurrInstr = cmd->nextInstr; // can heal - return; - } - case VARIOUS_JUMP_IF_UNDER_200: - { - VARIOUS_ARGS(const u8 *jumpInstr); - // If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail. - if (GetBattlerWeight(gBattlerTarget) < 2000) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SET_SKY_DROP: - { - VARIOUS_ARGS(); - gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR); - /* skyDropTargets holds the information of who is in a particular instance of Sky Drop. - This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if - the target of a Sky Drop faints while in the air.*/ - gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget; - gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker; - - // End any multiturn effects caused by the target except STATUS2_LOCK_CONFUSE - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_MULTIPLETURNS); - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_UPROAR); - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_BIDE); - gDisableStructs[gBattlerTarget].rolloutTimer = 0; - gDisableStructs[gBattlerTarget].furyCutterCounter = 0; - - // End any Follow Me/Rage Powder effects caused by the target - if (gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer != 0 && gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget == gBattlerTarget) - gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 0; - - break; - } - case VARIOUS_CLEAR_SKY_DROP: - { - VARIOUS_ARGS(const u8 *failInstr); - // Check to see if the initial target of this Sky Drop fainted before the 2nd turn of Sky Drop. - // If so, make the move fail. If not, clear all of the statuses and continue the move. - if (gBattleStruct->skyDropTargets[gBattlerAttacker] == SKY_DROP_NO_TARGET) - gBattlescriptCurrInstr = cmd->failInstr; - else - { - gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET; - gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET; - gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); - gBattlescriptCurrInstr = cmd->nextInstr; - } - - // Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted. - if (gBattleMons[gBattlerTarget].status2 & STATUS2_LOCK_CONFUSE) - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; - return; - } - case VARIOUS_SKY_DROP_YAWN: // If the mon that's sleeping due to Yawn was holding a Pokemon in Sky Drop, release the target and clear Sky Drop data. - { - VARIOUS_ARGS(); - if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED)) - { - // Set the target of Sky Drop as gEffectBattler - gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler]; - - // Clear skyDropTargets data - gBattleStruct->skyDropTargets[gBattleStruct->skyDropTargets[gEffectBattler]] = SKY_DROP_NO_TARGET; - gBattleStruct->skyDropTargets[gEffectBattler] = SKY_DROP_NO_TARGET; - - // If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation - if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE && CanBeConfused(gEffectBattler)) - { - gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); - gBattlerAttacker = gEffectBattler; - gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); - gBattlescriptCurrInstr = BattleScript_ThrashConfuses; - return; - } - } - break; - } - case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (BlocksPrankster(gCurrentMove, gBattlerAttacker, battler, TRUE)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER: - { - bool8 shouldNotClear = FALSE; - - for (i = 0; i < gBattlersCount; i++) - { - u32 ability = GetBattlerAbility(i); - if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) - || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) - || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) - && IsBattlerAlive(i)) - shouldNotClear = TRUE; - } - if (gBattleWeather & B_WEATHER_SUN_PRIMAL && !shouldNotClear) - { - gBattleWeather &= ~B_WEATHER_SUN_PRIMAL; - PrepareStringBattle(STRINGID_EXTREMESUNLIGHTFADED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; - } - else if (gBattleWeather & B_WEATHER_RAIN_PRIMAL && !shouldNotClear) - { - gBattleWeather &= ~B_WEATHER_RAIN_PRIMAL; - PrepareStringBattle(STRINGID_HEAVYRAINLIFTED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; - } - else if (gBattleWeather & B_WEATHER_STRONG_WINDS && !shouldNotClear) - { - gBattleWeather &= ~B_WEATHER_STRONG_WINDS; - PrepareStringBattle(STRINGID_STRONGWINDSDISSIPATED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; - } - break; - } - case VARIOUS_TRY_END_NEUTRALIZING_GAS: - { - VARIOUS_ARGS(); - if (gSpecialStatuses[battler].neutralizingGasRemoved) - { - gSpecialStatuses[battler].neutralizingGasRemoved = FALSE; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; - return; - } - break; - } - case VARIOUS_GET_ROTOTILLER_TARGETS: - { - VARIOUS_ARGS(const u8 *failInstr); - // Gets the battlers to be affected by rototiller. If there are none, print 'But it failed!' - { - u32 count = 0; - for (i = 0; i < gBattlersCount; i++) - { - gSpecialStatuses[i].rototillerAffected = FALSE; - if (IsRototillerAffected(i)) - { - gSpecialStatuses[i].rototillerAffected = TRUE; - count++; - } - } - - if (count == 0) - gBattlescriptCurrInstr = cmd->failInstr; // Rototiller fails - else - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (gSpecialStatuses[battler].rototillerAffected) - { - gSpecialStatuses[battler].rototillerAffected = FALSE; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->jumpInstr; // Unaffected by rototiller - print STRINGID_NOEFFECTONTARGET - } - return; - } - case VARIOUS_CONSUME_BERRY: - { - VARIOUS_ARGS(bool8 fromBattler); - if (gBattleScripting.overrideBerryRequirements == 2) - { - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - - if (cmd->fromBattler) - gLastUsedItem = gBattleMons[battler].item; - - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; - gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID - if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) - return; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == gBattleMons[battler].species) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_WEATHER_AFFECTED: - { - VARIOUS_ARGS(u32 flags, const u8 *jumpInstr); - u32 flags = cmd->flags; - if (IsBattlerWeatherAffected(battler, flags)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_SPECIES: - { - VARIOUS_ARGS(u16 species, const u8 *jumpInstr); - if (gBattleMons[battler].species == cmd->species) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsLeafGuardProtected(battler, GetBattlerAbility(battler))) - { - gBattlerAbility = battler; - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_SET_ATTACKER_STICKY_WEB_USER: - { - VARIOUS_ARGS(); - // For Mirror Armor: "If the Pokémon with this Ability is affected by Sticky Web, the effect is reflected back to the Pokémon which set it up. - // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." - gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - if (gSideTimers[GetBattlerSide(battler)].stickyWebBattlerId != 0xFF) - gBattlerAttacker = gSideTimers[GetBattlerSide(battler)].stickyWebBattlerId; - break; - } - case VARIOUS_CUT_1_3_HP_RAISE_STATS: - { - VARIOUS_ARGS(const u8 *failInstr); - - bool8 atLeastOneStatBoosted = FALSE; - u16 hpFraction = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); - - for (i = 1; i < NUM_STATS; i++) - { - if (CompareStat(gBattlerAttacker, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - atLeastOneStatBoosted = TRUE; - break; - } - } - if (atLeastOneStatBoosted && gBattleMons[gBattlerAttacker].hp > hpFraction) - { - gBattleStruct->moveDamage[gBattlerAttacker] = hpFraction; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_CHECK_POLTERGEIST: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gBattleMons[battler].item == ITEM_NONE - || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM - || GetBattlerAbility(battler) == ABILITY_KLUTZ) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[battler].item); - gLastUsedItem = gBattleMons[battler].item; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_NO_RETREAT: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gDisableStructs[battler].noRetreat) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (!(gBattleMons[battler].status2 & STATUS2_ESCAPE_PREVENTION)) - gDisableStructs[battler].noRetreat = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_CURE_CERTAIN_STATUSES: - { - VARIOUS_ARGS(); - // Check infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) - { - gBattleMons[battler].status2 &= ~(STATUS2_INFATUATION); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - } - // Check taunt - if (gDisableStructs[battler].tauntTimer != 0) - { - gDisableStructs[battler].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - } - // Check encore - if (gDisableStructs[battler].encoreTimer != 0) - { - gDisableStructs[battler].encoredMove = 0; - gDisableStructs[battler].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - } - // Check torment - if (gBattleMons[battler].status2 & STATUS2_TORMENT) - { - gBattleMons[battler].status2 &= ~(STATUS2_TORMENT); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; - } - // Check heal block - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) - { - gStatuses3[battler] &= ~(STATUS3_HEAL_BLOCK); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; - } - // Check disable - if (gDisableStructs[battler].disableTimer != 0) - { - gDisableStructs[battler].disableTimer = 0; - gDisableStructs[battler].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; - } - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES: - { - VARIOUS_ARGS(); - battler = gBattlerTarget; - for (i = 0; i < NUM_BATTLE_STATS; i++) - if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetItemPocket(gLastUsedItem) == POCKET_BERRIES) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SAVE_BATTLER_ITEM: - { - VARIOUS_ARGS(); - gBattleHistory->heldItems[battler] = gBattleMons[battler].item; - break; - } - case VARIOUS_RESTORE_BATTLER_ITEM: - { - VARIOUS_ARGS(); - gBattleMons[battler].item = gBattleHistory->heldItems[battler]; - break; - } - case VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM: - { - VARIOUS_ARGS(); - gBattleMons[battler].item = gLastUsedItem; - break; - } - case VARIOUS_GET_BATTLERS_FOR_RECALL: - { - battler = 1; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - for (i = 0; battler < MAX_BATTLERS_COUNT; battler += 2) - { - if (battler < gBattlersCount && gBattleMons[battler].hp != 0) - gBattleCommunication[MULTISTRING_CHOOSER] |= gBitTable[i]; - i++; - } - break; - } - } // End of switch (cmd->id) - gBattlescriptCurrInstr = cmd->nextInstr; } @@ -11398,8 +9532,8 @@ static void TryResetProtectUseCounter(u32 battler) enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove); if (lastMove == MOVE_UNAVAILABLE || (!gBattleMoveEffects[lastEffect].usesProtectCounter - && ((B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) - || B_ALLY_SWITCH_FAIL_CHANCE < GEN_9))) + && ((GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) + || GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) < GEN_9))) gDisableStructs[battler].protectUses = 0; } @@ -11422,7 +9556,7 @@ static void Cmd_setprotectlike(void) { if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) { - gProtectStructs[gBattlerAttacker].endured = TRUE; + gDisableStructs[gBattlerAttacker].endured = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; } else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE) @@ -11492,14 +9626,19 @@ static void Cmd_jumpifnexttargetvalid(void) } if (gBattlerTarget >= gBattlersCount) + { + gBattlerTarget = gBattlersCount - 1; gBattlescriptCurrInstr = cmd->nextInstr; + } else + { gBattlescriptCurrInstr = jumpInstr; + } } static void Cmd_tryhealhalfhealth(void) { - CMD_ARGS(const u8 *failInstr, u8 battler); + CMD_ARGS(u8 battler, const u8 *failInstr); const u8 *failInstr = cmd->failInstr; @@ -11517,59 +9656,8 @@ static void Cmd_tryhealhalfhealth(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void SetMoveForMirrorMove(u32 move) +static void Cmd_unused_0x7e(void) { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - // Edge case, we used Z Mirror Move, got the stat boost and now need to use the Z-move - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCurrentMove = GetTypeBasedZMove(move); - } - else - { - gCurrentMove = move; - } - - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); -} - -static void Cmd_trymirrormove(void) -{ - CMD_ARGS(); - - s32 i, validMovesCount; - u16 move; - u16 validMoves[MAX_BATTLERS_COUNT] = {0}; - - for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) - { - if (i != gBattlerAttacker) - { - move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) - { - validMoves[validMovesCount] = move; - validMovesCount++; - } - } - } - - move = gBattleStruct->lastTakenMove[gBattlerAttacker]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) - { - SetMoveForMirrorMove(move); - } - else if (validMovesCount != 0) - { - SetMoveForMirrorMove(validMoves[Random() % validMovesCount]); - } - else // no valid moves found - { - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_setfieldweather(void) @@ -11624,7 +9712,7 @@ static void Cmd_setseeded(void) { CMD_ARGS(); - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gBattleMons[gBattlerTarget].volatiles.leechSeed) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_MISS; @@ -11636,8 +9724,7 @@ static void Cmd_setseeded(void) } else { - gStatuses3[gBattlerTarget] |= gBattlerAttacker; - gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + gBattleMons[gBattlerTarget].volatiles.leechSeed = LEECHSEEDED_BY(gBattlerAttacker); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_SET; } @@ -11675,21 +9762,18 @@ static void Cmd_manipulatedamage(void) static void Cmd_trysetrest(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - const u8 *failInstr = cmd->failInstr; gBattlerTarget = gBattlerAttacker; gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP * (-1); + enum Ability ability = GetBattlerAbility(gBattlerTarget); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - { - gBattlescriptCurrInstr = failInstr; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; } @@ -11707,31 +9791,12 @@ static void Cmd_trysetrest(void) } } -static void Cmd_jumpifnotfirstturn(void) +static void Cmd_unused_0x82(void) { - CMD_ARGS(const u8 *jumpInstr); - - const u8 *jumpInstr = cmd->jumpInstr; - - if (gDisableStructs[gBattlerAttacker].isFirstTurn && !(gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = jumpInstr; } -static void Cmd_setmiracleeye(void) +static void Cmd_unused_0x83(void) { - CMD_ARGS(const u8 *failInstr); - - if (!(gStatuses3[gBattlerTarget] & STATUS3_MIRACLE_EYED)) - { - gStatuses3[gBattlerTarget] |= STATUS3_MIRACLE_EYED; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } } bool8 UproarWakeUpCheck(u8 battler) @@ -11741,7 +9806,7 @@ bool8 UproarWakeUpCheck(u8 battler) for (i = 0; i < gBattlersCount; i++) { - if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || hasSoundproof) + if (!(gBattleMons[i].volatiles.uproarTurns) || hasSoundproof) continue; gBattleScripting.battler = i; @@ -11779,19 +9844,10 @@ static void Cmd_stockpile(void) switch (cmd->id) { case 0: - if (gDisableStructs[gBattlerAttacker].stockpileCounter >= 3) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_STOCKPILE; - } - else - { - gDisableStructs[gBattlerAttacker].stockpileCounter++; - gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; - gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STOCKPILED; - } + gDisableStructs[gBattlerAttacker].stockpileCounter++; + gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; + gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); break; case 1: // Save def/sp def stats. if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) @@ -11807,20 +9863,12 @@ static void Cmd_stockpile(void) static void Cmd_stockpiletobasedamage(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - const u8 *failInstr = cmd->failInstr; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) - { - gBattlescriptCurrInstr = failInstr; - } - else - { - if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; + if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_stockpiletohpheal(void) @@ -11829,40 +9877,31 @@ static void Cmd_stockpiletohpheal(void) const u8 *failInstr = cmd->failInstr; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) + if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) { + gDisableStructs[gBattlerAttacker].stockpileCounter = 0; gBattlescriptCurrInstr = failInstr; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FAILED; + gBattlerTarget = gBattlerAttacker; } else { - if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) + if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) { - gDisableStructs[gBattlerAttacker].stockpileCounter = 0; - gBattlescriptCurrInstr = failInstr; - gBattlerTarget = gBattlerAttacker; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FULL_HP; + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter)); + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; } - else + else // Snatched move { - if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter)); - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - } - else // Snatched move - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - gBattleScripting.animTurn = 1; - } - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - - gBattlescriptCurrInstr = cmd->nextInstr; - gBattlerTarget = gBattlerAttacker; + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + gBattleScripting.animTurn = 1; } + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + + gBattlescriptCurrInstr = cmd->nextInstr; + gBattlerTarget = gBattlerAttacker; } } @@ -11870,7 +9909,7 @@ void BS_RemoveStockpileCounters(void) { NATIVE_ARGS(); - if (GetMoveEffect(gCurrentMove) == EFFECT_SWALLOW + if (GetMoveEffect(gCurrentMove) == EFFECT_SPIT_UP && gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) { @@ -11965,7 +10004,7 @@ static u16 ReverseStatChangeMoveEffect(u16 moveEffect) } } -static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 statValue, u32 statId, bool32 certain) +static void TryPlayStatChangeAnimation(u32 battler, enum Ability ability, u32 stats, s32 statValue, u32 statId, bool32 certain) { u32 currStat = 0; u32 changeableStatsCount = 1; // current stat is counted automatically @@ -11992,7 +10031,7 @@ static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 } } else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC) - && !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) + && !(GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) && !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK) && !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF)) { @@ -12058,7 +10097,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan u32 index, battlerAbility; enum ItemHoldEffect battlerHoldEffect; battlerAbility = GetBattlerAbility(battler); - battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); + battlerHoldEffect = GetBattlerHoldEffect(battler); gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker; if (battlerAbility == ABILITY_CONTRARY) @@ -12161,7 +10200,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan } else if (!flags.certain && (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC) - || (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) + || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK) || (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF))) { @@ -12196,37 +10235,32 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statValue = -1; else if (gBattleMons[battler].statStages[statId] == 2 && statValue < -2) statValue = -2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; + if (statValue == -2) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATHARSHLY; - gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATHARSHLY); } else if (statValue <= -3) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_SEVERELY & 0xFF; - gBattleTextBuff2[3] = STRINGID_SEVERELY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_SEVERELY); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_EMPTYSTRING3); } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATFELL; - gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_CHANGED or B_MSG_DEFENDER_STAT_CHANGED if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_CHANGE; + gBattleScripting.statChanger |= STAT_BUFF_NEGATIVE; } else if (!flags.onlyChecking) { - gProtectStructs[battler].tryEjectPack = TRUE; + gDisableStructs[battler].tryEjectPack = TRUE; gProtectStructs[battler].lashOutAffected = TRUE; + gBattleScripting.statChanger |= STAT_BUFF_NEGATIVE; } } } @@ -12237,32 +10271,26 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statValue = 1; else if (gBattleMons[battler].statStages[statId] == 10 && statValue > 2) statValue = 2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; + if (statValue == 2) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATSHARPLY; - gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATSHARPLY); } else if (statValue >= 3) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_DRASTICALLY & 0xFF; - gBattleTextBuff2[3] = STRINGID_DRASTICALLY >> 8; - index = 4; + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_DRASTICALLY); + } + else + { + PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_EMPTYSTRING3); } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATROSE; - gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_CHANGED or B_MSG_DEFENDER_STAT_CHANGED if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE) { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_CHANGE; + gBattleScripting.statChanger &= ~STAT_BUFF_NEGATIVE; } else if (!flags.onlyChecking) { @@ -12273,6 +10301,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan statIncrease = statValue; gProtectStructs[battler].statRaised = TRUE; + gBattleScripting.statChanger &= ~STAT_BUFF_NEGATIVE; if (statIncrease) { @@ -12287,7 +10316,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan { gProtectStructs[index].activateOpportunist = 2; // set stats to copy } - if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB) + if (GetBattlerHoldEffect(index) == HOLD_EFFECT_MIRROR_HERB) { gProtectStructs[index].eatMirrorHerb = 1; } @@ -12302,7 +10331,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan } } - if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE) // same as B_MSG_STAT_WONT_DECREASE + if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_CHANGE) // at max or min { if (!flags.allowPtr) return STAT_CHANGE_DIDNT_WORK; @@ -12385,10 +10414,10 @@ static void Cmd_setbide(void) { CMD_ARGS(); - gBattleMons[gBattlerAttacker].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; gLockedMoves[gBattlerAttacker] = gCurrentMove; gBideDmg[gBattlerAttacker] = 0; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_BIDE_TURN(2); + gBattleMons[gBattlerAttacker].volatiles.bideTurns = 2; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12409,12 +10438,13 @@ static void Cmd_trynonvolatilestatus(void) CMD_ARGS(); bool32 canInflictStatus = TRUE; - if (!CanSetNonVolatileStatus(gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - GetBattlerAbility(gBattlerTarget), - GetMoveNonVolatileStatus(gCurrentMove), - STATUS_RUN_SCRIPT)) + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + GetMoveNonVolatileStatus(gCurrentMove), + RUN_SCRIPT)) canInflictStatus = FALSE; if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) @@ -12752,6 +10782,11 @@ static void Cmd_setlightscreen(void) gBattlescriptCurrInstr = cmd->nextInstr; } +// for var lands +#define NO_HIT 0 +#define CALC_ACC 1 +#define SURE_HIT 2 +// for var endured #define NOT_ENDURED 0 #define FOCUS_SASHED 1 #define FOCUS_BANDED 2 @@ -12760,10 +10795,9 @@ static void Cmd_tryKO(void) { CMD_ARGS(const u8 *failInstr); - bool32 lands = FALSE; enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE); - u16 targetAbility = GetBattlerAbility(gBattlerTarget); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); + enum Ability targetAbility = GetBattlerAbility(gBattlerTarget); u32 rand = Random() % 100; u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); u32 endured = NOT_ENDURED; @@ -12806,26 +10840,30 @@ static void Cmd_tryKO(void) } else { - if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level - && ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS - && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) - || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) - || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))) - { - lands = TRUE; - } - else + u32 lands = NO_HIT; + if (gBattleMons[gBattlerTarget].level > gBattleMons[gBattlerAttacker].level) + lands = NO_HIT; + else if ((gBattleMons[gBattlerTarget].volatiles.lockOn && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) + || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) + || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD)) + lands = SURE_HIT; + else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) + lands = NO_HIT; + else if (!JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, cmd->failInstr)) + lands = CALC_ACC; + + if (lands == CALC_ACC) { u16 odds = GetMoveAccuracy(gCurrentMove) + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level); if (B_SHEER_COLD_ACC >= GEN_7 && effect == EFFECT_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) odds -= 10; if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) - lands = TRUE; + lands = SURE_HIT; } - if (lands) + if (lands == SURE_HIT) { - if (gProtectStructs[gBattlerTarget].endured) + if (gDisableStructs[gBattlerTarget].endured) { gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED; @@ -12859,13 +10897,30 @@ static void Cmd_tryKO(void) } } } +#undef NO_HIT +#undef CALC_ACC +#undef SURE_HIT #undef NOT_ENDURED #undef FOCUS_SASHED #undef FOCUS_BANDED #undef AFFECTION_ENDURED -static void Cmd_unused_0x94(void) +static void Cmd_checknonvolatiletrigger(void) { + CMD_ARGS(u16 nonVolatile, const u8 *failInstr); + + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + cmd->nonVolatile, + CHECK_TRIGGER)) + gBattlescriptCurrInstr = cmd->failInstr; + else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_copybidedmg(void) @@ -12875,8 +10930,12 @@ static void Cmd_copybidedmg(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_unused_96(void) +static void Cmd_animatewildpokemonafterfailedpokeball(void) { + CMD_ARGS(u8 battler); + u8 battler = GetBattlerForBattleScript(cmd->battler); + AnimateMonAfterPokeBallFail(battler); + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_tryinfatuating(void) @@ -12891,14 +10950,14 @@ static void Cmd_tryinfatuating(void) } else { - if (gBattleMons[gBattlerTarget].status2 & STATUS2_INFATUATION + if (gBattleMons[gBattlerTarget].volatiles.infatuation || !AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_INFATUATED_WITH(gBattlerAttacker); + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12918,7 +10977,7 @@ static void Cmd_updatestatusicon(void) { if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } } @@ -12929,7 +10988,7 @@ static void Cmd_updatestatusicon(void) battler = gBattlerAttacker; if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } if ((IsDoubleBattle())) @@ -12937,7 +10996,7 @@ static void Cmd_updatestatusicon(void) battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } } @@ -12946,7 +11005,7 @@ static void Cmd_updatestatusicon(void) else { battler = GetBattlerForBattleScript(cmd->battler); - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12977,22 +11036,22 @@ static void Cmd_setfocusenergy(void) enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); if ((effect == EFFECT_DRAGON_CHEER && (!(IsDoubleBattle()) || (gAbsentBattlerFlags & (1u << battler)))) - || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + || gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED; } else if (effect == EFFECT_DRAGON_CHEER && !IS_BATTLER_OF_TYPE(battler, TYPE_DRAGON)) { - gBattleMons[battler].status2 |= STATUS2_DRAGON_CHEER; + gBattleMons[battler].volatiles.dragonCheer = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } else { if (GetGenConfig(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3) - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; else - gBattleMons[battler].status2 |= STATUS2_DRAGON_CHEER; + gBattleMons[battler].volatiles.dragonCheer = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -13004,9 +11063,9 @@ static void Cmd_transformdataexecution(void) gChosenMove = MOVE_UNAVAILABLE; gBattlescriptCurrInstr = cmd->nextInstr; - if (gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED + if (gBattleMons[gBattlerTarget].volatiles.transformed || gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER) + || IsSemiInvulnerable(gBattlerTarget, EXCLUDE_COMMANDER)) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORM_FAILED; @@ -13017,7 +11076,7 @@ static void Cmd_transformdataexecution(void) u8 *battleMonAttacker, *battleMonTarget; u8 timesGotHit; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_TRANSFORMED; + gBattleMons[gBattlerAttacker].volatiles.transformed = TRUE; gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; @@ -13025,8 +11084,8 @@ static void Cmd_transformdataexecution(void) gDisableStructs[gBattlerAttacker].mimickedMoves = 0; gDisableStructs[gBattlerAttacker].usedMoves = 0; - timesGotHit = gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]; - gBattleStruct->timesGotHit[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = timesGotHit; + timesGotHit = GetBattlerPartyState(gBattlerTarget)->timesGotHit; + GetBattlerPartyState(gBattlerAttacker)->timesGotHit = timesGotHit; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].species) @@ -13082,8 +11141,8 @@ static void Cmd_setsubstitute(void) if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_SUBSTITUTE; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED; + gBattleMons[gBattlerAttacker].volatiles.substitute = TRUE; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; if (factor == 2) gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker] / 2; else @@ -13100,7 +11159,7 @@ static void Cmd_mimicattackcopy(void) CMD_ARGS(const u8 *failInstr); if ((IsMoveMimicBanned(gLastMoves[gBattlerTarget])) - || (gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED) + || (gBattleMons[gBattlerAttacker].volatiles.transformed) || gLastMoves[gBattlerTarget] == MOVE_NONE || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) { @@ -13138,41 +11197,11 @@ static void Cmd_mimicattackcopy(void) } } -static bool32 InvalidMetronomeMove(u32 move) -{ - return GetMoveEffect(move) == EFFECT_PLACEHOLDER - || IsMoveMetronomeBanned(move); -} - -static void Cmd_metronome(void) +static void Cmd_setcalledmove(void) { CMD_ARGS(); - -#if B_METRONOME_MOVES >= GEN_9 - u32 moveCount = MOVES_COUNT_GEN9; -#elif B_METRONOME_MOVES >= GEN_8 - u32 moveCount = MOVES_COUNT_GEN8; -#elif B_METRONOME_MOVES >= GEN_7 - u32 moveCount = MOVES_COUNT_GEN7; -#elif B_METRONOME_MOVES >= GEN_6 - u32 moveCount = MOVES_COUNT_GEN6; -#elif B_METRONOME_MOVES >= GEN_5 - u32 moveCount = MOVES_COUNT_GEN5; -#elif B_METRONOME_MOVES >= GEN_4 - u32 moveCount = MOVES_COUNT_GEN4; -#elif B_METRONOME_MOVES >= GEN_3 - u32 moveCount = MOVES_COUNT_GEN3; -#elif B_METRONOME_MOVES >= GEN_2 - u32 moveCount = MOVES_COUNT_GEN2; -#else - u32 moveCount = MOVES_COUNT_GEN1; -#endif - - gCurrentMove = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); - PrepareStringBattle(STRINGID_WAGGLINGAFINGER, gBattlerAttacker); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); + gCurrentMove = gCalledMove; + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_0x9f(void) @@ -13194,13 +11223,12 @@ static void Cmd_counterdamagecalculator(void) && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13221,13 +11249,13 @@ static void Cmd_mirrorcoatdamagecalculator(void) && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13303,7 +11331,7 @@ static void Cmd_trysetencore(void) gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; gDisableStructs[gBattlerTarget].encoredMovePos = i; // Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn. - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + if (HasBattlerActedThisTurn(gBattlerTarget)) gDisableStructs[gBattlerTarget].encoreTimer = 4; else gDisableStructs[gBattlerTarget].encoreTimer = 3; @@ -13349,7 +11377,7 @@ static void Cmd_settypetorandomresistance(void) gBattlescriptCurrInstr = cmd->failInstr; } else if (gBattleMoveEffects[GetMoveEffect(gLastLandedMoves[gBattlerAttacker])].twoTurnEffect - && gBattleMons[gLastHitBy[gBattlerAttacker]].status2 & STATUS2_MULTIPLETURNS) + && gBattleMons[gLastHitBy[gBattlerAttacker]].volatiles.multipleTurns) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13407,7 +11435,7 @@ static void Cmd_settypetorandomresistance(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove)) + else if (!BreaksThroughSemiInvulnerablity(gBattlerTarget, gCurrentMove)) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13461,9 +11489,7 @@ static void Cmd_settypetorandomresistance(void) static void Cmd_setalwayshitflag(void) { CMD_ARGS(); - - gStatuses3[gBattlerTarget] &= ~STATUS3_ALWAYS_HITS; - gStatuses3[gBattlerTarget] |= STATUS3_ALWAYS_HITS_TURN(2); + gBattleMons[gBattlerTarget].volatiles.lockOn = 2; gDisableStructs[gBattlerTarget].battlerWithSureHit = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -13475,7 +11501,7 @@ static void Cmd_copymovepermanently(void) gChosenMove = MOVE_UNAVAILABLE; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED) + if (!(gBattleMons[gBattlerAttacker].volatiles.transformed) && gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE && !IsMoveSketchBanned(gLastPrintedMoves[gBattlerTarget])) { @@ -13521,49 +11547,8 @@ static void Cmd_copymovepermanently(void) } } -static void Cmd_trychoosesleeptalkmove(void) +static void Cmd_unused_0xA9(void) { - CMD_ARGS(const u8 *failInstr); - - u32 i, unusableMovesBits = 0, movePosition; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) - || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) - { - unusableMovesBits |= (1 << (i)); - } - } - - unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); - if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - else // at least one move can be chosen - { - // Set Sleep Talk as used move, so it works with Last Resort. - gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; - do - { - movePosition = MOD(Random(), MAX_MON_MOVES); - } while ((1u << movePosition) & unusableMovesBits); - - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gBattleMons[gBattlerAttacker].moves[movePosition])) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gBattleMons[gBattlerAttacker].moves[movePosition]; - gCalledMove = GetTypeBasedZMove(gBattleMons[gBattlerAttacker].moves[movePosition]); - } - else - { - gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition]; - } - gCurrMovePos = movePosition; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->failInstr; - } } static inline bool32 IsDanamaxMonPresent(void) @@ -13580,28 +11565,13 @@ static inline bool32 IsDanamaxMonPresent(void) return FALSE; } -static void Cmd_trysetdestinybond(void) +static void Cmd_unused_AA(void) { - CMD_ARGS(const u8 *failInstr); - - if (IsDanamaxMonPresent()) - { - gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; - } - else if (DoesDestinyBondFail(gBattlerAttacker)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND; - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void TrySetDestinyBondToHappen(void) { - if (gBattleMons[gBattlerTarget].status2 & STATUS2_DESTINY_BOND + if (gBattleMons[gBattlerTarget].volatiles.destinyBond && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && !(gHitMarker & HITMARKER_GRUDGE)) { @@ -13682,7 +11652,7 @@ static void Cmd_tryspiteppreduce(void) // if (MOVE_IS_PERMANENT(gBattlerTarget, i)), but backwards if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) - && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[gBattlerTarget].volatiles.transformed)) { BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); MarkBattlerForControllerExec(gBattlerTarget); @@ -13725,7 +11695,7 @@ static void Cmd_healpartystatus(void) else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA; gBattleMons[gBattlerAttacker].status1 = 0; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; } else { @@ -13741,7 +11711,7 @@ static void Cmd_healpartystatus(void) || !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF)) { gBattleMons[partner].status1 = 0; - gBattleMons[partner].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[partner].volatiles.nightmare = FALSE; } else { @@ -13759,7 +11729,7 @@ static void Cmd_healpartystatus(void) if (species != SPECIES_NONE && species != SPECIES_EGG) { - u16 ability; + enum Ability ability; bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i; bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner); @@ -13806,13 +11776,13 @@ static void Cmd_cursetarget(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_CURSED) + if (gBattleMons[gBattlerTarget].volatiles.cursed) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_CURSED; + gBattleMons[gBattlerTarget].volatiles.cursed = TRUE; gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) gBattleStruct->moveDamage[gBattlerAttacker] = 1; @@ -13833,17 +11803,18 @@ static void Cmd_trysetspikes(void) } else { - gSideStatuses[targetSide] |= SIDE_STATUS_SPIKES; + if (gSideTimers[targetSide].spikesAmount == 0) // Add only once to the queue + PushHazardTypeToQueue(targetSide, HAZARDS_SPIKES); gSideTimers[targetSide].spikesAmount++; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setforesight(void) +static void Cmd_setvolatile(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler, u8 _volatile, u8 value); - gBattleMons[gBattlerTarget].status2 |= STATUS2_FORESIGHT; + SetMonVolatile(GetBattlerForBattleScript(cmd->battler), cmd->_volatile, cmd->value); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -13856,16 +11827,16 @@ static void Cmd_trysetperishsong(void) for (i = 0; i < gBattlersCount; i++) { - if (gStatuses3[i] & STATUS3_PERISH_SONG + if (gBattleMons[i].volatiles.perishSong || GetBattlerAbility(i) == ABILITY_SOUNDPROOF || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE) - || gStatuses3[i] & STATUS3_COMMANDER) + || gBattleMons[i].volatiles.semiInvulnerable == STATE_COMMANDER) { notAffectedCount++; } else { - gStatuses3[i] |= STATUS3_PERISH_SONG; + gBattleMons[i].volatiles.perishSong = TRUE; gDisableStructs[i].perishSongTimer = 3; } } @@ -13887,16 +11858,16 @@ static void Cmd_handlerollout(void) } else { - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) // First hit. + if (!(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) // First hit. { gDisableStructs[gBattlerAttacker].rolloutTimer = 5; gDisableStructs[gBattlerAttacker].rolloutTimerStartValue = 5; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; gLockedMoves[gBattlerAttacker] = gCurrentMove; } if (--gDisableStructs[gBattlerAttacker].rolloutTimer == 0) // Last hit. { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -13907,7 +11878,7 @@ static void Cmd_jumpifconfusedandstatmaxed(void) { CMD_ARGS(u8 stat, const u8 *jumpInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION + if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0 && !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN)) gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised else @@ -13946,13 +11917,13 @@ static void Cmd_setembargo(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_EMBARGO) + if (gBattleMons[gBattlerTarget].volatiles.embargo) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_EMBARGO; + gBattleMons[gBattlerTarget].volatiles.embargo = TRUE; gDisableStructs[gBattlerTarget].embargoTimer = gBattleTurnCounter + 5; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -13962,7 +11933,7 @@ static void Cmd_presentdamagecalculation(void) { CMD_ARGS(); - u32 rand = Random() & 0xFF; + u32 rand = RandomUniform(RNG_PRESENT, 0, 0xFF); /* Don't reroll present effect/power for the second hit of Parental Bond. * Not sure if this is the correct behaviour, but bulbapedia states @@ -14033,7 +12004,7 @@ static void Cmd_magnitudedamagecalculation(void) { CMD_ARGS(); - u32 magnitude = Random() % 100; + u32 magnitude = RandomUniform(RNG_MAGNITUDE, 0, 99); if (magnitude < 5) { @@ -14130,8 +12101,9 @@ static void Cmd_jumpifnopursuitswitchdmg(void) static void Cmd_tryrestorehpberry(void) { - CMD_ARGS(); - if (TryRestoreHPBerries(gBattlerAttacker, ITEMEFFECT_TRY_HEALING)) + CMD_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (TryRestoreHPBerries(battler, ITEMEFFECT_TRY_HEALING)) return; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -14163,7 +12135,7 @@ static void Cmd_halvehp(void) // Psych Up static void Cmd_copyfoestats(void) { - CMD_ARGS(const u8 *unused); + CMD_ARGS(); s32 i; @@ -14171,8 +12143,9 @@ static void Cmd_copyfoestats(void) { gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i]; } + gBattleScripting.battler = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; // Has an unused jump ptr(possibly for a failed attempt) parameter. + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_rapidspinfree(void) @@ -14181,49 +12154,31 @@ static void Cmd_rapidspinfree(void) u8 atkSide = GetBattlerSide(gBattlerAttacker); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_WRAPPED) + if (gBattleMons[gBattlerAttacker].volatiles.wrapped) { gBattleScripting.battler = gBattlerTarget; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker]; PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); BattleScriptCall(BattleScript_WrapFree); } - else if (gStatuses3[gBattlerAttacker] & STATUS3_LEECHSEED) + else if (gBattleMons[gBattlerAttacker].volatiles.leechSeed) { - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED; - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED_BATTLER; + gBattleMons[gBattlerAttacker].volatiles.leechSeed = 0; BattleScriptCall(BattleScript_LeechSeedFree); } - else if (gSideStatuses[atkSide] & SIDE_STATUS_SPIKES) + else if (AreAnyHazardsOnSide(atkSide)) { - gSideStatuses[atkSide] &= ~SIDE_STATUS_SPIKES; - gSideTimers[atkSide].spikesAmount = 0; - BattleScriptCall(BattleScript_SpikesFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_TOXIC_SPIKES) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_TOXIC_SPIKES; - gSideTimers[atkSide].toxicSpikesAmount = 0; - BattleScriptCall(BattleScript_ToxicSpikesFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STICKY_WEB) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STICKY_WEB; - gSideTimers[atkSide].stickyWebAmount = 0; - BattleScriptCall(BattleScript_StickyWebFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STEALTH_ROCK) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STEALTH_ROCK; - gSideTimers[atkSide].stealthRockAmount = 0; - BattleScriptCall(BattleScript_StealthRockFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STEELSURGE) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STEELSURGE; - gSideTimers[atkSide].steelsurgeAmount = 0; - BattleScriptCall(BattleScript_SteelsurgeFree); + for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) + { + if (IsHazardOnSideAndClear(atkSide, hazardType)) + { + gBattleStruct->numHazards[atkSide]--; + gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; + BattleScriptCall(BattleScript_SpinHazardsAway); + return; + } + } } else { @@ -14231,12 +12186,8 @@ static void Cmd_rapidspinfree(void) } } -static void Cmd_setdefensecurlbit(void) +static void Cmd_unused_0xBF(void) { - CMD_ARGS(); - - gBattleMons[gBattlerAttacker].status2 |= STATUS2_DEFENSE_CURL; - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_recoverbasedonsunlight(void) @@ -14255,7 +12206,7 @@ static void Cmd_recoverbasedonsunlight(void) } else if (GetGenConfig(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2) { - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA) gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; else if (gBattleWeather & B_WEATHER_SUN) gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; @@ -14266,7 +12217,7 @@ static void Cmd_recoverbasedonsunlight(void) { u32 healingModifier = 1; u32 time = GetTimeOfDay(); - + switch (GetMoveEffect(gCurrentMove)) { case EFFECT_MOONLIGHT: @@ -14286,14 +12237,14 @@ static void Cmd_recoverbasedonsunlight(void) healingModifier = 1; break; } - - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_UTILITY_UMBRELLA) gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4; else if (gBattleWeather & B_WEATHER_SUN) gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2; else // not sunny weather gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - + } if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -14314,16 +12265,15 @@ static void Cmd_setstickyweb(void) u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STICKY_WEB) + if (IsHazardOnSide(targetSide, HAZARDS_STICKY_WEB)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; + PushHazardTypeToQueue(targetSide, HAZARDS_STICKY_WEB); gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side - gSideTimers[targetSide].stickyWebAmount = 1; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14339,42 +12289,31 @@ static void Cmd_selectfirstvalidtarget(void) if (IsBattlerAlive(gBattlerTarget)) break; } + if (gBattlerTarget >= gBattlersCount) + gBattlerTarget = 0; gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trysetfutureattack(void) +static void Cmd_setfutureattack(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - if (gWishFutureKnock.futureSightCounter[gBattlerTarget] > gBattleTurnCounter) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + gSideStatuses[GetBattlerSide(gBattlerTarget)] |= SIDE_STATUS_FUTUREATTACK; + gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; + gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; + gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; + gWishFutureKnock.futureSightCounter[gBattlerTarget] = gBattleTurnCounter + 3; + + if (gCurrentMove == MOVE_DOOM_DESIRE) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; else - { - gSideStatuses[GetBattlerSide(gBattlerTarget)] |= SIDE_STATUS_FUTUREATTACK; - gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; - gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; - gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; - gWishFutureKnock.futureSightCounter[gBattlerTarget] = gBattleTurnCounter + 3; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; - if (gCurrentMove == MOVE_DOOM_DESIRE) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; - - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_trydobeatup(void) { -#if B_BEAT_UP >= GEN_5 - CMD_ARGS(); - - gBattleStruct->beatUpSlot++; - gBattlescriptCurrInstr = cmd->nextInstr; -#else CMD_ARGS(const u8 *endInstr, const u8 *failInstr); struct Pokemon *party = GetBattlerParty(gBattlerAttacker); @@ -14419,7 +12358,6 @@ static void Cmd_trydobeatup(void) gBattlescriptCurrInstr = cmd->failInstr; } } -#endif } static void Cmd_setsemiinvulnerablebit(void) @@ -14430,9 +12368,9 @@ static void Cmd_setsemiinvulnerablebit(void) { u32 semiInvulnerableEffect = GetMoveTwoTurnAttackStatus(gCurrentMove); if (cmd->clear) - gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE; else - gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = semiInvulnerableEffect; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -14471,14 +12409,8 @@ static void Cmd_tryfiretwoturnmovenowbyeffect(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setminimize(void) +static void Cmd_unused_0xC7(void) { - CMD_ARGS(); - - if (gHitMarker & HITMARKER_OBEYS) - gStatuses3[gBattlerAttacker] |= STATUS3_MINIMIZED; - - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_c8(void) @@ -14491,7 +12423,7 @@ static void Cmd_trymemento(void) if (B_MEMENTO_FAIL >= GEN_4 && (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE + || IsSemiInvulnerable(gBattlerTarget, CHECK_ALL) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) { @@ -14532,7 +12464,7 @@ static void Cmd_setcharge(void) CMD_ARGS(u8 battler); u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses3[battler] |= STATUS3_CHARGED_UP; + gBattleMons[battler].volatiles.charge = TRUE; if (B_CHARGE < GEN_9) gDisableStructs[battler].chargeTimer = 2; else @@ -14540,39 +12472,8 @@ static void Cmd_setcharge(void) gBattlescriptCurrInstr = cmd->nextInstr; } -// Nature Power -static void Cmd_callenvironmentattack(void) +static void Cmd_unused_0xCC(void) { - CMD_ARGS(); - - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCurrentMove = GetNaturePowerMove(gBattlerAttacker); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - BattleScriptPush(GetMoveBattleScript(gCurrentMove)); - gBattlescriptCurrInstr = cmd->nextInstr; -} - -u32 GetNaturePowerMove(u32 battler) -{ - u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; - if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) - move = MOVE_MOONBLAST; - else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - move = MOVE_THUNDERBOLT; - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) - move = MOVE_ENERGY_BALL; - else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - move = MOVE_PSYCHIC; - else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) - move = MOVE_TRI_ATTACK; - - if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - move = GetTypeBasedZMove(move); - } - - return move; } static void Cmd_curestatuswithmove(void) @@ -14581,7 +12482,7 @@ static void Cmd_curestatuswithmove(void) u32 shouldHeal; if (GetMoveEffect(gCurrentMove) == EFFECT_REFRESH) - shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_REFRESH; + shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_CAN_MOVE; else // Take Heart shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; @@ -14605,14 +12506,14 @@ static void Cmd_settorment(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT + if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_TORMENT; + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14643,7 +12544,7 @@ static void Cmd_settaunt(void) if (B_TAUNT_TURNS >= GEN_5) { turns = 4; - if (GetBattlerTurnOrderNum(gBattlerTarget) > GetBattlerTurnOrderNum(gBattlerAttacker)) + if (!HasBattlerActedThisTurn(gBattlerTarget)) turns--; // If the target hasn't yet moved this turn, Taunt lasts for only three turns (source: Bulbapedia) } else if (B_TAUNT_TURNS >= GEN_4) @@ -14672,10 +12573,9 @@ static void Cmd_trysethelpinghand(void) if (IsDoubleBattle() && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) - && !gProtectStructs[gBattlerAttacker].helpingHand - && !gProtectStructs[gBattlerTarget].helpingHand) + && !HasBattlerActedThisTurn(gBattlerTarget)) { - gProtectStructs[gBattlerTarget].helpingHand = TRUE; + gProtectStructs[gBattlerTarget].helpingHand++; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -14793,24 +12693,43 @@ static void Cmd_tryswapitems(void) } } +static bool32 CanAbilityShieldActivateForBattler(u32 battler) +{ + if (GetBattlerHoldEffectIgnoreAbility(battler) != HOLD_EFFECT_ABILITY_SHIELD) + return FALSE; + + RecordItemEffectBattle(battler, HOLD_EFFECT_ABILITY_SHIELD); + gBattlerAbility = battler; + gLastUsedItem = gBattleMons[battler].item; + return TRUE; +} + // Role Play, Doodle static void Cmd_trycopyability(void) { CMD_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - u16 defAbility = gBattleMons[gBattlerTarget].ability; + u32 partner = BATTLE_PARTNER(battler); + enum Ability defAbility = gBattleMons[gBattlerTarget].ability; + bool32 shouldConsiderPartner = IsBattlerAlive(partner) && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE; if (gBattleMons[battler].ability == defAbility || defAbility == ABILITY_NONE || gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed - || (IsBattlerAlive(BATTLE_PARTNER(battler)) && gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE) + || (shouldConsiderPartner && gAbilitiesInfo[gBattleMons[partner].ability].cantBeSuppressed) || gAbilitiesInfo[defAbility].cantBeCopied) { gBattlescriptCurrInstr = cmd->failInstr; } + else if (CanAbilityShieldActivateForBattler(battler) || (shouldConsiderPartner && CanAbilityShieldActivateForBattler(partner))) + { + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); + } else { + RemoveAbilityFlags(battler); gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = defAbility; gLastUsedAbility = defAbility; @@ -14822,7 +12741,7 @@ static void Cmd_trywish(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + if (gBattleMons[gBattlerTarget].volatiles.healBlock) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -14849,8 +12768,9 @@ static void Cmd_settoxicspikes(void) } else { + if (gSideTimers[targetSide].toxicSpikesAmount == 0) + PushHazardTypeToQueue(targetSide, HAZARDS_TOXIC_SPIKES); gSideTimers[targetSide].toxicSpikesAmount++; - gSideStatuses[targetSide] |= SIDE_STATUS_TOXIC_SPIKES; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14863,12 +12783,17 @@ static void Cmd_setgastroacid(void) { gBattlescriptCurrInstr = cmd->failInstr; } + else if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget) == HOLD_EFFECT_ABILITY_SHIELD) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + gBattlescriptCurrInstr = cmd->failInstr; + } else { if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; + gBattleMons[gBattlerTarget].volatiles.gastroAcid = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14876,19 +12801,21 @@ static void Cmd_setgastroacid(void) static void Cmd_setyawn(void) { CMD_ARGS(const u8 *failInstr); + enum Ability ability = GetBattlerAbility(gBattlerTarget); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget); - if (gStatuses3[gBattlerTarget] & STATUS3_YAWN + if (gBattleMons[gBattlerTarget].volatiles.yawn || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_ELECTRIC_TERRAIN)) { // When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: // "But it failed" will display first. gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(gBattlerTarget, ability, holdEffect, STATUS_FIELD_MISTY_TERRAIN)) { // When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: // "But it failed" will display first. @@ -14896,7 +12823,7 @@ static void Cmd_setyawn(void) } else { - gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); + gBattleMons[gBattlerTarget].volatiles.yawn = 2; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14964,10 +12891,10 @@ static void Cmd_tryswapabilities(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerAttacker) || CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { @@ -14980,6 +12907,8 @@ static void Cmd_tryswapabilities(void) if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + RemoveAbilityFlags(gBattlerTarget); + RemoveAbilityFlags(gBattlerAttacker); gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gLastUsedAbility; @@ -14992,13 +12921,13 @@ static void Cmd_tryimprison(void) { CMD_ARGS(const u8 *failInstr); - if ((gStatuses3[gBattlerAttacker] & STATUS3_IMPRISONED_OTHERS)) + if (gBattleMons[gBattlerAttacker].volatiles.imprison) { gBattlescriptCurrInstr = cmd->failInstr; } else if (B_IMPRISON >= GEN_5) { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattleMons[gBattlerAttacker].volatiles.imprison = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -15024,7 +12953,7 @@ static void Cmd_tryimprison(void) } if (attackerMoveId != MAX_MON_MOVES) { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattleMons[gBattlerAttacker].volatiles.imprison = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; break; } @@ -15040,86 +12969,47 @@ static void Cmd_setstealthrock(void) CMD_ARGS(const u8 *failInstr); u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STEALTH_ROCK) + if (IsHazardOnSide(targetSide, HAZARDS_STEALTH_ROCK)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STEALTH_ROCK; - gSideTimers[targetSide].stealthRockAmount = 1; + PushHazardTypeToQueue(targetSide, HAZARDS_STEALTH_ROCK); gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setuserstatus3(void) +static void Cmd_trysetvolatile(void) { - CMD_ARGS(u32 flags, const u8 *failInstr); + CMD_ARGS(u8 battler, u8 _volatile, const u8 *failInstr); - u32 flags = cmd->flags; + u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gStatuses3[gBattlerAttacker] & flags) + if (GetBattlerVolatile(battler, cmd->_volatile) != 0) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerAttacker] |= flags; - if (flags & STATUS3_MAGNET_RISE) - gDisableStructs[gBattlerAttacker].magnetRiseTimer = gBattleTurnCounter + 5; - if (flags & STATUS3_LASER_FOCUS) - gDisableStructs[gBattlerAttacker].laserFocusTimer = gBattleTurnCounter + 2; - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - -static void Cmd_assistattackselect(void) -{ - CMD_ARGS(const u8 *failInstr); - - s32 chooseableMovesNo = 0; - struct Pokemon *party; - s32 monId, moveId; - u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); - - if (validMoves != NULL) - { - party = GetBattlerParty(gBattlerAttacker); - - for (monId = 0; monId < PARTY_SIZE; monId++) + SetMonVolatile(battler, cmd->_volatile, TRUE); + switch (cmd->_volatile) { - if (monId == gBattlerPartyIndexes[gBattlerAttacker]) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) - continue; - - for (moveId = 0; moveId < MAX_MON_MOVES; moveId++) - { - u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); - - if (IsMoveAssistBanned(move)) - continue; - - validMoves[chooseableMovesNo++] = move; - } + case VOLATILE_MAGNET_RISE: + gDisableStructs[battler].magnetRiseTimer = gBattleTurnCounter + 5; + break; + case VOLATILE_LASER_FOCUS: + gDisableStructs[battler].laserFocusTimer = gBattleTurnCounter + 2; + break; + default: + break; } - } - - if (chooseableMovesNo) - { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCalledMove = validMoves[Random() % chooseableMovesNo]; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gBattlescriptCurrInstr = cmd->nextInstr; } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } +} - TRY_FREE_AND_SET_NULL(validMoves); +static void Cmd_unused_0xde(void) +{ } static void Cmd_trysetmagiccoat(void) @@ -15195,6 +13085,8 @@ static void Cmd_switchoutabilities(void) ®enerate); MarkBattlerForControllerExec(battler); break; + default: + break; } } @@ -15214,18 +13106,8 @@ static void Cmd_jumpifhasnohp(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifnotcurrentmoveargtype(void) +static void Cmd_unused_0xE4(void) { - CMD_ARGS(u8 battler, const u8 *failInstr); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - const u8 *failInstr = cmd->failInstr; - u32 type = GetMoveArgType(gCurrentMove); - - if (!IS_BATTLER_OF_TYPE(battler, type)) - gBattlescriptCurrInstr = failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_pickup(void) @@ -15233,8 +13115,9 @@ static void Cmd_pickup(void) CMD_ARGS(); u32 i, j; - u16 species, heldItem, ability; + u16 species, heldItem; u8 lvlDivBy10; + enum Ability ability; for (i = 0; i < PARTY_SIZE; i++) { @@ -15318,9 +13201,9 @@ static void Cmd_settypebasedhalvers(void) } else { - if (!(gStatuses4[gBattlerAttacker] & STATUS4_MUD_SPORT)) + if (!gBattleMons[gBattlerAttacker].volatiles.waterSport) { - gStatuses4[gBattlerAttacker] |= STATUS4_MUD_SPORT; + gBattleMons[gBattlerAttacker].volatiles.waterSport = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; worked = TRUE; } @@ -15340,9 +13223,9 @@ static void Cmd_settypebasedhalvers(void) } else { - if (!(gStatuses4[gBattlerAttacker] & STATUS4_WATER_SPORT)) + if (!gBattleMons[gBattlerAttacker].volatiles.mudSport) { - gStatuses4[gBattlerAttacker] |= STATUS4_WATER_SPORT; + gBattleMons[gBattlerAttacker].volatiles.mudSport = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; worked = TRUE; } @@ -15357,7 +13240,7 @@ static void Cmd_settypebasedhalvers(void) bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) { - if (!(gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)) + if (!gBattleMons[battlerDef].volatiles.substitute) return FALSE; else if (MoveIgnoresSubstitute(move)) return FALSE; @@ -15370,8 +13253,8 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) bool32 DoesDisguiseBlockMove(u32 battler, u32 move) { if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) - || gBattleMons[battler].status2 & STATUS2_TRANSFORMED - || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + || gBattleMons[battler].volatiles.transformed + || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) || gHitMarker & HITMARKER_IGNORE_DISGUISE || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) return FALSE; @@ -15759,9 +13642,9 @@ static void Cmd_handleballthrow(void) * (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2) / (3 * gBattleMons[gBattlerTarget].maxHP); - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) + if (gBattleMons[gBattlerTarget].status1 & STATUS1_INCAPACITATED) odds *= 2; - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) + if (gBattleMons[gBattlerTarget].status1 & STATUS1_CAN_MOVE) odds = (odds * 15) / 10; if (gBattleResults.catchAttempts[ballId] < 255) @@ -15820,7 +13703,11 @@ static void Cmd_handleballthrow(void) { odds = Sqrt(Sqrt(16711680 / odds)); odds = 1048560 / odds; - for (shakes = 0; shakes < maxShakes && Random() < odds; shakes++); + for (shakes = 0; shakes < maxShakes; shakes++) + { + if (RandomUniform(RNG_BALLTHROW_SHAKE, 0, MAX_u16) >= odds) + break; + } } BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, shakes); @@ -15828,9 +13715,13 @@ static void Cmd_handleballthrow(void) if (shakes == maxShakes) // mon caught, copy of the code above { - if (IsCriticalCapture()) + enum NationalDexOrder natDexNo = SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species); + if ((B_CRITICAL_CAPTURE_IF_OWNED >= GEN_9 && GetSetPokedexFlag(natDexNo, FLAG_GET_CAUGHT)) + || IsCriticalCapture()) + { + gBattleSpritesDataPtr->animationData->isCriticalCapture = TRUE; gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - + } TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); @@ -15874,6 +13765,9 @@ static void Cmd_givecaughtmon(void) { CMD_ARGS(const u8 *passInstr); enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE]; + // Restore players party in order to handle properly the case when a wild mon is caught. + // if (IsNPCFollowerWildBattle()) + // LoadPlayerParty(); switch (state) { @@ -16014,6 +13908,9 @@ static void Cmd_givecaughtmon(void) break; } } + // Save the player's party again to not interferes with RestorePartyAfterFollowerNPCBattle() called after battle. + // if (IsNPCFollowerWildBattle()) + // SavePlayerParty(); } static void Cmd_trysetcaughtmondexflags(void) @@ -16305,7 +14202,9 @@ static void Cmd_settelekinesis(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) + if (gBattleMons[gBattlerTarget].volatiles.telekinesis + || gBattleMons[gBattlerTarget].volatiles.root + || gBattleMons[gBattlerTarget].volatiles.smackDown || gFieldStatuses & STATUS_FIELD_GRAVITY || IsTelekinesisBannedSpecies(gBattleMons[gBattlerTarget].species)) { @@ -16313,7 +14212,7 @@ static void Cmd_settelekinesis(void) } else { - gStatuses3[gBattlerTarget] |= STATUS3_TELEKINESIS; + gBattleMons[gBattlerTarget].volatiles.telekinesis = TRUE; gDisableStructs[gBattlerTarget].telekinesisTimer = gBattleTurnCounter + 3; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16381,20 +14280,20 @@ static void Cmd_setnonvolatilestatus(void) { CMD_ARGS(u8 trigger); gBattlescriptCurrInstr = cmd->nextInstr - 1; - + switch (cmd->trigger) { case TRIGGER_ON_ABILITY: - if (gBattleScripting.moveEffect == MOVE_EFFECT_CONFUSION) + if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION) SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); else - SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); + SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); break; case TRIGGER_ON_MOVE: - SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); + SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); break; case TRIGGER_ON_PROTECT: - SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); + SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); break; } } @@ -16409,16 +14308,17 @@ static void Cmd_tryworryseed(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + RemoveAbilityFlags(gBattlerTarget); gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; @@ -16513,26 +14413,26 @@ void BS_CalcMetalBurstDmg(void) && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId)) && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; gBattlescriptCurrInstr = cmd->nextInstr; } else if (gProtectStructs[gBattlerAttacker].specialDmg && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId)) && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -16541,17 +14441,6 @@ void BS_CalcMetalBurstDmg(void) } } -void BS_JumpIfCantFling(void) -{ - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!CanFling(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_JumpIfMoreThanHalfHP(void) { NATIVE_ARGS(u8 battler, const u8 *jumpInstr); @@ -16590,6 +14479,7 @@ static bool32 CriticalCapture(u32 odds) { u32 numCaught; u32 totalDexCount; + u32 charmBoost = 1; if (B_CRITICAL_CAPTURE == FALSE) return FALSE; @@ -16599,27 +14489,28 @@ static bool32 CriticalCapture(u32 odds) else totalDexCount = NATIONAL_DEX_COUNT; - numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); - - if (numCaught <= (totalDexCount * 30) / 650) - odds = 0; - else if (numCaught <= (totalDexCount * 150) / 650) - odds /= 2; - else if (numCaught <= (totalDexCount * 300) / 650) - ; // odds = (odds * 100) / 100; - else if (numCaught <= (totalDexCount * 450) / 650) - odds = (odds * 150) / 100; - else if (numCaught <= (totalDexCount * 600) / 650) - odds *= 2; - else - odds = (odds * 250) / 100; - if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1)) - odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100; + charmBoost = (100 + B_CATCHING_CHARM_BOOST) / 100; + + numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); + if (numCaught > (totalDexCount * 600) / 650) + odds = (odds * (250 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 450) / 650) + odds = (odds * (200 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 300) / 650) + odds = (odds * (150 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 150) / 650) + odds = (odds * (100 * charmBoost)) / 100; + else if (numCaught > (totalDexCount * 30) / 650) + odds = (odds * (50 * charmBoost)) / 100; + else + return FALSE; + + if (odds > 255) + odds = 255; odds /= 6; - - if ((Random() % 255) < odds) + if (RandomUniform(RNG_BALLTHROW_CRITICAL, 0, MAX_u8) < odds) return TRUE; return FALSE; @@ -16670,7 +14561,7 @@ static bool8 IsFinalStrikeEffect(enum BattleMoveEffects moveEffect) return FALSE; } -static bool32 CanAbilityPreventStatLoss(u32 abilityDef) +static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef) { switch (abilityDef) { @@ -16678,6 +14569,8 @@ static bool32 CanAbilityPreventStatLoss(u32 abilityDef) case ABILITY_FULL_METAL_BODY: case ABILITY_WHITE_SMOKE: return TRUE; + default: + break; } return FALSE; } @@ -16782,7 +14675,7 @@ static void TryUpdateRoundTurnOrder(void) } // update turn order for round users - for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && roundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = roundUsers[i]; gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again @@ -16790,7 +14683,7 @@ static void TryUpdateRoundTurnOrder(void) } // Update turn order for non-round users - for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && nonRoundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; currRounder++; @@ -16942,35 +14835,24 @@ void BS_ItemCureStatus(void) { NATIVE_ARGS(const u8 *noStatusInstr); u32 battler = gBattlerAttacker; - u32 previousStatus2 = 0; bool32 statusChanged = FALSE; struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - // Heal Status2 conditions if battler is active. + // Heal volatile conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - { - previousStatus2 = gBattleMons[battler].status2; - gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); - } + statusChanged = ItemHealMonVolatile(battler, gLastUsedItem); else if (IsDoubleBattle() - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) - { - battler = BATTLE_PARTNER(gBattlerAttacker); - previousStatus2 = gBattleMons[battler].status2; - gBattleMons[battler].status2 &= ~GetItemStatus2Mask(gLastUsedItem); - } - - if (previousStatus2 != gBattleMons[battler].status2) - statusChanged = TRUE; + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem); // Heal Status1 conditions. if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler)) { statusChanged = TRUE; if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; - if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION) - gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.nightmare = FALSE; + if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } if (statusChanged) @@ -17051,7 +14933,7 @@ void BS_ItemRestorePP(void) void BS_TryRevertWeatherForm(void) { NATIVE_ARGS(); - if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_WEATHER)) + if (IsBattlerAlive(gBattlerTarget) && TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_WEATHER)) { gBattleScripting.battler = gBattlerTarget; BattleScriptPush(cmd->nextInstr); @@ -17101,7 +14983,7 @@ void BS_JumpIfShellTrap(void) void BS_JumpIfElectricAbilityAffected(void) { - NATIVE_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + NATIVE_ARGS(u8 battler, enum Ability ability, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); if (IsElectricAbilityAffected(battler, cmd->ability)) @@ -17110,26 +14992,7 @@ void BS_JumpIfElectricAbilityAffected(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ApplySaltCure(void) -{ - NATIVE_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses4[battler] |= STATUS4_SALT_CURE; - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_JumpIfMovePropertyArgument(void) -{ - NATIVE_ARGS(u8 argument, const u8 *jumpInstr); - - if (GetMoveEffectArg_MoveProperty(gCurrentMove) == cmd->argument) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_SetRemoveTerrain(void) +void BS_SetTerrain(void) { NATIVE_ARGS(const u8 *jumpInstr); u32 statusFlag = 0; @@ -17152,48 +15015,19 @@ void BS_SetRemoveTerrain(void) statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; - case EFFECT_HIT_SET_REMOVE_TERRAIN: - switch (GetMoveEffectArg_MoveProperty(gCurrentMove)) - { - case ARG_SET_PSYCHIC_TERRAIN: // Genesis Supernova - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - break; - case ARG_TRY_REMOVE_TERRAIN_HIT: // Splintered Stormshards - case ARG_TRY_REMOVE_TERRAIN_FAIL: // Steel Roller - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) - { - // No terrain to remove, jump to battle script pointer. - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - // Remove all terrains. - RemoveAllTerrains(); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - default: - break; - } + case EFFECT_HIT_SET_TERRAIN: + statusFlag = GetMoveTerrainFlag(gCurrentMove); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; default: break; } + enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker); - if (gFieldStatuses & statusFlag || statusFlag == 0) - { - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - - gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; - gFieldStatuses |= statusFlag; - gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; + gFieldStatuses |= statusFlag; + gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; + gBattlescriptCurrInstr = cmd->nextInstr; } void BS_JumpIfTerrainAffected(void) @@ -17201,7 +15035,7 @@ void BS_JumpIfTerrainAffected(void) NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (IsBattlerTerrainAffected(battler, cmd->flags)) + if (IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), cmd->flags)) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -17258,43 +15092,33 @@ void BS_TryReflectType(void) void BS_TrySetOctolock(void) { - NATIVE_ARGS(u8 battler, const u8 *failInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); + NATIVE_ARGS(const u8 *failInstr); - if (gDisableStructs[battler].octolock) + if (gDisableStructs[gBattlerTarget].octolock) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; - gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; + gDisableStructs[gBattlerTarget].octolock = TRUE; + gDisableStructs[gBattlerTarget].octolockedBy = gBattlerAttacker; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; + gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_SetGlaiveRush(void) -{ - NATIVE_ARGS(); - gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_SetPledge(void) { NATIVE_ARGS(const u8 *jumpInstr); u32 partner = BATTLE_PARTNER(gBattlerAttacker); - u32 partnerMove = gBattleMons[partner].moves[gBattleStruct->chosenMovePositions[partner]]; + u32 partnerMove = GetChosenMoveFromPosition(partner); u32 i = 0; u32 k = 0; if (gBattleStruct->pledgeMove && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)) { - PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); - gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - if ((gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_WATER_PLEDGE) || (gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)) { @@ -17319,7 +15143,7 @@ void BS_SetPledge(void) else if ((gChosenActionByBattler[partner] == B_ACTION_USE_MOVE) && IsDoubleBattle() && IsBattlerAlive(partner) - && GetBattlerTurnOrderNum(gBattlerAttacker) < GetBattlerTurnOrderNum(partner) + && !HasBattlerActedThisTurn(partner) && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gCurrentMove != partnerMove && GetMoveEffect(partnerMove) == EFFECT_PLEDGE) @@ -17461,36 +15285,6 @@ void BS_TryHealPulse(void) } } -void BS_TryCopycat(void) -{ - NATIVE_ARGS(const u8 *failInstr); - - if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || IsMoveCopycatBanned(gLastUsedMove) || IsZMove(gLastUsedMove)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gLastUsedMove)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gLastUsedMove; - gCalledMove = GetTypeBasedZMove(gLastUsedMove); - } - else if (IsMaxMove(gLastUsedMove)) - { - gCalledMove = gBattleStruct->dynamax.lastUsedBaseMove; - } - else - { - gCalledMove = gLastUsedMove; - } - - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - void BS_TryDefog(void) { NATIVE_ARGS(u8 clear, const u8 *failInstr); @@ -17515,10 +15309,10 @@ void BS_TryUpperHand(void) { NATIVE_ARGS(const u8 *failInstr); - u32 abilityDef = GetBattlerAbility(gBattlerTarget); + enum Ability abilityDef = GetBattlerAbility(gBattlerTarget); u32 prio = GetChosenMovePriority(gBattlerTarget, abilityDef); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) + if (HasBattlerActedThisTurn(gBattlerTarget) || gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE || IsBattleMoveStatus(gChosenMoveByBattler[gBattlerTarget]) || prio < 1 @@ -17561,7 +15355,7 @@ void BS_TryAllySwitch(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9) + else if (GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9) { TryResetProtectUseCounter(gBattlerAttacker); if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random()) @@ -17581,15 +15375,6 @@ void BS_TryAllySwitch(void) } } -void BS_RunStatChangeItems(void) -{ - NATIVE_ARGS(u8 battler); - - // Change instruction before calling ItemBattleEffects. - gBattlescriptCurrInstr = cmd->nextInstr; - ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler)); -} - static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove) { u32 i, j; @@ -17687,9 +15472,14 @@ void BS_TryGulpMissile(void) && (gCurrentMove == MOVE_DIVE) && GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) + { + gBattleScripting.battler = gBattlerAttacker; gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; + } else + { gBattlescriptCurrInstr = cmd->nextInstr; + } } void BS_TryActivateGulpMissile(void) @@ -17730,7 +15520,7 @@ void BS_TryQuash(void) u32 i, j; // It's true if foe is faster, has a bigger priority, or switches - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + if (HasBattlerActedThisTurn(gBattlerTarget)) { gBattlescriptCurrInstr = cmd->failInstr; return; @@ -17825,7 +15615,6 @@ void BS_JumpIfSleepClause(void) void BS_FickleBeamDamageCalculation(void) { NATIVE_ARGS(); - gBattleStruct->fickleBeamBoosted = FALSE; if (RandomPercentage(RNG_FICKLE_BEAM, 30)) { @@ -17896,7 +15685,7 @@ void BS_TeatimeInvul(void) NATIVE_ARGS(u8 battler, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))) + if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) gBattlescriptCurrInstr = cmd->nextInstr; else gBattlescriptCurrInstr = cmd->jumpInstr; @@ -17923,7 +15712,7 @@ void BS_TryWindRiderPower(void) NATIVE_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - u16 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); if (IsBattlerAlly(battler, gBattlerAttacker) && (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER)) { @@ -17956,6 +15745,16 @@ void BS_ActivateTerrainChangeAbilities(void) AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); } +void BS_ResetTerrainAbilityFlags(void) +{ + NATIVE_ARGS(); + // reset terrain ability checks + for (u32 i = 0; i < gBattlersCount; i++) + gDisableStructs[i].terrainAbilityDone = 0; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_StoreHealingWish(void) { NATIVE_ARGS(u8 battler); @@ -18016,9 +15815,9 @@ void BS_JumpIfCommanderActive(void) { NATIVE_ARGS(const u8 *jumpInstr); - if (gBattleStruct->commanderActive[gBattlerTarget] != SPECIES_NONE) + if (gBattleStruct->battlerState[gBattlerTarget].commanderSpecies != SPECIES_NONE) gBattlescriptCurrInstr = cmd->jumpInstr; - else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER) + else if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_COMMANDER) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -18063,7 +15862,7 @@ void BS_CheckPokeFlute(void) if (GetBattlerAbility(i) != ABILITY_SOUNDPROOF) { gBattleMons[i].status1 &= ~STATUS1_SLEEP; - gBattleMons[i].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[i].volatiles.nightmare = FALSE; } } @@ -18246,12 +16045,8 @@ static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr) { if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))) { - gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS; - gBattleCommunication[MULTISTRING_CHOOSER] = 3; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, TRIGGER_ON_MOVE); } else { @@ -18263,12 +16058,8 @@ static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr) { if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget))) { - gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, TRIGGER_ON_MOVE); } else { @@ -18280,17 +16071,8 @@ static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr) { if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)) { - if (B_SLEEP_TURNS >= GEN_5) - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2); - else - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3); - - TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); - gBattleCommunication[MULTISTRING_CHOOSER] = 4; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, TRIGGER_ON_MOVE); } else { @@ -18344,8 +16126,7 @@ void BS_TrySetConfusion(void) if (CanBeConfused(gBattlerTarget)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattleCommunication[MULTIUSE_STATE] = 1; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18360,13 +16141,12 @@ void BS_TrySetInfatuation(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_INFATUATION) + if (!gBattleMons[gBattlerTarget].volatiles.infatuation && gBattleMons[gBattlerTarget].ability != ABILITY_OBLIVIOUS && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_INFATUATED_WITH(gBattlerAttacker); - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); gBattleCommunication[MULTIUSE_STATE] = 2; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18381,11 +16161,10 @@ void BS_TrySetEscapePrevention(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; - gBattleCommunication[MULTISTRING_CHOOSER] = 2; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18399,12 +16178,11 @@ void BS_TrySetTorment(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT) + if (!(gBattleMons[gBattlerTarget].volatiles.torment == TRUE) && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_TORMENT; + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; gDisableStructs[gBattlerTarget].tormentTimer = gBattleTurnCounter + 3; // 3 turns excluding current turn - gBattleCommunication[MULTISTRING_CHOOSER] = 3; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18458,14 +16236,13 @@ void BS_SetSteelsurge(void) { NATIVE_ARGS(const u8 *failInstr); u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STEELSURGE) + if (IsHazardOnSide(targetSide, HAZARDS_STEELSURGE)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STEELSURGE; - gSideTimers[targetSide].steelsurgeAmount = 1; + PushHazardTypeToQueue(targetSide, HAZARDS_STEELSURGE); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -18475,7 +16252,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void) NATIVE_ARGS(); u32 hasAbility = FALSE; - u32 ability = GetBattlerAbility(gBattlerTarget); + enum Ability ability = GetBattlerAbility(gBattlerTarget); switch (ability) { @@ -18483,7 +16260,7 @@ void BS_JumpIfIntimidateAbilityPrevented(void) case ABILITY_SCRAPPY: case ABILITY_OWN_TEMPO: case ABILITY_OBLIVIOUS: - if (B_UPDATED_INTIMIDATE >= GEN_8) + if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8) { hasAbility = TRUE; gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; @@ -18549,10 +16326,10 @@ void BS_TryBoosterEnergy(void) for (u32 orderNum = 0; orderNum < gBattlersCount; orderNum++) { u32 battlerByTurnOrder = gBattlerByTurnOrder[orderNum]; - if (GetBattlerHoldEffect(battlerByTurnOrder, TRUE) != HOLD_EFFECT_BOOSTER_ENERGY) + if (GetBattlerHoldEffect(battlerByTurnOrder) != HOLD_EFFECT_BOOSTER_ENERGY) continue; - u32 ability = GetBattlerAbility(battlerByTurnOrder); + enum Ability ability = GetBattlerAbility(battlerByTurnOrder); if (!(ability == ABILITY_PROTOSYNTHESIS && cmd->onFieldStatus != ON_TERRAIN) && !(ability == ABILITY_QUARK_DRIVE && cmd->onFieldStatus != ON_WEATHER)) continue; @@ -18579,13 +16356,1642 @@ void BS_TryActivateAbilityShield(void) { NATIVE_ARGS(u8 battler); u32 battler = GetBattlerForBattleScript(cmd->battler); + enum Ability ability = GetBattlerAbility(battler); gBattlescriptCurrInstr = cmd->nextInstr; - if (GetBattlerAbilityNoAbilityShield(battler) != GetBattlerAbility(battler)) + if (ability != ABILITY_NONE // if ability would be negated by breaking effects Ability Shield doesn't print message + && ability == GetBattlerAbilityInternal(battler, TRUE, TRUE)) + return; + + if (GetBattlerAbilityNoAbilityShield(battler) != ability) { gLastUsedItem = gBattleMons[battler].item; RecordItemEffectBattle(battler, GetItemHoldEffect(gLastUsedItem)); BattleScriptCall(BattleScript_AbilityShieldProtects); } } + +void BS_TrySynchronoise(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + bool32 atleastOneSharedType = FALSE; + + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SYNCHRONOISE_AFFECTED + || gBattlerAttacker == battlerDef + || !IsBattlerAlive(battlerDef)) + continue; + + if (DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + atleastOneSharedType = TRUE; + continue; + } + + if (!DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + gBattleScripting.battler = battlerDef; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_NO_EFFECT | MOVE_RESULT_SYNCHRONOISE_AFFECTED; + BattleScriptCall(BattleScript_ItDoesntAffectFoe); + return; + } + } + + if (atleastOneSharedType) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} + +void BS_JumpIfRoarFails(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + + if (WILD_DOUBLE_BATTLE + && IsOnPlayerSide(gBattlerAttacker) + && !IsOnPlayerSide(gBattlerTarget) + && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else if (WILD_DOUBLE_BATTLE + && !IsOnPlayerSide(gBattlerAttacker) + && !IsOnPlayerSide(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else if (FlagGet(B_FLAG_NO_RUNNING)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfAbsent(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + if (!IsBattlerAlive(GetBattlerForBattleScript(cmd->battler))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfHoldEffect(void) +{ + NATIVE_ARGS(u8 battler, u8 holdEffect, const u8 *jumpInstr, u8 equal); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if ((GetBattlerHoldEffect(battler) == cmd->holdEffect) == cmd->equal) + { + if (cmd->equal) + gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM + gBattlescriptCurrInstr = cmd->jumpInstr; + } + else + { + if (!cmd->equal) + gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_JumpIfNoAlly(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 partner = BATTLE_PARTNER(GetBattlerForBattleScript(cmd->battler)); + if (!IsBattlerAlive(partner)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_InfatuateWithBattler(void) +{ + NATIVE_ARGS(u8 battler, u8 infatuateWith); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleScripting.battler = battler; + gBattleMons[battler].volatiles.infatuation = INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetLastUsedItem(void) +{ + NATIVE_ARGS(u8 battler); + gLastUsedItem = gBattleMons[GetBattlerForBattleScript(cmd->battler)].item; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TrySetFairyLock(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gFieldStatuses |= STATUS_FIELD_FAIRY_LOCK; + gFieldTimers.fairyLockTimer = gBattleTurnCounter + 2; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_GetStatValue(void) +{ + NATIVE_ARGS(u8 stat); + u32 stat = cmd->stat; + gBattleStruct->moveDamage[gBattlerAttacker] = *(u16 *)(&gBattleMons[gBattlerTarget].attack) + (stat - 1); + gBattleStruct->moveDamage[gBattlerAttacker] *= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][0]; + gBattleStruct->moveDamage[gBattlerAttacker] /= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][1]; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfFullHp(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + if (IsBattlerAtMaxHp(GetBattlerForBattleScript(cmd->battler))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryFriskMessage(void) +{ + NATIVE_ARGS(); + while (gBattleStruct->friskedBattler < gBattlersCount) + { + gBattlerTarget = gBattleStruct->friskedBattler++; + if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattleMons[gBattlerTarget].item != ITEM_NONE) + { + gLastUsedItem = gBattleMons[gBattlerTarget].item; + RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffectIgnoreNegation(gBattlerTarget)); + // If Frisk identifies two mons' items, show the pop-up only once. + if (gBattleStruct->friskedAbility) + { + BattleScriptCall(BattleScript_FriskMsg); + } + else + { + gBattleStruct->friskedAbility = TRUE; + BattleScriptCall(BattleScript_FriskMsgWithPopup); + } + return; + } + } + gBattleStruct->friskedBattler = 0; + gBattleStruct->friskedAbility = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetTracedAbility(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = gBattleStruct->tracedAbility[battler]; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryIllusionOff(void) +{ + NATIVE_ARGS(u8 battler); + if (TryClearIllusion(GetBattlerForBattleScript(cmd->battler), ABILITYEFFECT_MOVE_END)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetSpriteIgnore0Hp(void) +{ + NATIVE_ARGS(bool8 ignore0HP); + gBattleStruct->spriteIgnore0Hp = cmd->ignore0HP; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_UpdateNick(void) +{ + NATIVE_ARGS(); + u32 battler = gBattleScripting.battler; + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], GetBattlerMon(battler), HEALTHBOX_NICK); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfNotBerry(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + if (GetItemPocket(gBattleMons[GetBattlerForBattleScript(cmd->battler)].item) == POCKET_BERRIES) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} + +void BS_GravityOnAirborneMons(void) +{ + NATIVE_ARGS(); + // Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop. + if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_ON_AIR) + CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_GRAVITY_ON_AIRBORNE); + + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; + gBattleMons[gBattlerTarget].volatiles.magnetRise = FALSE; + gBattleMons[gBattlerTarget].volatiles.telekinesis = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryAcupressure(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 bits = 0; + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + { + if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + bits |= 1u << stat; + } + if (bits) + { + u32 statId; + do + { + statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1; + } while (!(bits & (1u << statId))); + + SET_STATCHANGER(statId, 2, FALSE); + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_CancelMultiTurnMoves(void) +{ + NATIVE_ARGS(); + const u8 *result = CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_CANCEL_MULTI_TURN_MOVES); + if (result) + gBattlescriptCurrInstr = result; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_IsRunningImpossible(void) +{ + NATIVE_ARGS(); + gBattleCommunication[0] = IsRunningFromBattleImpossible(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_GetMoveTarget(void) +{ + NATIVE_ARGS(); + gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_GetBattlerFainted(void) +{ + NATIVE_ARGS(u8 battler); + if (gHitMarker & HITMARKER_FAINTED(GetBattlerForBattleScript(cmd->battler))) + gBattleCommunication[0] = TRUE; + else + gBattleCommunication[0] = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ResetSwitchInAbilityBits(void) +{ + NATIVE_ARGS(); + gSpecialStatuses[gBattlerAttacker].switchInAbilityDone = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_UpdateChoiceMoveOnLvlUp(void) +{ + NATIVE_ARGS(); + // if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId || gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) + // { + // u32 battler; + // if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId) + // battler = 0; + // else + // battler = 2; + + // u32 moveIndex; + // for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + // { + // if (gBattleMons[battler].moves[moveIndex] == gBattleStruct->choicedMove[battler]) + // break; + // } + // if (moveIndex == MAX_MON_MOVES) + // gBattleStruct->choicedMove[battler] = MOVE_NONE; + // } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ResetPlayerFainted(void) +{ + NATIVE_ARGS(); + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE)) + && gBattleTypeFlags & BATTLE_TYPE_TRAINER + && IsBattlerAlive(B_POSITION_PLAYER_LEFT) + && IsBattlerAlive(B_POSITION_OPPONENT_LEFT)) + { + gHitMarker &= ~HITMARKER_PLAYER_FAINTED; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PalaceFlavorText(void) +{ + NATIVE_ARGS(); + // Try and print end-of-turn Battle Palace flavor text (e.g. "A glint appears in mon's eyes") + // u32 battler; + // gBattleCommunication[0] = FALSE; // whether or not msg should be printed + // gBattleScripting.battler = battler = gBattleCommunication[1]; + // if (!(gBattleStruct->palaceFlags & (1u << battler)) + // && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp + // && IsBattlerAlive(battler) + // && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) + // { + // gBattleStruct->palaceFlags |= 1u << battler; + // gBattleCommunication[0] = TRUE; + // gBattleCommunication[MULTISTRING_CHOOSER] = gNaturesInfo[GetNatureFromPersonality(gBattleMons[battler].personality)].battlePalaceFlavorText; + // } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ArenaJudgmentWindow(void) +{ + NATIVE_ARGS(); + // u32 judgmentWindow = BattleArena_ShowJudgmentWindow(&gBattleCommunication[0]); + + // // BattleArena_ShowJudgmentWindow's last state was an intermediate step. + // // Return without advancing the current instruction so that it will be called again. + // if (judgmentWindow == ARENA_RESULT_RUNNING) + // return; + + // gBattleCommunication[1] = judgmentWindow; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void UNUSED SetArenMonLostValues(u32 battler) +{ + // gBattleMons[battler].hp = 0; + // gHitMarker |= HITMARKER_FAINTED(battler); + // gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[battler]; + // gDisableStructs[battler].truantSwitchInHack = TRUE; +} + +#define playerMon 0 +#define opponentMon 1 +void BS_ArenaOpponentMonLost(void) +{ + NATIVE_ARGS(); + // SetArenMonLostValues(opponentMon); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ArenaPlayerMonLost(void) +{ + NATIVE_ARGS(); + // SetArenMonLostValues(playerMon); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ArenaBothMonsLost(void) +{ + NATIVE_ARGS(); + // SetArenMonLostValues(playerMon); + // SetArenMonLostValues(opponentMon); + gBattlescriptCurrInstr = cmd->nextInstr; +} +#undef playerMon +#undef opponentMon + +void BS_ForfeitYesNoBox(void) +{ + NATIVE_ARGS(); + BtlController_EmitYesNoBox(gBattlerAttacker, B_COMM_TO_CONTROLLER); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_DrawArenaRefTextBox(void) +{ + NATIVE_ARGS(); + // DrawArenaRefereeTextBox(); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_EraseArenaRefTextBox(void) +{ + NATIVE_ARGS(); + // EraseArenaRefereeTextBox(); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ArenaJudgmentString(void) +{ + CMD_ARGS(u8 id); + // BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[cmd->id]); + // BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGMENT_TEXT); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +// Argument passed but no use +void BS_ArenaWaitMessage(void) +{ + NATIVE_ARGS(); + // if (IsTextPrinterActive(ARENA_WIN_JUDGMENT_TEXT)) + // return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_WaitCry(void) +{ + NATIVE_ARGS(); + if (!IsCryFinished()) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +#define opponentFirstBattler 1 +#define opponentSecondBattler 3 +void BS_ReturnOpponentMon1ToBall(void) +{ + NATIVE_ARGS(); + if (IsBattlerAlive(opponentFirstBattler)) + { + BtlController_EmitReturnMonToBall(opponentFirstBattler, B_COMM_TO_CONTROLLER, FALSE); + MarkBattlerForControllerExec(opponentFirstBattler); + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ReturnOpponentMon2ToBall(void) +{ + NATIVE_ARGS(); + if (gBattlersCount > opponentSecondBattler) + { + if (IsBattlerAlive(opponentSecondBattler)) + { + BtlController_EmitReturnMonToBall(opponentSecondBattler, B_COMM_TO_CONTROLLER, FALSE); + MarkBattlerForControllerExec(opponentSecondBattler); + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} +#undef opponentFirstBattler +#undef opponentSecondBattler + +void BS_VolumeDown(void) +{ + NATIVE_ARGS(); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x55); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_VolumeUp(void) +{ + NATIVE_ARGS(); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetAlreadyStatusedMoveAttempt(void) +{ + NATIVE_ARGS(); + gBattleStruct->battlerState[gBattlerAttacker].alreadyStatusedMoveAttempt = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PalaceTryEscapeStatus(void) +{ + NATIVE_ARGS(); + // if (BattlePalace_TryEscapeStatus(gBattlerAttacker)) + // return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetTeleportOutcome(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + // Don't end the battle if one of the wild mons teleported from the wild double battle + // and its partner is still alive. + if (!IsOnPlayerSide(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + gAbsentBattlerFlags |= 1u << battler; + gHitMarker |= HITMARKER_FAINTED(battler); + gBattleMons[battler].hp = 0; + SetMonData(GetBattlerMon(battler), MON_DATA_HP, &gBattleMons[battler].hp); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[battler]); + FaintClearSetData(battler); + } + else if (IsOnPlayerSide(battler)) + { + gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED; + } + else + { + gBattleOutcome = B_OUTCOME_MON_TELEPORTED; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PlayTrainerDefeatedMusic(void) +{ + NATIVE_ARGS(); + BtlController_EmitPlayFanfareOrBGM(gBattlerAttacker, B_COMM_TO_CONTROLLER, MUS_VICTORY_TRAINER, TRUE); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_StatTextBuffer(void) +{ + NATIVE_ARGS(); + PREPARE_STAT_BUFFER(gBattleTextBuff1, gBattleCommunication[0]); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SwitchinAbilities(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlescriptCurrInstr = cmd->nextInstr; + AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); + + if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect()) + AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); + + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); +} + +void BS_InstantHpDrop(void) +{ + NATIVE_ARGS(); + BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ClearStatus(void) +{ + NATIVE_ARGS(); + gBattleMons[gBattlerAttacker].status1 = 0; + BtlController_EmitSetMonData( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + sizeof(gBattleMons[gBattlerAttacker].status1), + &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +// NEW BATCH + +void BS_RestoreMovePp(void) +{ + NATIVE_ARGS(); + u32 moveIndex; + u32 data[MAX_MON_MOVES + 1]; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + gBattleMons[gBattlerAttacker].pp[moveIndex] = CalculatePPWithBonus(gBattleMons[gBattlerAttacker].moves[moveIndex], gBattleMons[gBattlerAttacker].ppBonuses, moveIndex); + data[moveIndex] = gBattleMons[gBattlerAttacker].pp[moveIndex]; + } + data[moveIndex] = gBattleMons[gBattlerAttacker].ppBonuses; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_PP_DATA_BATTLE, 0, 5, data); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryActivateReceiver(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlerAbility = BATTLE_PARTNER(battler); + u32 partnerAbility = GetBattlerAbility(gBattlerAbility); + if (IsBattlerAlive(gBattlerAbility) + && (partnerAbility == ABILITY_RECEIVER || partnerAbility == ABILITY_POWER_OF_ALCHEMY) + && GetBattlerHoldEffect(battler) != HOLD_EFFECT_ABILITY_SHIELD + && !gAbilitiesInfo[gBattleMons[battler].ability].cantBeCopied) + { + gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_ReceiverActivates; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryActivateSoulheart(void) +{ + NATIVE_ARGS(); + while (gBattleStruct->soulheartBattlerId < gBattlersCount) + { + gBattleScripting.battler = gBattleStruct->soulheartBattlerId++; + if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART + && IsBattlerAlive(gBattleScripting.battler) + && !NoAliveMonsForEitherParty() + && CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); + BattleScriptCall(BattleScript_ScriptingAbilityStatRaise); + return; + } + } + gBattleStruct->soulheartBattlerId = 0; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PlayMoveAnimation(void) +{ + NATIVE_ARGS(u16 move); + BtlController_EmitMoveAnimation( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + cmd->move, + gBattleScripting.animTurn, + 0, + 0, + gBattleMons[gBattlerAttacker].friendship, + &gDisableStructs[gBattlerAttacker], + gMultiHitCounter); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetLuckyChant(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 side = GetBattlerSide(gBattlerAttacker); + if (!(gSideStatuses[side] & SIDE_STATUS_LUCKY_CHANT)) + { + gSideStatuses[side] |= SIDE_STATUS_LUCKY_CHANT; + gSideTimers[side].luckyChantTimer = gBattleTurnCounter + 5; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_SetSimpleBeam(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten + || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) + { + RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) + { + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); + } + else + { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + + RemoveAbilityFlags(gBattlerTarget); + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryEntrainment(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeCopied + || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten) + { + RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) + { + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); + } + else + { + if (gBattleMons[gBattlerTarget].ability == gBattleMons[gBattlerAttacker].ability + || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + RemoveAbilityFlags(gBattlerTarget); + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; + gBattlescriptCurrInstr = cmd->nextInstr; + } + } +} + +void BS_SetLastUsedAbility(void) +{ + NATIVE_ARGS(); + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_InvertStatStages(void) +{ + NATIVE_ARGS(); + for (u32 i = 0; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[gBattlerTarget].statStages[i] < DEFAULT_STAT_STAGE) // Negative becomes positive. + gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE + (DEFAULT_STAT_STAGE - gBattleMons[gBattlerTarget].statStages[i]); + else if (gBattleMons[gBattlerTarget].statStages[i] > DEFAULT_STAT_STAGE) // Positive becomes negative. + gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE - (gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE); + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryElectrify(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (HasBattlerActedThisTurn(gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerTarget].volatiles.electrified = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TrySoak(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 types[3]; + GetBattlerTypes(gBattlerTarget, FALSE, types); + u32 typeToSet = GetMoveArgType(gCurrentMove); + if ((types[0] == typeToSet && types[1] == typeToSet) + || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + SET_BATTLER_TYPE(gBattlerTarget, typeToSet); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, typeToSet); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_HandleFormChange(void) +{ + NATIVE_ARGS(u8 battler, u8 case_); + u32 battler = GetBattlerForBattleScript(cmd->battler); + struct Pokemon *mon = GetBattlerMon(battler); + + if (cmd->case_ == 0) // Change species. + { + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); + MarkBattlerForControllerExec(battler); + } + else if (cmd->case_ == 1) // Change stats. + { + RecalcBattlerStats(battler, mon, FALSE); + } + else // Update healthbox. + { + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryAutotomize(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (GetBattlerWeight(gBattlerAttacker) > 1) + { + gDisableStructs[gBattlerAttacker].autotomizeCount++; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_TryInstruct(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u16 move = gLastPrintedMoves[gBattlerTarget]; + if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasAdditionalEffectSelf(move, MOVE_EFFECT_RECHARGE) + || IsMoveInstructBanned(move) + || gBattleMoveEffects[GetMoveEffect(move)].twoTurnEffect + || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) + || IsZMove(move) + || IsMaxMove(move)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4; + gCalledMove = move; + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (gBattleMons[gBattlerTarget].moves[moveIndex] == gCalledMove) + { + gCurrMovePos = moveIndex; + moveIndex = 4; + break; + } + } + if (moveIndex != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget]; + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); + gBattlescriptCurrInstr = cmd->nextInstr; + } + } +} + +void BS_ShowAbilityPopup(void) +{ + NATIVE_ARGS(); + CreateAbilityPopUp(gBattlerAbility, gBattleMons[gBattlerAbility].ability, (IsDoubleBattle()) != 0); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_UpdateAbilityPopup(void) +{ + NATIVE_ARGS(); + UpdateAbilityPopup(gBattlerAbility); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfTargetAlly(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} + +void BS_TryPsychoShift(void) +{ + NATIVE_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr); + u32 targetAbility = GetBattlerAbility(gBattlerTarget); + // Psycho shift works + if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_TOXIC_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_BURN) && CanBeBurned(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerAttacker, gBattlerTarget, targetAbility, BLOCKED_BY_SLEEP_CLAUSE)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + } + else if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) + { + gBattlescriptCurrInstr = cmd->sleepClauseFailInstr; + return; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + return; + } + gBattleMons[gBattlerTarget].status1 = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; + BtlController_EmitSetMonData( + gBattlerTarget, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + sizeof(gBattleMons[gBattlerTarget].status1), + &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_CureStatus(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + + gBattleMons[battler].status1 = 0; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PowerTrick(void) +{ + NATIVE_ARGS(); + u32 temp; + gBattleMons[gBattlerAttacker].volatiles.powerTrick = !gBattleMons[gBattlerAttacker].volatiles.powerTrick; + SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerAttacker].defense, temp); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryAfterYou(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (ChangeOrderTargetAfterAttacker()) + { + gSpecialStatuses[gBattlerTarget].afterYou = 1; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_TryBestow(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gBattleMons[gBattlerAttacker].item == ITEM_NONE + || gBattleMons[gBattlerTarget].item != ITEM_NONE + || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) + || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) + || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + BestowItem(gBattlerAttacker, gBattlerTarget); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_HandleTrainerSlideMsg(void) +{ + NATIVE_ARGS(u8 battler, u8 case_); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (cmd->case_ == PRINT_SLIDE_MESSAGE) + { + BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, STRINGID_TRAINERSLIDE); + MarkBattlerForControllerExec(battler); + } + else if (cmd->case_ == RESTORE_BATTLER_SLIDE_CONTROL) + { + if (IsBattlerAlive(battler)) + { + SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species); + BattleLoadMonSpriteGfx(GetBattlerMon(battler), battler); + } + u32 partner = BATTLE_PARTNER(battler); + if (IsBattlerAlive(partner)) + { + SetBattlerShadowSpriteCallback(partner, gBattleMons[partner].species); + BattleLoadMonSpriteGfx(GetBattlerMon(partner), partner); + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryTrainerSlideMsgFirstOff(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 shouldDoTrainerSlide = 0; + if ((shouldDoTrainerSlide = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN))) + { + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldDoTrainerSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryTrainerSlideMsgLastOn(void) +{ + NATIVE_ARGS(u8 battler); + u32 shouldDoTrainerSlide = 0; + u32 battler = GetBattlerForBattleScript(cmd->battler); + if ((shouldDoTrainerSlide = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_LAST_SWITCHIN))) + { + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldDoTrainerSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +// Potential bug with failing message and missed result on wrong battler +void BS_SetAuroraVeil(void) +{ + NATIVE_ARGS(); + u32 side = GetBattlerSide(gBattlerAttacker); + if (gSideStatuses[side] & SIDE_STATUS_AURORA_VEIL) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else + { + gSideStatuses[side] |= SIDE_STATUS_AURORA_VEIL; + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8; + else + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; + + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryThirdType(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 type = GetMoveArgType(gCurrentMove); + if (IS_BATTLER_OF_TYPE(gBattlerTarget, type) || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerTarget].types[2] = type; + PREPARE_TYPE_BUFFER(gBattleTextBuff1, type); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_DestroyAbilityPopup(void) +{ + NATIVE_ARGS(); + for (u32 battler = 0; battler < gBattlersCount; battler++) + DestroyAbilityPopUp(battler); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_GetTotemBoost(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + u32 battler = gBattlerAttacker; + if (gQueuedStatBoosts[battler].stats == 0) + { + gBattlescriptCurrInstr = cmd->nextInstr; // stats done, exit + } + else + { + for (u32 i = 0; i < (NUM_BATTLE_STATS - 1); i++) + { + if (gQueuedStatBoosts[battler].stats & (1 << i)) + { + if (gQueuedStatBoosts[battler].statChanges[i] <= -1) + SET_STATCHANGER(i + 1, abs(gQueuedStatBoosts[battler].statChanges[i]), TRUE); + else + SET_STATCHANGER(i + 1, gQueuedStatBoosts[battler].statChanges[i], FALSE); + + gQueuedStatBoosts[battler].stats &= ~(1 << i); + gBattleScripting.battler = battler; + gBattlerTarget = battler; + if (gQueuedStatBoosts[battler].stats & 0x80) + { + gQueuedStatBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag + gBattlescriptCurrInstr = BattleScript_TotemFlaredToLife; + } + else + { + gBattlescriptCurrInstr = cmd->jumpInstr; // do boost + } + return; + } + } + gBattlescriptCurrInstr = cmd->nextInstr; // exit if loop failed (failsafe) + } +} + +void BS_ActivateItemEffects(void) +{ + NATIVE_ARGS(); + if (ItemBattleEffects(ITEMEFFECT_TRY_HEALING, gBattlerTarget)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryRoomService(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(battler)) + { + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_TryTerrainSeed(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_SEEDS) + { + enum ItemEffect effect = ITEM_NO_EFFECT; + u16 item = gBattleMons[battler].item; + switch (GetBattlerHoldEffectParam(battler)) + { + case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_MISTY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); + break; + } + + if (effect != ITEM_NO_EFFECT) + return; + } + gBattlescriptCurrInstr = cmd->failInstr; +} + +void BS_MakeInvisible(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gBattleControllerExecFlags) + return; + + BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); + MarkBattlerForControllerExec(battler); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfTeamHealthy(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + u32 battler = gBattlerAttacker; + if ((IsDoubleBattle()) && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + u8 partner = BATTLE_PARTNER(battler); + if ((gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) + && (gBattleMons[partner].hp == gBattleMons[partner].maxHP && !(gBattleMons[partner].status1 & STATUS1_ANY))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + } + else // single battle + { + if (gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryHealQuarterHealth(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + gBattleStruct->moveDamage[battler] *= -1; + + if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) + gBattlescriptCurrInstr = cmd->failInstr; // fail + else + gBattlescriptCurrInstr = cmd->nextInstr; // can heal +} + +void BS_JumpIfUnder200(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + // If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail. + if (GetBattlerWeight(gBattlerTarget) < 2000) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetSkyDrop(void) +{ + NATIVE_ARGS(); + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_SKY_DROP; + /* skyDropTargets holds the information of who is in a particular instance of Sky Drop. + This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if + the target of a Sky Drop faints while in the air.*/ + gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget; + gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker; + + // End any multiturn effects caused by the target except VOLATILE_LOCK_CONFUSE + gBattleMons[gBattlerTarget].volatiles.multipleTurns = 0; + gBattleMons[gBattlerTarget].volatiles.uproarTurns = 0; + gBattleMons[gBattlerTarget].volatiles.bideTurns = 0; + gDisableStructs[gBattlerTarget].rolloutTimer = 0; + gDisableStructs[gBattlerTarget].furyCutterCounter = 0; + + // End any Follow Me/Rage Powder effects caused by the target + if (gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer != 0 && gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget == gBattlerTarget) + gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 0; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ClearSkyDrop(void) +{ + NATIVE_ARGS(const u8 *failInstr); + // Check to see if the initial target of this Sky Drop fainted before the 2nd turn of Sky Drop. + // If so, make the move fail. If not, clear all of the statuses and continue the move. + if (gBattleStruct->skyDropTargets[gBattlerAttacker] == SKY_DROP_NO_TARGET) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET; + gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET; + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; + gBattlescriptCurrInstr = cmd->nextInstr; + } + + // Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted. + if (gBattleMons[gBattlerTarget].volatiles.lockConfusionTurns) + gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; +} + +void BS_SkyDropYawn(void) +{ + NATIVE_ARGS(); + if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && gBattleMons[gEffectBattler].volatiles.semiInvulnerable != STATE_SKY_DROP) + { + // Set the target of Sky Drop as gEffectBattler + gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler]; + + // Clear skyDropTargets data + gBattleStruct->skyDropTargets[gBattleStruct->skyDropTargets[gEffectBattler]] = SKY_DROP_NO_TARGET; + gBattleStruct->skyDropTargets[gEffectBattler] = SKY_DROP_NO_TARGET; + + // If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation + if (gBattleMons[gEffectBattler].volatiles.lockConfusionTurns && CanBeConfused(gEffectBattler)) + { + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; + gBattlerAttacker = gEffectBattler; + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; + gBattlescriptCurrInstr = BattleScript_ThrashConfuses; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_JumpIfPranksterBlocked(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget, TRUE)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryToClearPrimalWeather(void) +{ + NATIVE_ARGS(); + bool32 shouldNotClear = FALSE; + + for (u32 i = 0; i < gBattlersCount; i++) + { + enum Ability ability = GetBattlerAbility(i); + if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) + || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) + || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) + && IsBattlerAlive(i)) + shouldNotClear = TRUE; + } + if (gBattleWeather & B_WEATHER_SUN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_SUN_PRIMAL; + PrepareStringBattle(STRINGID_EXTREMESUNLIGHTFADED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_RAIN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_RAIN_PRIMAL; + PrepareStringBattle(STRINGID_HEAVYRAINLIFTED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_STRONG_WINDS && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_STRONG_WINDS; + PrepareStringBattle(STRINGID_STRONGWINDSDISSIPATED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryEndNeutralizingGas(void) +{ + NATIVE_ARGS(); + if (gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved) + { + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = FALSE; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_GetRototillerTargets(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 count = 0; + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + gSpecialStatuses[battler].rototillerAffected = FALSE; + if (IsRototillerAffected(battler)) + { + gSpecialStatuses[battler].rototillerAffected = TRUE; + count++; + } + } + + if (count == 0) + gBattlescriptCurrInstr = cmd->failInstr; // Rototiller fails + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfNotRototillerAffected(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + if (gSpecialStatuses[gBattlerTarget].rototillerAffected) + { + gSpecialStatuses[gBattlerTarget].rototillerAffected = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->jumpInstr; // Unaffected by rototiller - print STRINGID_NOEFFECTONTARGET + } +} + +void BS_ConsumeBerry(void) +{ + NATIVE_ARGS(u8 battler, bool8 fromBattler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (gBattleScripting.overrideBerryRequirements == 2) + { + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + if (cmd->fromBattler) + gLastUsedItem = gBattleMons[battler].item; + + GetBattlerPartyState(battler)->ateBerry = TRUE; + gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID + if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfWeatherAffected(void) +{ + NATIVE_ARGS(u16 flags, const u8 *jumpInstr); + u32 weather = cmd->flags; + if (IsBattlerWeatherAffected(gBattlerAttacker, weather)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfSpecies(void) +{ + NATIVE_ARGS(u16 species, const u8 *jumpInstr); + if (gBattleMons[gBattlerAttacker].species == cmd->species) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfLeafGuardProtected(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (IsLeafGuardProtected(battler, GetBattlerAbility(battler))) + { + gBattlerAbility = battler; + gBattlescriptCurrInstr = cmd->jumpInstr; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_SetAttackerToStickyWebUser(void) +{ + NATIVE_ARGS(); + // For Mirror Armor: "If the Pokémon with this Ability is affected by Sticky Web, the effect is reflected back to the Pokémon which set it up. + // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." + gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + if (gSideTimers[GetBattlerSide(gBattlerTarget)].stickyWebBattlerId != 0xFF) + gBattlerAttacker = gSideTimers[GetBattlerSide(gBattlerTarget)].stickyWebBattlerId; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_CutOneThirdHpAndRaiseStats(void) +{ + NATIVE_ARGS(const u8 *failInstr); + + bool32 atLeastOneStatBoosted = FALSE; + for (u32 stat = 1; stat < NUM_STATS; stat++) + { + if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + atLeastOneStatBoosted = TRUE; + break; + } + } + if (atLeastOneStatBoosted) + { + gBattleStruct->moveDamage[gBattlerAttacker] = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_SetPoltergeistMessage(void) +{ + NATIVE_ARGS(const u8 *failInstr); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].item); + gLastUsedItem = gBattleMons[gBattlerTarget].item; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_CureCertainStatuses(void) +{ + NATIVE_ARGS(); + // Check infatuation + if (gBattleMons[gBattlerTarget].volatiles.infatuation) + { + gBattleMons[gBattlerTarget].volatiles.infatuation = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); + } + // Check taunt + if (gDisableStructs[gBattlerTarget].tauntTimer != 0) + { + gDisableStructs[gBattlerTarget].tauntTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + } + // Check encore + if (gDisableStructs[gBattlerTarget].encoreTimer != 0) + { + gDisableStructs[gBattlerTarget].encoredMove = 0; + gDisableStructs[gBattlerTarget].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED + } + // Check torment + if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE) + { + gBattleMons[gBattlerTarget].volatiles.torment = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; + } + // Check heal block + if (gBattleMons[gBattlerTarget].volatiles.healBlock) + { + gBattleMons[gBattlerTarget].volatiles.healBlock = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; + } + // Check disable + if (gDisableStructs[gBattlerTarget].disableTimer != 0) + { + gDisableStructs[gBattlerTarget].disableTimer = 0; + gDisableStructs[gBattlerTarget].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryResetNegativeStatStages(void) +{ + NATIVE_ARGS(); + for (u32 stat = 0; stat < NUM_BATTLE_STATS; stat++) + if (gBattleMons[gBattlerTarget].statStages[stat] < DEFAULT_STAT_STAGE) + gBattleMons[gBattlerTarget].statStages[stat] = DEFAULT_STAT_STAGE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfLastUsedItemBerry(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + if (GetItemPocket(gLastUsedItem) == POCKET_BERRIES) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SaveBattlerItem(void) +{ + NATIVE_ARGS(); + gBattleHistory->heldItems[gBattlerTarget] = gBattleMons[gBattlerTarget].item; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_RestoreBattlerItem(void) +{ + NATIVE_ARGS(); + gBattleMons[gBattlerTarget].item = gBattleHistory->heldItems[gBattlerTarget]; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_BattlerItemToLastUsedItem(void) +{ + NATIVE_ARGS(); + gBattleMons[gBattlerTarget].item = gLastUsedItem; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfGenConfigLowerThan(void) +{ + NATIVE_ARGS(u16 tag, u8 gen, const u8 *jumpInstr); + if (GetGenConfig(cmd->tag) < cmd->gen) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_GetBattlersForRecall(void) +{ + NATIVE_ARGS(); + u32 battler = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + for (u32 i = 0; battler < MAX_BATTLERS_COUNT; battler += 2) + { + if (battler < gBattlersCount && gBattleMons[battler].hp != 0) + gBattleCommunication[MULTISTRING_CHOOSER] |= gBitTable[i]; + i++; + } + + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_terastal.c b/src/battle_terastal.c index 6984f3fc6..05b27a48f 100644 --- a/src/battle_terastal.c +++ b/src/battle_terastal.c @@ -62,9 +62,9 @@ void ApplyBattlerVisualsForTeraAnim(u32 battler) // Returns whether a battler can Terastallize. bool32 CanTerastallize(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED && GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_TERAPAGOS) + if (gBattleMons[battler].volatiles.transformed && GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_TERAPAGOS) return FALSE; // Prevents Zigzagoon from terastalizing in vanilla. @@ -132,20 +132,19 @@ bool32 IsTypeStellarBoosted(u32 battler, u32 type) // Returns the STAB power multiplier to use when Terastallized. // Power multipliers from Smogon Research thread. -uq4_12_t GetTeraMultiplier(u32 battler, u32 type) +uq4_12_t GetTeraMultiplier(struct DamageContext *ctx) { - u32 teraType = GetBattlerTeraType(battler); - bool32 hasAdaptability = (GetBattlerAbility(battler) == ABILITY_ADAPTABILITY); + u32 teraType = GetBattlerTeraType(ctx->battlerAtk); // Safety check. - if (GetActiveGimmick(battler) != GIMMICK_TERA) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_TERA) return UQ_4_12(1.0); // Stellar-type checks. if (teraType == TYPE_STELLAR) { - bool32 shouldBoost = IsTypeStellarBoosted(battler, type); - if (IS_BATTLER_OF_BASE_TYPE(battler, type)) + bool32 shouldBoost = IsTypeStellarBoosted(ctx->battlerAtk, ctx->moveType); + if (IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) { if (shouldBoost) return UQ_4_12(2.0); @@ -158,18 +157,18 @@ uq4_12_t GetTeraMultiplier(u32 battler, u32 type) return UQ_4_12(1.0); } // Base and Tera type. - if (type == teraType && IS_BATTLER_OF_BASE_TYPE(battler, type)) + if (ctx->moveType == teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) { - if (hasAdaptability) + if (ctx->abilityAtk == ABILITY_ADAPTABILITY) return UQ_4_12(2.25); else return UQ_4_12(2.0); } // Base or Tera type only. - else if ((type == teraType && !IS_BATTLER_OF_BASE_TYPE(battler, type)) - || (type != teraType && IS_BATTLER_OF_BASE_TYPE(battler, type))) + else if ((ctx->moveType == teraType && !IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType)) + || (ctx->moveType != teraType && IS_BATTLER_OF_BASE_TYPE(ctx->battlerAtk, ctx->moveType))) { - if (hasAdaptability) + if (ctx->abilityAtk == ABILITY_ADAPTABILITY) return UQ_4_12(2.0); else return UQ_4_12(1.5); diff --git a/src/battle_util.c b/src/battle_util.c index d87ee8fb8..fb7092030 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2,6 +2,7 @@ #include "battle.h" #include "battle_anim.h" // #include "battle_arena.h" +#include "battle_environment.h" // #include "battle_pyramid.h" #include "battle_util.h" #include "battle_controllers.h" @@ -44,6 +45,7 @@ #include "constants/battle_string_ids.h" #include "constants/hold_effects.h" #include "constants/items.h" +#include "constants/item_effects.h" #include "constants/moves.h" #include "constants/songs.h" #include "constants/species.h" @@ -65,8 +67,16 @@ static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); static bool32 CanBeInfinitelyConfused(u32 battler); static bool32 IsAnyTargetAffected(u32 battlerAtk); -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum NonVolatileStatus option); -static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonVolatileStatus option); +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option); +static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option); + +// Submoves +static u32 GetMirrorMoveMove(void); +static u32 GetMetronomeMove(void); +static u32 GetAssistMove(void); +static u32 GetSleepTalkMove(void); +static u32 GetCopyCatMove(void); +static u32 GetMeFirstMove(void); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent); @@ -182,7 +192,7 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = // Helper function for actual dmg calcs during battle. For simulated AI dmg, CalcTypeEffectivenessMultiplier should be used directly // This should stay a static function. Ideally everything else is handled through CalcTypeEffectivenessMultiplier just like AI -static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u32 defAbility, bool32 recordAbilities) +static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, bool32 recordAbilities) { struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; @@ -190,10 +200,10 @@ static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u3 ctx.move = move; ctx.moveType = moveType; ctx.updateFlags = recordAbilities; - ctx.abilityAtk = GetBattlerAbility(battlerAtk); - ctx.abilityDef = defAbility; - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.abilityAtk = abilityAtk; + ctx.abilityDef = abilityDef; + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); return CalcTypeEffectivenessMultiplier(&ctx); } @@ -243,18 +253,11 @@ bool32 EndOrContinueWeather(void) static u32 CalcBeatUpPower(void) { - u32 basePower; - u32 species; - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - - // Party slot is incremented by the battle script for Beat Up after this damage calculation - species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); - basePower = (GetSpeciesBaseAttack(species) / 10) + 5; - - return basePower; + u32 species = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++]; + return (GetSpeciesBaseAttack(species) / 10) + 5; } -static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef) +static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, enum Ability abilityDef) { if (!gSpecialStatuses[battlerDef].distortedTypeMatchups && gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL @@ -279,7 +282,7 @@ static inline bool32 IsDragonDartsSecondHit(u32 effect) bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) { - u32 ability = GetBattlerAbility(battlerAtk); + enum Ability ability = GetBattlerAbility(battlerAtk); enum BattleMoveEffects effect = GetMoveEffect(move); if (gSideTimers[defSide].followmeTimer == 0 @@ -293,7 +296,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) return FALSE; - if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) + if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk))) return FALSE; return TRUE; @@ -306,7 +309,7 @@ bool32 HandleMoveTargetRedirection(void) u32 moveType = GetBattleMoveType(gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); u32 side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); - u32 ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); + enum Ability ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove) && moveTarget == MOVE_TARGET_SELECTED @@ -322,7 +325,7 @@ bool32 HandleMoveTargetRedirection(void) || (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { // Find first battler that redirects the move (in turn order) - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 battler; for (battler = 0; battler < gBattlersCount; battler++) { @@ -341,17 +344,13 @@ bool32 HandleMoveTargetRedirection(void) redirectorOrderNum = GetBattlerTurnOrderNum(battler); } } - if (redirectorOrderNum != MAX_BATTLERS_COUNT) + if (redirectorOrderNum != MAX_BATTLERS_COUNT && gCurrentMove != MOVE_TEATIME) { - u16 battlerAbility; + enum Ability battlerAbility; battler = gBattlerByTurnOrder[redirectorOrderNum]; battlerAbility = GetBattlerAbility(battler); - - RecordAbilityBattle(battler, gBattleMons[battler].ability); - if (battlerAbility == ABILITY_LIGHTNING_ROD && gCurrentMove != MOVE_TEATIME) - gSpecialStatuses[battler].lightningRodRedirected = TRUE; - else if (battlerAbility == ABILITY_STORM_DRAIN) - gSpecialStatuses[battler].stormDrainRedirected = TRUE; + RecordAbilityBattle(battler, battlerAbility); + gSpecialStatuses[battler].abilityRedirected = TRUE; gBattlerTarget = battler; return TRUE; } @@ -386,10 +385,9 @@ void HandleAction_UseMove(void) { gProtectStructs[gBattlerAttacker].noValidMoves = FALSE; gCurrentMove = gChosenMove = MOVE_STRUGGLE; - gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE); } - else if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS || gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) + else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gBattleMons[gBattlerAttacker].volatiles.recharge) { gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker]; } @@ -575,6 +573,11 @@ void HandleAction_UseItem(void) ClearVariousBattlerFlags(gBattlerAttacker); gLastUsedItem = gBattleResources->bufferB[gBattlerAttacker][1] | (gBattleResources->bufferB[gBattlerAttacker][2] << 8); + if (X_ITEM_FRIENDSHIP_INCREASE > 0 + && GetItemEffectType(gLastUsedItem) == ITEM_EFFECT_X_ITEM + && !ShouldSkipFriendshipChange()) + UpdateFriendshipFromXItem(gBattlerAttacker); + gBattlescriptCurrInstr = gBattlescriptsForUsingItem[GetItemBattleUsage(gLastUsedItem) - 1]; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } @@ -609,7 +612,7 @@ bool32 TryRunFromBattle(u32 battler) } else if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY) { - // if (InBattlePyramid()) + // if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) // { // gBattleStruct->runTries++; // pyramidMultiplier = GetPyramidRunMultiplier(); @@ -628,7 +631,7 @@ bool32 TryRunFromBattle(u32 battler) effect++; // } } - else if (IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)) + else if (IsGhostBattleWithoutScope()) { if (GetBattlerSide(battler) == B_SIDE_PLAYER) effect++; @@ -647,7 +650,7 @@ bool32 TryRunFromBattle(u32 battler) if (!IsBattlerAlive(runningFromBattler)) runningFromBattler |= BIT_FLANK; - // if (InBattlePyramid()) + // if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) // { // pyramidMultiplier = GetPyramidRunMultiplier(); // speedVar = (gBattleMons[battler].speed * pyramidMultiplier) / (gBattleMons[runningFromBattler].speed) + (gBattleStruct->runTries * 30); @@ -867,9 +870,12 @@ void HandleAction_NothingIsFainted(void) gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED - | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE - | HITMARKER_OBEYS); + gHitMarker &= ~(HITMARKER_DESTINYBOND + | HITMARKER_ATTACKSTRING_PRINTED + | HITMARKER_IGNORE_SUBSTITUTE + | HITMARKER_STATUS_ABILITY_EFFECT + | HITMARKER_PASSIVE_HP_UPDATE + | HITMARKER_OBEYS); } void HandleAction_ActionFinished(void) @@ -880,9 +886,13 @@ void HandleAction_ActionFinished(void) gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; SpecialStatusesClear(); - gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED - | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE - | HITMARKER_OBEYS | HITMARKER_IGNORE_DISGUISE); + gHitMarker &= ~(HITMARKER_DESTINYBOND + | HITMARKER_IGNORE_SUBSTITUTE + | HITMARKER_ATTACKSTRING_PRINTED + | HITMARKER_STATUS_ABILITY_EFFECT + | HITMARKER_PASSIVE_HP_UPDATE + | HITMARKER_OBEYS + | HITMARKER_IGNORE_DISGUISE); ClearDamageCalcResults(); gCurrentMove = 0; @@ -894,11 +904,10 @@ void HandleAction_ActionFinished(void) gBattleScripting.moveendState = 0; gBattleCommunication[3] = 0; gBattleCommunication[4] = 0; - gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_NONE; - if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) + if (GetGenConfig(GEN_CONFIG_RECALC_TURN_AFTER_ACTIONS) >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action @@ -1041,7 +1050,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) const u8 *result = NULL; u8 otherSkyDropper = gBattleStruct->skyDropTargets[battler]; - gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE; // Makes both attacker and target's sprites visible gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; @@ -1050,18 +1059,19 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) // If target was sky dropped in the middle of Outrage/Thrash/Petal Dance, // confuse them upon release and display "confused by fatigue" message & animation. // Don't do this if this CancelMultiTurnMoves is caused by falling asleep via Yawn. - if (gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE && skyDropState != SKY_DROP_STATUS_YAWN) + if (gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns && skyDropState != SKY_DROP_STATUS_YAWN) { - gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns = 0; // If the target can be confused, confuse them. // Don't use CanBeConfused, can cause issues in edge cases. - if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION - || IsAbilityAndRecord(otherSkyDropper, GetBattlerAbility(otherSkyDropper), ABILITY_OWN_TEMPO) - || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) + enum Ability ability = GetBattlerAbility(otherSkyDropper); + if (!(gBattleMons[otherSkyDropper].volatiles.confusionTurns > 0 + || IsAbilityAndRecord(otherSkyDropper, ability, ABILITY_OWN_TEMPO) + || IsBattlerTerrainAffected(otherSkyDropper, ability, GetBattlerHoldEffect(otherSkyDropper), STATUS_FIELD_MISTY_TERRAIN))) { // Set confused status - gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; if (skyDropState == SKY_DROP_ATTACKCANCELLER_CHECK) { @@ -1069,9 +1079,9 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) } else if (skyDropState == SKY_DROP_GRAVITY_ON_AIRBORNE) { - // Reapplying STATUS3_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target. + // Reapplying STATE_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target. gBattleStruct->skyDropTargets[battler] = SKY_DROP_RELEASED_TARGET; - gStatuses3[otherSkyDropper] |= STATUS3_SKY_DROPPED; + gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_SKY_DROP; } else if (skyDropState == SKY_DROP_CANCEL_MULTI_TURN_MOVES) { @@ -1088,7 +1098,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) } // Clear skyDropTargets data, unless this CancelMultiTurnMoves is caused by Yawn, attackcanceler, or VARIOUS_GRAVITY_ON_AIRBORNE_MONS - if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[battler] < 4) + if (!(gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns) && gBattleStruct->skyDropTargets[battler] < 4) { gBattleStruct->skyDropTargets[battler] = SKY_DROP_NO_TARGET; gBattleStruct->skyDropTargets[otherSkyDropper] = SKY_DROP_NO_TARGET; @@ -1100,25 +1110,25 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState) { const u8 *result = NULL; - gBattleMons[battler].status2 &= ~(STATUS2_UPROAR); - gBattleMons[battler].status2 &= ~(STATUS2_BIDE); + gBattleMons[battler].volatiles.uproarTurns = 0; + gBattleMons[battler].volatiles.bideTurns = 0; if (B_RAMPAGE_CANCELLING < GEN_5) { - gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); - gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[battler].volatiles.multipleTurns = 0; + gBattleMons[battler].volatiles.lockConfusionTurns = 0; } - else if (!(gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) - || ((gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) > STATUS2_LOCK_CONFUSE_TURN(1))) + else if (!gBattleMons[battler].volatiles.lockConfusionTurns + || gBattleMons[battler].volatiles.lockConfusionTurns > 1) { - gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); + gBattleMons[battler].volatiles.multipleTurns = 0; } // Clear battler's semi-invulnerable bits if they are not held by Sky Drop. - if (!(gStatuses3[battler] & STATUS3_SKY_DROPPED)) - gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE); + if (gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) + gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE; - if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) result = CheckSkyDropState(battler, skyDropState); gDisableStructs[battler].rolloutTimer = 0; @@ -1131,13 +1141,12 @@ bool32 WasUnableToUseMove(u32 battler) { if (gProtectStructs[battler].nonVolatileStatusImmobility || gProtectStructs[battler].unableToUseMove - || gProtectStructs[battler].powderSelfDmg || gProtectStructs[battler].confusionSelfDmg) return TRUE; return FALSE; } -bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability) +bool32 ShouldDefiantCompetitiveActivate(u32 battler, enum Ability ability) { u32 side = GetBattlerSide(battler); if (ability != ABILITY_DEFIANT && ability != ABILITY_COMPETITIVE) @@ -1159,19 +1168,54 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) // Support for Contrary ability. // If a move attempted to raise stat - print "won't increase". // If a move attempted to lower stat - print "won't decrease". - if (stringId == STRINGID_STATSWONTDECREASE && !(gBattleScripting.statChanger & STAT_BUFF_NEGATIVE)) - stringId = STRINGID_STATSWONTINCREASE; - else if (stringId == STRINGID_STATSWONTINCREASE && gBattleScripting.statChanger & STAT_BUFF_NEGATIVE) - stringId = STRINGID_STATSWONTDECREASE; + switch (stringId) + { + case STRINGID_ATTACKERSSTATROSE: + case STRINGID_DEFENDERSSTATROSE: + case STRINGID_STATSWONTINCREASE: + case STRINGID_USINGITEMSTATOFPKMNROSE: + if (gBattleScripting.statChanger & STAT_BUFF_NEGATIVE) + stringId = gStatDownStringIds[gBattleCommunication[MULTISTRING_CHOOSER]]; + break; + case STRINGID_ATTACKERSSTATFELL: + case STRINGID_DEFENDERSSTATFELL: + case STRINGID_STATSWONTDECREASE: + case STRINGID_USINGITEMSTATOFPKMNFELL: + if (!(gBattleScripting.statChanger & STAT_BUFF_NEGATIVE)) + stringId = gStatUpStringIds[gBattleCommunication[MULTISTRING_CHOOSER]]; + break; + case STRINGID_STATSWONTINCREASE2: + if (battlerAbility == ABILITY_CONTRARY) + stringId = STRINGID_STATSWONTDECREASE2; + break; + case STRINGID_STATSWONTDECREASE2: + if (battlerAbility == ABILITY_CONTRARY) + stringId = STRINGID_STATSWONTINCREASE2; + break; + case STRINGID_PKMNCUTSATTACKWITH: + if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8 + && targetAbility == ABILITY_RATTLED + && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gBattlerAbility = gBattlerTarget; + BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); + SET_STATCHANGER(STAT_SPEED, 1, FALSE); + } + else if (targetAbility == ABILITY_CONTRARY) + { + stringId = STRINGID_DEFENDERSSTATROSE; + } + break; + case STRINGID_ITDOESNTAFFECT: + case STRINGID_PKMNUNAFFECTED: + TryInitializeTrainerSlideEnemyMonUnaffected(gBattlerTarget); + break; + default: + break; + } - else if (stringId == STRINGID_STATSWONTDECREASE2 && battlerAbility == ABILITY_CONTRARY) - stringId = STRINGID_STATSWONTINCREASE2; - else if (stringId == STRINGID_STATSWONTINCREASE2 && battlerAbility == ABILITY_CONTRARY) - stringId = STRINGID_STATSWONTDECREASE2; - - // Check Defiant and Competitive stat raise whenever a stat is lowered. - else if ((stringId == STRINGID_DEFENDERSSTATFELL || stringId == STRINGID_PKMNCUTSATTACKWITH) - && ShouldDefiantCompetitiveActivate(gBattlerTarget, targetAbility)) + if ((stringId == STRINGID_PKMNCUTSATTACKWITH || stringId == STRINGID_DEFENDERSSTATFELL) + && ShouldDefiantCompetitiveActivate(gBattlerTarget, targetAbility)) { gBattlerAbility = gBattlerTarget; BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); @@ -1180,16 +1224,6 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) else SET_STATCHANGER(STAT_SPATK, 2, FALSE); } - else if (B_UPDATED_INTIMIDATE >= GEN_8 && stringId == STRINGID_PKMNCUTSATTACKWITH && targetAbility == ABILITY_RATTLED - && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - gBattlerAbility = gBattlerTarget; - BattleScriptCall(BattleScript_AbilityRaisesDefenderStat); - SET_STATCHANGER(STAT_SPEED, 1, FALSE); - } - - if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED)) - TryInitializeTrainerSlideEnemyMonUnaffected(gBattlerTarget); BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, stringId); MarkBattlerForControllerExec(battler); @@ -1275,7 +1309,7 @@ static bool32 IsGravityPreventingMove(u32 move) bool32 IsHealBlockPreventingMove(u32 battler, u32 move) { - if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!gBattleMons[battler].volatiles.healBlock) return FALSE; return IsHealingMove(move); @@ -1286,7 +1320,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move) if (GetMoveEffect(move) != EFFECT_BELCH) return FALSE; - return !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry; + return !GetBattlerPartyState(battler)->ateBerry; } // Dynamax bypasses all selection prevention except Taunt and Assault Vest. @@ -1297,7 +1331,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) u32 limitations = 0; u8 moveId = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK; u32 move = gBattleMons[battler].moves[moveId]; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); u16 *choicedMove = &gBattleStruct->choicedMove[battler]; enum BattleMoveEffects moveEffect = GetMoveEffect(move); @@ -1335,7 +1369,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) // } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].volatiles.torment == TRUE)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); // if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1475,7 +1509,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } gPotentialItemEffectBattler = battler; - if (DYNAMAX_BYPASS_CHECK && HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) + if (DYNAMAX_BYPASS_CHECK && IsHoldEffectChoice(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) { gCurrentMove = *choicedMove; gLastUsedItem = gBattleMons[battler].item; @@ -1559,7 +1593,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) { u32 move; enum BattleMoveEffects moveEffect; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); u16 *choicedMove = &gBattleStruct->choicedMove[battler]; s32 i; @@ -1582,7 +1616,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) else if (check & MOVE_LIMITATION_DISABLED && move == gDisableStructs[battler].disabledMove) unusableMoves |= 1u << i; // Torment - else if (check & MOVE_LIMITATION_TORMENTED && move == gLastMoves[battler] && gBattleMons[battler].status2 & STATUS2_TORMENT) + else if (check & MOVE_LIMITATION_TORMENTED && move == gLastMoves[battler] && gBattleMons[battler].volatiles.torment == TRUE) unusableMoves |= 1u << i; // Taunt else if (check & MOVE_LIMITATION_TAUNT && gDisableStructs[battler].tauntTimer && IsBattleMoveStatus(move)) @@ -1594,7 +1628,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) else if (check & MOVE_LIMITATION_ENCORE && gDisableStructs[battler].encoreTimer && gDisableStructs[battler].encoredMove != move) unusableMoves |= 1u << i; // Choice Items - else if (check & MOVE_LIMITATION_CHOICE_ITEM && HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) + else if (check & MOVE_LIMITATION_CHOICE_ITEM && IsHoldEffectChoice(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) unusableMoves |= 1u << i; // Assault Vest else if (check & MOVE_LIMITATION_ASSAULT_VEST && holdEffect == HOLD_EFFECT_ASSAULT_VEST && IsBattleMoveStatus(move) && moveEffect != EFFECT_ME_FIRST) @@ -1650,7 +1684,7 @@ u8 GetImprisonedMovesCount(u32 battler, u16 move) for (i = 0; i < gBattlersCount; i++) { - if (battlerSide != GetBattlerSide(i) && gStatuses3[i] & STATUS3_IMPRISONED_OTHERS) + if (battlerSide != GetBattlerSide(i) && gBattleMons[i].volatiles.imprison) { s32 j; for (j = 0; j < MAX_MON_MOVES; j++) @@ -1730,7 +1764,7 @@ void TryToRevertMimicryAndFlags(void) // Ingrain, Leech Seed, Strength Sap and Aqua Ring s32 GetDrainedBigRootHp(u32 battler, s32 hp) { - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_BIG_ROOT) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_BIG_ROOT) hp = (hp * 1300) / 1000; if (hp == 0) hp = 1; @@ -1739,7 +1773,7 @@ s32 GetDrainedBigRootHp(u32 battler, s32 hp) } // Should always be the last check. Otherwise the ability might be wrongly recorded. -bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck) +bool32 IsAbilityAndRecord(u32 battler, enum Ability battlerAbility, enum Ability abilityToCheck) { if (battlerAbility != abilityToCheck) return FALSE; @@ -1843,8 +1877,8 @@ void TryClearRageAndFuryCutter(void) s32 i; for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_RAGE) && gChosenMoveByBattler[i] != MOVE_RAGE) - gBattleMons[i].status2 &= ~STATUS2_RAGE; + if (gBattleMons[i].volatiles.rage && gChosenMoveByBattler[i] != MOVE_RAGE) + gBattleMons[i].volatiles.rage = FALSE; if (gDisableStructs[i].furyCutterCounter != 0 && gChosenMoveByBattler[i] != MOVE_FURY_CUTTER) gDisableStructs[i].furyCutterCounter = 0; } @@ -1858,14 +1892,15 @@ static inline bool32 TryFormChangeBeforeMove(void) if (!result) return FALSE; - BattleScriptCall(BattleScript_AttackerFormChange); + gBattleScripting.battler = gBattlerAttacker; + BattleScriptCall(BattleScript_BattlerFormChange); return TRUE; } static inline bool32 TryActivatePowderStatus(u32 move) { - u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]]; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)) + u32 partnerMove = GetChosenMoveFromPosition(BATTLE_PARTNER(gBattlerAttacker)); + if (!gBattleMons[gBattlerAttacker].volatiles.powder) return FALSE; if (GetBattleMoveType(move) == TYPE_FIRE && !gBattleStruct->pledgeMove) return TRUE; @@ -1876,62 +1911,56 @@ static inline bool32 TryActivatePowderStatus(u32 move) return FALSE; } -void SetAtkCancellerForCalledMove(void) +static enum MoveCanceller CancellerClearFlags(struct BattleContext *ctx) { - gBattleStruct->atkCancellerTracker = CANCELLER_VOLATILE_BLOCKED; - gBattleStruct->isAtkCancelerForCalledMove = TRUE; -} - -static enum MoveCanceller CancellerFlags(void) -{ - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND; - gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; - gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH; + gBattleMons[ctx->battlerAtk].volatiles.grudge = FALSE; + gBattleMons[ctx->battlerAtk].volatiles.glaiveRush = FALSE; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerStanceChangeOne(void) +static enum MoveCanceller CancellerStanceChangeOne(struct BattleContext *ctx) { - if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) + if (B_STANCE_CHANGE_FAIL < GEN_7 && gChosenMove == ctx->currentMove && TryFormChangeBeforeMove()) return MOVE_STEP_BREAK; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerSkyDrop(void) +static enum MoveCanceller CancellerSkyDrop(struct BattleContext *ctx) { // If Pokemon is being held in Sky Drop - if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED) + if (gBattleMons[ctx->battlerAtk].volatiles.semiInvulnerable == STATE_SKY_DROP) { gBattlescriptCurrInstr = BattleScript_MoveEnd; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerRecharge(void) +static enum MoveCanceller CancellerRecharge(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) + if (gBattleMons[ctx->battlerAtk].volatiles.recharge) { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RECHARGE; - gDisableStructs[gBattlerAttacker].rechargeTimer = 0; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gBattleMons[ctx->battlerAtk].volatiles.recharge = TRUE; + gDisableStructs[ctx->battlerAtk].rechargeTimer = 0; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerAsleepOrFrozen(void) +static enum MoveCanceller CancellerAsleepOrFrozen(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) { - if (UproarWakeUpCheck(gBattlerAttacker)) + if (UproarWakeUpCheck(ctx->battlerAtk)) { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]); + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP; + gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE; + gEffectBattler = ctx->battlerAtk; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; @@ -1939,20 +1968,19 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void) else { u8 toSub; - if (IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_EARLY_BIRD)) + if (IsAbilityAndRecord(ctx->battlerAtk, ctx->ability[ctx->battlerAtk], ABILITY_EARLY_BIRD)) toSub = 2; else toSub = 1; - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) < toSub) - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; + if ((gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) < toSub) + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP; else - gBattleMons[gBattlerAttacker].status1 -= toSub; - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + gBattleMons[ctx->battlerAtk].status1 -= toSub; + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) { - enum BattleMoveEffects moveEffect = GetMoveEffect(gChosenMove); - if (moveEffect != EFFECT_SNORE && moveEffect != EFFECT_SLEEP_TALK) + if (ctx->moveEffect != EFFECT_SNORE && ctx->moveEffect != EFFECT_SLEEP_TALK) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_REMOVES_STATUS; @@ -1960,169 +1988,186 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void) } else { - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]); + gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; } } } - else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !MoveThawsUser(gCurrentMove)) + else if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE && !MoveThawsUser(ctx->currentMove)) { if (!RandomPercentage(RNG_FROZEN, 20)) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; - gHitMarker |= (HITMARKER_NO_ATTACKSTRING | HITMARKER_UNABLE_TO_USE_MOVE); + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; } else // unfreeze { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE; BattleScriptCall(BattleScript_MoveUsedUnfroze); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED; } - return MOVE_STEP_REMOVES_STATUS; + return MOVE_STEP_REMOVES_STATUS; // Move failure but also removes status } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerObedience(void) +static enum MoveCanceller CancellerObedience(struct BattleContext *ctx) { - enum Obedience obedienceResult = GetAttackerObedienceForAction(); - if (!(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves - && !gBattleMons[gBattlerAttacker].volatiles.multipleTurns) + if (!gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) { + enum Obedience obedienceResult = GetAttackerObedienceForAction(); switch (obedienceResult) { case OBEYS: gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_SUCCESS; case DISOBEYS_LOAFS: // Randomly select, then print a disobedient string // B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE gBattleCommunication[MULTISTRING_CHOOSER] = MOD(Random(), NUM_LOAF_STRINGS); gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; case DISOBEYS_HITS_SELF: - gBattlerTarget = gBattlerAttacker; - struct DamageContext ctx; - ctx.battlerAtk = ctx.battlerDef = gBattlerAttacker; - ctx.move = MOVE_NONE; - ctx.moveType = TYPE_MYSTERY; - ctx.isCrit = FALSE; - ctx.randomFactor = FALSE; - ctx.updateFlags = TRUE; - ctx.fixedBasePower = 40; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); + gBattlerTarget = ctx->battlerAtk; + struct DamageContext dmgCtx; + dmgCtx.battlerAtk = dmgCtx.battlerDef = ctx->battlerAtk; + dmgCtx.move = MOVE_NONE; + dmgCtx.moveType = TYPE_MYSTERY; + dmgCtx.isCrit = FALSE; + dmgCtx.randomFactor = FALSE; + dmgCtx.updateFlags = TRUE; + dmgCtx.fixedBasePower = 40; + gBattleStruct->moveDamage[ctx->battlerAtk] = CalculateMoveDamage(&dmgCtx); gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_FAILURE; // Move doesn't fail but mon hits itself case DISOBEYS_FALL_ASLEEP: if (IsSleepClauseEnabled()) - gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; + gBattleStruct->battlerState[ctx->battlerAtk].sleepClauseEffectExempt = TRUE; gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; break; case DISOBEYS_WHILE_ASLEEP: gBattlescriptCurrInstr = BattleScript_IgnoresWhileAsleep; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - break; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; case DISOBEYS_RANDOM_MOVE: - gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - SetAtkCancellerForCalledMove(); - gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; + gCurrentMove = gCalledMove = gBattleMons[ctx->battlerAtk].moves[gCurrMovePos]; + BattleScriptCall(BattleScript_IgnoresAndUsesRandomMove); gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gHitMarker |= HITMARKER_OBEYS; - break; + return MOVE_STEP_BREAK; } - return MOVE_STEP_BREAK; } gHitMarker |= HITMARKER_OBEYS; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerTruant(void) +static enum MoveCanceller CancellerPowerPoints(struct BattleContext *ctx) { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) + if (gBattleMons[ctx->battlerAtk].pp[gCurrMovePos] == 0 + && ctx->currentMove != MOVE_STRUGGLE + && !gSpecialStatuses[ctx->battlerAtk].dancerUsedMove + && !gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gBattlescriptCurrInstr = BattleScript_NoPPForMove; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerTruant(struct BattleContext *ctx) +{ + if (GetBattlerAbility(ctx->battlerAtk) == ABILITY_TRUANT && gDisableStructs[ctx->battlerAtk].truantCounter) + { + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING; - gBattlerAbility = gBattlerAttacker; + gBattlerAbility = ctx->battlerAtk; gBattlescriptCurrInstr = BattleScript_TruantLoafingAround; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return MOVE_STEP_BREAK; + gBattleStruct->moveResultFlags[ctx->battlerDef] |= MOVE_RESULT_MISSED; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerFlinch(void) +static enum MoveCanceller CancellerFlinch(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) + if (gBattleMons[ctx->battlerAtk].volatiles.flinched) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerDisabled(void) +static enum MoveCanceller CancellerDisabled(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + && gDisableStructs[ctx->battlerAtk].disabledMove == ctx->currentMove + && gDisableStructs[ctx->battlerAtk].disabledMove != MOVE_NONE) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerVolatileBlocked(void) +static enum MoveCanceller CancellerVolatileBlocked(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + && gBattleMons[ctx->battlerAtk].volatiles.healBlock + && IsHealBlockPreventingMove(ctx->battlerAtk, ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } - else if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove)) + else if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + gBattleScripting.battler = ctx->battlerAtk; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } - else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer > gBattleTurnCounter && IsSoundMove(gCurrentMove)) + else if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && gDisableStructs[ctx->battlerAtk].throatChopTimer > gBattleTurnCounter && IsSoundMove(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerTaunted(void) +static enum MoveCanceller CancellerTaunted(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IsBattleMoveStatus(gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && gDisableStructs[ctx->battlerAtk].tauntTimer && IsBattleMoveStatus(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2130,45 +2175,41 @@ static enum MoveCanceller CancellerTaunted(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerImprisoned(void) +static enum MoveCanceller CancellerImprisoned(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(ctx->battlerAtk, ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerConfused(void) +static enum MoveCanceller CancellerConfused(struct BattleContext *ctx) { - if (gBattleStruct->isAtkCancelerForCalledMove) - return MOVE_STEP_SUCCESS; - - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + if (gBattleMons[ctx->battlerAtk].volatiles.confusionTurns) { - if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) - gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + if (!gBattleMons[ctx->battlerAtk].volatiles.infiniteConfusion) + gBattleMons[ctx->battlerAtk].volatiles.confusionTurns--; + if (gBattleMons[ctx->battlerAtk].volatiles.confusionTurns) { // confusion dmg if (RandomPercentage(RNG_CONFUSION, (GetGenConfig(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50))) { gBattleCommunication[MULTISTRING_CHOOSER] = TRUE; - gBattlerTarget = gBattlerAttacker; - struct DamageContext ctx; - ctx.battlerAtk = ctx.battlerDef = gBattlerAttacker; - ctx.move = MOVE_NONE; - ctx.moveType = TYPE_MYSTERY; - ctx.isCrit = FALSE; - ctx.randomFactor = FALSE; - ctx.updateFlags = TRUE; - ctx.fixedBasePower = 40; - gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); - gProtectStructs[gBattlerAttacker].confusionSelfDmg = TRUE; + struct DamageContext dmgCtx; + dmgCtx.battlerAtk = dmgCtx.battlerDef = ctx->battlerAtk; + dmgCtx.move = MOVE_NONE; + dmgCtx.moveType = TYPE_MYSTERY; + dmgCtx.isCrit = FALSE; + dmgCtx.randomFactor = FALSE; + dmgCtx.updateFlags = TRUE; + dmgCtx.fixedBasePower = 40; + gBattleStruct->moveDamage[ctx->battlerAtk] = CalculateMoveDamage(&dmgCtx); + gProtectStructs[ctx->battlerAtk].confusionSelfDmg = TRUE; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; } @@ -2187,11 +2228,11 @@ static enum MoveCanceller CancellerConfused(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerGhost(void) // GHOST in pokemon tower +static enum MoveCanceller CancellerGhost(struct BattleContext *ctx) // GHOST in pokemon tower { - if (IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)) + if (IsGhostBattleWithoutScope()) { - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) + if (GetBattlerSide(ctx->battlerAtk) == B_SIDE_PLAYER) gBattlescriptCurrInstr = BattleScript_TooScaredToMove; else gBattlescriptCurrInstr = BattleScript_GhostGetOutGetOut; @@ -2201,93 +2242,196 @@ static enum MoveCanceller CancellerGhost(void) // GHOST in pokemon tower return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerParalysed(void) +static enum MoveCanceller CancellerParalysed(struct BattleContext *ctx) { - if (!gBattleStruct->isAtkCancelerForCalledMove - && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) - && !(B_MAGIC_GUARD == GEN_4 && IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_PARALYSIS + && !(B_MAGIC_GUARD == GEN_4 && IsAbilityAndRecord(ctx->battlerAtk, ctx->ability[ctx->battlerAtk], ABILITY_MAGIC_GUARD)) && !RandomPercentage(RNG_PARALYSIS, 75)) { - gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; + gProtectStructs[ctx->battlerAtk].nonVolatileStatusImmobility = TRUE; // This is removed in FRLG and Emerald for some reason //CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerInfatuation(void) +static enum MoveCanceller CancellerInfatuation(struct BattleContext *ctx) { - if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) + if (gBattleMons[ctx->battlerAtk].volatiles.infatuation) { - gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10); + gBattleScripting.battler = gBattleMons[ctx->battlerAtk].volatiles.infatuation - 1; if (!RandomPercentage(RNG_INFATUATION, 50)) { BattleScriptCall(BattleScript_MoveUsedIsInLove); + return MOVE_STEP_BREAK; } else { BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].unableToUseMove = TRUE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; + return MOVE_STEP_FAILURE; } - return MOVE_STEP_BREAK; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerBide(void) +static enum MoveCanceller CancellerBide(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + if (gBattleMons[ctx->battlerAtk].volatiles.bideTurns) { - gBattleMons[gBattlerAttacker].status2 -= STATUS2_BIDE_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + if (--gBattleMons[ctx->battlerAtk].volatiles.bideTurns) { gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; } else { // This is removed in FRLG and Emerald for some reason - //gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; - if (gBideDmg[gBattlerAttacker]) + //gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; + if (gBideDmg[ctx->battlerAtk]) { gCurrentMove = MOVE_BIDE; - gBattlerTarget = gBideTarget[gBattlerAttacker]; - if (gAbsentBattlerFlags & (1u << gBattlerTarget)) + gBattlerTarget = gBideTarget[ctx->battlerAtk]; + if (gAbsentBattlerFlags & (1u << ctx->battlerDef)) gBattlerTarget = GetBattleMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); gBattlescriptCurrInstr = BattleScript_BideAttack; + return MOVE_STEP_BREAK; // Jumps to a different script but no failure } else { gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; + return MOVE_STEP_FAILURE; } } + } + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerZMoves(struct BattleContext *ctx) +{ + if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_Z_MOVE) + { + // attacker has a queued z move + RecordItemEffectBattle(ctx->battlerAtk, HOLD_EFFECT_Z_CRYSTAL); + SetGimmickAsActivated(ctx->battlerAtk, GIMMICK_Z_MOVE); + + gBattleScripting.battler = ctx->battlerAtk; + if (GetMoveCategory(ctx->currentMove) == DAMAGE_CATEGORY_STATUS) + BattleScriptCall(BattleScript_ZMoveActivateStatus); + else + BattleScriptCall(BattleScript_ZMoveActivateDamaging); + return MOVE_STEP_BREAK; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerThaw(void) +static enum MoveCanceller CancellerChoiceLock(struct BattleContext *ctx) { - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) + u16 *choicedMoveAtk = &gBattleStruct->choicedMove[ctx->battlerAtk]; + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(ctx->battlerAtk); + + if (gChosenMove != MOVE_STRUGGLE + && (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE) + && (IsHoldEffectChoice(holdEffect) || ctx->ability[ctx->battlerAtk] == ABILITY_GORILLA_TACTICS)) + *choicedMoveAtk = gChosenMove; + + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + if (gBattleMons[ctx->battlerAtk].moves[moveIndex] == *choicedMoveAtk) + break; + } + + if (moveIndex == MAX_MON_MOVES) + *choicedMoveAtk = MOVE_NONE; + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerCallSubmove(struct BattleContext *ctx) +{ + u32 noEffect = FALSE; + u32 calledMove = MOVE_NONE; + const u8 *battleScript = NULL; + battleScript = BattleScript_SubmoveAttackstring; + + switch(ctx->moveEffect) + { + case EFFECT_MIRROR_MOVE: + calledMove = GetMirrorMoveMove(); + break; + case EFFECT_METRONOME: + calledMove = GetMetronomeMove(); + battleScript = BattleScript_MetronomeAttackstring; + break; + case EFFECT_ASSIST: + calledMove = GetAssistMove(); + break; + case EFFECT_NATURE_POWER: + calledMove = GetNaturePowerMove(ctx->battlerAtk); + battleScript = BattleScript_NaturePowerAttackstring; + break; + case EFFECT_SLEEP_TALK: + calledMove = GetSleepTalkMove(); + battleScript = BattleScript_SleepTalkAttackstring; + break; + case EFFECT_COPYCAT: + calledMove = GetCopyCatMove(); + break; + case EFFECT_ME_FIRST: + calledMove = GetMeFirstMove(); + break; + default: + noEffect = TRUE; + break; + } + + if (noEffect) + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + return MOVE_STEP_SUCCESS; + } + + if (calledMove != MOVE_NONE) + { + if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(calledMove)) + calledMove = GetTypeBasedZMove(calledMove); + if (ctx->moveEffect == EFFECT_COPYCAT && IsMaxMove(calledMove)) + calledMove = gBattleStruct->dynamax.lastUsedBaseMove; + + gBattleStruct->submoveAnnouncement = SUBMOVE_SUCCESS; + gCalledMove = calledMove; + BattleScriptCall(battleScript); + return MOVE_STEP_BREAK; + } + + gBattleStruct->submoveAnnouncement = SUBMOVE_FAILURE; + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerThaw(struct BattleContext *ctx) +{ + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FREEZE) + { + if (!(IsMoveEffectRemoveSpeciesType(ctx->currentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))) { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE; + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FREEZE; BattleScriptCall(BattleScript_MoveUsedUnfroze); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE; } return MOVE_STEP_REMOVES_STATUS; } - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && MoveThawsUser(gCurrentMove)) + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_FROSTBITE && MoveThawsUser(ctx->currentMove)) { - if (!(IsMoveEffectRemoveSpeciesType(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + if (!(IsMoveEffectRemoveSpeciesType(ctx->currentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(ctx->battlerAtk, TYPE_FIRE))) { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE; + gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_FROSTBITE; BattleScriptCall(BattleScript_MoveUsedUnfrostbite); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE; } @@ -2296,62 +2440,270 @@ static enum MoveCanceller CancellerThaw(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerStanceChangeTwo(void) +static enum MoveCanceller CancellerStanceChangeTwo(struct BattleContext *ctx) { - if (B_STANCE_CHANGE_FAIL >= GEN_7 && !gBattleStruct->isAtkCancelerForCalledMove && TryFormChangeBeforeMove()) + if (B_STANCE_CHANGE_FAIL >= GEN_7 && gChosenMove == ctx->currentMove && TryFormChangeBeforeMove()) return MOVE_STEP_BREAK; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerWeatherPrimal(void) +static enum MoveCanceller CancellerAttackstring(struct BattleContext *ctx) +{ + gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; + BattleScriptCall(BattleScript_Attackstring); + return MOVE_STEP_BREAK; +} + +static enum MoveCanceller CancellerPPDeduction(struct BattleContext *ctx) +{ + if (gBattleMons[ctx->battlerAtk].volatiles.multipleTurns + || gSpecialStatuses[ctx->battlerAtk].dancerUsedMove + || ctx->currentMove == MOVE_STRUGGLE) + return MOVE_STEP_SUCCESS; + + s32 ppToDeduct = 1; + u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->currentMove); + u32 movePosition = gCurrMovePos; + + if (gBattleStruct->submoveAnnouncement == SUBMOVE_SUCCESS) + movePosition = gChosenMovePos; + + if (moveTarget == MOVE_TARGET_BOTH + || moveTarget == MOVE_TARGET_FOES_AND_ALLY + || moveTarget == MOVE_TARGET_ALL_BATTLERS + || MoveForcesPressure(ctx->currentMove)) + { + for (u32 i = 0; i < gBattlersCount; i++) + { + if (!IsBattlerAlly(i, ctx->battlerAtk) && IsBattlerAlive(i)) + ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE); + } + } + else if (moveTarget != MOVE_TARGET_OPPONENTS_FIELD) + { + if (ctx->battlerAtk != ctx->battlerDef && ctx->ability[ctx->battlerDef] == ABILITY_PRESSURE) + ppToDeduct++; + } + + // For item Metronome, echoed voice + if (ctx->currentMove != gLastResultingMoves[ctx->battlerAtk] || WasUnableToUseMove(ctx->battlerAtk)) + gBattleStruct->sameMoveTurns[ctx->battlerAtk] = 0; + + if (gBattleMons[ctx->battlerAtk].pp[movePosition] > ppToDeduct) + gBattleMons[ctx->battlerAtk].pp[movePosition] -= ppToDeduct; + else + gBattleMons[ctx->battlerAtk].pp[movePosition] = 0; + + if (MOVE_IS_PERMANENT(ctx->battlerAtk, movePosition)) + { + BtlController_EmitSetMonData( + ctx->battlerAtk, + B_COMM_TO_CONTROLLER, + REQUEST_PPMOVE1_BATTLE + movePosition, + 0, + sizeof(gBattleMons[ctx->battlerAtk].pp[movePosition]), + &gBattleMons[ctx->battlerAtk].pp[movePosition]); + MarkBattlerForControllerExec(ctx->battlerAtk); + } + + if (gBattleStruct->submoveAnnouncement != SUBMOVE_NO_EFFECT) + { + if (gBattleStruct->submoveAnnouncement == SUBMOVE_FAILURE) + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + gBattlescriptCurrInstr = BattleScript_ButItFailed; + return MOVE_STEP_FAILURE; + } + else if (CancellerVolatileBlocked(ctx) == MOVE_STEP_FAILURE) // Check Gravity/Heal Block/Throat Chop for Submove + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + return MOVE_STEP_FAILURE; + } + else + { + gBattleStruct->submoveAnnouncement = SUBMOVE_NO_EFFECT; + gBattlerTarget = GetBattleMoveTarget(ctx->currentMove, NO_TARGET_OVERRIDE); + gBattleScripting.animTurn = 0; + gBattleScripting.animTargetsHit = 0; + + // Possibly better to just move type setting and redirection to attackcanceller as a new case at this point + SetTypeBeforeUsingMove(ctx->currentMove, ctx->battlerAtk); + HandleMoveTargetRedirection(); + gBattlescriptCurrInstr = GetMoveBattleScript(ctx->currentMove); + return MOVE_STEP_BREAK; + } + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerWeatherPrimal(struct BattleContext *ctx) { enum MoveCanceller effect = MOVE_STEP_SUCCESS; - if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0) + if (HasWeatherEffect() && GetMovePower(ctx->currentMove) > 0) { - u32 moveType = GetBattleMoveType(gCurrentMove); - if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (B_POWDER_RAIN >= GEN_7 || !TryActivatePowderStatus(gCurrentMove))) + u32 moveType = GetBattleMoveType(ctx->currentMove); + if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetGenConfig(GEN_CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove))) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; - effect = MOVE_STEP_BREAK; + effect = MOVE_STEP_FAILURE; } else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN; - effect = MOVE_STEP_BREAK; + effect = MOVE_STEP_FAILURE; } - if (effect == MOVE_STEP_BREAK) + if (effect == MOVE_STEP_FAILURE) { gBattleScripting.moveEffect = MOVE_EFFECT_NONE; - gProtectStructs[gBattlerAttacker].chargingTurn = FALSE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + gProtectStructs[ctx->battlerAtk].chargingTurn = FALSE; + CancelMultiTurnMoves(ctx->battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - BattleScriptCall(BattleScript_PrimalWeatherBlocksMove); + gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; } } return effect; } -static enum MoveCanceller CancellerDynamaxBlocked(void) +static enum MoveCanceller CancellerMoveFailure(struct BattleContext *ctx) { - if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove)) + const u8 *battleScript = NULL; + + switch (ctx->moveEffect) + { + case EFFECT_FAIL_IF_NOT_ARG_TYPE: + if (!IS_BATTLER_OF_TYPE(ctx->battlerAtk, GetMoveArgType(ctx->currentMove))) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_AURA_WHEEL: + if (gBattleMons[ctx->battlerAtk].species != SPECIES_MORPEKO_FULL_BELLY + && gBattleMons[ctx->battlerAtk].species != SPECIES_MORPEKO_HANGRY) + battleScript = BattleScript_PokemonCantUseTheMove; + break; + case EFFECT_AURORA_VEIL: + if (!(gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW) && HasWeatherEffect())) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_CLANGOROUS_SOUL: + if (gBattleMons[ctx->battlerAtk].hp <= max(1, GetNonDynamaxMaxHP(ctx->battlerAtk) / 3)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_COUNTER: + case EFFECT_MIRROR_COAT: + case EFFECT_METAL_BURST: + // TODO: Needs a refactor because the moves currently don't work according to new gens + break; + case EFFECT_DESTINY_BOND: + if (DoesDestinyBondFail(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FIRST_TURN_ONLY: + if (!gDisableStructs[ctx->battlerAtk].isFirstTurn || gSpecialStatuses[ctx->battlerAtk].instructedChosenTarget) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_MAT_BLOCK: + if (!gDisableStructs[ctx->battlerAtk].isFirstTurn || gSpecialStatuses[ctx->battlerAtk].instructedChosenTarget) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FLING: + if (!CanFling(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FOLLOW_ME: + if (B_UPDATED_MOVE_DATA >= GEN_8 && !(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_FUTURE_SIGHT: + if (gWishFutureKnock.futureSightCounter[ctx->battlerDef] > gBattleTurnCounter) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_LAST_RESORT: + if (!CanUseLastResort(ctx->battlerAtk)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_NO_RETREAT: + if (gBattleMons[ctx->battlerDef].volatiles.noRetreat) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_POLTERGEIST: + if (gBattleMons[ctx->battlerDef].item == ITEM_NONE + || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM + || ctx->ability[ctx->battlerDef] == ABILITY_KLUTZ) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_PROTECT: + // TODO + break; + case EFFECT_REST: + if (gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP + || ctx->ability[ctx->battlerAtk] == ABILITY_COMATOSE) + battleScript = BattleScript_RestIsAlreadyAsleep; + else if (gBattleMons[ctx->battlerAtk].hp == gBattleMons[ctx->battlerAtk].maxHP) + battleScript = BattleScript_AlreadyAtFullHp; + else if (ctx->ability[ctx->battlerAtk] == ABILITY_INSOMNIA + || ctx->ability[ctx->battlerAtk] == ABILITY_VITAL_SPIRIT + || ctx->ability[ctx->battlerAtk] == ABILITY_PURIFYING_SALT) + battleScript = BattleScript_InsomniaProtects; + break; + case EFFECT_SUCKER_PUNCH: + if (HasBattlerActedThisTurn(ctx->battlerDef) + || (IsBattleMoveStatus(GetChosenMoveFromPosition(ctx->battlerDef)) && !gProtectStructs[ctx->battlerDef].noValidMoves)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_SNORE: + if (!(gBattleMons[ctx->battlerAtk].status1 & STATUS1_SLEEP) + && ctx->ability[ctx->battlerAtk] != ABILITY_COMATOSE) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STOCKPILE: + if (gDisableStructs[ctx->battlerAtk].stockpileCounter >= 3) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_STUFF_CHEEKS: + if (GetItemPocket(gBattleMons[ctx->battlerAtk].item) != POCKET_BERRIES) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_SWALLOW: + case EFFECT_SPIT_UP: + if (gDisableStructs[ctx->battlerAtk].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) + battleScript = BattleScript_ButItFailed; + break; + case EFFECT_TELEPORT: + // TODO: follow up: Can't make sense of teleport logic + break; + case EFFECT_LOW_KICK: + case EFFECT_HEAT_CRASH: + if (GetActiveGimmick(ctx->battlerDef) == GIMMICK_DYNAMAX) + battleScript = BattleScript_MoveBlockedByDynamax; + break; + default: + break; + } + + if (battleScript != NULL) { gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - BattleScriptCall(BattleScript_MoveBlockedByDynamax); - return MOVE_STEP_BREAK; + gBattlescriptCurrInstr = battleScript; + return MOVE_STEP_FAILURE; } + return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerPowderStatus(void) +static enum MoveCanceller CancellerPowderStatus(struct BattleContext *ctx) { - if (TryActivatePowderStatus(gCurrentMove)) + if (TryActivatePowderStatus(ctx->currentMove)) { - gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; - if (!IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (!IsAbilityAndRecord(ctx->battlerAtk, ctx->ability[ctx->battlerAtk], ABILITY_MAGIC_GUARD)) + gBattleStruct->moveDamage[ctx->battlerAtk] = GetNonDynamaxMaxHP(ctx->battlerAtk) / 4; - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE - || HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE)) + // This might be incorrect + if (GetActiveGimmick(ctx->battlerAtk) != GIMMICK_Z_MOVE + || HasTrainerUsedGimmick(ctx->battlerAtk, GIMMICK_Z_MOVE)) gBattlescriptCurrInstr = BattleScript_MoveUsedPowder; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2359,16 +2711,67 @@ static enum MoveCanceller CancellerPowderStatus(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerProtean(void) +bool32 IsDazzlingAbility(enum Ability ability) { - u32 moveType = GetBattleMoveType(gCurrentMove); - if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType)) + switch (ability) { - if (B_PROTEAN_LIBERO == GEN_9) - gDisableStructs[gBattlerAttacker].usedProteanLibero = TRUE; + case ABILITY_DAZZLING: return TRUE; + case ABILITY_QUEENLY_MAJESTY: return TRUE; + case ABILITY_ARMOR_TAIL: return TRUE; + default: break; + } + return FALSE; +} + +static enum MoveCanceller CancellerPriorityBlock(struct BattleContext *ctx) +{ + bool32 effect = FALSE; + s32 priority = GetChosenMovePriority(ctx->battlerAtk, ctx->ability[ctx->battlerAtk]); + u32 blockAbility = ABILITY_NONE; // ability of battler who is blocking + u32 blockedByBattler = ctx->battlerDef; + + if (priority <= 0 || IsBattlerAlly(ctx->battlerAtk, ctx->battlerDef)) + return MOVE_STEP_SUCCESS; + + if (IsDazzlingAbility(ctx->ability[ctx->battlerDef])) + { + blockAbility = ctx->ability[ctx->battlerDef]; + effect = TRUE; + } + else if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(ctx->battlerDef))) + { + blockAbility = GetBattlerAbility(BATTLE_PARTNER(ctx->battlerDef)); + if (IsDazzlingAbility(blockAbility)) + { + blockedByBattler = BATTLE_PARTNER(ctx->battlerDef); + effect = TRUE; + } + } + + if (effect) + { + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + gLastUsedAbility = blockAbility; + RecordAbilityBattle(blockedByBattler, blockAbility); + gBattleScripting.battler = gBattlerAbility = blockedByBattler; + gBattlescriptCurrInstr = BattleScript_DazzlingProtected; + gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; + return MOVE_STEP_FAILURE; + } + + return MOVE_STEP_SUCCESS; +} + +static enum MoveCanceller CancellerProtean(struct BattleContext *ctx) +{ + u32 moveType = GetBattleMoveType(ctx->currentMove); + if (ProteanTryChangeType(ctx->battlerAtk, ctx->ability[ctx->battlerAtk], ctx->currentMove, moveType)) + { + if (GetGenConfig(GEN_PROTEAN_LIBERO) >= GEN_9) + gDisableStructs[ctx->battlerAtk].usedProteanLibero = TRUE; PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - gBattlerAbility = gBattlerAttacker; - PrepareStringBattle(STRINGID_EMPTYSTRING3, gBattlerAttacker); + gBattlerAbility = ctx->battlerAtk; + PrepareStringBattle(STRINGID_EMPTYSTRING3, ctx->battlerAtk); gBattleCommunication[MSG_DISPLAY] = 1; BattleScriptCall(BattleScript_ProteanActivates); return MOVE_STEP_BREAK; @@ -2376,49 +2779,32 @@ static enum MoveCanceller CancellerProtean(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerPsychicTerrain(void) -{ - if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN - && IsBattlerGrounded(gBattlerTarget) - && GetChosenMovePriority(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) > 0 - && GetMoveTarget(gCurrentMove) != MOVE_TARGET_ALL_BATTLERS - && GetMoveTarget(gCurrentMove) != MOVE_TARGET_OPPONENTS_FIELD - && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) - { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); - gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; - gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; - } - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceller CancellerExplodingDamp(void) +static enum MoveCanceller CancellerExplodingDamp(struct BattleContext *ctx) { u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); - if (dampBattler && IsMoveDampBanned(gCurrentMove)) + if (dampBattler && IsMoveDampBanned(ctx->currentMove)) { gBattleScripting.battler = dampBattler - 1; gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; - return MOVE_STEP_BREAK; + return MOVE_STEP_FAILURE; } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerMultihitMoves(void) +static enum MoveCanceller CancellerMultihitMoves(struct BattleContext *ctx) { - if (GetMoveEffect(gCurrentMove) == EFFECT_MULTI_HIT) + if (GetMoveEffect(ctx->currentMove) == EFFECT_MULTI_HIT) { - u32 ability = GetBattlerAbility(gBattlerAttacker); + enum Ability ability = ctx->ability[ctx->battlerAtk]; if (ability == ABILITY_SKILL_LINK) { gMultiHitCounter = 5; } else if (ability == ABILITY_BATTLE_BOND - && gCurrentMove == MOVE_WATER_SHURIKEN - && gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_ASH) + && ctx->currentMove == MOVE_WATER_SHURIKEN + && gBattleMons[ctx->battlerAtk].species == SPECIES_GRENINJA_ASH) { gMultiHitCounter = 3; } @@ -2429,37 +2815,42 @@ static enum MoveCanceller CancellerMultihitMoves(void) PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } - else if (GetMoveStrikeCount(gCurrentMove) > 1) + else if (GetMoveStrikeCount(ctx->currentMove) > 1) { - if (GetMoveEffect(gCurrentMove) == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + if (ctx->moveEffect == EFFECT_POPULATION_BOMB && GetBattlerHoldEffect(ctx->battlerAtk) == HOLD_EFFECT_LOADED_DICE) { gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 10); } else { - gMultiHitCounter = GetMoveStrikeCount(gCurrentMove); + gMultiHitCounter = GetMoveStrikeCount(ctx->currentMove); - if (GetMoveEffect(gCurrentMove) == EFFECT_DRAGON_DARTS - && !IsAffectedByFollowMe(gBattlerAttacker, GetBattlerSide(gBattlerTarget), gCurrentMove) - && CanTargetPartner(gBattlerAttacker, gBattlerTarget) - && TargetFullyImmuneToCurrMove(gBattlerAttacker, gBattlerTarget)) - gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); + if (ctx->moveEffect == EFFECT_DRAGON_DARTS + && !IsAffectedByFollowMe(ctx->battlerAtk, GetBattlerSide(ctx->battlerDef), ctx->currentMove) + && CanTargetPartner(ctx->battlerAtk, ctx->battlerDef) + && TargetFullyImmuneToCurrMove(ctx->battlerAtk, ctx->battlerDef)) + gBattlerTarget = BATTLE_PARTNER(ctx->battlerDef); } PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) } - else if (B_BEAT_UP >= GEN_5 && GetMoveEffect(gCurrentMove) == EFFECT_BEAT_UP) + else if (B_BEAT_UP >= GEN_5 && ctx->moveEffect == EFFECT_BEAT_UP) { - struct Pokemon* party = GetBattlerParty(gBattlerAttacker); + struct Pokemon* party = GetBattlerParty(ctx->battlerAtk); int i; + gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) - && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + u32 species = GetMonData(&party[i], MON_DATA_SPECIES); + if (species != SPECIES_NONE + && GetMonData(&party[i], MON_DATA_HP) && !GetMonData(&party[i], MON_DATA_IS_EGG) && !GetMonData(&party[i], MON_DATA_STATUS)) + { + gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++] = species; gMultiHitCounter++; + } } gBattleStruct->beatUpSlot = 0; @@ -2473,42 +2864,10 @@ static enum MoveCanceller CancellerMultihitMoves(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerZMoves(void) +static enum MoveCanceller CancellerMultiTargetMoves(struct BattleContext *ctx) { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) - { - // For Z-Mirror Move, so it doesn't play the animation twice. - bool32 alreadyUsed = HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE); - - // attacker has a queued z move - RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_Z_CRYSTAL); - SetGimmickAsActivated(gBattlerAttacker, GIMMICK_Z_MOVE); - - gBattleScripting.battler = gBattlerAttacker; - if (gProtectStructs[gBattlerAttacker].powderSelfDmg) - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivatePowder); - } - else if (GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS) - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivateStatus); - } - else - { - if (!alreadyUsed) - BattleScriptCall(BattleScript_ZMoveActivateDamaging); - } - return MOVE_STEP_BREAK; // The original move is cancelled, not the z move - } - return MOVE_STEP_SUCCESS; -} - -static enum MoveCanceller CancellerMultiTargetMoves(void) -{ - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); + u32 moveTarget = GetBattlerMoveTargetType(ctx->battlerAtk, ctx->currentMove); + enum Ability abilityAtk = ctx->ability[ctx->battlerAtk]; if (IsSpreadMove(moveTarget)) { @@ -2517,51 +2876,52 @@ static enum MoveCanceller CancellerMultiTargetMoves(void) if (gBattleStruct->bouncedMoveIsUsed && !IsOnPlayerSide(battlerDef)) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); - if (gBattlerAttacker == battlerDef + if (ctx->battlerAtk == battlerDef || !IsBattlerAlive(battlerDef) - || (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef)) - || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check + || (ctx->moveEffect == EFFECT_SYNCHRONOISE && !DoBattlersShareType(ctx->battlerAtk, battlerDef)) + || (moveTarget == MOVE_TARGET_BOTH && ctx->battlerAtk == BATTLE_PARTNER(battlerDef)) + || IsBattlerProtected(ctx->battlerAtk, battlerDef, ctx->currentMove)) // Missing Invulnerable check { gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; - gBattleStruct->noResultString[battlerDef] = TRUE; + gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } - else if (CanAbilityBlockMove(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER) - || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetBattleMovePriority(gBattlerAttacker, abilityAtk, gCurrentMove) > 0)) + else if (CanAbilityBlockMove(ctx->battlerAtk, battlerDef, abilityAtk, abilityDef, ctx->currentMove, CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = TRUE; + gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } - else if (CanAbilityAbsorbMove(gBattlerAttacker, battlerDef, abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), ABILITY_CHECK_TRIGGER)) + else if (CanAbilityAbsorbMove(ctx->battlerAtk, battlerDef, abilityDef, ctx->currentMove, GetBattleMoveType(gCurrentMove), CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = DO_ACCURACY_CHECK; + gBattleStruct->noResultString[battlerDef] = CHECK_ACCURACY; } else { - CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); + CalcTypeEffectivenessMultiplierHelper(ctx->currentMove, GetBattleMoveType(ctx->currentMove), ctx->battlerAtk, battlerDef, abilityAtk, abilityDef, TRUE); // Sets moveResultFlags + gBattleStruct->noResultString[battlerDef] = CAN_DAMAGE; } } if (moveTarget == MOVE_TARGET_BOTH) - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker); + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, ctx->battlerAtk); else - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker); + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, ctx->battlerAtk); } return MOVE_STEP_SUCCESS; } -static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(void) = +static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(struct BattleContext *ctx) = { - [CANCELLER_FLAGS] = CancellerFlags, + [CANCELLER_CLEAR_FLAGS] = CancellerClearFlags, [CANCELLER_STANCE_CHANGE_1] = CancellerStanceChangeOne, [CANCELLER_SKY_DROP] = CancellerSkyDrop, [CANCELLER_RECHARGE] = CancellerRecharge, [CANCELLER_ASLEEP_OR_FROZEN] = CancellerAsleepOrFrozen, [CANCELLER_OBEDIENCE] = CancellerObedience, + [CANCELLER_POWER_POINTS] = CancellerPowerPoints, [CANCELLER_TRUANT] = CancellerTruant, [CANCELLER_FLINCH] = CancellerFlinch, - [CANCELLER_INFATUATION] = CancellerInfatuation, [CANCELLER_DISABLED] = CancellerDisabled, [CANCELLER_VOLATILE_BLOCKED] = CancellerVolatileBlocked, [CANCELLER_TAUNTED] = CancellerTaunted, @@ -2569,34 +2929,45 @@ static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(void) = [CANCELLER_CONFUSED] = CancellerConfused, [CANCELLER_GHOST] = CancellerGhost, [CANCELLER_PARALYSED] = CancellerParalysed, + [CANCELLER_INFATUATION] = CancellerInfatuation, [CANCELLER_BIDE] = CancellerBide, + [CANCELLER_Z_MOVES] = CancellerZMoves, + [CANCELLER_CHOICE_LOCK] = CancellerChoiceLock, + [CANCELLER_CALLSUBMOVE] = CancellerCallSubmove, [CANCELLER_THAW] = CancellerThaw, [CANCELLER_STANCE_CHANGE_2] = CancellerStanceChangeTwo, + [CANCELLER_ATTACKSTRING] = CancellerAttackstring, + [CANCELLER_PPDEDUCTION] = CancellerPPDeduction, [CANCELLER_WEATHER_PRIMAL] = CancellerWeatherPrimal, - [CANCELLER_DYNAMAX_BLOCKED] = CancellerDynamaxBlocked, + [CANCELLER_MOVE_FAILURE] = CancellerMoveFailure, [CANCELLER_POWDER_STATUS] = CancellerPowderStatus, + [CANCELLER_PRIORITY_BLOCK] = CancellerPriorityBlock, [CANCELLER_PROTEAN] = CancellerProtean, - [CANCELLER_PSYCHIC_TERRAIN] = CancellerPsychicTerrain, [CANCELLER_EXPLODING_DAMP] = CancellerExplodingDamp, [CANCELLER_MULTIHIT_MOVES] = CancellerMultihitMoves, - [CANCELLER_Z_MOVES] = CancellerZMoves, [CANCELLER_MULTI_TARGET_MOVES] = CancellerMultiTargetMoves, }; -enum MoveCanceller AtkCanceller_MoveSuccessOrder(void) +enum MoveCanceller AtkCanceller_MoveSuccessOrder(struct BattleContext *ctx) { enum MoveCanceller effect = MOVE_STEP_SUCCESS; while (gBattleStruct->atkCancellerTracker < CANCELLER_END && effect == MOVE_STEP_SUCCESS) { - effect = sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker](); + effect = sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker](ctx); gBattleStruct->atkCancellerTracker++; } if (effect == MOVE_STEP_REMOVES_STATUS) { - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); - MarkBattlerForControllerExec(gBattlerAttacker); + BtlController_EmitSetMonData( + ctx->battlerAtk, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + 4, + &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(ctx->battlerAtk); } return effect; @@ -2762,7 +3133,7 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility) { - u16 battlerAbility = GetBattlerAbility(battler); + enum Ability battlerAbility = GetBattlerAbility(battler); if (gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag) { @@ -2786,7 +3157,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbilit gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; if (gBattleWeather & B_WEATHER_PRIMAL_ANY) gWishFutureKnock.weatherDuration = 0; - else if (rock != 0 && GetBattlerHoldEffect(battler, TRUE) == rock) + else if (rock != 0 && GetBattlerHoldEffect(battler) == rock) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; @@ -2804,7 +3175,7 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u16 *timer) gFieldStatuses |= statusFlag; gDisableStructs[battler].terrainAbilityDone = FALSE; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) + if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_TERRAIN_EXTENDER) *timer = gBattleTurnCounter + 8; else *timer = gBattleTurnCounter + 5; @@ -2871,9 +3242,9 @@ static void ForewarnChooseMove(u32 battler) bestId = i; } - gBattlerTarget = data[bestId].battler; + gEffectBattler = data[bestId].battler; PREPARE_MOVE_BUFFER(gBattleTextBuff1, data[bestId].moveId) - RecordKnownMove(gBattlerTarget, data[bestId].moveId); + RecordKnownMove(data[bestId].battler, data[bestId].moveId); Free(data); } @@ -2970,44 +3341,19 @@ static void ChooseStatBoostAnimation(u32 battler) #undef ANIM_STAT_ACC #undef ANIM_STAT_EVASION -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum AbilityEffectOptions option) +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option) { const u8 *battleScriptBlocksMove = NULL; - u32 battlerAbility = battlerDef; - s32 atkPriority = 0; - - if (option == ABILITY_CHECK_TRIGGER_AI) - atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); - else - atkPriority = GetChosenMovePriority(battlerAtk, abilityAtk); switch (abilityDef) { case ABILITY_SOUNDPROOF: if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) - { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) - gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; - } break; case ABILITY_BULLETPROOF: if (IsBallisticMove(move)) - { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) - gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; - } - break; - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (atkPriority > 0 && !IsBattlerAlly(battlerAtk, battlerDef)) - { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - battleScriptBlocksMove = BattleScript_DazzlingProtected; - } break; case ABILITY_GOOD_AS_GOLD: if (IsBattleMoveStatus(move)) @@ -3016,44 +3362,43 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a battleScriptBlocksMove = BattleScript_GoodAsGoldActivates; } break; + default: + break; } - if (atkPriority > 0) + if (battleScriptBlocksMove == NULL) { - // Prankster check - if (battleScriptBlocksMove == NULL - && IsBattleMoveStatus(move) - && BlocksPrankster(move, battlerAtk, battlerDef, TRUE) - && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) - { - if (option == ABILITY_RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) - CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected + s32 atkPriority = 0; + if (option == AI_CHECK) + atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); + else + atkPriority = GetChosenMovePriority(battlerAtk, abilityAtk); - battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; + if (atkPriority <= 0) + { + // Not a priority move } - - // Check def partner ability - u32 partnerDef = BATTLE_PARTNER(battlerDef); - if (battleScriptBlocksMove == NULL - && IsDoubleBattle() - && IsBattlerAlive(partnerDef) - && !IsBattlerAlly(battlerAtk, partnerDef)) + else if (IsBattleMoveStatus(move) + && BlocksPrankster(move, battlerAtk, battlerDef, TRUE) + && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) { - if (option == ABILITY_CHECK_TRIGGER_AI) - abilityDef = gAiLogicData->abilities[partnerDef]; - else - abilityDef = GetBattlerAbility(partnerDef); - - switch (abilityDef) + if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) + CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected + battleScriptBlocksMove = BattleScript_DoesntAffectTargetAtkString; + } + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_PSYCHIC_TERRAIN) // Not an ability but similar conditions + && !IsBattlerAlly(battlerAtk, battlerDef) + && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS + && GetMoveTarget(move) != MOVE_TARGET_OPPONENTS_FIELD) + { + battleScriptBlocksMove = BattleScript_MoveUsedPsychicTerrainPrevents; + if (option == RUN_SCRIPT) { - case ABILITY_DAZZLING: - case ABILITY_QUEENLY_MAJESTY: - case ABILITY_ARMOR_TAIL: - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) - gHitMarker |= HITMARKER_NO_PPDEDUCT; - battlerAbility = partnerDef; - battleScriptBlocksMove = BattleScript_DazzlingProtected; - break; + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + if (!IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) + CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected + gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; + return TRUE; // Early return since we don't want to set remaining values } } } @@ -3061,19 +3406,19 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a if (battleScriptBlocksMove == NULL) return FALSE; - if (option == ABILITY_RUN_SCRIPT) + if (option == RUN_SCRIPT) { - gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. + gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. gLastUsedAbility = abilityDef; RecordAbilityBattle(battlerDef, abilityDef); - gBattleScripting.battler = gBattlerAbility = battlerAbility; + gBattleScripting.battler = gBattlerAbility = battlerDef; gBattlescriptCurrInstr = battleScriptBlocksMove; } return TRUE; } -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option) +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, u32 moveType, enum FunctionCallOption option) { enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; const u8 *battleScript = NULL; @@ -3147,7 +3492,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 break; } - if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option != ABILITY_RUN_SCRIPT) + if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option != RUN_SCRIPT) return effect; switch (effect) @@ -3156,20 +3501,13 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 return FALSE; case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY: gBattleStruct->pledgeMove = FALSE; - if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK)) + if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battlerDef].volatiles.healBlock)) { - if ((gProtectStructs[battlerAtk].notFirstStrike)) - battleScript = BattleScript_MonMadeMoveUseless; - else - battleScript = BattleScript_MonMadeMoveUseless_PPLoss; + battleScript = BattleScript_MonMadeMoveUseless; } else { - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_MoveHPDrain; - else - battleScript = BattleScript_MoveHPDrain_PPLoss; - + battleScript = BattleScript_MoveHPDrain; gBattleStruct->moveDamage[battlerDef] = GetNonDynamaxMaxHP(battlerDef) / 4; if (gBattleStruct->moveDamage[battlerDef] == 0) gBattleStruct->moveDamage[battlerDef] = 1; @@ -3180,18 +3518,11 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 gBattleStruct->pledgeMove = FALSE; if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { - if ((gProtectStructs[battlerAtk].notFirstStrike)) - battleScript = BattleScript_MonMadeMoveUseless; - else - battleScript = BattleScript_MonMadeMoveUseless_PPLoss; + battleScript = BattleScript_MonMadeMoveUseless; } else { - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_MoveStatDrain; - else - battleScript = BattleScript_MoveStatDrain_PPLoss; - + battleScript = BattleScript_MoveStatDrain; SET_STATCHANGER(statId, statAmount, FALSE); if (B_ABSORBING_ABILITY_STRING < GEN_5) PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); @@ -3202,19 +3533,13 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 if (!gDisableStructs[battlerDef].flashFireBoosted) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_FlashFireBoost; - else - battleScript = BattleScript_FlashFireBoost_PPLoss; + battleScript = BattleScript_FlashFireBoost; gDisableStructs[battlerDef].flashFireBoosted = TRUE; } else { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST; - if (gProtectStructs[battlerAtk].notFirstStrike) - battleScript = BattleScript_FlashFireBoost; - else - battleScript = BattleScript_FlashFireBoost_PPLoss; + battleScript = BattleScript_FlashFireBoost; } break; } @@ -3268,14 +3593,13 @@ static inline u32 SetStartingSideStatus(u32 flag, u32 side, u32 message, u32 ani return 0; } -u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg) +u32 AbilityBattleEffects(u32 caseID, u32 battler, enum Ability ability, u32 special, u32 moveArg) { u32 effect = 0; u32 moveType = 0, move = 0; u32 side = 0; u32 i = 0, j = 0; u32 partner = 0; - struct Pokemon *mon; if (gBattleTypeFlags & (BATTLE_TYPE_SAFARI | BATTLE_TYPE_OLD_MAN_TUTORIAL)) return 0; @@ -3517,6 +3841,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gSpecialStatuses[battler].switchInAbilityDone) break; + if (GetBattlerHoldEffectIgnoreAbility(battler) == HOLD_EFFECT_ABILITY_SHIELD) + break; side = (BATTLE_OPPOSITE(GetBattlerPosition(battler))) & BIT_SIDE; target1 = GetBattlerAtPosition(side); @@ -3542,8 +3868,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptPushCursorAndCallback(BattleScript_TraceActivates); gBattleStruct->tracedAbility[battler] = gLastUsedAbility = gBattleMons[chosenTarget].ability; RecordAbilityBattle(chosenTarget, gLastUsedAbility); // Record the opposing battler has this ability - gBattlerAbility = battler; - PREPARE_MON_NICK_WITH_PREFIX_LOWER_BUFFER(gBattleTextBuff1, chosenTarget, gBattlerPartyIndexes[chosenTarget]) PREPARE_ABILITY_BUFFER(gBattleTextBuff2, gLastUsedAbility) } @@ -3559,11 +3883,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gDisableStructs[battler].isFirstTurn == 2 && !gDisableStructs[battler].overwrittenAbility && IsBattlerAlive(diagonalBattler) - && !(gBattleMons[diagonalBattler].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE)) - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[diagonalBattler].volatiles.substitute + && !gBattleMons[diagonalBattler].volatiles.transformed + && !gBattleMons[battler].volatiles.transformed && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON - && !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER)) + && !IsSemiInvulnerable(diagonalBattler, EXCLUDE_COMMANDER)) { + SaveBattlerAttacker(gBattlerAttacker); + SaveBattlerTarget(gBattlerTarget); gBattlerAttacker = battler; gBattlerTarget = diagonalBattler; BattleScriptPushCursorAndCallback(BattleScript_ImposterActivates); @@ -3611,7 +3938,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_UNNERVE: if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated) { - gBattlerTarget = GetOppositeBattler(battler); + gEffectBattler = GetOppositeBattler(battler); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE; gDisableStructs[battler].unnerveActivated = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -3623,7 +3950,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_AS_ONE_SHADOW_RIDER: if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated) { - gBattlerTarget = GetOppositeBattler(battler); + gEffectBattler = GetOppositeBattler(battler); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE; gDisableStructs[battler].unnerveActivated = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -3645,6 +3972,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_PASTEL_VEIL: if (!gSpecialStatuses[battler].switchInAbilityDone) { + SaveBattlerTarget(gBattlerTarget); gBattlerTarget = battler; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_PASTEL_VEIL; BattleScriptPushCursorAndCallback(BattleScript_PastelVeilActivates); @@ -3692,7 +4020,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_FriskActivates); // Try activate effect++; } @@ -3737,6 +4064,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(statId, 1, FALSE); + SaveBattlerAttacker(gBattlerAttacker); gBattlerAttacker = battler; PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); BattleScriptPushCursorAndCallback(BattleScript_AttackerAbilityStatRaiseEnd3); @@ -3838,12 +4166,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SNOW_WARNING: - if (B_SNOW_WARNING >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, TRUE)) + if (GetGenConfig(GEN_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow); effect++; } - else if (B_SNOW_WARNING < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, TRUE)) + else if (GetGenConfig(GEN_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail); effect++; @@ -3887,7 +4215,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_INTIMIDATE: if (!gSpecialStatuses[battler].switchInAbilityDone) { - gBattlerAbility = gBattlerAttacker = battler; + SaveBattlerAttacker(gBattlerAttacker); + gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, TRUE); BattleScriptPushCursorAndCallback(BattleScript_IntimidateActivates); @@ -3896,11 +4225,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_SUPERSWEET_SYRUP: if (!gSpecialStatuses[battler].switchInAbilityDone - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup) + && !GetBattlerPartyState(battler)->supersweetSyrup) { - gBattlerAbility = gBattlerAttacker = battler; + SaveBattlerAttacker(gBattlerAttacker); + gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE; + GetBattlerPartyState(battler)->supersweetSyrup = TRUE; BattleScriptPushCursorAndCallback(BattleScript_SupersweetSyrupActivates); effect++; } @@ -3922,6 +4252,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero); effect++; } + break; case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; @@ -3930,37 +4261,38 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SHIELDS_DOWN: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3); effect++; } break; case ABILITY_INTREPID_SWORD: - if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].intrepidSwordBoost) + if (!gSpecialStatuses[battler].switchInAbilityDone + && !GetBattlerPartyState(battler)->intrepidSwordBoost) { - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; - if (B_INTREPID_SWORD == GEN_9) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].intrepidSwordBoost = TRUE; + if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9) + GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - SET_STATCHANGER(STAT_ATK, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); - effect++; + if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_ATK, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } } break; case ABILITY_DAUNTLESS_SHIELD: - if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN) - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].dauntlessShieldBoost) + if (!gSpecialStatuses[battler].switchInAbilityDone + && !GetBattlerPartyState(battler)->dauntlessShieldBoost) { - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; - if (B_DAUNTLESS_SHIELD == GEN_9) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].dauntlessShieldBoost = TRUE; + if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9) + GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - SET_STATCHANGER(STAT_DEF, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); - effect++; + if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_DEF, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } } break; case ABILITY_WIND_RIDER: @@ -3968,8 +4300,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND) { - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); @@ -4000,6 +4330,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_VESSEL_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.vesselOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4009,6 +4340,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SWORD_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.swordOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_DEF); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4018,6 +4350,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_TABLETS_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.tabletsOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4027,6 +4360,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_BEADS_OF_RUIN: if (!gSpecialStatuses[battler].switchInAbilityDone) { + gBattleMons[battler].volatiles.beadsOfRuin = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPDEF); gSpecialStatuses[battler].switchInAbilityDone = TRUE; BattleScriptPushCursorAndCallback(BattleScript_RuinAbilityActivates); @@ -4059,24 +4393,20 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE)) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattlerAttacker = gBattlerAbility = battler; for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i]; - gBattleScripting.battler = BATTLE_PARTNER(battler); + gEffectBattler = BATTLE_PARTNER(battler); BattleScriptPushCursorAndCallback(BattleScript_CostarActivates); effect++; } break; case ABILITY_ZERO_TO_HERO: - side = GetBattlerSide(battler); - mon = GetBattlerMon(battler); - if (!gSpecialStatuses[battler].switchInAbilityDone - && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO - && !gBattleStruct->partyState[side][gBattlerPartyIndexes[battler]].transformZeroToHero) + && GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO + && !GetBattlerPartyState(battler)->transformZeroToHero) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battler]].transformZeroToHero = TRUE; + GetBattlerPartyState(battler)->transformZeroToHero = TRUE; BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates); effect++; } @@ -4086,12 +4416,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() - && !(gStatuses3[partner] & STATUS3_HEAL_BLOCK) + && !gBattleMons[partner].volatiles.healBlock && gBattleMons[partner].hp < gBattleMons[partner].maxHP && IsBattlerAlive(partner)) { - gBattlerTarget = partner; - gBattlerAttacker = battler; + gEffectBattler = partner; gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattleStruct->moveDamage[partner] = (GetNonDynamaxMaxHP(partner) / 4) * -1; BattleScriptPushCursorAndCallback(BattleScript_HospitalityActivates); @@ -4118,8 +4447,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL)) break; - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(stat, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); @@ -4131,17 +4458,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH)) { - gBattlerAttacker = battler; gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3); + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; } break; case ABILITY_ICE_FACE: if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) && gBattleMons[battler].species == SPECIES_EISCUE_NOICE - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { // TODO: Convert this to a proper FORM_CHANGE type. gBattleMons[battler].species = SPECIES_EISCUE_ICE; @@ -4154,7 +4480,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && IsBattlerAlive(partner) && IsBattlerAlive(battler) - && gBattleStruct->commanderActive[partner] == SPECIES_NONE + && gBattleStruct->battlerState[partner].commanderSpecies == SPECIES_NONE && gBattleMons[partner].species == SPECIES_DONDOZO && GET_BASE_SPECIES_ID(GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)) == SPECIES_TATSUGIRI) { @@ -4162,17 +4488,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattlerAttacker = partner; gBattleStruct->battlerState[battler].commandingDondozo = TRUE; - gBattleStruct->commanderActive[partner] = gBattleMons[battler].species; - gStatuses3[battler] |= STATUS3_COMMANDER; - if (gBattleMons[battler].status2 & STATUS2_CONFUSION - && !(gStatuses4[battler] & STATUS4_INFINITE_CONFUSION)) - gBattleMons[battler].status2 -= STATUS2_CONFUSION_TURN(1); + gBattleStruct->battlerState[partner].commanderSpecies = gBattleMons[battler].species; + gBattleMons[battler].volatiles.semiInvulnerable = STATE_COMMANDER; + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !gBattleMons[battler].volatiles.infiniteConfusion) + gBattleMons[battler].volatiles.confusionTurns--; BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); MarkBattlerForControllerExec(battler); BattleScriptPushCursorAndCallback(BattleScript_CommanderActivates); effect++; } break; + default: + break; } break; case ABILITYEFFECT_ENDTURN: @@ -4188,7 +4515,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gBattlerTarget = RandomUniformExcept(RNG_PICKUP, 0, gBattlersCount - 1, CantPickupItem); gLastUsedItem = GetUsedHeldItem(gBattlerTarget); - BattleScriptPushCursorAndCallback(BattleScript_PickupActivates); + BattleScriptExecute(BattleScript_PickupActivates); effect++; } break; @@ -4199,17 +4526,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) { gLastUsedItem = GetUsedHeldItem(battler); - BattleScriptPushCursorAndCallback(BattleScript_HarvestActivates); + BattleScriptExecute(BattleScript_HarvestActivates); effect++; } break; case ABILITY_ICE_BODY: if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER + && !gBattleMons[battler].volatiles.healBlock) { - BattleScriptPushCursorAndCallback(BattleScript_IceBodyHeal); + BattleScriptExecute(BattleScript_IceBodyHeal); gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) gBattleStruct->moveDamage[battler] = 1; @@ -4224,9 +4552,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_RAIN_DISH: if (IsBattlerWeatherAffected(battler, B_WEATHER_RAIN) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && !gBattleMons[battler].volatiles.healBlock) { - BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates); + BattleScriptExecute(BattleScript_RainDishActivates); gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (gLastUsedAbility == ABILITY_RAIN_DISH ? 16 : 8); if (gBattleStruct->moveDamage[battler] == 0) gBattleStruct->moveDamage[battler] = 1; @@ -4262,9 +4590,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); gBattleMons[battler].status1 = 0; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; gBattleScripting.battler = battler; - BattleScriptPushCursorAndCallback(BattleScript_ShedSkinActivates); + BattleScriptExecute(BattleScript_ShedSkinActivates); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); effect++; @@ -4273,8 +4601,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SPEED_BOOST: if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && gDisableStructs[battler].isFirstTurn != 2) { + SaveBattlerAttacker(gBattlerAttacker); SET_STATCHANGER(STAT_SPEED, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_SpeedBoostActivates); + BattleScriptExecute(BattleScript_AttackerAbilityStatRaiseEnd2); gBattleScripting.battler = battler; effect++; } @@ -4306,7 +4635,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 i = RandomUniformExcept(RNG_MOODY_DECREASE, STAT_ATK, statsNum - 1, MoodyCantLowerStat); SET_STATCHANGER2(gBattleScripting.savedStatChanger, i, 1, TRUE); } - BattleScriptPushCursorAndCallback(BattleScript_MoodyActivates); + BattleScriptExecute(BattleScript_MoodyActivates); effect++; } break; @@ -4321,14 +4650,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_BAD_DREAMS: - BattleScriptPushCursorAndCallback(BattleScript_BadDreamsActivates); + BattleScriptExecute(BattleScript_BadDreamsActivates); effect++; break; case ABILITY_SOLAR_POWER: if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) { SOLAR_POWER_HP_DROP: - BattleScriptPushCursorAndCallback(BattleScript_SolarPowerActivates); + BattleScriptExecute(BattleScript_SolarPowerActivates); gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) gBattleStruct->moveDamage[battler] = 1; @@ -4341,7 +4670,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[gBattleScripting.battler].status1 & STATUS1_ANY && RandomPercentage(RNG_HEALER, 30)) { - BattleScriptPushCursorAndCallback(BattleScript_HealerActivates); + BattleScriptExecute(BattleScript_HealerActivates); effect++; } break; @@ -4353,40 +4682,41 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SHIELDS_DOWN: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); + gBattleScripting.battler = battler; + BattleScriptExecute(BattleScript_BattlerFormChangeEnd2); effect++; } break; case ABILITY_POWER_CONSTRUCT: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_PowerConstruct); + gBattleScripting.battler = battler; + BattleScriptExecute(BattleScript_PowerConstruct); effect++; } break; case ABILITY_BALL_FETCH: if (gBattleMons[battler].item == ITEM_NONE - && gBattleResults.catchAttempts[gLastUsedBall - ITEM_ULTRA_BALL] >= 1 + && gBattleResults.catchAttempts[ItemIdToBallId(gLastUsedBall)] >= 1 && !gHasFetchedBall) { + gLastUsedItem = gLastUsedBall; gBattleScripting.battler = battler; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedBall); + gBattleMons[battler].item = gLastUsedItem; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem); MarkBattlerForControllerExec(battler); gHasFetchedBall = TRUE; - gLastUsedItem = gLastUsedBall; - BattleScriptPushCursorAndCallback(BattleScript_BallFetch); + BattleScriptExecute(BattleScript_BallFetch); effect++; } break; case ABILITY_HUNGER_SWITCH: - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (!gBattleMons[battler].volatiles.transformed && GetActiveGimmick(battler) != GIMMICK_TERA && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); + gBattleScripting.battler = battler; + BattleScriptExecute(BattleScript_BattlerFormChangeEnd3NoPopup); effect++; } break; @@ -4397,7 +4727,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gDisableStructs[battler].cudChew = FALSE; gLastUsedItem = gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)]; gBattleStruct->usedHeldItems[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = ITEM_NONE; - BattleScriptPushCursorAndCallback(BattleScript_CudChewActivates); + BattleScriptExecute(BattleScript_CudChewActivates); effect++; } else if (!gDisableStructs[battler].cudChew && GetItemPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES) @@ -4405,19 +4735,75 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gDisableStructs[battler].cudChew = TRUE; } break; + default: + break; } } break; + case ABILITYEFFECT_COLOR_CHANGE: + switch (gLastUsedAbility) + { + case ABILITY_COLOR_CHANGE: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && !IS_BATTLER_OF_TYPE(battler, moveType) + && move != MOVE_STRUGGLE + && moveType != TYPE_STELLAR + && moveType != TYPE_MYSTERY) + { + gEffectBattler = gBattlerAbility = battler; + SET_BATTLER_TYPE(battler, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + BattleScriptCall(BattleScript_ColorChangeActivates); + effect++; + } + break; + case ABILITY_BERSERK: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && HadMoreThanHalfHpNowDoesnt(battler) + && CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gEffectBattler = gBattlerAbility = battler; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + BattleScriptCall(BattleScript_BerserkActivates); + effect++; + } + break; + case ABILITY_ANGER_SHELL: + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && HadMoreThanHalfHpNowDoesnt(battler)) + { + gEffectBattler = gBattlerAbility = battler; + BattleScriptCall(BattleScript_AngerShellActivates); + effect++; + } + break; + default: + break; + } + break; case ABILITYEFFECT_MOVE_END: // Think contact abilities. switch (gLastUsedAbility) { + case ABILITY_STICKY_HOLD: + if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerTarget)) + { + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; + gBattlerAbility = gBattlerTarget; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + effect++; + } + break; case ABILITY_JUSTIFIED: if (IsBattlerTurnDamaged(battler) && IsBattlerAlive(battler) && moveType == TYPE_DARK && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4429,7 +4815,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST) && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_SPEED, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4441,7 +4827,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && moveType == TYPE_WATER && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_DEF, 2, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4453,26 +4839,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(battler) && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_DEF, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; } break; - case ABILITY_BERSERK: - if (IsBattlerTurnDamaged(battler) - && IsBattlerAlive(battler) - && HadMoreThanHalfHpNowDoesnt(battler) - && (gMultiHitCounter == 0 || gMultiHitCounter == 1) - && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) - && CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - gEffectBattler = battler; - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); - effect++; - } - break; case ABILITY_WEAK_ARMOR: if (IsBattlerTurnDamaged(battler) && IsBattlerAlive(battler) @@ -4507,19 +4879,19 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_MUMMY: if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && gDisableStructs[gBattlerAttacker].overwrittenAbility != GetBattlerAbility(gBattlerTarget) && gBattleMons[gBattlerAttacker].ability != ABILITY_MUMMY && gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSuppressed) { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; } + RemoveAbilityFlags(gBattlerAttacker); gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; BattleScriptCall(BattleScript_MummyActivates); @@ -4530,17 +4902,22 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_WANDERING_SPIRIT: if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped) { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; } + if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget) == HOLD_EFFECT_ABILITY_SHIELD) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + break; + } + RemoveAbilityFlags(gBattlerAttacker); gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gLastUsedAbility; @@ -4560,29 +4937,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; - case ABILITY_COLOR_CHANGE: - if (move != MOVE_STRUGGLE - && !IsBattleMoveStatus(move) - && IsBattlerTurnDamaged(battler) - && !IS_BATTLER_OF_TYPE(battler, moveType) - && moveType != TYPE_STELLAR - && moveType != TYPE_MYSTERY - && IsBattlerAlive(battler)) - { - SET_BATTLER_TYPE(battler, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - BattleScriptCall(BattleScript_ColorChangeActivates); - effect++; - } - break; case ABILITY_GOOEY: case ABILITY_TANGLING_HAIR: if (IsBattlerAlive(gBattlerAttacker) && (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { SET_STATCHANGER(STAT_SPEED, 1, TRUE); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -4596,8 +4957,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16); if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -4611,8 +4971,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { if ((battler = IsAbilityOnField(ABILITY_DAMP))) { @@ -4647,10 +5006,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_EFFECT_SPORE: { - u32 ability = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if ((!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) || B_POWDER_GRASS < GEN_6) - && ability != ABILITY_OVERCOAT - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) + && abilityAtk != ABILITY_OVERCOAT + && GetBattlerHoldEffect(gBattlerAttacker) != HOLD_EFFECT_SAFETY_GOGGLES) { u32 poison, paralysis, sleep; @@ -4676,9 +5035,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move)) { if (IsSleepClauseEnabled()) gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; @@ -4696,12 +5054,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_POISON_POINT, 30) : RandomChance(RNG_POISON_POINT, 1, 3)) { POISON_POINT: + { + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, abilityAtk) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -4711,17 +5070,19 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } } + } break; case ABILITY_STATIC: if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_STATIC, 30) : RandomChance(RNG_STATIC, 1, 3)) { STATIC: + { + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, abilityAtk) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -4731,12 +5092,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } } + } break; case ABILITY_FLAME_BODY: if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && (IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && IsBattlerTurnDamaged(gBattlerTarget) && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3))) @@ -4755,14 +5116,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3)) - && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) + && !(gBattleMons[gBattlerAttacker].volatiles.infatuation) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)) { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_INFATUATED_WITH(gBattlerTarget); + gBattleMons[gBattlerAttacker].volatiles.infatuation = INFATUATED_WITH(gBattlerTarget); BattleScriptCall(BattleScript_CuteCharmActivates); effect++; } @@ -4791,7 +5151,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && (moveType == TYPE_FIRE || moveType == TYPE_WATER)) { - gEffectBattler = battler; + gEffectBattler = gBattlerAbility = battler; SET_STATCHANGER(STAT_SPEED, 6, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; @@ -4819,16 +5179,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && (IsMoveMakingContact(move, gBattlerAttacker)) - && !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) + && !gBattleMons[gBattlerAttacker].volatiles.perishSong) { - if (!(gStatuses3[battler] & STATUS3_PERISH_SONG)) + if (!gBattleMons[battler].volatiles.perishSong) { - gStatuses3[battler] |= STATUS3_PERISH_SONG; + gBattleMons[battler].volatiles.perishSong = TRUE; gDisableStructs[battler].perishSongTimer = 3; } - gStatuses3[gBattlerAttacker] |= STATUS3_PERISH_SONG; + gBattleMons[gBattlerAttacker].volatiles.perishSong = TRUE; gDisableStructs[gBattlerAttacker].perishSongTimer = 3; BattleScriptCall(BattleScript_PerishBodyActivates); effect++; @@ -4878,24 +5237,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && moveType == TYPE_FIRE) { - gEffectBattler = gBattlerTarget; + gEffectBattler = gBattlerAbility = gBattlerTarget; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptCall(BattleScript_TargetAbilityStatRaiseRet); effect++; } break; - case ABILITY_ANGER_SHELL: - if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg - && IsBattlerTurnDamaged(gBattlerTarget) - && (gMultiHitCounter == 0 || gMultiHitCounter == 1) // Activates after all hits from a multi-hit move. - && IsBattlerAlive(gBattlerTarget) - && HadMoreThanHalfHpNowDoesnt(gBattlerTarget) - && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove))) - { - BattleScriptCall(BattleScript_AngerShellActivates); - effect++; - } - break; case ABILITY_WIND_POWER: if (!IsWindMove(gCurrentMove)) break; @@ -4921,6 +5268,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; case ABILITYEFFECT_MOVE_END_ATTACKER: // Same as above, but for attacker @@ -4930,8 +5279,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomPercentage(RNG_POISON_TOUCH, 30)) { @@ -4944,13 +5292,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_TOXIC_CHAIN: - if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && IsBattlerAlive(gBattlerTarget) - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target - && RandomWeighted(RNG_TOXIC_CHAIN, 7, 3)) + if (gBattleStruct->toxicChainPriority) { + gBattleStruct->toxicChainPriority = FALSE; gEffectBattler = gBattlerTarget; gBattleScripting.battler = gBattlerAttacker; gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; @@ -4975,10 +5319,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_GULP_MISSILE: if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) - && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_UNDERWATER) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { - BattleScriptCall(BattleScript_AttackerFormChange); + gBattleScripting.battler = gBattlerAttacker; + BattleScriptCall(BattleScript_BattlerFormChange); effect++; } break; @@ -4995,6 +5340,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -5015,39 +5362,36 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Set the target to the original target of the mon that first used a Dance move gBattlerTarget = gBattleScripting.savedBattler & 0x3; - // Edge case for dance moves that hit multiply targets - gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; - // Make sure that the target isn't an ally - if it is, target the original user if (IsBattlerAlly(gBattlerTarget, gBattlerAttacker)) gBattlerTarget = (gBattleScripting.savedBattler & 0xF0) >> 4; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; BattleScriptExecute(BattleScript_DancerActivates); effect++; } break; + default: + break; } break; case ABILITYEFFECT_OPPORTUNIST: - /* Similar to ABILITYEFFECT_IMMUNITY in that it loops through all battlers. - * Is called after ABILITYEFFECT_ON_SWITCHIN to copy any boosts - * from switch in abilities e.g. intrepid sword, as - */ - for (battler = 0; battler < gBattlersCount; battler++) + case ABILITYEFFECT_OPPORTUNIST_FIRST_TURN: + switch (ability) { - switch (GetBattlerAbility(battler)) + case ABILITY_OPPORTUNIST: + if (gProtectStructs[battler].activateOpportunist == 2) { - case ABILITY_OPPORTUNIST: - if (gProtectStructs[battler].activateOpportunist == 2) - { - gBattleScripting.battler = battler; - gProtectStructs[battler].activateOpportunist--; - ChooseStatBoostAnimation(battler); - BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChange); - effect = 1; - } - break; + gBattleScripting.battler = battler; + gProtectStructs[battler].activateOpportunist--; + ChooseStatBoostAnimation(battler); + if (caseID == ABILITYEFFECT_OPPORTUNIST_FIRST_TURN) + BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChangeEnd3); + else + BattleScriptCall(BattleScript_OpportunistCopyStatChange); + effect = 1; } + break; + default: + break; } break; case ABILITYEFFECT_IMMUNITY: @@ -5064,7 +5408,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_OWN_TEMPO: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) { StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); effect = 2; @@ -5082,7 +5426,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gBattleMons[battler].status1 & STATUS1_SLEEP) { TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); effect = 1; } @@ -5104,11 +5448,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_OBLIVIOUS: - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) + if (gBattleMons[battler].volatiles.infatuation) effect = 3; else if (gDisableStructs[battler].tauntTimer != 0) effect = 4; break; + default: + break; } if (effect != 0) @@ -5124,7 +5470,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptCall(BattleScript_AbilityCuredStatus); break; case 3: // get rid of infatuation - gBattleMons[battler].status2 &= ~STATUS2_INFATUATION; + gBattleMons[battler].volatiles.infatuation = 0; BattleScriptCall(BattleScript_BattlerGotOverItsInfatuation); break; case 4: // get rid of taunt @@ -5146,17 +5492,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleScripting.battler = gBattlerAbility = gBattlerTarget; RecordAbilityBattle(gBattlerTarget, ABILITY_SYNCHRONIZE); + if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + if (CanSetNonVolatileStatus( gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker), gBattleStruct->synchronizeMoveEffect, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) { - if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) - gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; - gEffectBattler = gBattlerAttacker; gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE); @@ -5176,13 +5522,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleScripting.battler = gBattlerAbility = gBattlerAttacker; RecordAbilityBattle(gBattlerAttacker, ABILITY_SYNCHRONIZE); + if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + if (CanSetNonVolatileStatus( gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker), gBattleStruct->synchronizeMoveEffect, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) { if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; @@ -5202,49 +5551,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITYEFFECT_NEUTRALIZINGGAS: + case ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN: // Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards - for (i = 0; i < gBattlersCount; i++) + if (ability == ABILITY_NEUTRALIZING_GAS && !gDisableStructs[battler].neutralizingGas) { - if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gDisableStructs[i].neutralizingGas) - { - gDisableStructs[i].neutralizingGas = TRUE; - gBattlerAbility = i; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + gDisableStructs[battler].neutralizingGas = TRUE; + gBattlerAbility = battler; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; + if (caseID == ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN) BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); - effect++; - } - - if (effect != 0) - break; - } - break; - case ABILITYEFFECT_FIELD_SPORT: - switch (gLastUsedAbility) - { - case ABILITYEFFECT_MUD_SPORT: - for (i = 0; i < gBattlersCount; i++) - { - if (gStatuses4[i] & STATUS4_MUD_SPORT) - effect = i + 1; - } - break; - case ABILITYEFFECT_WATER_SPORT: - for (i = 0; i < gBattlersCount; i++) - { - if (gStatuses4[i] & STATUS4_WATER_SPORT) - effect = i + 1; - } - break; - default: - for (i = 0; i < gBattlersCount; i++) - { - if (gBattleMons[i].ability == ability) - { - gLastUsedAbility = ability; - effect = i + 1; - } - } - break; + else + BattleScriptCall(BattleScript_SwitchInAbilityMsgRet); + effect++; } break; case ABILITYEFFECT_ON_WEATHER: // For ability effects that activate when the battle weather changes. @@ -5274,7 +5592,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].weatherAbilityDone && battlerWeatherAffected && gBattleMons[battler].species == SPECIES_EISCUE_NOICE - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { // TODO: Convert this to a proper FORM_CHANGE type. gBattleScripting.battler = battler; @@ -5288,7 +5606,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_PROTOSYNTHESIS: if (!gDisableStructs[battler].weatherAbilityDone && (gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect() - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[battler].volatiles.transformed && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].weatherAbilityDone = TRUE; @@ -5298,6 +5616,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; case ABILITYEFFECT_ON_TERRAIN: // For ability effects that activate when the field terrain changes. @@ -5317,7 +5637,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_QUARK_DRIVE: if (!gDisableStructs[battler].terrainAbilityDone && gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[battler].volatiles.transformed && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].terrainAbilityDone = TRUE; @@ -5327,6 +5647,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; + default: + break; } break; } @@ -5341,7 +5663,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 bool32 TryPrimalReversion(u32 battler) { - if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_PRIMAL_ORB + if (GetBattlerHoldEffectIgnoreNegation(battler) == HOLD_EFFECT_PRIMAL_ORB && GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != gBattleMons[battler].species) { gBattleScripting.battler = battler; @@ -5357,16 +5679,16 @@ bool32 IsNeutralizingGasOnField(void) for (i = 0; i < gBattlersCount; i++) { - if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gStatuses3[i] & STATUS3_GASTRO_ACID)) + if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gBattleMons[i].volatiles.gastroAcid) return TRUE; } return FALSE; } -bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) +bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability) { - if (gStatuses3[battler] & STATUS3_GASTRO_ACID) + if (gBattleMons[battler].volatiles.gastroAcid) return FALSE; if (ability == ABILITY_MOLD_BREAKER @@ -5381,7 +5703,7 @@ bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) return FALSE; } -static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 ability, u32 hasAbilityShield, u32 ignoreMoldBreaker) +static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, enum Ability ability, u32 hasAbilityShield, u32 ignoreMoldBreaker) { if (hasAbilityShield || ignoreMoldBreaker) return FALSE; @@ -5404,21 +5726,21 @@ u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler) return GetBattlerAbilityInternal(battler, TRUE, FALSE); } -u32 GetBattlerAbility(u32 battler) +enum Ability GetBattlerAbility(u32 battler) { return GetBattlerAbilityInternal(battler, FALSE, FALSE); } u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield) { - bool32 hasAbilityShield = !noAbilityShield && GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD; + bool32 hasAbilityShield = !noAbilityShield && GetBattlerHoldEffectIgnoreAbility(battler) == HOLD_EFFECT_ABILITY_SHIELD; bool32 abilityCantBeSuppressed = gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed; if (abilityCantBeSuppressed) { // Edge case: pokemon under the effect of gastro acid transforms into a pokemon with Comatose (Todo: verify how other unsuppressable abilities behave) - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED - && gStatuses3[battler] & STATUS3_GASTRO_ACID + if (gBattleMons[battler].volatiles.transformed + && gBattleMons[battler].volatiles.gastroAcid && gBattleMons[battler].ability == ABILITY_COMATOSE) return ABILITY_NONE; @@ -5428,7 +5750,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS return gBattleMons[battler].ability; } - if (gStatuses3[battler] & STATUS3_GASTRO_ACID) + if (gBattleMons[battler].volatiles.gastroAcid) return ABILITY_NONE; if (!hasAbilityShield @@ -5442,7 +5764,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS return gBattleMons[battler].ability; } -u32 IsAbilityOnSide(u32 battler, u32 ability) +u32 IsAbilityOnSide(u32 battler, enum Ability ability) { if (IsBattlerAlive(battler) && GetBattlerAbility(battler) == ability) return battler + 1; @@ -5452,12 +5774,12 @@ u32 IsAbilityOnSide(u32 battler, u32 ability) return 0; } -u32 IsAbilityOnOpposingSide(u32 battler, u32 ability) +u32 IsAbilityOnOpposingSide(u32 battler, enum Ability ability) { return IsAbilityOnSide(BATTLE_OPPOSITE(battler), ability); } -u32 IsAbilityOnField(u32 ability) +u32 IsAbilityOnField(enum Ability ability) { u32 i; @@ -5470,7 +5792,7 @@ u32 IsAbilityOnField(u32 ability) return 0; } -u32 IsAbilityOnFieldExcept(u32 battler, u32 ability) +u32 IsAbilityOnFieldExcept(u32 battler, enum Ability ability) { u32 i; @@ -5488,17 +5810,18 @@ u32 IsAbilityPreventingEscape(u32 battler) if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return 0; + bool32 isBattlerGrounded = IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)); for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (battler == battlerDef || IsBattlerAlly(battler, battlerDef)) continue; - u32 ability = GetBattlerAbility(battlerDef); + enum Ability ability = GetBattlerAbility(battlerDef); if (ability == ABILITY_SHADOW_TAG && (B_SHADOW_TAG_ESCAPE <= GEN_3 || GetBattlerAbility(battler) != ABILITY_SHADOW_TAG)) return battlerDef + 1; - if (ability == ABILITY_ARENA_TRAP && IsBattlerGrounded(battler)) + if (ability == ABILITY_ARENA_TRAP && isBattlerGrounded) return battlerDef + 1; if (ability == ABILITY_MAGNET_PULL && IS_BATTLER_OF_TYPE(battler, TYPE_STEEL)) @@ -5510,19 +5833,21 @@ u32 IsAbilityPreventingEscape(u32 battler) bool32 CanBattlerEscape(u32 battler) // no ability check { - if (gBattleStruct->commanderActive[battler] != SPECIES_NONE) + if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE) return FALSE; - else if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SHED_SHELL) + else if (GetBattlerHoldEffect(battler) == HOLD_EFFECT_SHED_SHELL) return TRUE; else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return TRUE; - else if (gBattleMons[battler].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) + else if (gBattleMons[battler].volatiles.escapePrevention) return FALSE; - else if (gStatuses3[battler] & STATUS3_ROOTED) + else if (gBattleMons[battler].volatiles.wrapped) + return FALSE; + else if (gBattleMons[battler].volatiles.root) return FALSE; else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return FALSE; - else if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + else if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; else return TRUE; @@ -5543,94 +5868,105 @@ void BattleScriptPushCursorAndCallback(const u8 *BS_ptr) gBattleMainFunc = RunBattleScriptCommands; } -bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) +bool32 IsBattlerTerrainAffected(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect, u32 terrainFlag) { if (!(gFieldStatuses & terrainFlag)) return FALSE; - else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; - return IsBattlerGrounded(battler); + return IsBattlerGrounded(battler, ability, holdEffect); } -bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause) +bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, enum SleepClauseBlock isBlockedBySleepClause) { - if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause) + if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE) return FALSE; - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_SLEEP, // also covers yawn - STATUS_CHECK_TRIGGER)) - return TRUE; - return FALSE; + if (isBlockedBySleepClause == NOT_BLOCKED_BY_SLEEP_CLAUSE) + gBattleStruct->sleepClauseNotBlocked = TRUE; + + bool32 effect = FALSE; + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_SLEEP, // also covers yawn + CHECK_TRIGGER)) + effect = TRUE; + + gBattleStruct->sleepClauseNotBlocked = FALSE; + return effect; } -bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) +bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - abilityAtk, - abilityDef, - MOVE_EFFECT_TOXIC, // also covers poison - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + abilityAtk, + abilityDef, + MOVE_EFFECT_TOXIC, // also covers poison + CHECK_TRIGGER)) return TRUE; return FALSE; } // TODO: check order of battlerAtk and battlerDef -bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_BURN, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_BURN, + CHECK_TRIGGER)) return TRUE; return FALSE; } -bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_PARALYSIS, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_PARALYSIS, + CHECK_TRIGGER)) return TRUE; return FALSE; } -bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef) +bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_FREEZE, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_FREEZE, + CHECK_TRIGGER)) + return TRUE; + return FALSE; +} +// Unused, technically also redundant because it is just a copy of CanBeFrozen +bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef) +{ + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_FREEZE_OR_FROSTBITE, // also covers frostbite + CHECK_TRIGGER)) return TRUE; return FALSE; } -// Unused, technically also redundant -bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) -{ - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_FREEZE_OR_FROSTBITE, // also covers frostbite - STATUS_CHECK_TRIGGER)) - return TRUE; - return FALSE; -} - -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects effect, enum NonVolatileStatus option) +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, enum MoveEffect effect, enum FunctionCallOption option) { const u8 *battleScript = NULL; u32 sideBattler = ABILITY_NONE; @@ -5654,13 +5990,11 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battlerDef = sideBattler - 1; abilityDef = ABILITY_PASTEL_VEIL; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PASTEL_VEIL; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_IMMUNITY) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_POISON; battleScript = BattleScript_ImmunityProtected; } break; @@ -5673,8 +6007,8 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_NotAffected; } - else if (option == STATUS_RUN_SCRIPT // Check only important during battle execution for moves - && CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), battlerAtk, battlerDef, abilityDef, TRUE) + else if (option == RUN_SCRIPT // Check only important during battle execution for moves + && CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), battlerAtk, battlerDef, abilityAtk, abilityDef, TRUE) && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) { battleScript = BattleScript_ButItFailed; @@ -5682,7 +6016,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u else if (abilityDef == ABILITY_LIMBER) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_PARALYSIS; battleScript = BattleScript_ImmunityProtected; } break; @@ -5698,7 +6031,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u else if (abilityDef == ABILITY_WATER_VEIL || abilityDef == ABILITY_WATER_BUBBLE) { abilityAffected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABILITY_PREVENTS_MOVE_BURN; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_THERMAL_EXCHANGE) @@ -5716,11 +6048,11 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_CantMakeAsleep; } - else if (CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) + else if (!gBattleStruct->sleepClauseNotBlocked && CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) { battleScript = BattleScript_SleepClauseBlocked; } - else if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_ELECTRIC_TERRAIN)) { battleScript = BattleScript_ElectricTerrainPrevents; } @@ -5729,7 +6061,6 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battlerDef = sideBattler - 1; abilityDef = ABILITY_SWEET_VEIL; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT; battleScript = BattleScript_ImmunityProtected; } else if (abilityDef == ABILITY_VITAL_SPIRIT || abilityDef == ABILITY_INSOMNIA) @@ -5769,7 +6100,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u abilityAffected = TRUE; battleScript = BattleScript_AbilityProtectsDoesntAffect; } - else if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN)) + else if (IsBattlerTerrainAffected(battlerDef, abilityDef, GetBattlerHoldEffect(battlerDef), STATUS_FIELD_MISTY_TERRAIN)) { battleScript = BattleScript_MistyTerrainPrevents; } @@ -5800,11 +6131,11 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u return TRUE; } -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum NonVolatileStatus option) +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option) { if (battleScript != NULL) { - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) { if (battleScript != BattleScript_NotAffected) gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FAILED; @@ -5825,17 +6156,17 @@ static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abi return FALSE; } -static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonVolatileStatus option) +static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option) { // Can freely sleep own partner if (IsDoubleBattle() && IsSleepClauseEnabled() && IsBattlerAlly(battlerAtk, battlerDef)) { - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) gBattleStruct->battlerState[battlerDef].sleepClauseEffectExempt = TRUE; return FALSE; } - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) gBattleStruct->battlerState[battlerDef].sleepClauseEffectExempt = FALSE; // Can't sleep if clause is active otherwise if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef))) @@ -5846,9 +6177,10 @@ static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonV bool32 CanBeConfused(u32 battler) { - if (gBattleMons[battler].status2 & STATUS2_CONFUSION - || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) - || IsAbilityAndRecord(battler, GetBattlerAbility(battler),ABILITY_OWN_TEMPO)) + enum Ability ability = GetBattlerAbility(battler); + if (gBattleMons[battler].volatiles.confusionTurns > 0 + || IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_MISTY_TERRAIN) + || IsAbilityAndRecord(battler, ability, ABILITY_OWN_TEMPO)) return FALSE; return TRUE; } @@ -5879,7 +6211,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID) { if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId); @@ -5918,7 +6250,6 @@ static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum { if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId)) { - BufferStatChange(battler, statId, STRINGID_STATROSE); gEffectBattler = gBattleScripting.battler = battler; if (GetBattlerAbility(battler) == ABILITY_RIPEN) SET_STATCHANGER(statId, 2, FALSE); @@ -5940,7 +6271,6 @@ static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, u32 statId, enum static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCaseId caseID) { s32 stat; - enum StringID stringId; for (stat = STAT_ATK; stat < NUM_STATS; stat++) { @@ -5949,23 +6279,18 @@ static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, enum ItemCa } if (stat != NUM_STATS && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId)) { - u16 battlerAbility = GetBattlerAbility(battler); + enum Ability battlerAbility = GetBattlerAbility(battler); u32 savedAttacker = gBattlerAttacker; // MoodyCantRaiseStat requires that the battler is set to gBattlerAttacker gBattlerAttacker = gBattleScripting.battler = battler; - stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantRaiseStat); + gBattleScripting.statChanger = 0; + if (battlerAbility != ABILITY_CONTRARY) + stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantRaiseStat); + else + stat = RandomUniformExcept(RNG_RANDOM_STAT_UP, STAT_ATK, NUM_STATS - 1, MoodyCantLowerStat); gBattlerAttacker = savedAttacker; PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); - stringId = (battlerAbility == ABILITY_CONTRARY) ? STRINGID_STATFELL : STRINGID_STATROSE; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATSHARPLY; - gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; - gBattleTextBuff2[4] = B_BUFF_STRING; - gBattleTextBuff2[5] = stringId; - gBattleTextBuff2[6] = stringId >> 8; - gBattleTextBuff2[7] = EOS; gEffectBattler = battler; if (battlerAbility == ABILITY_RIPEN) SET_STATCHANGER(stat, 4, FALSE); @@ -6007,7 +6332,7 @@ static enum ItemEffect TrySetEnigmaBerry(u32 battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && ((IsBattlerTurnDamaged(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { gBattleScripting.battler = battler; gBattleStruct->moveDamage[battler] = (gBattleMons[battler].maxHP * 25 / 100) * -1; @@ -6031,8 +6356,6 @@ static enum ItemEffect DamagedStatBoostBerryEffect(u32 battler, u8 statId, enum && IsBattlerTurnDamaged(battler))) ) { - BufferStatChange(battler, statId, STRINGID_STATROSE); - gEffectBattler = battler; if (GetBattlerAbility(battler) == ABILITY_RIPEN) SET_STATCHANGER(statId, 2, FALSE); @@ -6052,7 +6375,6 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item { if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { - BufferStatChange(battler, statId, STRINGID_STATROSE); gLastUsedItem = itemId; // For surge abilities gEffectBattler = gBattleScripting.battler = battler; SET_STATCHANGER(statId, 1, FALSE); @@ -6067,35 +6389,11 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item return ITEM_NO_EFFECT; } -static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID) -{ - if (gProtectStructs[battler].tryEjectPack - && !gProtectStructs[battler].disableEjectPack - && CountUsablePartyMons(battler) > 0 - && !(GetMoveEffect(gCurrentMove) == EFFECT_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out - { - gProtectStructs[battler].tryEjectPack = FALSE; - gBattleScripting.battler = battler; - gAiLogicData->ejectPackSwitch = TRUE; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN) - { - BattleScriptExecute(BattleScript_EjectPackActivate_End2); - } - else - { - BattleScriptCall(BattleScript_EjectPackActivate_Ret); - } - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID) { if (CanBeInfinitelyConfused(battler)) - gStatuses4[battler] |= STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.infiniteConfusion = TRUE; - BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE); gBattlerAttacker = gEffectBattler = battler; SET_STATCHANGER(STAT_ATK, 2, FALSE); gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK; @@ -6139,6 +6437,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID) else BattleScriptCall(BattleScript_BerryPPHealRet); + gBattleScripting.battler = battler; BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP); MarkBattlerForControllerExec(battler); if (MOVE_IS_PERMANENT(battler, i)) @@ -6152,7 +6451,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID) static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal) { if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock) && HasEnoughHpToEatBerry(battler, 2, itemId)) { if (percentHeal) @@ -6190,9 +6489,9 @@ static bool32 GetMentalHerbEffect(u32 battler) bool32 ret = FALSE; // Check infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) + if (gBattleMons[battler].volatiles.infatuation) { - gBattleMons[battler].status2 &= ~STATUS2_INFATUATION; + gBattleMons[battler].volatiles.infatuation = 0; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; @@ -6216,16 +6515,16 @@ static bool32 GetMentalHerbEffect(u32 battler) ret = TRUE; } // Check torment - if (gBattleMons[battler].status2 & STATUS2_TORMENT) + if (gBattleMons[battler].volatiles.torment == TRUE) { - gBattleMons[battler].status2 &= ~STATUS2_TORMENT; + gBattleMons[battler].volatiles.torment = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; ret = TRUE; } // Check heal block - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.healBlock) { - gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; + gBattleMons[battler].volatiles.healBlock = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; ret = TRUE; } @@ -6251,7 +6550,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) gBattleScripting.battler = battler; gProtectStructs[battler].eatMirrorHerb = 0; ChooseStatBoostAnimation(battler); - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) + if (caseID == ITEMEFFECT_MIRROR_HERB_FIRST_TURN) BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2); else BattleScriptCall(BattleScript_MirrorHerbCopyStatChange); @@ -6260,9 +6559,9 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) return effect; } -u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID) +u32 TryBoosterEnergy(u32 battler, enum Ability ability, enum ItemCaseId caseID) { - if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].volatiles.transformed) return ITEM_NO_EFFECT; if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) @@ -6283,7 +6582,7 @@ u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID) return ITEM_NO_EFFECT; } -u32 RestoreWhiteHerbStats(u32 battler) +static u32 RestoreWhiteHerbStats(u32 battler, enum ItemCaseId caseID) { u32 i, effect = 0; @@ -6300,7 +6599,12 @@ u32 RestoreWhiteHerbStats(u32 battler) gLastUsedItem = gBattleMons[battler].item; gBattleScripting.battler = battler; gPotentialItemEffectBattler = battler; - } + if (caseID == ITEMEFFECT_WHITE_HERB) + BattleScriptCall(BattleScript_WhiteHerbRet); + else + BattleScriptExecute(BattleScript_WhiteHerbEnd2); +} + return effect; } @@ -6421,14 +6725,14 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptCall(BattleScript_BerryCureSlpRet); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION && !UnnerveOn(battler, gLastUsedItem)) + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) { RemoveConfusionStatus(battler); BattleScriptCall(BattleScript_BerryCureConfusionRet); @@ -6445,14 +6749,14 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) } break; case HOLD_EFFECT_CURE_STATUS: - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem)) + if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) { if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); if (gBattleMons[battler].status1 & STATUS1_SLEEP) { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } @@ -6466,7 +6770,7 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); gBattleMons[battler].status1 = 0; @@ -6478,10 +6782,10 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) break; case HOLD_EFFECT_CRITICAL_UP: // lansat berry if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; gPotentialItemEffectBattler = battler; BattleScriptCall(BattleScript_BerryFocusEnergyRet); @@ -6491,8 +6795,20 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) case HOLD_EFFECT_BERSERK_GENE: effect = ConsumeBerserkGene(battler, ITEMEFFECT_NONE); break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE); + case HOLD_EFFECT_THROAT_SPRAY: + if (IsSoundMove(gCurrentMove) + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && IsBattlerAlive(gBattlerAttacker) + && IsAnyTargetAffected(gBattlerAttacker) + && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) + && !NoAliveMonsForEitherParty()) // Don't activate if battle will end + { + gLastUsedItem = gBattleMons[gBattlerAttacker].item; + gBattleScripting.battler = gBattlerAttacker; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + effect = ITEM_STATS_CHANGE; + BattleScriptCall(BattleScript_AttackerItemStatRaise); + } break; default: break; @@ -6506,7 +6822,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) u32 effect = ITEM_NO_EFFECT; u32 string = 0; - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem)) + if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) { if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) { @@ -6515,7 +6831,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) } if (gBattleMons[battler].status1 & STATUS1_SLEEP) { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); string++; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); @@ -6535,7 +6851,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); string++; } - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) { StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); string++; @@ -6556,6 +6872,43 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) return effect; } +// This is hacky and could potentially be improved because ideally this function wouldn't exist but there is some inconsitency with timings. +static bool32 ShouldWaitWithActivation(u32 battler, enum ItemHoldEffect holdEffect) +{ + if (holdEffect != HOLD_EFFECT_RESTORE_HP + && holdEffect != HOLD_EFFECT_RESTORE_PCT_HP + && holdEffect != HOLD_EFFECT_RESTORE_PP + && holdEffect != HOLD_EFFECT_CONFUSE_SPICY + && holdEffect != HOLD_EFFECT_CONFUSE_DRY + && holdEffect != HOLD_EFFECT_CONFUSE_SWEET + && holdEffect != HOLD_EFFECT_CONFUSE_BITTER + && holdEffect != HOLD_EFFECT_CONFUSE_SOUR) + return FALSE; + + // Restore HP berries can be knocked off + if (gBattleStruct->battlerState[battler].itemCanBeKnockedOff) + return TRUE; + + if (IsBattlerTurnDamaged(battler) + && gMultiHitCounter == 0 // Non multi hit moves don't wait for Berserk / Anger Shell activation + && IsBattlerAlive(battler) + && !TestIfSheerForceAffected(battler, gCurrentMove) + && HadMoreThanHalfHpNowDoesnt(battler)) + { + switch (GetBattlerAbility(battler)) + { + case ABILITY_BERSERK: + return CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN); + case ABILITY_ANGER_SHELL: + return TRUE; + default: + return FALSE; + } + } + + return FALSE; +} + u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) { u32 moveType = 0; @@ -6567,11 +6920,11 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) if (caseID != ITEMEFFECT_USE_LAST_ITEM) { gLastUsedItem = gBattleMons[battler].item; - battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); + battlerHoldEffect = GetBattlerHoldEffect(battler); } atkItem = gBattleMons[gBattlerAttacker].item; - atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker); atkHoldEffectParam = GetBattlerHoldEffectParam(gBattlerAttacker); switch (caseID) @@ -6591,11 +6944,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) gBattleStruct->moneyMultiplierItem = 1; } break; - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptExecute(BattleScript_WhiteHerbEnd2); - break; case HOLD_EFFECT_CONFUSE_SPICY: if (B_BERRIES_INSTANT >= GEN_4) effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); @@ -6638,10 +6986,10 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; case HOLD_EFFECT_CRITICAL_UP: if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); effect = ITEM_EFFECT_OTHER; @@ -6705,7 +7053,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); @@ -6723,6 +7071,9 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) if (B_BERRIES_INSTANT >= GEN_4) effect = ItemHealHp(battler, gLastUsedItem, caseID, TRUE); break; + case HOLD_EFFECT_RESTORE_PP: + effect = ItemRestorePp(battler, gLastUsedItem, caseID); + break; case HOLD_EFFECT_AIR_BALLOON: effect = ITEM_EFFECT_OTHER; gBattleScripting.battler = battler; @@ -6753,15 +7104,9 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; } break; - case HOLD_EFFECT_EJECT_PACK: - effect = TryEjectPack(battler, caseID); - break; case HOLD_EFFECT_BERSERK_GENE: effect = ConsumeBerserkGene(battler, caseID); break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, caseID); - break; case HOLD_EFFECT_BOOSTER_ENERGY: effect = TryBoosterEnergy(battler, GetBattlerAbility(battler), caseID); break; @@ -6780,9 +7125,48 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) } } break; + case ITEMEFFECT_LEFTOVERS: + switch (battlerHoldEffect) + { + case HOLD_EFFECT_BLACK_SLUDGE: + if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) + { + goto LEFTOVERS; + } + else if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) + { + gBattleScripting.battler = battler; + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + BattleScriptExecute(BattleScript_ItemHurtEnd2); + effect = ITEM_HP_CHANGE; + RecordItemEffectBattle(battler, battlerHoldEffect); + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); + } + break; + case HOLD_EFFECT_LEFTOVERS: + LEFTOVERS: + if (gBattleMons[battler].hp < gBattleMons[battler].maxHP + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) + { + gBattleScripting.battler = battler; + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + gBattleStruct->moveDamage[battler] *= -1; + BattleScriptExecute(BattleScript_ItemHealHP_End2); + effect = ITEM_HP_CHANGE; + RecordItemEffectBattle(battler, battlerHoldEffect); + } + break; + default: + break; + } + break; case ITEMEFFECT_NORMAL: case ITEMEFFECT_TRY_HEALING: - if (gBattleMons[battler].hp) + if (IsBattlerAlive(battler)) { switch (battlerHoldEffect) { @@ -6795,41 +7179,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) case HOLD_EFFECT_RESTORE_PP: effect = ItemRestorePp(battler, gLastUsedItem, caseID); break; - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptExecute(BattleScript_WhiteHerbEnd2); - break; - case HOLD_EFFECT_BLACK_SLUDGE: - if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) - { - goto LEFTOVERS; - } - else if (!IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - BattleScriptExecute(BattleScript_ItemHurtEnd2); - effect = ITEM_HP_CHANGE; - RecordItemEffectBattle(battler, battlerHoldEffect); - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); - } - break; - case HOLD_EFFECT_LEFTOVERS: - LEFTOVERS: - if (gBattleMons[battler].hp < gBattleMons[battler].maxHP - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - BattleScriptExecute(BattleScript_ItemHealHP_End2); - effect = ITEM_HP_CHANGE; - RecordItemEffectBattle(battler, battlerHoldEffect); - } - break; case HOLD_EFFECT_CONFUSE_SPICY: effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, caseID); break; @@ -6861,10 +7210,10 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); break; case HOLD_EFFECT_CRITICAL_UP: - if (!(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (!(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); effect = ITEM_EFFECT_OTHER; @@ -6915,14 +7264,14 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION && !UnnerveOn(battler, gLastUsedItem)) + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) { RemoveConfusionStatus(battler); BattleScriptExecute(BattleScript_BerryCureConfusionEnd2); @@ -6947,9 +7296,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) case HOLD_EFFECT_BERSERK_GENE: effect = ConsumeBerserkGene(battler, caseID); break; - case HOLD_EFFECT_MIRROR_HERB: - effect = TryConsumeMirrorHerb(battler, caseID); - break; default: break; } @@ -6982,8 +7328,12 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) case ITEMEFFECT_MOVE_END: for (battler = 0; battler < gBattlersCount; battler++) { + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); + if (ShouldWaitWithActivation(battler, holdEffect)) + continue; + gLastUsedItem = gBattleMons[battler].item; - effect = ItemEffectMoveEnd(battler, GetBattlerHoldEffect(battler, TRUE)); + effect = ItemEffectMoveEnd(battler, holdEffect); if (effect) { gPotentialItemEffectBattler = gBattleScripting.battler = battler; @@ -7002,7 +7352,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) { case HOLD_EFFECT_FLINCH: { - u16 ability = GetBattlerAbility(gBattlerAttacker); + enum Ability ability = GetBattlerAbility(gBattlerAttacker); if (B_SERENE_GRACE_BOOST >= GEN_5 && ability == ABILITY_SERENE_GRACE) atkHoldEffectParam *= 2; if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW && gCurrentMove != MOVE_SECRET_POWER) @@ -7049,7 +7399,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) && IsBattlerAlive(gBattlerAttacker) && GetMoveEffect(gCurrentMove) != EFFECT_FUTURE_SIGHT && GetMoveEffect(gCurrentMove) != EFFECT_PAIN_SPLIT - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { gLastUsedItem = atkItem; gPotentialItemEffectBattler = gBattlerAttacker; @@ -7064,11 +7414,9 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) case HOLD_EFFECT_LIFE_ORB: if (IsBattlerAlive(gBattlerAttacker) && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && !IsBattleMoveStatus(gCurrentMove) - && (IsBattlerTurnDamaged(gBattlerTarget) || !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Needs the second check in case of Substitute - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove) - && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) + && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleScripting.savedDmg > 0) + && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD) + && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -7078,20 +7426,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) gLastUsedItem = atkItem; } break; - case HOLD_EFFECT_THROAT_SPRAY: // Does NOT need to be a damaging move - if (IsSoundMove(gCurrentMove) - && IsBattlerAlive(gBattlerAttacker) - && IsAnyTargetAffected(gBattlerAttacker) - && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !NoAliveMonsForEitherParty()) // Don't activate if battle will end - { - gLastUsedItem = atkItem; - gBattleScripting.battler = gBattlerAttacker; - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_AttackerItemStatRaise); - } - break; default: break; } @@ -7111,8 +7445,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; case HOLD_EFFECT_ROCKY_HELMET: if (IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) && IsBattlerAlive(gBattlerAttacker) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -7235,8 +7568,8 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; case HOLD_EFFECT_STICKY_BARB: if (IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && IsBattlerAlive(gBattlerAttacker) && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) @@ -7256,7 +7589,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; case ITEMEFFECT_ORBS: { - u16 battlerAbility = GetBattlerAbility(battler); + enum Ability battlerAbility = GetBattlerAbility(battler); switch (battlerHoldEffect) { case HOLD_EFFECT_TOXIC_ORB: @@ -7300,23 +7633,22 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) } } break; - case ITEMEFFECT_STATS_CHANGED: - switch (battlerHoldEffect) - { - case HOLD_EFFECT_WHITE_HERB: - effect = RestoreWhiteHerbStats(battler); - if (effect != 0) - BattleScriptCall(BattleScript_WhiteHerbRet); - break; - default: - break; - } + case ITEMEFFECT_WHITE_HERB: + case ITEMEFFECT_WHITE_HERB_ENDTURN: + case ITEMEFFECT_WHITE_HERB_FIRST_TURN: + if (battlerHoldEffect == HOLD_EFFECT_WHITE_HERB) + effect = RestoreWhiteHerbStats(battler, caseID); + break; + case ITEMEFFECT_MIRROR_HERB: + case ITEMEFFECT_MIRROR_HERB_FIRST_TURN: + if (battlerHoldEffect == HOLD_EFFECT_MIRROR_HERB) + effect = TryConsumeMirrorHerb(battler, caseID); break; } // Berry was successfully used on a Pokemon. if (effect && (gLastUsedItem >= FIRST_BERRY_INDEX && gLastUsedItem <= LAST_BERRY_INDEX)) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; + GetBattlerPartyState(battler)->ateBerry = TRUE; return effect; } @@ -7324,9 +7656,9 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) void ClearVariousBattlerFlags(u32 battler) { gDisableStructs[battler].furyCutterCounter = 0; - gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND; - gStatuses3[battler] &= ~STATUS3_GRUDGE; - gStatuses4[battler] &= ~ STATUS4_GLAIVE_RUSH; + gBattleMons[battler].volatiles.destinyBond = 0; + gBattleMons[battler].volatiles.glaiveRush = FALSE; + gBattleMons[battler].volatiles.grudge = FALSE; } void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands @@ -7380,7 +7712,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) } else { - u32 battlerAbilityOnField = 0; + enum Ability battlerAbilityOnField = 0; targetBattler = SetRandomTarget(gBattlerAttacker); if (moveType == TYPE_ELECTRIC && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) @@ -7390,11 +7722,11 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_LIGHTNING_ROD); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + gSpecialStatuses[targetBattler].abilityRedirected = TRUE; } } else if (moveType == TYPE_WATER && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) @@ -7404,11 +7736,11 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_STORM_DRAIN); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + gSpecialStatuses[targetBattler].abilityRedirected = TRUE; } } } @@ -7507,7 +7839,7 @@ u8 GetAttackerObedienceForAction() // is not obedient enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); if (moveEffect == EFFECT_RAGE) - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE; + gBattleMons[gBattlerAttacker].volatiles.rage = FALSE; if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (moveEffect == EFFECT_SNORE || moveEffect == EFFECT_SLEEP_TALK)) return DISOBEYS_WHILE_ASLEEP; @@ -7533,7 +7865,7 @@ u8 GetAttackerObedienceForAction() // try putting asleep int i; for (i = 0; i < gBattlersCount; i++) - if (gBattleMons[i].status2 & STATUS2_UPROAR) + if (gBattleMons[i].volatiles.uproarTurns) break; if (i == gBattlersCount) return DISOBEYS_FALL_ASLEEP; @@ -7546,27 +7878,24 @@ u8 GetAttackerObedienceForAction() } } -enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating) +enum ItemHoldEffect GetBattlerHoldEffect(u32 battler) { - return GetBattlerHoldEffectInternal(battler, checkNegating, TRUE); + return GetBattlerHoldEffectInternal(battler, GetBattlerAbility(battler)); } -enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating) +enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler) { - return GetBattlerHoldEffectInternal(battler, checkNegating, FALSE); + return GetBattlerHoldEffectInternal(battler, ABILITY_NONE); } -enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility) +enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, u32 ability) { - if (checkNegating) - { - if (gStatuses3[battler] & STATUS3_EMBARGO) - return HOLD_EFFECT_NONE; - if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) - return HOLD_EFFECT_NONE; - if (checkAbility && GetBattlerAbility(battler) == ABILITY_KLUTZ && !(gStatuses3[battler] & STATUS3_GASTRO_ACID)) - return HOLD_EFFECT_NONE; - } + if (gBattleMons[battler].volatiles.embargo) + return HOLD_EFFECT_NONE; + if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) + return HOLD_EFFECT_NONE; + if (ability == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) + return HOLD_EFFECT_NONE; gPotentialItemEffectBattler = battler; @@ -7576,6 +7905,15 @@ enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegati return GetItemHoldEffect(gBattleMons[battler].item); } +enum ItemHoldEffect GetBattlerHoldEffectIgnoreNegation(u32 battler) +{ + gPotentialItemEffectBattler = battler; + if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY_E_READER) + return gEnigmaBerries[battler].holdEffect; + else + return GetItemHoldEffect(gBattleMons[battler].item); +} + static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item) { if (item == ITEM_ENIGMA_BERRY_E_READER) @@ -7592,26 +7930,35 @@ u32 GetBattlerHoldEffectParam(u32 battler) return GetItemHoldEffectParam(gBattleMons[battler].item); } -bool32 IsMoveMakingContact(u32 move, u32 battlerAtk) +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) { - enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE); - - if (!MoveMakesContact(move)) + if (holdEffectAtk == HOLD_EFFECT_PROTECTIVE_PADS) { - if (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL) - return TRUE; - else - return FALSE; + RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PROTECTIVE_PADS); + return TRUE; } - else if ((atkHoldEffect == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move)) - || GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH) + + return !IsMoveMakingContact(battlerAtk, battlerDef, abilityAtk, holdEffectAtk, move); +} + +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) +{ + if (!(MoveMakesContact(move) || (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM + && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL))) { return FALSE; } - else + else if (holdEffectAtk == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move)) { - return TRUE; + RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PUNCHING_GLOVE); + return FALSE; } + else if (abilityAtk == ABILITY_LONG_REACH) + { + RecordAbilityBattle(battlerAtk, ABILITY_LONG_REACH); + return FALSE; + } + return TRUE; } static inline bool32 IsSideProtected(u32 battler, enum ProtectMethod method) @@ -7630,7 +7977,8 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) { if (IsZMove(move) || IsMaxMove(move)) return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). - if (IsMoveMakingContact(move, battlerAtk) && IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_UNSEEN_FIST)) + if (GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST + && IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_UNSEEN_FIST, GetBattlerHoldEffect(battlerAtk), move)) return FALSE; } @@ -7711,34 +8059,32 @@ enum IronBallCheck }; // Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics -static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall) +bool32 IsBattlerGroundedInverseCheck(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect, enum InverseBattleCheck checkInverse) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); - - if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL) + if (holdEffect == HOLD_EFFECT_IRON_BALL) return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY) return TRUE; - if (B_ROOTED_GROUNDING >= GEN_4 && gStatuses3[battler] & STATUS3_ROOTED) + if (B_ROOTED_GROUNDING >= GEN_4 && gBattleMons[battler].volatiles.root) return TRUE; - if (gStatuses3[battler] & STATUS3_SMACKED_DOWN) + if (gBattleMons[battler].volatiles.smackDown) return TRUE; - if (gStatuses3[battler] & STATUS3_TELEKINESIS) + if (gBattleMons[battler].volatiles.telekinesis) return FALSE; - if (gStatuses3[battler] & STATUS3_MAGNET_RISE) + if (gBattleMons[battler].volatiles.magnetRise) return FALSE; if (holdEffect == HOLD_EFFECT_AIR_BALLOON) return FALSE; - if (gAiLogicData->aiCalcInProgress ? gAiLogicData->abilities[battler] == ABILITY_LEVITATE : IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_LEVITATE)) + if (ability == ABILITY_LEVITATE) return FALSE; - if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE))) + if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (checkInverse != INVERSE_BATTLE || !FlagGet(B_FLAG_INVERSE_BATTLE))) return FALSE; return TRUE; } -bool32 IsBattlerGrounded(u32 battler) +bool32 IsBattlerGrounded(u32 battler, enum Ability ability, enum ItemHoldEffect holdEffect) { - return IsBattlerGroundedInverseCheck(battler, NOT_INVERSE_BATTLE, CHECK_IRON_BALL); + return IsBattlerGroundedInverseCheck(battler, ability, holdEffect, NOT_INVERSE_BATTLE); } u32 GetMoveSlot(u16 *moves, u32 move) @@ -7757,8 +8103,8 @@ u32 GetBattlerWeight(u32 battler) { u32 i; u32 weight = GetSpeciesWeight(gBattleMons[battler].species); - u32 ability = GetBattlerAbility(battler); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum Ability ability = GetBattlerAbility(battler); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); if (ability == ABILITY_HEAVY_METAL) weight *= 2; @@ -7933,7 +8279,7 @@ u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer) u32 i; for (i = 1; i < (5 - rolloutTimer); i++) basePower *= 2; - if (gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL) + if (gBattleMons[battlerAtk].volatiles.defenseCurl) basePower *= 2; return basePower; } @@ -7946,6 +8292,40 @@ u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter) return basePower; } +static inline u32 IsFieldMudSportAffected(u32 moveType) +{ + if (moveType == TYPE_ELECTRIC && (gFieldStatuses & STATUS_FIELD_MUDSPORT)) + return TRUE; + + if (B_SPORT_TURNS < GEN_6) + { + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleMons[battler].volatiles.mudSport) + return TRUE; + } + } + + return FALSE; +} + +static inline u32 IsFieldWaterSportAffected(u32 moveType) +{ + if (moveType == TYPE_FIRE && (gFieldStatuses & STATUS_FIELD_WATERSPORT)) + return TRUE; + + if (B_SPORT_TURNS < GEN_6) + { + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleMons[battler].volatiles.waterSport) + return TRUE; + } + } + + return FALSE; +} + static inline u32 CalcMoveBasePower(struct DamageContext *ctx) { u32 battlerAtk = ctx->battlerAtk; @@ -7954,15 +8334,16 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) u32 i; u32 basePower = GetMovePower(move); + u32 moveEffect = GetMoveEffect(move); u32 weight, hpFraction, speed; if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE) - return GetZMovePower(gBattleStruct->zmove.baseMoves[battlerAtk]); + return GetZMovePower(gCurrentMove); if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX) return GetMaxMovePower(move); - switch (GetMoveEffect(move)) + switch (moveEffect) { case EFFECT_PLEDGE: if (gBattleStruct->pledgeMove) @@ -8035,7 +8416,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = gBattleMons[battlerDef].hp * basePower / gBattleMons[battlerDef].maxHP; break; case EFFECT_ASSURANCE: - if (gProtectStructs[battlerDef].physicalDmg != 0 || gProtectStructs[battlerDef].specialDmg != 0 || gProtectStructs[battlerDef].confusionSelfDmg) + if (gProtectStructs[battlerDef].assuranceDoubled) basePower *= 2; break; case EFFECT_TRUMP_CARD: @@ -8051,7 +8432,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) case EFFECT_ACROBATICS: if (gBattleMons[battlerAtk].item == ITEM_NONE // Edge case, because removal of items happens after damage calculation. - || (gSpecialStatuses[battlerAtk].gemBoost && GetBattlerHoldEffect(battlerAtk, FALSE) == HOLD_EFFECT_GEMS)) + || (gSpecialStatuses[battlerAtk].gemBoost && GetBattlerHoldEffect(battlerAtk) == HOLD_EFFECT_GEMS)) basePower *= 2; break; case EFFECT_LOW_KICK: @@ -8088,13 +8469,23 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = sSpeedDiffPowerTable[speed]; break; case EFFECT_GYRO_BALL: - basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / GetBattlerTotalSpeedStat(battlerAtk)) + 1; - if (basePower > 150) - basePower = 150; - break; + { + u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk); + if (attackerSpeed == 0) + { + basePower = 1; + } + else + { + basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / attackerSpeed) + 1; + if (basePower > 150) + basePower = 150; + } + break; + } case EFFECT_ECHOED_VOICE: // gBattleStruct->sameMoveTurns incremented in ppreduce - if (gBattleStruct->sameMoveTurns[battlerAtk] != 0) + if (gBattleStruct->sameMoveTurns[battlerAtk] != 0 && GetMoveEffect(gLastResultingMoves[battlerAtk]) == EFFECT_ECHOED_VOICE) { basePower += (basePower * gBattleStruct->sameMoveTurns[battlerAtk]); if (basePower > 200) @@ -8102,27 +8493,24 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) } break; case EFFECT_PAYBACK: - if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef) + if (HasBattlerActedThisTurn(battlerDef) && (B_PAYBACK_SWITCH_BOOST < GEN_5 || gDisableStructs[battlerDef].isFirstTurn != 2)) basePower *= 2; break; case EFFECT_BOLT_BEAK: - if (GetBattlerTurnOrderNum(battlerAtk) < GetBattlerTurnOrderNum(battlerDef) + if (!HasBattlerActedThisTurn(battlerDef) || gDisableStructs[battlerDef].isFirstTurn == 2) basePower *= 2; break; - case EFFECT_ROUND: - for (i = 0; i < gBattlersCount; i++) - { - if (i != battlerAtk && IsBattlerAlive(i) && GetMoveEffect(gLastUsedMove) == EFFECT_ROUND) - { - basePower *= 2; - break; - } - } - break; case EFFECT_FUSION_COMBO: - if (GetMoveEffect(gLastUsedMove) == EFFECT_FUSION_COMBO && move != gLastUsedMove) + if (move == gLastUsedMove) + break; + // fallthrough + case EFFECT_ROUND: + // don't double power due to previous turn's Round/Fusion move + if (gCurrentTurnActionNumber != 0 + && gActionsByTurnOrder[gCurrentTurnActionNumber - 1] == B_ACTION_USE_MOVE + && GetMoveEffect(gLastUsedMove) == moveEffect) basePower *= 2; break; case EFFECT_LASH_OUT: @@ -8130,7 +8518,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower *= 2; break; case EFFECT_MISTY_EXPLOSION: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_MISTY_TERRAIN)) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_DYNAMAX_DOUBLE_DMG: @@ -8157,15 +8545,15 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_TERRAIN_PULSE: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_TERRAIN_ANY)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_TERRAIN_ANY)) basePower *= 2; break; case EFFECT_EXPANDING_FORCE: - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, ctx->abilityDef, ctx->holdEffectDef, STATUS_FIELD_ELECTRIC_TERRAIN)) basePower *= 2; break; case EFFECT_BEAT_UP: @@ -8177,10 +8565,10 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = uq4_12_multiply(basePower, UQ_4_12(1.5)); break; case EFFECT_MAX_MOVE: - basePower = GetMaxMovePower(gBattleMons[battlerAtk].moves[gBattleStruct->chosenMovePositions[battlerAtk]]); + basePower = GetMaxMovePower(GetChosenMoveFromPosition(battlerAtk)); break; case EFFECT_RAGE_FIST: - basePower += 50 * gBattleStruct->timesGotHit[GetBattlerSide(battlerAtk)][gBattlerPartyIndexes[battlerAtk]]; + basePower += 50 * GetBattlerPartyState(battlerAtk)->timesGotHit; basePower = (basePower > 350) ? 350 : basePower; break; case EFFECT_FICKLE_BEAM: @@ -8251,7 +8639,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) break; case EFFECT_MAGNITUDE: case EFFECT_EARTHQUAKE: - if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_KNOCK_OFF: @@ -8265,28 +8653,26 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) } // various effects - if (gProtectStructs[battlerAtk].helpingHand) + for (u32 i = 0; i < gProtectStructs[battlerAtk].helpingHand; i++) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); + if (gSpecialStatuses[battlerAtk].gemBoost) modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam))); - if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) + if (gBattleMons[battlerAtk].volatiles.charge && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); if (GetMoveEffect(gChosenMove) == EFFECT_ME_FIRST) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); - if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) && moveType == TYPE_DRAGON) + if (IsBattlerTerrainAffected(battlerDef, ctx->abilityDef, ctx->holdEffectDef, STATUS_FIELD_MISTY_TERRAIN) && moveType == TYPE_DRAGON) modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN) && moveType == TYPE_ELECTRIC) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_ELECTRIC_TERRAIN) && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); - if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC) + if (IsBattlerTerrainAffected(battlerAtk, ctx->abilityAtk, ctx->holdEffectAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC) modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); - - if (moveType == TYPE_ELECTRIC && ((gFieldStatuses & STATUS_FIELD_MUDSPORT) - || AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_MUD_SPORT, 0))) + if (IsFieldMudSportAffected(ctx->moveType)) modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.33 : 0.5)); - if (moveType == TYPE_FIRE && ((gFieldStatuses & STATUS_FIELD_WATERSPORT) - || AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0))) + if (IsFieldWaterSportAffected(ctx->moveType)) modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.33 : 0.5)); // attacker's abilities @@ -8332,7 +8718,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_TOUGH_CLAWS: - if (IsMoveMakingContact(move, battlerAtk)) + if (IsMoveMakingContact(battlerAtk, battlerDef, ctx->abilityAtk, ctx->holdEffectAtk, ctx->move)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_STRONG_JAW: @@ -8352,23 +8738,23 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PIXILATE: - if (moveType == TYPE_FAIRY && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_FAIRY && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_GALVANIZE: - if (moveType == TYPE_ELECTRIC && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_ELECTRIC && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_REFRIGERATE: - if (moveType == TYPE_ICE && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_ICE && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_AERILATE: - if (moveType == TYPE_FLYING && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_FLYING && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_NORMALIZE: - if (moveType == TYPE_NORMAL && gBattleStruct->ateBoost[battlerAtk] && GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7) + if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7) modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_PUNK_ROCK: @@ -8386,6 +8772,8 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) case ABILITY_SUPREME_OVERLORD: modifier = uq4_12_multiply(modifier, GetSupremeOverlordModifier(battlerAtk)); break; + default: + break; } // field abilities @@ -8414,6 +8802,8 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) if (moveType == TYPE_STEEL) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; + default: + break; } } @@ -8438,7 +8828,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) u8 defHighestStat = GetHighestStatId(battlerDef); if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) - && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; @@ -8447,10 +8837,12 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) u8 defHighestStat = GetHighestStatId(battlerDef); if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) - && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; + default: + break; } holdEffectParamAtk = GetBattlerHoldEffectParam(battlerAtk); @@ -8523,6 +8915,20 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) return uq4_12_multiply_by_int_half_down(modifier, basePower); } +static bool32 IsRuinStatusActive(u32 fieldEffect) +{ + if (IsNeutralizingGasOnField()) // Neutralizing Gas still blocks Ruin field statuses + return FALSE; + + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (GetBattlerVolatile(battler, fieldEffect)) + return TRUE; + } + + return FALSE; +} + static inline u32 CalcAttackStat(struct DamageContext *ctx) { u8 atkStage; @@ -8637,7 +9043,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_PLUS: if (IsBattleMoveSpecial(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { - u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); + enum Ability partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); if (partnerAbility == ABILITY_MINUS || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_PLUS)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); @@ -8646,7 +9052,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_MINUS: if (IsBattleMoveSpecial(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { - u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); + enum Ability partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); if (partnerAbility == ABILITY_PLUS || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_MINUS)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); @@ -8671,7 +9077,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_TRANSISTOR: if (moveType == TYPE_ELECTRIC) { - if (B_TRANSISTOR_BOOST >= GEN_9) + if (GetGenConfig(GEN_CONFIG_TRANSISTOR_BOOST) >= GEN_9) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); else modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); @@ -8690,7 +9096,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PROTOSYNTHESIS: - if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battlerAtk].volatiles.transformed)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivated) @@ -8701,7 +9107,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) } break; case ABILITY_QUARK_DRIVE: - if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battlerAtk].volatiles.transformed)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivated) @@ -8719,6 +9125,8 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && IsBattleMoveSpecial(move)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333)); break; + default: + break; } // target's abilities @@ -8732,6 +9140,16 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) RecordAbilityBattle(battlerDef, ABILITY_THICK_FAT); } break; + case ABILITY_PURIFYING_SALT: + if (moveType == TYPE_GHOST) + { + modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.5)); + if (ctx->updateFlags) + RecordAbilityBattle(battlerDef, ABILITY_PURIFYING_SALT); + } + break; + default: + break; } // ally's abilities @@ -8743,14 +9161,16 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) if (gBattleMons[BATTLE_PARTNER(battlerAtk)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerAtk), B_WEATHER_SUN) && IsBattleMovePhysical(move)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; + default: + break; } } - // field abilities - if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && ctx->abilityAtk != ABILITY_VESSEL_OF_RUIN && IsBattleMoveSpecial(move)) + // Ruin field effects + if (IsBattleMoveSpecial(move) && !gBattleMons[ctx->battlerAtk].volatiles.vesselOfRuin && IsRuinStatusActive(VOLATILE_VESSEL_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); - if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && ctx->abilityAtk != ABILITY_TABLETS_OF_RUIN && IsBattleMovePhysical(move)) + if (IsBattleMovePhysical(move) && !gBattleMons[ctx->battlerAtk].volatiles.tabletsOfRuin && IsRuinStatusActive(VOLATILE_TABLETS_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); // attacker's hold effect @@ -8814,31 +9234,38 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) uq4_12_t modifier; u32 battlerDef = ctx->battlerDef; u32 move = ctx->move; - u32 moveType = ctx->moveType; enum BattleMoveEffects moveEffect = GetMoveEffect(move); - if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped - { - def = gBattleMons[battlerDef].spDefense; - spDef = gBattleMons[battlerDef].defense; - } - else - { - def = gBattleMons[battlerDef].defense; - spDef = gBattleMons[battlerDef].spDefense; - } + def = gBattleMons[battlerDef].defense; + spDef = gBattleMons[battlerDef].spDefense; if (moveEffect == EFFECT_PSYSHOCK || IsBattleMovePhysical(move)) // uses defense stat instead of sp.def { - defStat = def; + if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped + { + defStat = spDef; + usesDefStat = FALSE; + } + else + { + defStat = def; + usesDefStat = TRUE; + } defStage = gBattleMons[battlerDef].statStages[STAT_DEF]; - usesDefStat = TRUE; } else // is special { - defStat = spDef; + if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped + { + defStat = def; + usesDefStat = TRUE; + } + else + { + defStat = spDef; + usesDefStat = FALSE; + } defStage = gBattleMons[battlerDef].statStages[STAT_SPDEF]; - usesDefStat = FALSE; } // Self-destruct / Explosion cut defense in half @@ -8893,9 +9320,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) if (gBattleMons[battlerDef].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; - case ABILITY_PURIFYING_SALT: - if (moveType == TYPE_GHOST) - modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); + default: break; } @@ -8908,14 +9333,16 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) if (gBattleMons[BATTLE_PARTNER(battlerDef)].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(BATTLE_PARTNER(battlerDef), B_WEATHER_SUN) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; + default: + break; } } - // field abilities - if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && ctx->abilityDef != ABILITY_SWORD_OF_RUIN && usesDefStat) + // Ruin field effects + if (usesDefStat && !gBattleMons[ctx->battlerDef].volatiles.swordOfRuin && IsRuinStatusActive(VOLATILE_SWORD_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); - if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && ctx->abilityDef != ABILITY_BEADS_OF_RUIN && !usesDefStat) + if (!usesDefStat && !gBattleMons[ctx->battlerDef].volatiles.beadsOfRuin && IsRuinStatusActive(VOLATILE_BEADS_OF_RUIN)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.75)); // target's hold effects @@ -8926,7 +9353,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_METAL_POWDER: - if (gBattleMons[battlerDef].species == SPECIES_DITTO && usesDefStat && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + if (gBattleMons[battlerDef].species == SPECIES_DITTO && usesDefStat && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_EVIOLITE: @@ -9045,7 +9472,7 @@ static inline uq4_12_t GetCriticalModifier(bool32 isCrit) static inline uq4_12_t GetGlaiveRushModifier(u32 battlerDef) { - if (gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH) + if (gBattleMons[battlerDef].volatiles.glaiveRush) return UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9063,28 +9490,28 @@ static inline uq4_12_t GetZMaxMoveAgainstProtectionModifier(struct DamageContext static inline uq4_12_t GetMinimizeModifier(u32 move, u32 battlerDef) { - if (MoveIncreasesPowerToMinimizedTargets(move) && gStatuses3[battlerDef] & STATUS3_MINIMIZED) + if (MoveIncreasesPowerToMinimizedTargets(move) && gBattleMons[battlerDef].volatiles.minimize) return UQ_4_12(2.0); return UQ_4_12(1.0); } static inline uq4_12_t GetUndergroundModifier(u32 move, u32 battlerDef) { - if (MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND) + if (MoveDamagesUnderground(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERGROUND) return UQ_4_12(2.0); return UQ_4_12(1.0); } static inline uq4_12_t GetDiveModifier(u32 move, u32 battlerDef) { - if (MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER) + if (MoveDamagesUnderWater(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERWATER) return UQ_4_12(2.0); return UQ_4_12(1.0); } static inline uq4_12_t GetAirborneModifier(u32 move, u32 battlerDef) { - if (MoveDamagesAirborneDoubleDamage(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR) + if (MoveDamagesAirborneDoubleDamage(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_ON_AIR) return UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9120,7 +9547,7 @@ static inline uq4_12_t GetCollisionCourseElectroDriftModifier(u32 move, uq4_12_t return UQ_4_12(1.0); } -static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit, u32 abilityAtk) +static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, bool32 isCrit, enum Ability abilityAtk) { switch (abilityAtk) { @@ -9136,6 +9563,8 @@ static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typ if (typeEffectivenessModifier <= UQ_4_12(0.5)) return UQ_4_12(2.0); break; + default: + break; } return UQ_4_12(1.0); } @@ -9165,12 +9594,12 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx) } break; case ABILITY_FLUFFY: - if (!IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType == TYPE_FIRE) + if (ctx->moveType == TYPE_FIRE && !IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move)) { modifier = UQ_4_12(2.0); recordAbility = TRUE; } - else if (IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType != TYPE_FIRE) + if (ctx->moveType != TYPE_FIRE && IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move)) { modifier = UQ_4_12(0.5); recordAbility = TRUE; @@ -9190,6 +9619,8 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx) recordAbility = TRUE; } break; + default: + break; } if (recordAbility && ctx->updateFlags) @@ -9208,6 +9639,8 @@ static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef case ABILITY_FRIEND_GUARD: return UQ_4_12(0.75); break; + default: + break; } return UQ_4_12(1.0); } @@ -9351,7 +9784,7 @@ static inline s32 DoMoveDamageCalcVars(struct DamageContext *ctx) s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg) { if (GetActiveGimmick(ctx->battlerAtk) == GIMMICK_TERA) - DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(ctx->battlerAtk, ctx->moveType)); + DAMAGE_APPLY_MODIFIER(GetTeraMultiplier(ctx)); else DAMAGE_APPLY_MODIFIER(GetSameTypeAttackBonusModifier(ctx)); DAMAGE_APPLY_MODIFIER(ctx->typeEffectivenessModifier); @@ -9362,7 +9795,7 @@ s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg) return dmg; } -static inline s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) +s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) { s32 dmg = 0; s32 randDamage; @@ -9373,7 +9806,7 @@ static inline s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) dmg = gBattleMons[ctx->battlerAtk].level; break; case EFFECT_PSYWAVE: - randDamage = B_PSYWAVE_DMG >= GEN_6 ? (Random() % 101) : ((Random() % 11) * 10); + randDamage = B_PSYWAVE_DMG >= GEN_5 ? (Random() % 101) : ((Random() % 11) * 10); dmg = gBattleMons[ctx->battlerAtk].level * (randDamage + 50) / 100; break; case EFFECT_FIXED_HP_DAMAGE: @@ -9408,8 +9841,8 @@ static inline s32 DoMoveDamageCalc(struct DamageContext *ctx) ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk); ctx->abilityDef = GetBattlerAbility(ctx->battlerDef); - ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef, TRUE); - ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk, TRUE); + ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef); + ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk); return DoMoveDamageCalcVars(ctx); } @@ -9497,8 +9930,8 @@ s32 CalculateMoveDamage(struct DamageContext *ctx) ctx->weather = GetWeather(); ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk); ctx->abilityDef = GetBattlerAbility(ctx->battlerDef); - ctx->holdEffectAtk = GetItemHoldEffect(ctx->battlerAtk); - ctx->holdEffectDef = GetItemHoldEffect(ctx->battlerDef); + ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk); + ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef); ctx->typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(ctx); @@ -9528,7 +9961,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m if (ctx->updateFlags) RecordItemEffectBattle(ctx->battlerDef, HOLD_EFFECT_RING_TARGET); } - else if ((ctx->moveType == TYPE_FIGHTING || ctx->moveType == TYPE_NORMAL) && defType == TYPE_GHOST && gBattleMons[ctx->battlerDef].status2 & STATUS2_FORESIGHT && mod == UQ_4_12(0.0)) + else if ((ctx->moveType == TYPE_FIGHTING || ctx->moveType == TYPE_NORMAL) && defType == TYPE_GHOST && gBattleMons[ctx->battlerDef].volatiles.foresight && mod == UQ_4_12(0.0)) { mod = UQ_4_12(1.0); } @@ -9541,11 +9974,11 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m RecordAbilityBattle(ctx->battlerAtk, ctx->abilityAtk); } - if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gStatuses3[ctx->battlerDef] & STATUS3_MIRACLE_EYED && mod == UQ_4_12(0.0)) + if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gBattleMons[ctx->battlerDef].volatiles.miracleEye && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); if (GetMoveEffect(ctx->move) == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == GetMoveArgType(ctx->move)) mod = UQ_4_12(2.0); - if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef) && mod == UQ_4_12(0.0)) + if (ctx->moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef) && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); if (ctx->moveType == TYPE_STELLAR && GetActiveGimmick(ctx->battlerDef) == GIMMICK_TERA) mod = UQ_4_12(2.0); @@ -9584,8 +10017,8 @@ static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, ctx.updateFlags = FALSE; ctx.abilityAtk = GetBattlerAbility(battlerAtk); ctx.abilityDef = ABILITY_ILLUSION; - ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); - ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); + ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk); + ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef); MulByTypeEffectiveness(&ctx, &presumedModifier, GetSpeciesType(illusionSpecies, 0)); if (GetSpeciesType(illusionSpecies, 1) != GetSpeciesType(illusionSpecies, 0)) @@ -9642,7 +10075,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST)) modifier = UQ_4_12(0.0); } - else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) + else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef, INVERSE_BATTLE) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) { modifier = UQ_4_12(0.0); if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE) @@ -9654,14 +10087,14 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont RecordAbilityBattle(ctx->battlerDef, ABILITY_LEVITATE); } } - else if (B_SHEER_COLD_IMMUNITY >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) + else if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) { modifier = UQ_4_12(0.0); } // Thousand Arrows ignores type modifiers for flying mons - if (!IsBattlerGrounded(ctx->battlerDef) - && MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move) + if (MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move) + && !IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, ctx->holdEffectDef) && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)) { modifier = UQ_4_12(1.0); @@ -9670,9 +10103,9 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont // Iron Ball ignores type modifiers for flying-type mons if it is the only source of grounding if (B_IRON_BALL >= GEN_5 && ctx->moveType == TYPE_GROUND + && ctx->holdEffectDef == HOLD_EFFECT_IRON_BALL && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING) - && GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL - && !IsBattlerGroundedInverseCheck(ctx->battlerDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL) + && !IsBattlerGrounded(ctx->battlerDef, ctx->abilityDef, HOLD_EFFECT_NONE) // We want to ignore Iron Ball so skip item check && !FlagGet(B_FLAG_INVERSE_BATTLE)) { modifier = UQ_4_12(1.0); @@ -9718,7 +10151,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx) return modifier; } -uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef) +uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, enum Ability abilityDef) { uq4_12_t modifier = UQ_4_12(1.0); u32 moveType = GetBattleMoveType(move); @@ -9762,7 +10195,7 @@ static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier) uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) { uq4_12_t modifier = UQ_4_12(1.0); - u16 abilityDef = GetMonAbility(mon); + enum Ability abilityDef = GetMonAbility(mon); u16 speciesDef = GetMonData(mon, MON_DATA_SPECIES); u8 type1 = GetSpeciesType(speciesDef, 0); u8 type2 = GetSpeciesType(speciesDef, 1); @@ -9780,7 +10213,7 @@ uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) MulByTypeEffectiveness(&ctx, &modifier, type2); if ((modifier <= UQ_4_12(1.0) && abilityDef == ABILITY_WONDER_GUARD) - || CanAbilityAbsorbMove(0, 0, abilityDef, MOVE_NONE, moveType, ABILITY_CHECK_TRIGGER)) + || CanAbilityAbsorbMove(0, 0, abilityDef, MOVE_NONE, moveType, CHECK_TRIGGER)) modifier = UQ_4_12(0.0); return modifier; @@ -9885,7 +10318,7 @@ bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) bool32 CanMegaEvolve(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has a Mega Ring. if (!TESTING @@ -9902,7 +10335,7 @@ bool32 CanMegaEvolve(u32 battler) return FALSE; // Check if battler is currently held by Sky Drop. - if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; // Check if battler is holding a Z-Crystal. @@ -9923,7 +10356,7 @@ bool32 CanMegaEvolve(u32 battler) bool32 CanUltraBurst(u32 battler) { - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has a Z-Ring if (!TESTING && (GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT @@ -9940,7 +10373,7 @@ bool32 CanUltraBurst(u32 battler) return FALSE; // Check if mon is currently held by Sky Drop - if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; // Check if there is an entry in the form change table for Ultra Burst and battler is holding a Z-Crystal. @@ -9971,7 +10404,7 @@ void ActivateUltraBurst(u32 battler) bool32 IsBattlerMegaEvolved(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isMegaEvolution); } @@ -9979,7 +10412,7 @@ bool32 IsBattlerMegaEvolved(u32 battler) bool32 IsBattlerPrimalReverted(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isPrimalReversion); } @@ -9987,7 +10420,7 @@ bool32 IsBattlerPrimalReverted(u32 battler) bool32 IsBattlerUltraBursted(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Ultra Burst. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isUltraBurst); } @@ -9995,7 +10428,7 @@ bool32 IsBattlerUltraBursted(u32 battler) bool32 IsBattlerInTeraForm(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as a true Tera Form. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isTeraForm); } @@ -10113,7 +10546,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, enum FormChanges method) bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) { // Can't change form if transformed. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED + if (gBattleMons[battler].volatiles.transformed && B_TRANSFORM_FORM_CHANGES >= GEN_5) return FALSE; // Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle. @@ -10130,7 +10563,6 @@ bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) bool32 TryBattleFormChange(u32 battler, enum FormChanges method) { u32 monId = gBattlerPartyIndexes[battler]; - u32 side = GetBattlerSide(battler); struct Pokemon *party = GetBattlerParty(battler); u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); u32 targetSpecies; @@ -10144,8 +10576,9 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) if (targetSpecies != currentSpecies) { // Saves the original species on the first form change. - if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][monId] = gBattleMons[battler].species; + + if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); @@ -10153,7 +10586,7 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); return TRUE; } - else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) + else if (GetBattlerPartyState(battler)->changedSpecies != SPECIES_NONE) { bool32 restoreSpecies = FALSE; @@ -10171,10 +10604,11 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) if (restoreSpecies) { - u32 abilityForm = gBattleMons[battler].ability; + enum Ability abilityForm = gBattleMons[battler].ability; // Reverts the original species TryToSetBattleFormChangeMoves(&party[monId], method); - SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]); + u32 changedSpecies = GetBattlerPartyState(battler)->changedSpecies; + SetMonData(&party[monId], MON_DATA_SPECIES, &changedSpecies); RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); // Battler data is not updated with regular form's ability, not doing so could cause wrong ability activation. if (method == FORM_CHANGE_FAINT) @@ -10273,11 +10707,29 @@ u32 GetIllusionMonSpecies(u32 battler) return SPECIES_NONE; } -u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon) +u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler) { - s32 id; + s32 partyEnd=6; + s32 partyStart=0; + + // Adjust party search range for Multibattles and Player vs two-trainers + if((GetBattlerSide(battler) == B_SIDE_PLAYER && (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + || (GetBattlerSide(battler) == B_SIDE_OPPONENT && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) + { + if((GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) || (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT)) + { + partyEnd = 3; + partyStart = 0; + } + else + { + partyEnd = 6; + partyStart = 3; + } + } + // Find last alive non-egg pokemon. - for (id = PARTY_SIZE - 1; id >= 0; id--) + for (s32 id = partyEnd - 1; id >= partyStart; id--) { if (GetMonData(&party[id], MON_DATA_SANITY_HAS_SPECIES) && GetMonData(&party[id], MON_DATA_HP) @@ -10311,7 +10763,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler) else partnerMon = mon; - id = GetIllusionMonPartyId(party, mon, partnerMon); + id = GetIllusionMonPartyId(party, mon, partnerMon, battler); if (id != PARTY_SIZE) { gBattleStruct->illusion[battler].state = ILLUSION_ON; @@ -10426,13 +10878,15 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler) if (!IsBattlerAlive(battlerDef)) continue; - u32 ability = GetBattlerAbility(battlerDef); + enum Ability ability = GetBattlerAbility(battlerDef); switch (ability) { case ABILITY_UNNERVE: case ABILITY_AS_ONE_ICE_RIDER: case ABILITY_AS_ONE_SHADOW_RIDER: return TRUE; + default: + break; } } @@ -10459,7 +10913,7 @@ enum DamageCategory GetCategoryBasedOnStats(u32 battler) static u32 GetFlingPowerFromItemId(u32 itemId) { - if (IsItemTMHM(itemId)) + if (gItemsInfo[itemId].pocket == POCKET_TM_HM) { u32 power = GetMovePower(ItemIdToBattleMoveId(itemId)); if (power > 1) @@ -10477,7 +10931,7 @@ bool32 CanFling(u32 battler) if (item == ITEM_NONE || (B_KLUTZ_FLING_INTERACTION >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ) || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM - || gStatuses3[battler] & STATUS3_EMBARGO + || gBattleMons[battler].volatiles.embargo || GetFlingPowerFromItemId(item) == 0 || !CanBattlerGetOrLoseItem(battler, item)) return FALSE; @@ -10607,7 +11061,7 @@ void TrySaveExchangedItem(u32 battler, u16 stolenItem) bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes) { bool32 ret = TRUE; - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler); if (toxicSpikes && holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) { ret = FALSE; @@ -10678,36 +11132,10 @@ bool32 CompareStat(u32 battler, u8 statId, u8 cmpTo, u8 cmpKind) return ret; } -void BufferStatChange(u32 battler, u8 statId, enum StringID stringId) -{ - bool32 hasContrary = (GetBattlerAbility(battler) == ABILITY_CONTRARY); - - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - if (stringId == STRINGID_STATFELL) - { - if (hasContrary) - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) - else - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) - } - else if (stringId == STRINGID_STATROSE) - { - if (hasContrary) - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL) - else - PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE) - } - else - { - PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId) - } -} - bool32 TryRoomService(u32 battler) { if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN)) { - BufferStatChange(battler, STAT_SPEED, STRINGID_STATFELL); gEffectBattler = gBattleScripting.battler = battler; SET_STATCHANGER(STAT_SPEED, 1, TRUE); gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED; @@ -10723,7 +11151,7 @@ bool32 TryRoomService(u32 battler) bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget) { - if (B_PRANKSTER_DARK_TYPES < GEN_7) + if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) < GEN_7) return FALSE; if (!gProtectStructs[battlerPrankster].pranksterElevated) return FALSE; @@ -10733,7 +11161,7 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return FALSE; if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)) return FALSE; - if (gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battlerDef, CHECK_ALL)) return FALSE; return TRUE; @@ -10747,7 +11175,7 @@ u16 GetUsedHeldItem(u32 battler) bool32 CantPickupItem(u32 battler) { // Used by RandomUniformExcept() for RNG_PICKUP - if (battler == gBattlerAttacker && (B_PICKUP_WILD < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) + if (battler == gBattlerAttacker && (GetGenConfig(GEN_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) return TRUE; return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->battlerState[battler].canPickupItem); } @@ -10769,7 +11197,7 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) if (gBattleWeather & weatherFlags && HasWeatherEffect()) { // given weather is active -> check if its sun, rain against utility umbrella (since only 1 weather can be active at once) - if (gBattleWeather & (B_WEATHER_SUN | B_WEATHER_RAIN) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + if (gBattleWeather & (B_WEATHER_SUN | B_WEATHER_RAIN) && GetBattlerHoldEffect(battler) == HOLD_EFFECT_UTILITY_UMBRELLA) return FALSE; // utility umbrella blocks sun, rain effects return TRUE; @@ -10779,12 +11207,13 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) // Gets move target before redirection effects etc. are applied // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED +// TODO: Add args: ability and hold effect u32 GetBattlerMoveTargetType(u32 battler, u32 move) { enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_CURSE && !IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return MOVE_TARGET_USER; - if (effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler), STATUS_FIELD_PSYCHIC_TERRAIN)) return MOVE_TARGET_BOTH; if (effect == EFFECT_TERA_STARSTORM && gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR) return MOVE_TARGET_BOTH; @@ -10796,7 +11225,7 @@ bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move) { if (GetMoveEffect(move) == EFFECT_HIT_ENEMY_HEAL_ALLY && IsBattlerAlly(battlerAtk, battlerDef) - && gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + && gBattleMons[battlerAtk].volatiles.healBlock) return FALSE; // Pokémon affected by Heal Block cannot target allies with Pollen Puff if (IsBattlerAlly(battlerAtk, battlerDef) && (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX || IsGimmickSelected(battlerAtk, GIMMICK_DYNAMAX))) @@ -10807,7 +11236,7 @@ bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move) static void SetRandomMultiHitCounter() { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + if (GetBattlerHoldEffect(gBattlerAttacker) == HOLD_EFFECT_LOADED_DICE) gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5); else if (GetGenConfig(GEN_CONFIG_MULTI_HIT_CHANCE) >= GEN_5) gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. @@ -10863,18 +11292,17 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing) void RemoveConfusionStatus(u32 battler) { - gBattleMons[battler].status2 &= ~STATUS2_CONFUSION; - gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.confusionTurns = 0; + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } static bool32 CanBeInfinitelyConfused(u32 battler) { - if (GetBattlerAbility(battler) == ABILITY_OWN_TEMPO - || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) - || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) - { + enum Ability ability = GetBattlerAbility(battler); + if (ability == ABILITY_OWN_TEMPO + || IsBattlerTerrainAffected(battler, ability, GetBattlerHoldEffect(battler), STATUS_FIELD_MISTY_TERRAIN) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) return FALSE; - } return TRUE; } @@ -10900,7 +11328,7 @@ bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2) return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2); } -u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect) +u32 CalcSecondaryEffectChance(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect) { bool8 hasSereneGrace = (battlerAbility == ABILITY_SERENE_GRACE); bool8 hasRainbow = (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW) != 0; @@ -10917,7 +11345,7 @@ u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct Addi return secondaryEffectChance; } -bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect) +bool32 MoveEffectIsGuaranteed(u32 battler, enum Ability battlerAbility, const struct AdditionalEffect *additionalEffect) { return additionalEffect->chance == 0 || CalcSecondaryEffectChance(battler, battlerAbility, additionalEffect) >= 100; } @@ -10994,12 +11422,7 @@ bool32 MoveIsAffectedBySheerForce(u32 move) for (i = 0; i < numAdditionalEffects; i++) { const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - if (additionalEffect->sheerForceBoost == SHEER_FORCE_NO_BOOST) - continue; - - if (additionalEffect->chance > 0) - return TRUE; - if (additionalEffect->sheerForceBoost == SHEER_FORCE_BOOST) + if ((additionalEffect->chance > 0) != additionalEffect->sheerForceOverride) return TRUE; } return FALSE; @@ -11169,18 +11592,18 @@ bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef) static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerDef, u32 moveType) { - u32 abilityDef = GetBattlerAbility(battlerDef); + enum Ability abilityDef = GetBattlerAbility(battlerDef); - return CanAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER) - || CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, gCurrentMove, moveType, ABILITY_CHECK_TRIGGER); + return CanAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), abilityDef, gCurrentMove, CHECK_TRIGGER) + || CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER); } bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef) { u32 moveType = GetBattleMoveType(gCurrentMove); - return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) + return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) || IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove) - || IsSemiInvulnerable(battlerDef, gCurrentMove) + || !BreaksThroughSemiInvulnerablity(battlerDef, gCurrentMove) || DoesBattlerHaveAbilityImmunity(battlerAtk, battlerDef, moveType)); } @@ -11239,7 +11662,7 @@ void ClearDamageCalcResults(void) { gBattleStruct->moveDamage[battler] = 0; gBattleStruct->critChance[battler] = 0; - gBattleStruct->moveResultFlags[battler] = 0; + gBattleStruct->moveResultFlags[battler] = CAN_DAMAGE; gBattleStruct->noResultString[battler] = 0; gBattleStruct->missStringId[battler] = 0; gSpecialStatuses[battler].criticalHit = FALSE; @@ -11254,22 +11677,18 @@ void ClearDamageCalcResults(void) bool32 DoesDestinyBondFail(u32 battler) { - if (B_DESTINY_BOND_FAIL >= GEN_7 - && GetMoveEffect(gLastLandedMoves[battler]) == EFFECT_DESTINY_BOND - && GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND) - return TRUE; - return FALSE; + return GetGenConfig(GEN_CONFIG_DESTINY_BOND_FAIL) >= GEN_7 && gBattleMons[battler].volatiles.destinyBond; } // This check has always to be the last in a condtion statement because of the recording of AI data. -bool32 IsMoveEffectBlockedByTarget(u32 ability) +bool32 IsMoveEffectBlockedByTarget(enum Ability ability) { if (ability == ABILITY_SHIELD_DUST) { RecordAbilityBattle(gBattlerTarget, ability); return TRUE; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_COVERT_CLOAK) + else if (GetBattlerHoldEffect(gBattlerTarget) == HOLD_EFFECT_COVERT_CLOAK) { RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_COVERT_CLOAK); return TRUE; @@ -11308,12 +11727,14 @@ bool32 HasWeatherEffect(void) if (!IsBattlerAlive(battler)) continue; - u32 ability = GetBattlerAbility(battler); + enum Ability ability = GetBattlerAbility(battler); switch (ability) { case ABILITY_CLOUD_NINE: case ABILITY_AIR_LOCK: return FALSE; + default: + break; } } @@ -11340,13 +11761,13 @@ void UpdateStallMons(void) if (!IsDoubleBattle() || gMovesInfo[gCurrentMove].target == MOVE_TARGET_SELECTED) { u32 moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - u32 abilityDef = GetBattlerAbility(gBattlerTarget); - if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, abilityDef, gCurrentMove, moveType, ABILITY_CHECK_TRIGGER)) + enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker); + enum Ability abilityDef = GetBattlerAbility(gBattlerTarget); + if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER)) { gAiBattleData->playerStallMons[gBattlerPartyIndexes[gBattlerTarget]]++; } - else if (CanAbilityBlockMove(gBattlerAttacker, gBattlerTarget, abilityAtk, abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER)) + else if (CanAbilityBlockMove(gBattlerAttacker, gBattlerTarget, abilityAtk, abilityDef, gCurrentMove, CHECK_TRIGGER)) { gAiBattleData->playerStallMons[gBattlerPartyIndexes[gBattlerTarget]]++; } @@ -11361,7 +11782,7 @@ void UpdateStallMons(void) bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId) { if (gItemsInfo[gBattleMons[battler].item].pocket == POCKET_BERRIES - || GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP) // Edge case for Berry Juice + || GetBattlerHoldEffect(battler) == HOLD_EFFECT_RESTORE_HP) // Edge case for Berry Juice { if (ItemBattleEffects(caseId, battler)) return TRUE; @@ -11377,8 +11798,8 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) for (u32 i = 0; i < gBattlersCount; i++) { - if (gProtectStructs[i].tryEjectPack - && GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK + if (gDisableStructs[i].tryEjectPack + && GetBattlerHoldEffect(i) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(i) && CountUsablePartyMons(i) > 0) { @@ -11395,7 +11816,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) SortBattlersBySpeed(battlers, FALSE); for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; for (u32 i = 0; i < gBattlersCount; i++) { @@ -11422,11 +11843,11 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) return FALSE; } -#define UNPACK_VOLATILE_GETTERS(_enum, _fieldName, _typeBitSize, ...) case _enum: return gBattleMons[battler].volatiles._fieldName; +#define UNPACK_VOLATILE_GETTERS(_enum, _fieldName, _typeMaxValue, ...) case _enum: return gBattleMons[battler].volatiles._fieldName; // Gets the value of a volatile status flag for a certain battler // Primarily used for the debug menu and scripts. Outside of it explicit references are preferred -u32 GetMonVolatile(u32 battler, enum Volatile _volatile) +u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile) { switch (_volatile) { @@ -11440,7 +11861,7 @@ u32 GetMonVolatile(u32 battler, enum Volatile _volatile) } } -#define UNPACK_VOLATILE_SETTERS(_enum, _fieldName, _typeBitSize, ...) case _enum: gBattleMons[battler].volatiles._fieldName = min(GET_VOLATILE_MAXIMUM(_typeBitSize), newValue); break; +#define UNPACK_VOLATILE_SETTERS(_enum, _fieldName, _typeMaxValue, ...) case _enum: gBattleMons[battler].volatiles._fieldName = min(GET_VOLATILE_MAXIMUM(_typeMaxValue), newValue); break; // Sets the value of a volatile status flag for a certain battler // Primarily used for the debug menu and scripts. Outside of it explicit references are preferred @@ -11458,3 +11879,559 @@ void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue) return; } } + +bool32 ItemHealMonVolatile(u32 battler, u16 itemId) +{ + bool32 statusChanged = FALSE; + const u8 *effect = GetItemEffect(itemId); + if (effect[3] & ITEM3_STATUS_ALL) + { + statusChanged = (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0); + gBattleMons[battler].volatiles.infatuation = 0; + gBattleMons[battler].volatiles.confusionTurns = 0; + } + else if (effect[0] & ITEM0_INFATUATION) + { + statusChanged = !!gBattleMons[battler].volatiles.infatuation; + gBattleMons[battler].volatiles.infatuation = 0; + } + else if (effect[3] & ITEM3_CONFUSION) + { + statusChanged = gBattleMons[battler].volatiles.confusionTurns > 0; + gBattleMons[battler].volatiles.confusionTurns = 0; + } + + return statusChanged; +} + +// Hazards are added to a queue and applied based in order (FIFO) +void PushHazardTypeToQueue(u32 side, enum Hazards hazardType) +{ + if (!IsHazardOnSide(side, hazardType)) // Failsafe + gBattleStruct->hazardsQueue[side][gBattleStruct->numHazards[side]++] = hazardType; +} + +bool32 IsHazardOnSide(u32 side, enum Hazards hazardType) +{ + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + return TRUE; + } + return FALSE; +} + +bool32 AreAnyHazardsOnSide(u32 side) +{ + return gBattleStruct->numHazards[side] > 0; +} + +bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType) +{ + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + if (hazardType == HAZARDS_SPIKES) + gSideTimers[side].spikesAmount = 0; + else if (hazardType == HAZARDS_TOXIC_SPIKES) + gSideTimers[side].toxicSpikesAmount = 0; + return TRUE; + } + } + return FALSE; +} + +void RemoveAllHazardsFromField(u32 side) +{ + gSideTimers[side].spikesAmount = 0; + gSideTimers[side].toxicSpikesAmount = 0; + gBattleStruct->numHazards[side] = 0; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; +} + +void RemoveHazardFromField(u32 side, enum Hazards hazardType) +{ + u32 i; + for (i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + gBattleStruct->numHazards[side]--; + if (hazardType == HAZARDS_SPIKES) + gSideTimers[side].spikesAmount = 0; + else if (hazardType == HAZARDS_TOXIC_SPIKES) + gSideTimers[side].toxicSpikesAmount = 0; + break; + } + } + while (i < HAZARDS_MAX_COUNT) + { + if (i+1 == HAZARDS_MAX_COUNT) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + break; + } + gBattleStruct->hazardsQueue[side][i] = gBattleStruct->hazardsQueue[side][i+1]; + i++; + } +} + +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option) +{ + bool32 effect = FALSE; + enum Ability ability = ABILITY_NONE; + enum BattleMoveEffects moveEffect = GetMoveEffect(move); + u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); + + if ((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) + || (B_TOXIC_NEVER_MISS >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + || gBattleMons[battlerDef].volatiles.glaiveRush) + { + effect = TRUE; + } + // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. + else if (abilityAtk == ABILITY_NO_GUARD + && gBattleMons[battlerDef].volatiles.semiInvulnerable != STATE_COMMANDER + && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET)) + { + effect = TRUE; + ability = ABILITY_NO_GUARD; + } + // If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits. + else if (abilityDef == ABILITY_NO_GUARD + && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET)) + { + effect = TRUE; + ability = ABILITY_NO_GUARD; + } + // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. + else if (gBattleMons[battlerDef].volatiles.telekinesis + && !IsSemiInvulnerable(battlerDef, CHECK_ALL) + && moveEffect != EFFECT_OHKO + && moveEffect != EFFECT_SHEER_COLD) + { + effect = TRUE; + } + else if (gBattleStruct->battlerState[battlerDef].pursuitTarget) + { + effect = TRUE; + } + else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) + { + effect = TRUE; + } + else if (!BreaksThroughSemiInvulnerablity(battlerDef, move)) + { + if (option == RUN_SCRIPT) + { + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_MISSED; + effect = TRUE; + } + else + { + effect = FALSE; + } + } + else if (B_MINIMIZE_DMG_ACC >= GEN_6 + && gBattleMons[battlerDef].volatiles.minimize + && MoveIncreasesPowerToMinimizedTargets(move)) + { + effect = TRUE; + } + else if (GetMoveAccuracy(move) == 0) + { + effect = TRUE; + } + + if (!effect && HasWeatherEffect()) + { + if (MoveAlwaysHitsInRain(move) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_RAIN)) + effect = TRUE; + else if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) + effect = TRUE; + + if (effect) + return effect; + } + + if (ability != ABILITY_NONE && option == RUN_SCRIPT) + RecordAbilityBattle(battlerAtk, ABILITY_NO_GUARD); + + return effect; +} + +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, u32 atkHoldEffect, u32 defHoldEffect) +{ + u32 calc, moveAcc; + s8 buff, accStage, evasionStage; + u32 atkParam = GetBattlerHoldEffectParam(battlerAtk); + u32 defParam = GetBattlerHoldEffectParam(battlerDef); + + gPotentialItemEffectBattler = battlerDef; + accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; + evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; + if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE + || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) + evasionStage = DEFAULT_STAT_STAGE; + if (MoveIgnoresDefenseEvasionStages(move)) + evasionStage = DEFAULT_STAT_STAGE; + if (defAbility == ABILITY_UNAWARE) + accStage = DEFAULT_STAT_STAGE; + + if (gBattleMons[battlerDef].volatiles.foresight || gBattleMons[battlerDef].volatiles.miracleEye) + buff = accStage; + else + buff = accStage + DEFAULT_STAT_STAGE - evasionStage; + + if (buff < MIN_STAT_STAGE) + buff = MIN_STAT_STAGE; + if (buff > MAX_STAT_STAGE) + buff = MAX_STAT_STAGE; + + moveAcc = GetMoveAccuracy(move); + // Check Thunder and Hurricane on sunny weather. + if (IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) + moveAcc = 50; + // Check Wonder Skin. + if (defAbility == ABILITY_WONDER_SKIN && IsBattleMoveStatus(move) && moveAcc > 50) + moveAcc = 50; + + calc = gAccuracyStageRatios[buff].dividend * moveAcc; + calc /= gAccuracyStageRatios[buff].divisor; + + // Attacker's ability + switch (atkAbility) + { + case ABILITY_COMPOUND_EYES: + calc = (calc * 130) / 100; // 1.3 compound eyes boost + break; + case ABILITY_VICTORY_STAR: + calc = (calc * 110) / 100; // 1.1 victory star boost + break; + case ABILITY_HUSTLE: + if (IsBattleMovePhysical(move)) + calc = (calc * 80) / 100; // 1.2 hustle loss + break; + default: + break; + } + + // Target's ability + switch (defAbility) + { + case ABILITY_SAND_VEIL: + if (gBattleWeather & B_WEATHER_SANDSTORM && HasWeatherEffect()) + calc = (calc * 80) / 100; // 1.2 sand veil loss + break; + case ABILITY_SNOW_CLOAK: + if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && HasWeatherEffect()) + calc = (calc * 80) / 100; // 1.2 snow cloak loss + break; + case ABILITY_TANGLED_FEET: + if (gBattleMons[battlerDef].volatiles.confusionTurns) + calc = (calc * 50) / 100; // 1.5 tangled feet loss + break; + default: + break; + } + + // Attacker's ally's ability + u32 atkAlly = BATTLE_PARTNER(battlerAtk); + switch (GetBattlerAbility(atkAlly)) + { + case ABILITY_VICTORY_STAR: + if (IsBattlerAlive(atkAlly)) + calc = (calc * 110) / 100; // 1.1 ally's victory star boost + break; + default: + break; + } + + // Attacker's hold effect + switch (atkHoldEffect) + { + case HOLD_EFFECT_WIDE_LENS: + calc = (calc * (100 + atkParam)) / 100; + break; + case HOLD_EFFECT_ZOOM_LENS: + if (HasBattlerActedThisTurn(battlerDef)) + calc = (calc * (100 + atkParam)) / 100; + break; + } + + // Target's hold effect + switch (defHoldEffect) + { + case HOLD_EFFECT_EVASION_UP: + calc = (calc * (100 - defParam)) / 100; + break; + } + + if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) + { + if (atkAbility == ABILITY_RIPEN) + calc = (calc * 140) / 100; // ripen gives 40% acc boost + else + calc = (calc * 120) / 100; // 20% acc boost + } + + if (gFieldStatuses & STATUS_FIELD_GRAVITY) + calc = (calc * 5) / 3; // 1.66 Gravity acc boost + + if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerDef) == AFFECTION_FIVE_HEARTS) + calc = (calc * 90) / 100; + + if (HasWeatherEffect() && gBattleWeather & B_WEATHER_FOG) + calc = (calc * 60) / 100; // modified by 3/5 + + return calc; +} + +bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander) +{ + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_COMMANDER) + return excludeCommander != EXCLUDE_COMMANDER; + return gBattleMons[battler].volatiles.semiInvulnerable != STATE_NONE; +} + +bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move) +{ + switch (gBattleMons[battler].volatiles.semiInvulnerable) + { + case STATE_UNDERGROUND: + return MoveDamagesUnderground(move); + case STATE_UNDERWATER: + return MoveDamagesUnderWater(move); + case STATE_ON_AIR: + case STATE_SKY_DROP: + return MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move); + case STATE_PHANTOM_FORCE: + return FALSE; + case STATE_COMMANDER: + return FALSE; + case STATE_NONE: + return TRUE; + } + + return FALSE; +} + +static u32 GetMirrorMoveMove(void) +{ + s32 i, validMovesCount; + u16 move = MOVE_NONE; + u16 validMoves[MAX_BATTLERS_COUNT] = {0}; + + for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) + { + if (i != gBattlerAttacker) + { + move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; + if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) + { + validMoves[validMovesCount] = move; + validMovesCount++; + } + } + } + + move = gBattleStruct->lastTakenMove[gBattlerAttacker]; + if ((move == MOVE_NONE || move == MOVE_UNAVAILABLE) && validMovesCount != 0) + move = validMoves[Random() % validMovesCount]; + + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + move = GetTypeBasedZMove(move); + + return move; +} + +static bool32 InvalidMetronomeMove(u32 move) +{ + return GetMoveEffect(move) == EFFECT_PLACEHOLDER + || IsMoveMetronomeBanned(move); +} + +static u32 GetMetronomeMove(void) +{ + u32 move = MOVE_NONE; + +#if B_METRONOME_MOVES >= GEN_9 + u32 moveCount = MOVES_COUNT_GEN9; +#elif B_METRONOME_MOVES >= GEN_8 + u32 moveCount = MOVES_COUNT_GEN8; +#elif B_METRONOME_MOVES >= GEN_7 + u32 moveCount = MOVES_COUNT_GEN7; +#elif B_METRONOME_MOVES >= GEN_6 + u32 moveCount = MOVES_COUNT_GEN6; +#elif B_METRONOME_MOVES >= GEN_5 + u32 moveCount = MOVES_COUNT_GEN5; +#elif B_METRONOME_MOVES >= GEN_4 + u32 moveCount = MOVES_COUNT_GEN4; +#elif B_METRONOME_MOVES >= GEN_3 + u32 moveCount = MOVES_COUNT_GEN3; +#elif B_METRONOME_MOVES >= GEN_2 + u32 moveCount = MOVES_COUNT_GEN2; +#else + u32 moveCount = MOVES_COUNT_GEN1; +#endif + + move = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); + return move; +} + +static u32 GetAssistMove(void) +{ + u32 move = MOVE_NONE; + s32 chooseableMovesNo = 0; + struct Pokemon *party; + u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); + + if (validMoves != NULL) + { + party = GetBattlerParty(gBattlerAttacker); + + for (u32 monId = 0; monId < PARTY_SIZE; monId++) + { + if (monId == gBattlerPartyIndexes[gBattlerAttacker]) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + continue; + + for (u32 moveId = 0; moveId < MAX_MON_MOVES; moveId++) + { + u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); + + if (IsMoveAssistBanned(move)) + continue; + + validMoves[chooseableMovesNo++] = move; + } + } + } + + if (chooseableMovesNo) + move = validMoves[Random() % chooseableMovesNo]; + + TRY_FREE_AND_SET_NULL(validMoves); + + return move; +} + +u32 GetNaturePowerMove(u32 battler) +{ + u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + move = MOVE_MOONBLAST; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + move = MOVE_THUNDERBOLT; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + move = MOVE_ENERGY_BALL; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + move = MOVE_PSYCHIC; + else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) + move = MOVE_TRI_ATTACK; + + return move; +} + +static u32 GetSleepTalkMove(void) +{ + u32 move = MOVE_NONE; + + u32 i, unusableMovesBits = 0, movePosition; + + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_COMATOSE + && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)) + return move; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) + || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) + unusableMovesBits |= (1 << (i)); + } + + unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); + if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen + return move; + + // Set Sleep Talk as used move, so it works with Last Resort. + gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; + do + { + movePosition = MOD(Random(), MAX_MON_MOVES); + } while ((1u << movePosition) & unusableMovesBits); + + move = gBattleMons[gBattlerAttacker].moves[movePosition]; + gCurrMovePos = movePosition; + + return move; +} + +static u32 GetCopyCatMove(void) +{ + if (gLastUsedMove == MOVE_NONE + || gLastUsedMove == MOVE_UNAVAILABLE + || IsMoveCopycatBanned(gLastUsedMove) + || IsZMove(gLastUsedMove)) + return MOVE_NONE; + + return gLastUsedMove; +} + +static u32 GetMeFirstMove(void) +{ + u32 move = GetChosenMoveFromPosition(gBattlerTarget); + + if (IsBattleMoveStatus(move) + || IsMoveMeFirstBanned(move) + || HasBattlerActedThisTurn(gBattlerTarget)) + return MOVE_NONE; + + return move; +} + +void RemoveAbilityFlags(u32 battler) +{ + switch (GetBattlerAbility(battler)) + { + case ABILITY_FLASH_FIRE: + gDisableStructs[battler].flashFireBoosted = FALSE; + break; + case ABILITY_VESSEL_OF_RUIN: + gBattleMons[battler].volatiles.vesselOfRuin = FALSE; + break; + case ABILITY_TABLETS_OF_RUIN: + gBattleMons[battler].volatiles.tabletsOfRuin = FALSE; + break; + case ABILITY_SWORD_OF_RUIN: + gBattleMons[battler].volatiles.swordOfRuin = FALSE; + break; + case ABILITY_BEADS_OF_RUIN: + gBattleMons[battler].volatiles.beadsOfRuin = FALSE; + break; + default: + break; + } +} + +bool32 IsAllowedToUseBag(void) +{ + switch(VarGet(B_VAR_NO_BAG_USE)) + { + case NO_BAG_RESTRICTION: + return TRUE; + case NO_BAG_AGAINST_TRAINER: //True in wild battle; False in trainer battle + return (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER)); + case NO_BAG_IN_BATTLE: + return FALSE; + default: + return TRUE; // Undefined Behavior + } +} diff --git a/src/battle_z_move.c b/src/battle_z_move.c index bef4b0c5e..8125c8b55 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -113,7 +113,7 @@ bool32 IsZMove(u32 move) bool32 CanUseZMove(u32 battler) { - u32 holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); // Check if Player has Z-Power Ring. if (!TESTING && (battler == B_POSITION_PLAYER_LEFT @@ -122,7 +122,7 @@ bool32 CanUseZMove(u32 battler) return FALSE; // Add '| BATTLE_TYPE_FRONTIER' to below if issues occur - if (gBattleTypeFlags & (BATTLE_TYPE_SAFARI | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE)) + if (gBattleTypeFlags & (BATTLE_TYPE_SAFARI | BATTLE_TYPE_OLD_MAN_TUTORIAL)) return FALSE; // Check if Trainer has already used a Z-Move. @@ -144,7 +144,7 @@ bool32 CanUseZMove(u32 battler) u32 GetUsableZMove(u32 battler, u32 move) { u32 item = gBattleMons[battler].item; - u32 holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) { @@ -161,14 +161,13 @@ u32 GetUsableZMove(u32 battler, u32 move) void ActivateZMove(u32 battler) { - gBattleStruct->zmove.baseMoves[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; SetActiveGimmick(battler, GIMMICK_Z_MOVE); } bool32 IsViableZMove(u32 battler, u32 move) { u32 item; - u32 holdEffect = GetBattlerHoldEffect(battler, FALSE); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffectIgnoreNegation(battler); int moveSlotIndex; item = gBattleMons[battler].item; @@ -364,7 +363,7 @@ bool32 MoveSelectionDisplayZMove(u16 zmove, u32 battler) gDisplayedStringBattle[1] = CHAR_HYPHEN; StringCopy(gDisplayedStringBattle + 2, GetMoveName(move)); } - else if (zmove == MOVE_EXTREME_EVOBOOST) + else if (GetMoveEffect(zmove) == EFFECT_EXTREME_EVOBOOST) { // Damaging move -> status z move StringCopy(gDisplayedStringBattle, sText_StatsPlus2); @@ -438,7 +437,7 @@ static void ZMoveSelectionDisplayMoveType(u16 zMove, u32 battler) void SetZEffect(void) { u32 i; - u32 effect = GetMoveZEffect(gBattleStruct->zmove.baseMoves[gBattlerAttacker]); + u32 effect = GetMoveZEffect(gChosenMove); if (effect == Z_EFFECT_CURSE) { @@ -486,9 +485,9 @@ void SetZEffect(void) break; } case Z_EFFECT_BOOST_CRITS: - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY_ANY)) + if (!(gBattleMons[gBattlerAttacker].volatiles.dragonCheer || gBattleMons[gBattlerAttacker].volatiles.focusEnergy)) { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[gBattlerAttacker].volatiles.focusEnergy = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_BOOST_CRITS; BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH); gBattlescriptCurrInstr = BattleScript_ZEffectPrintString; @@ -549,7 +548,8 @@ u32 GetZMovePower(u32 move) { if (GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS) return 0; - if (GetMoveEffect(move) == EFFECT_OHKO) + enum BattleMoveEffects moveEffect = GetMoveEffect(move); + if (moveEffect == EFFECT_OHKO || moveEffect == EFFECT_SHEER_COLD) return 180; u32 power = GetMoveZPowerOverride(move); @@ -568,4 +568,3 @@ u32 GetZMovePower(u32 move) else if (power >= 60) return 120; else return 100; } - diff --git a/src/data/abilities.h b/src/data/abilities.h index f767e2407..379ce62fc 100644 --- a/src/data/abilities.h +++ b/src/data/abilities.h @@ -1,4 +1,4 @@ -const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = +const struct AbilityInfo gAbilitiesInfo[ABILITIES_COUNT] = { [ABILITY_NONE] = { diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index ca7e866e9..094f2c7df 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -49,7 +49,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MIRROR_MOVE] = { - .battleScript = BattleScript_EffectMirrorMove, + .battleScript = BattleScript_EffectHit, .battleTvScore = 1, }, @@ -398,7 +398,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_METRONOME] = { - .battleScript = BattleScript_EffectMetronome, + .battleScript = BattleScript_EffectHit, .battleTvScore = 1, }, @@ -502,7 +502,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_SLEEP_TALK] = { - .battleScript = BattleScript_EffectSleepTalk, + .battleScript = BattleScript_EffectHit, .battleTvScore = 3, .encourageEncore = TRUE, }, @@ -791,7 +791,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_BEAT_UP] = { - .battleScript = BattleScript_EffectBeatUp, + .battleScript = (B_BEAT_UP >= GEN_5) ? BattleScript_EffectHit : BattleScript_EffectBeatUp, .battleTvScore = 2, }, @@ -819,14 +819,14 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_FIRST_TURN_ONLY] = { - .battleScript = BattleScript_EffectFirstTurnOnly, + .battleScript = BattleScript_EffectHit, .battleTvScore = 4, .encourageEncore = TRUE, }, [EFFECT_UPROAR] = { - .battleScript = BattleScript_EffectUproar, + .battleScript = BattleScript_EffectHit, .battleTvScore = 4, }, @@ -911,7 +911,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_NATURE_POWER] = { - .battleScript = BattleScript_EffectNaturePower, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -956,7 +956,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_ASSIST] = { - .battleScript = BattleScript_EffectAssist, + .battleScript = BattleScript_EffectHit, .battleTvScore = 2, }, @@ -1004,6 +1004,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 2, }, + [EFFECT_STEAL_ITEM] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 3, + }, + [EFFECT_ENDEAVOR] = { .battleScript = BattleScript_EffectEndeavor, @@ -1386,7 +1392,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_SUCKER_PUNCH] = { - .battleScript = BattleScript_EffectSuckerPunch, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1480,7 +1486,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_ME_FIRST] = { - .battleScript = BattleScript_EffectMeFirst, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1525,7 +1531,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_LAST_RESORT] = { - .battleScript = BattleScript_EffectLastResort, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1595,7 +1601,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_COPYCAT] = { - .battleScript = BattleScript_EffectCopycat, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1715,7 +1721,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MAT_BLOCK] = { - .battleScript = BattleScript_EffectMatBlock, + .battleScript = BattleScript_EffectProtect, .battleTvScore = 0, // TODO: Assign points .encourageEncore = TRUE, }, @@ -1768,7 +1774,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_FAIL_IF_NOT_ARG_TYPE] = { - .battleScript = BattleScript_FailIfNotArgType, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1875,7 +1881,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_AURA_WHEEL] = { - .battleScript = BattleScript_EffectAuraWheel, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, @@ -1978,9 +1984,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_HIT_SET_REMOVE_TERRAIN] = + [EFFECT_HIT_SET_TERRAIN] = { - .battleScript = BattleScript_EffectHitSetRemoveTerrain, + .battleScript = BattleScript_EffectHitSetTerrain, .battleTvScore = 0, // TODO: Assign points }, @@ -2212,4 +2218,34 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, + + [EFFECT_LIFE_DEW] = + { + .battleScript = BattleScript_EffectLifeDew, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_ICE_SPINNER] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_STEEL_ROLLER] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_STONE_AXE] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_CEASELESS_EDGE] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, }; diff --git a/src/data/battle_partners.h b/src/data/battle_partners.h index 520f52381..a38068864 100644 --- a/src/data/battle_partners.h +++ b/src/data/battle_partners.h @@ -1,9 +1,7 @@ // // DO NOT MODIFY THIS FILE! It is auto-generated from src/data/battle_partners.party // -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'src/data/battle_partners.h' to remove #line markers. +// If you want to modify this file see expansion PR #7154 // #line 1 "src/data/battle_partners.party" @@ -14,45 +12,51 @@ #line 3 .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, #line 4 - .trainerPic = TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN, + .trainerPic = TRAINER_PIC_RS_BRENDAN_1, .encounterMusic_gender = #line 6 TRAINER_ENCOUNTER_MUSIC_MALE, +#line 7 + .trainerBackPic = TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN, .partySize = 0, .party = (const struct TrainerMon[]) { }, }, -#line 8 +#line 9 [DIFFICULTY_NORMAL][PARTNER_STEVEN] = { -#line 9 - .trainerName = _("STEVEN"), #line 10 - .trainerClass = TRAINER_CLASS_RIVAL_LATE, + .trainerName = _("STEVEN"), #line 11 - .trainerPic = TRAINER_BACK_PIC_STEVEN, + .trainerClass = TRAINER_CLASS_RIVAL_LATE, +#line 12 + .trainerPic = TRAINER_PIC_RS_BRENDAN_1, .encounterMusic_gender = -#line 13 +#line 14 TRAINER_ENCOUNTER_MUSIC_MALE, +#line 16 + .aiFlags = AI_FLAG_BASIC_TRAINER, +#line 15 + .trainerBackPic = TRAINER_BACK_PIC_STEVEN, .partySize = 3, .party = (const struct TrainerMon[]) { { -#line 15 +#line 18 .species = SPECIES_METANG, .gender = TRAINER_MON_RANDOM_GENDER, -#line 19 +#line 22 .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), -#line 18 +#line 21 .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 17 +#line 20 .lvl = 42, -#line 16 +#line 19 .nature = NATURE_BRAVE, .dynamaxLevel = MAX_DYNAMAX_LEVEL, .moves = { -#line 20 +#line 23 MOVE_LIGHT_SCREEN, MOVE_PSYCHIC, MOVE_REFLECT, @@ -60,20 +64,20 @@ }, }, { -#line 25 +#line 28 .species = SPECIES_SKARMORY, .gender = TRAINER_MON_RANDOM_GENDER, -#line 29 +#line 32 .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), -#line 28 +#line 31 .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 27 +#line 30 .lvl = 43, -#line 26 +#line 29 .nature = NATURE_IMPISH, .dynamaxLevel = MAX_DYNAMAX_LEVEL, .moves = { -#line 30 +#line 33 MOVE_TOXIC, MOVE_AERIAL_ACE, MOVE_PROTECT, @@ -81,20 +85,20 @@ }, }, { -#line 35 +#line 38 .species = SPECIES_AGGRON, .gender = TRAINER_MON_RANDOM_GENDER, -#line 39 +#line 42 .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), -#line 38 +#line 41 .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 37 +#line 40 .lvl = 44, -#line 36 +#line 39 .nature = NATURE_ADAMANT, .dynamaxLevel = MAX_DYNAMAX_LEVEL, .moves = { -#line 40 +#line 43 MOVE_THUNDER, MOVE_PROTECT, MOVE_SOLAR_BEAM, diff --git a/src/data/battle_partners.party b/src/data/battle_partners.party index 362fda23e..bcf818dca 100644 --- a/src/data/battle_partners.party +++ b/src/data/battle_partners.party @@ -1,16 +1,19 @@ === PARTNER_NONE === Name: Class: Pkmn Trainer 1 -Pic: Ruby Sapphire Brendan +Pic: RS Brendan 1 Gender: Male Music: Male +Back Pic: Ruby Sapphire Brendan === PARTNER_STEVEN === Name: STEVEN Class: Rival Late -Pic: Steven +Pic: RS Brendan 1 Gender: Male Music: Male +Back Pic: Steven +AI: Basic Trainer Metang Brave Nature diff --git a/src/data/debug_trainers.h b/src/data/debug_trainers.h new file mode 100644 index 000000000..3e02d70da --- /dev/null +++ b/src/data/debug_trainers.h @@ -0,0 +1,136 @@ +// +// DO NOT MODIFY THIS FILE! It is auto-generated from src/data/debug_trainers.party +// +// If you want to modify this file see expansion PR #7154 +// + +#line 1 "src/data/debug_trainers.party" + +#line 14 + [DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER] = + { +#line 15 + .trainerName = _("Player"), +#line 16 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 17 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 19 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 21 + .nickname = COMPOUND_STRING("Buffie"), +#line 21 + .species = SPECIES_WOBBUFFET, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 25 + .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), +#line 24 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 23 + .lvl = 100, +#line 22 + .nature = NATURE_BRAVE, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 26 + MOVE_EARTHQUAKE, + MOVE_FLAMETHROWER, + MOVE_CELEBRATE, + MOVE_CELEBRATE, + }, + }, + }, + }, +#line 31 + [DIFFICULTY_NORMAL][DEBUG_TRAINER_AI] = + { +#line 32 + .trainerName = _("Debugger"), +#line 34 + .trainerClass = TRAINER_CLASS_CHAMPION, +#line 36 + .trainerPic = TRAINER_PIC_CHAMPION_STEVEN, + .encounterMusic_gender = +#line 38 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 35 + .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 33 + .aiFlags = AI_FLAG_BASIC_TRAINER, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_STEVEN, + .partySize = 3, + .party = (const struct TrainerMon[]) + { + { +#line 40 + .species = SPECIES_METANG, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 44 + .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), +#line 43 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 42 + .lvl = 42, +#line 41 + .nature = NATURE_BRAVE, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 45 + MOVE_LIGHT_SCREEN, + MOVE_PSYCHIC, + MOVE_REFLECT, + MOVE_METAL_CLAW, + }, + }, + { +#line 50 + .species = SPECIES_SKARMORY, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 54 + .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), +#line 53 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 52 + .lvl = 43, +#line 51 + .nature = NATURE_IMPISH, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 55 + MOVE_TOXIC, + MOVE_AERIAL_ACE, + MOVE_PROTECT, + MOVE_STEEL_WING, + }, + }, + { +#line 60 + .species = SPECIES_AGGRON, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 64 + .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), +#line 63 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 62 + .lvl = 44, +#line 61 + .nature = NATURE_ADAMANT, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + .moves = { +#line 65 + MOVE_THUNDER, + MOVE_PROTECT, + MOVE_SOLAR_BEAM, + MOVE_DRAGON_CLAW, + }, + }, + }, + }, diff --git a/src/data/debug_trainers.party b/src/data/debug_trainers.party new file mode 100644 index 000000000..9c6f2abdc --- /dev/null +++ b/src/data/debug_trainers.party @@ -0,0 +1,68 @@ +/* + +Parties for the debug menu. + +The trainer description for DEBUG_TRAINER_PLAYER is not used, +its party is given to the player whenever the Set Party action is selected, +or the Start Debug Battle action is selected. + +The debug menu will start a battle against DEBUG_TRAINER_AI when the +Start Debug Battle action is selected. + +*/ + +=== DEBUG_TRAINER_PLAYER === +Name: Player +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male + +Buffie (Wobbuffet) +Brave Nature +Level: 100 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 Atk / 252 Def / 6 SpA +- Earthquake +- Flamethrower +- Celebrate +- Celebrate + +=== DEBUG_TRAINER_AI === +Name: Debugger +AI: Basic Trainer +Class: Champion +Battle Type: Singles +Pic: Champion Steven +Gender: Male +Music: Male + +Metang +Brave Nature +Level: 42 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 Atk / 252 Def / 6 SpA +- Light Screen +- Psychic +- Reflect +- Metal Claw + +Skarmory +Impish Nature +Level: 43 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 HP / 6 SpA / 252 SpD +- Toxic +- Aerial Ace +- Protect +- Steel Wing + +Aggron +Adamant Nature +Level: 44 +IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe +EVs: 252 Atk / 252 SpA / 6 SpD +- Thunder +- Protect +- Solar Beam +- Dragon Claw diff --git a/src/data/graphics/trainers.h b/src/data/graphics/trainers.h index e965f4209..c7a811f9b 100644 --- a/src/data/graphics/trainers.h +++ b/src/data/graphics/trainers.h @@ -689,84 +689,22 @@ static const union AnimCmd *const sBackAnims_Hoenn[] = sAnimCmd_Point_HGSS, }; -#define BACK_PIC_TABLE_ENTRY(backPicData, entryId) \ - {.data = backPicData + TRAINER_PIC_SIZE * entryId, .size = TRAINER_PIC_SIZE} - -const struct SpriteFrameImage gTrainerBackPicTable_Red[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Red, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Red, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Red, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Red, 3), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Red, 4), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_Leaf[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Leaf, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Leaf, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Leaf, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Leaf, 3), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Leaf, 4), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_Pokedude[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Pokedude, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Pokedude, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Pokedude, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Pokedude, 3), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_OldMan[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_OldMan, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_OldMan, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_OldMan, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_OldMan, 3), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_RSBrendan[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSBrendan, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSBrendan, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSBrendan, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSBrendan, 3), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_RSMay[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSMay, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSMay, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSMay, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_RSMay, 3), -}; - -const struct SpriteFrameImage gTrainerBackPicTable_Steven[] = -{ - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Steven, 0), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Steven, 1), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Steven, 2), - BACK_PIC_TABLE_ENTRY(gTrainerBackPic_Steven, 3), -}; - - -#define TRAINER_BACK_SPRITE(trainerId, yOffset, backPicData, backPicTable, paletteData, anim) \ - [trainerId] = \ - { \ - .coordinates = {.size = 8, .y_offset = yOffset}, \ - .backPic = {.data = (const u32 *)backPicData, .size = TRAINER_PIC_SIZE * ARRAY_COUNT(backPicTable), .tag = trainerId}, \ - .palette = {.data = paletteData, .tag = trainerId}, \ - .animation = anim, \ +#define TRAINER_BACK_SPRITE(trainerPic, yOffset, sprite, pal, anim) \ + [trainerPic] = \ + { \ + .coordinates = {.size = 8, .y_offset = yOffset}, \ + .backPic = {.data = sprite, .size = TRAINER_PIC_SIZE, .relativeFrames = TRUE}, \ + .palette = {.data = pal, .tag = trainerPic}, \ + .animation = anim, \ } const struct TrainerBacksprite gTrainerBacksprites[] = { - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RED, 5, gTrainerBackPic_Red, gTrainerBackPicTable_Red, gTrainerPalette_RedBackPic, sBackAnims_Kanto), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_LEAF, 5, gTrainerBackPic_Leaf, gTrainerBackPicTable_Leaf, gTrainerPalette_LeafBackPic, sBackAnims_Kanto), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN, 4, gTrainerBackPic_RSBrendan, gTrainerBackPicTable_RSBrendan, gTrainerPalette_RSBrendan1, sBackAnims_Hoenn), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RUBY_SAPPHIRE_MAY, 4, gTrainerBackPic_RSMay, gTrainerBackPicTable_RSMay, gTrainerPalette_RSMay1, sBackAnims_Hoenn), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_POKEDUDE, 4, gTrainerBackPic_Pokedude, gTrainerBackPicTable_Pokedude, gTrainerPalette_PokedudeBackPic, sBackAnims_OldManPokedude), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_OLD_MAN, 4, gTrainerBackPic_OldMan, gTrainerBackPicTable_OldMan, gTrainerPalette_OldManBackPic, sBackAnims_OldManPokedude), - TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_STEVEN, 4, gTrainerBackPic_Steven, gTrainerBackPicTable_Steven, gTrainerPalette_Steven, sBackAnims_Hoenn), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RED, 5, gTrainerBackPic_Red, gTrainerPalette_RedBackPic, sBackAnims_Kanto), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_LEAF, 5, gTrainerBackPic_Leaf, gTrainerPalette_LeafBackPic, sBackAnims_Kanto), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN, 4, gTrainerBackPic_RSBrendan, gTrainerPalette_RSBrendan1, sBackAnims_Hoenn), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_RUBY_SAPPHIRE_MAY, 4, gTrainerBackPic_RSMay, gTrainerPalette_RSMay1, sBackAnims_Hoenn), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_POKEDUDE, 4, gTrainerBackPic_Pokedude, gTrainerPalette_PokedudeBackPic, sBackAnims_OldManPokedude), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_OLD_MAN, 4, gTrainerBackPic_OldMan, gTrainerPalette_OldManBackPic, sBackAnims_OldManPokedude), + TRAINER_BACK_SPRITE(TRAINER_BACK_PIC_STEVEN, 4, gTrainerBackPic_Steven, gTrainerPalette_Steven, sBackAnims_Hoenn), }; diff --git a/src/data/items.h b/src/data/items.h index 44a55da5f..6e33f1174 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -14,6 +14,9 @@ #define TREASURE_FACTOR ((I_SELL_VALUE_FRACTION >= GEN_9) ? 2 : 1) +#define ITEM_NAME(str) COMPOUND_STRING_SIZE_LIMIT(str, ITEM_NAME_LENGTH) +#define ITEM_PLURAL_NAME(str) COMPOUND_STRING_SIZE_LIMIT(str, ITEM_NAME_PLURAL_LENGTH) + // Shared Item Description entries static const u8 sFullHealDesc[] = _("Heals all the " @@ -124,6 +127,8 @@ static const u8 sFigyBerryDesc[] = _("A hold item that " "restores HP but " "\nmay confuse."); +const u8 gQuestionMarksItemName[] = _("????????"); + static const u8 sQuestionMarksDesc[] = _("?????"); static const u8 sKeyToRoomDesc[] = _("A key that opens a " @@ -142,10 +147,11 @@ const struct Item gItemsInfo[] = { [ITEM_NONE] = { - .name = _("????????"), + .name = gQuestionMarksItemName, .price = 0, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_UNCATEGORIZED, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_QuestionMark, @@ -156,7 +162,7 @@ const struct Item gItemsInfo[] = [ITEM_STRANGE_BALL] = { - .name = _("Strange Ball"), + .name = ITEM_NAME("Strange Ball"), .price = 0, .description = COMPOUND_STRING( "An unusual Ball " @@ -172,7 +178,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_BALL] = { - .name = _("Poké Ball"), + .name = ITEM_NAME("Poké Ball"), .price = 200, .description = COMPOUND_STRING( "A tool used for " @@ -188,7 +194,7 @@ const struct Item gItemsInfo[] = [ITEM_GREAT_BALL] = { - .name = _("Great Ball"), + .name = ITEM_NAME("Great Ball"), .price = 600, .description = COMPOUND_STRING( "A good Ball with a " @@ -204,7 +210,7 @@ const struct Item gItemsInfo[] = [ITEM_ULTRA_BALL] = { - .name = _("Ultra Ball"), + .name = ITEM_NAME("Ultra Ball"), .price = (I_PRICE >= GEN_7) ? 800 : 1200, .description = COMPOUND_STRING( "A better Ball with " @@ -220,7 +226,7 @@ const struct Item gItemsInfo[] = [ITEM_MASTER_BALL] = { - .name = _("Master Ball"), + .name = ITEM_NAME("Master Ball"), .price = 0, .description = COMPOUND_STRING( "The best Ball that " @@ -236,7 +242,7 @@ const struct Item gItemsInfo[] = [ITEM_PREMIER_BALL] = { - .name = _("Premier Ball"), + .name = ITEM_NAME("Premier Ball"), .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING( "A rare Ball made " @@ -252,7 +258,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAL_BALL] = { - .name = _("Heal Ball"), + .name = ITEM_NAME("Heal Ball"), .price = 300, .description = COMPOUND_STRING( "A remedial Ball " @@ -268,7 +274,7 @@ const struct Item gItemsInfo[] = [ITEM_NET_BALL] = { - .name = _("Net Ball"), + .name = ITEM_NAME("Net Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works " @@ -284,7 +290,7 @@ const struct Item gItemsInfo[] = [ITEM_NEST_BALL] = { - .name = _("Nest Ball"), + .name = ITEM_NAME("Nest Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works " @@ -300,7 +306,7 @@ const struct Item gItemsInfo[] = [ITEM_DIVE_BALL] = { - .name = _("Dive Ball"), + .name = ITEM_NAME("Dive Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works " @@ -316,7 +322,7 @@ const struct Item gItemsInfo[] = [ITEM_DUSK_BALL] = { - .name = _("Dusk Ball"), + .name = ITEM_NAME("Dusk Ball"), .price = 1000, .description = COMPOUND_STRING( "Works well if " @@ -332,7 +338,7 @@ const struct Item gItemsInfo[] = [ITEM_TIMER_BALL] = { - .name = _("Timer Ball"), + .name = ITEM_NAME("Timer Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that gains " @@ -348,7 +354,7 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_BALL] = { - .name = _("Quick Ball"), + .name = ITEM_NAME("Quick Ball"), .price = 1000, .description = COMPOUND_STRING( "Works well if " @@ -364,7 +370,7 @@ const struct Item gItemsInfo[] = [ITEM_REPEAT_BALL] = { - .name = _("Repeat Ball"), + .name = ITEM_NAME("Repeat Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works " @@ -380,7 +386,7 @@ const struct Item gItemsInfo[] = [ITEM_LUXURY_BALL] = { - .name = _("Luxury Ball"), + .name = ITEM_NAME("Luxury Ball"), .price = (I_PRICE >= GEN_8) ? 3000 : 1000, .description = COMPOUND_STRING( "A cozy Ball that " @@ -396,7 +402,7 @@ const struct Item gItemsInfo[] = [ITEM_LEVEL_BALL] = { - .name = _("Level Ball"), + .name = ITEM_NAME("Level Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works " @@ -412,7 +418,7 @@ const struct Item gItemsInfo[] = [ITEM_LURE_BALL] = { - .name = _("Lure Ball"), + .name = ITEM_NAME("Lure Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works " @@ -428,7 +434,7 @@ const struct Item gItemsInfo[] = [ITEM_MOON_BALL] = { - .name = _("Moon Ball"), + .name = ITEM_NAME("Moon Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works " @@ -444,7 +450,7 @@ const struct Item gItemsInfo[] = [ITEM_FRIEND_BALL] = { - .name = _("Friend Ball"), + .name = ITEM_NAME("Friend Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that makes " @@ -460,7 +466,7 @@ const struct Item gItemsInfo[] = [ITEM_LOVE_BALL] = { - .name = _("Love Ball"), + .name = ITEM_NAME("Love Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on " @@ -476,7 +482,7 @@ const struct Item gItemsInfo[] = [ITEM_FAST_BALL] = { - .name = _("Fast Ball"), + .name = ITEM_NAME("Fast Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on " @@ -492,7 +498,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAVY_BALL] = { - .name = _("Heavy Ball"), + .name = ITEM_NAME("Heavy Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on " @@ -508,7 +514,7 @@ const struct Item gItemsInfo[] = [ITEM_DREAM_BALL] = { - .name = _("Dream Ball"), + .name = ITEM_NAME("Dream Ball"), .price = 0, .description = COMPOUND_STRING( #if B_DREAM_BALL_MODIFIER >= GEN_8 @@ -529,7 +535,7 @@ const struct Item gItemsInfo[] = [ITEM_SAFARI_BALL] = { - .name = _("Safari Ball"), + .name = ITEM_NAME("Safari Ball"), .price = 0, .description = COMPOUND_STRING( "A special Ball that " @@ -545,7 +551,7 @@ const struct Item gItemsInfo[] = [ITEM_SPORT_BALL] = { - .name = _("Sport Ball"), + .name = ITEM_NAME("Sport Ball"), .price = (I_PRICE < GEN_3 || I_PRICE >= GEN_9) ? 0 : 300, .description = COMPOUND_STRING( "A special Ball " @@ -561,7 +567,7 @@ const struct Item gItemsInfo[] = [ITEM_PARK_BALL] = { - .name = _("Park Ball"), + .name = ITEM_NAME("Park Ball"), .price = 0, .description = COMPOUND_STRING( "A special Ball for " @@ -576,7 +582,7 @@ const struct Item gItemsInfo[] = [ITEM_BEAST_BALL] = { - .name = _("Beast Ball"), + .name = ITEM_NAME("Beast Ball"), .price = 0, .description = COMPOUND_STRING( "A Ball designed to " @@ -591,7 +597,7 @@ const struct Item gItemsInfo[] = [ITEM_CHERISH_BALL] = { - .name = _("Cherish Ball"), + .name = ITEM_NAME("Cherish Ball"), .price = 0, .description = COMPOUND_STRING( "A rare Ball made " @@ -609,7 +615,7 @@ const struct Item gItemsInfo[] = [ITEM_POTION] = { - .name = _("Potion"), + .name = ITEM_NAME("Potion"), .price = (I_PRICE >= GEN_7) ? 200 : 300, .holdEffectParam = 20, .description = COMPOUND_STRING( @@ -617,6 +623,7 @@ const struct Item gItemsInfo[] = "a Pokémon by " "\n20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -628,7 +635,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_POTION] = { - .name = _("Super Potion"), + .name = ITEM_NAME("Super Potion"), .price = 700, .holdEffectParam = 60, .description = COMPOUND_STRING( @@ -640,6 +647,7 @@ const struct Item gItemsInfo[] = "\n50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -651,7 +659,7 @@ const struct Item gItemsInfo[] = [ITEM_HYPER_POTION] = { - .name = _("Hyper Potion"), + .name = ITEM_NAME("Hyper Potion"), .price = (I_PRICE >= GEN_2 && I_PRICE <= GEN_6) ? 1200 : 1500, .holdEffectParam = 120, .description = COMPOUND_STRING( @@ -663,6 +671,7 @@ const struct Item gItemsInfo[] = "\n200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -674,13 +683,14 @@ const struct Item gItemsInfo[] = [ITEM_MAX_POTION] = { - .name = _("Max Potion"), + .name = ITEM_NAME("Max Potion"), .price = 2500, .holdEffectParam = 255, .description = COMPOUND_STRING( "Fully restores the " "HP of a\nPokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -692,7 +702,7 @@ const struct Item gItemsInfo[] = [ITEM_FULL_RESTORE] = { - .name = _("Full Restore"), + .name = ITEM_NAME("Full Restore"), .price = 3000, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -700,6 +710,7 @@ const struct Item gItemsInfo[] = "HP and status\nof a " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_HEAL_AND_CURE_STATUS, @@ -711,13 +722,14 @@ const struct Item gItemsInfo[] = [ITEM_REVIVE] = { - .name = _("Revive"), + .name = ITEM_NAME("Revive"), .price = (I_PRICE >= GEN_7) ? 2000 : 1500, .description = COMPOUND_STRING( "Revives a fainted " "Pokémon with\nhalf " "its HP."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -729,10 +741,11 @@ const struct Item gItemsInfo[] = [ITEM_MAX_REVIVE] = { - .name = _("Max Revive"), + .name = ITEM_NAME("Max Revive"), .price = 4000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -744,7 +757,7 @@ const struct Item gItemsInfo[] = [ITEM_FRESH_WATER] = { - .name = _("Fresh Water"), + .name = ITEM_NAME("Fresh Water"), .price = 200, .holdEffectParam = 30, .description = COMPOUND_STRING( @@ -756,6 +769,7 @@ const struct Item gItemsInfo[] = "\nby 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -767,7 +781,7 @@ const struct Item gItemsInfo[] = [ITEM_SODA_POP] = { - .name = _("Soda Pop"), + .name = ITEM_NAME("Soda Pop"), .price = 300, .holdEffectParam = 50, .description = COMPOUND_STRING( @@ -779,6 +793,7 @@ const struct Item gItemsInfo[] = "by 60 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -790,7 +805,7 @@ const struct Item gItemsInfo[] = [ITEM_LEMONADE] = { - .name = _("Lemonade"), + .name = ITEM_NAME("Lemonade"), .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 70, #if I_HEALTH_RECOVERY >= GEN_7 @@ -805,6 +820,7 @@ const struct Item gItemsInfo[] = "by 80 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -816,8 +832,8 @@ const struct Item gItemsInfo[] = [ITEM_MOOMOO_MILK] = { - .name = _("Moomoo Milk"), - .pluralName = _("Moomoo Milk"), + .name = ITEM_NAME("Moomoo Milk"), + .pluralName = ITEM_PLURAL_NAME("Moomoo Milk"), .price = (I_PRICE >= GEN_7) ? 600 : 500, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -825,6 +841,7 @@ const struct Item gItemsInfo[] = "that restores\nHP " "by 100 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -836,8 +853,8 @@ const struct Item gItemsInfo[] = [ITEM_ENERGY_POWDER] = { - .name = _("Energy Powder"), - .pluralName = _("Energy Powder"), + .name = ITEM_NAME("Energy Powder"), + .pluralName = ITEM_PLURAL_NAME("Energy Powder"), .price = 500, .description = COMPOUND_STRING( "A bitter powder " @@ -848,6 +865,7 @@ const struct Item gItemsInfo[] = "\nby 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -859,7 +877,7 @@ const struct Item gItemsInfo[] = [ITEM_ENERGY_ROOT] = { - .name = _("Energy Root"), + .name = ITEM_NAME("Energy Root"), .price = (I_PRICE >= GEN_7) ? 1200 : 800, .description = COMPOUND_STRING( "A bitter root " @@ -870,6 +888,7 @@ const struct Item gItemsInfo[] = "by\n200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -881,14 +900,15 @@ const struct Item gItemsInfo[] = [ITEM_HEAL_POWDER] = { - .name = _("Heal Powder"), - .pluralName = _("Heal Powder"), + .name = ITEM_NAME("Heal Powder"), + .pluralName = ITEM_PLURAL_NAME("Heal Powder"), .price = (I_PRICE >= GEN_7) ? 300 : 450, .description = COMPOUND_STRING( "A bitter powder " "that heals all " "\nstatus problems."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -900,13 +920,14 @@ const struct Item gItemsInfo[] = [ITEM_REVIVAL_HERB] = { - .name = _("Revival Herb"), + .name = ITEM_NAME("Revival Herb"), .price = 2800, .description = COMPOUND_STRING( "A very bitter herb " "that revives a\n" "fainted Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -918,12 +939,13 @@ const struct Item gItemsInfo[] = [ITEM_ANTIDOTE] = { - .name = _("Antidote"), + .name = ITEM_NAME("Antidote"), .price = (I_PRICE >= GEN_7) ? 200 : 100, .description = COMPOUND_STRING( "Heals a poisoned " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -935,12 +957,13 @@ const struct Item gItemsInfo[] = [ITEM_PARALYZE_HEAL] = { - .name = _("Paralyze Heal"), + .name = ITEM_NAME("Paralyze Heal"), .price = (I_PRICE == GEN_7) ? 300 : 200, .description = COMPOUND_STRING( "Heals a paralyzed " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -952,12 +975,13 @@ const struct Item gItemsInfo[] = [ITEM_BURN_HEAL] = { - .name = _("Burn Heal"), + .name = ITEM_NAME("Burn Heal"), .price = (I_PRICE == GEN_7) ? 300 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING( "Heals Pokémon " "of a burn."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -969,12 +993,13 @@ const struct Item gItemsInfo[] = [ITEM_ICE_HEAL] = { - .name = _("Ice Heal"), + .name = ITEM_NAME("Ice Heal"), .price = (I_PRICE == GEN_7) ? 100 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING( "Defrosts a frozen " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -986,12 +1011,13 @@ const struct Item gItemsInfo[] = [ITEM_AWAKENING] = { - .name = _("Awakening"), + .name = ITEM_NAME("Awakening"), .price = (I_PRICE >= GEN_2 && I_PRICE <= GEN_6) ? 250 : ((I_PRICE == GEN_7) ? 100 : 200), .description = COMPOUND_STRING( "Awakens a sleeping " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1003,10 +1029,11 @@ const struct Item gItemsInfo[] = [ITEM_FULL_HEAL] = { - .name = _("Full Heal"), + .name = ITEM_NAME("Full Heal"), .price = (I_PRICE >= GEN_7) ? 400 : 600, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1018,7 +1045,7 @@ const struct Item gItemsInfo[] = [ITEM_ETHER] = { - .name = _("Ether"), + .name = ITEM_NAME("Ether"), .price = (I_PRICE >= GEN_2) ? 1200 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING( @@ -1026,6 +1053,7 @@ const struct Item gItemsInfo[] = "of a selected\nmove " "by 10."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1037,7 +1065,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_ETHER] = { - .name = _("Max Ether"), + .name = ITEM_NAME("Max Ether"), .price = (I_PRICE >= GEN_2) ? 2000 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -1045,6 +1073,7 @@ const struct Item gItemsInfo[] = "PP of a\nselected " "move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1056,13 +1085,14 @@ const struct Item gItemsInfo[] = [ITEM_ELIXIR] = { - .name = _("Elixir"), + .name = ITEM_NAME("Elixir"), .price = (I_PRICE >= GEN_2) ? 3000 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING( "Restores the PP " "of all moves by\n10."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1074,7 +1104,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_ELIXIR] = { - .name = _("Max Elixir"), + .name = ITEM_NAME("Max Elixir"), .price = (I_PRICE >= GEN_2) ? 4500 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -1082,6 +1112,7 @@ const struct Item gItemsInfo[] = "PP of a\nPokémon's " "moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1093,8 +1124,8 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_JUICE] = { - .name = _("Berry Juice"), - .pluralName = _("Berry Juice"), + .name = ITEM_NAME("Berry Juice"), + .pluralName = ITEM_PLURAL_NAME("Berry Juice"), .price = 100, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 20, @@ -1103,6 +1134,7 @@ const struct Item gItemsInfo[] = "that restores\nHP " "by 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1114,14 +1146,15 @@ const struct Item gItemsInfo[] = [ITEM_SACRED_ASH] = { - .name = _("Sacred Ash"), - .pluralName = _("Sacred Ashes"), + .name = ITEM_NAME("Sacred Ash"), + .pluralName = ITEM_PLURAL_NAME("Sacred Ashes"), .price = (I_PRICE >= GEN_7) ? 50000 : 200, .description = COMPOUND_STRING( "Fully revives and " "restores all " "\nfainted Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_SacredAsh, .effect = gItemEffect_SacredAsh, @@ -1132,7 +1165,7 @@ const struct Item gItemsInfo[] = [ITEM_SWEET_HEART] = { - .name = _("Sweet Heart"), + .name = ITEM_NAME("Sweet Heart"), .price = (I_PRICE >= GEN_7) ? 3000 : 100, .holdEffectParam = 20, .description = COMPOUND_STRING( @@ -1140,6 +1173,7 @@ const struct Item gItemsInfo[] = "that restores\nHP " "by 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1151,11 +1185,12 @@ const struct Item gItemsInfo[] = [ITEM_MAX_HONEY] = { - .name = _("Max Honey"), - .pluralName = _("Max Honey"), + .name = ITEM_NAME("Max Honey"), + .pluralName = ITEM_PLURAL_NAME("Max Honey"), .price = 8000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -1169,11 +1204,12 @@ const struct Item gItemsInfo[] = [ITEM_PEWTER_CRUNCHIES] = { - .name = _("Pewter Crunchies"), - .pluralName = _("Pewter Crunchies"), + .name = ITEM_NAME("Pewter Crunchies"), + .pluralName = ITEM_PLURAL_NAME("Pewter Crunchies"), .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1185,10 +1221,11 @@ const struct Item gItemsInfo[] = [ITEM_RAGE_CANDY_BAR] = { - .name = _("Rage Candy Bar"), + .name = ITEM_NAME("Rage Candy Bar"), .price = (I_PRICE >= GEN_7) ? 350 : 300, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1200,13 +1237,14 @@ const struct Item gItemsInfo[] = [ITEM_LAVA_COOKIE] = { - .name = _("Lava Cookie"), + .name = ITEM_NAME("Lava Cookie"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = COMPOUND_STRING( "A local specialty " "that heals all " "\nstatus problems."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1218,11 +1256,12 @@ const struct Item gItemsInfo[] = [ITEM_OLD_GATEAU] = { - .name = _("Old Gateau"), - .pluralName = _("Old Gateaux"), + .name = ITEM_NAME("Old Gateau"), + .pluralName = ITEM_PLURAL_NAME("Old Gateaux"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1234,10 +1273,11 @@ const struct Item gItemsInfo[] = [ITEM_CASTELIACONE] = { - .name = _("Casteliacone"), + .name = ITEM_NAME("Casteliacone"), .price = (I_PRICE >= GEN_7) ? 350 : 100, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1249,10 +1289,11 @@ const struct Item gItemsInfo[] = [ITEM_LUMIOSE_GALETTE] = { - .name = _("Lumiose Galette"), + .name = ITEM_NAME("Lumiose Galette"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1264,10 +1305,11 @@ const struct Item gItemsInfo[] = [ITEM_SHALOUR_SABLE] = { - .name = _("Shalour Sable"), + .name = ITEM_NAME("Shalour Sable"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1279,10 +1321,11 @@ const struct Item gItemsInfo[] = [ITEM_BIG_MALASADA] = { - .name = _("Big Malasada"), + .name = ITEM_NAME("Big Malasada"), .price = 350, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1296,12 +1339,13 @@ const struct Item gItemsInfo[] = [ITEM_HP_UP] = { - .name = _("HP Up"), + .name = ITEM_NAME("HP Up"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base HP " "of one\nPokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HPUp, @@ -1312,13 +1356,14 @@ const struct Item gItemsInfo[] = [ITEM_PROTEIN] = { - .name = _("Protein"), + .name = ITEM_NAME("Protein"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base " "Attack stat of\none " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Protein, @@ -1329,13 +1374,14 @@ const struct Item gItemsInfo[] = [ITEM_IRON] = { - .name = _("Iron"), + .name = ITEM_NAME("Iron"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base " "Defense stat of " "\none Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Iron, @@ -1346,13 +1392,14 @@ const struct Item gItemsInfo[] = [ITEM_CALCIUM] = { - .name = _("Calcium"), + .name = ITEM_NAME("Calcium"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base " "Sp. Atk stat of\none " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Calcium, @@ -1363,13 +1410,14 @@ const struct Item gItemsInfo[] = [ITEM_ZINC] = { - .name = _("Zinc"), + .name = ITEM_NAME("Zinc"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base " "Sp. Def stat of\none " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Zinc, @@ -1380,14 +1428,15 @@ const struct Item gItemsInfo[] = [ITEM_CARBOS] = { - .name = _("Carbos"), - .pluralName = _("Carbos"), + .name = ITEM_NAME("Carbos"), + .pluralName = ITEM_PLURAL_NAME("Carbos"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base " "Speed stat of one\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Carbos, @@ -1398,13 +1447,14 @@ const struct Item gItemsInfo[] = [ITEM_PP_UP] = { - .name = _("PP Up"), + .name = ITEM_NAME("PP Up"), .price = (I_PRICE == GEN_1) ? 1 : ((I_PRICE >= GEN_7) ? 10000 : 9800), .description = COMPOUND_STRING( "Raises the maximum " "PP of a\nselected " "move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPUp, @@ -1415,14 +1465,15 @@ const struct Item gItemsInfo[] = [ITEM_PP_MAX] = { - .name = _("PP Max"), - .pluralName = _("PP Maxes"), + .name = ITEM_NAME("PP Max"), + .pluralName = ITEM_PLURAL_NAME("PP Maxes"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the PP of a " "move to its\nmaximum " "points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPMax, @@ -1435,10 +1486,11 @@ const struct Item gItemsInfo[] = [ITEM_HEALTH_FEATHER] = { - .name = _("Health Feather"), + .name = ITEM_NAME("Health Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpFeather, @@ -1449,10 +1501,11 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_FEATHER] = { - .name = _("Muscle Feather"), + .name = ITEM_NAME("Muscle Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkFeather, @@ -1463,10 +1516,11 @@ const struct Item gItemsInfo[] = [ITEM_RESIST_FEATHER] = { - .name = _("Resist Feather"), + .name = ITEM_NAME("Resist Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefFeather, @@ -1477,10 +1531,11 @@ const struct Item gItemsInfo[] = [ITEM_GENIUS_FEATHER] = { - .name = _("Genius Feather"), + .name = ITEM_NAME("Genius Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkFeather, @@ -1491,10 +1546,11 @@ const struct Item gItemsInfo[] = [ITEM_CLEVER_FEATHER] = { - .name = _("Clever Feather"), + .name = ITEM_NAME("Clever Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefFeather, @@ -1505,10 +1561,11 @@ const struct Item gItemsInfo[] = [ITEM_SWIFT_FEATHER] = { - .name = _("Swift Feather"), + .name = ITEM_NAME("Swift Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedFeather, @@ -1521,13 +1578,14 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_CAPSULE] = { - .name = _("Ability Capsule"), + .name = ITEM_NAME("Ability Capsule"), .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE < GEN_9) ? 10000 : 100000), .holdEffectParam = 0, .description = COMPOUND_STRING( "Switches a Poké-" "mon's ability."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityCapsule, .iconPic = gItemIcon_AbilityCapsule, @@ -1536,8 +1594,8 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_PATCH] = { - .name = _("Ability Patch"), - .pluralName = _("Ability Patches"), + .name = ITEM_NAME("Ability Patch"), + .pluralName = ITEM_PLURAL_NAME("Ability Patches"), .price = (I_PRICE >= GEN_9) ? 250000 : 20, .holdEffectParam = 0, .description = COMPOUND_STRING( @@ -1545,6 +1603,7 @@ const struct Item gItemsInfo[] = "of a Pokémon\ninto " "a rare ability."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityPatch, .iconPic = gItemIcon_AbilityPatch, @@ -1555,13 +1614,14 @@ const struct Item gItemsInfo[] = [ITEM_LONELY_MINT] = { - .name = _("Lonely Mint"), + .name = ITEM_NAME("Lonely Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Attack,\nbut " "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LONELY, @@ -1572,13 +1632,14 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_MINT] = { - .name = _("Adamant Mint"), + .name = ITEM_NAME("Adamant Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Attack,\nbut " "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_ADAMANT, @@ -1589,13 +1650,14 @@ const struct Item gItemsInfo[] = [ITEM_NAUGHTY_MINT] = { - .name = _("Naughty Mint"), + .name = ITEM_NAME("Naughty Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Attack,\nbut " "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAUGHTY, @@ -1606,13 +1668,14 @@ const struct Item gItemsInfo[] = [ITEM_BRAVE_MINT] = { - .name = _("Brave Mint"), + .name = ITEM_NAME("Brave Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Attack,\nbut " "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BRAVE, @@ -1623,13 +1686,14 @@ const struct Item gItemsInfo[] = [ITEM_BOLD_MINT] = { - .name = _("Bold Mint"), + .name = ITEM_NAME("Bold Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Defense,\nbut " "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BOLD, @@ -1640,13 +1704,14 @@ const struct Item gItemsInfo[] = [ITEM_IMPISH_MINT] = { - .name = _("Impish Mint"), + .name = ITEM_NAME("Impish Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Defense,\nbut " "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_IMPISH, @@ -1657,13 +1722,14 @@ const struct Item gItemsInfo[] = [ITEM_LAX_MINT] = { - .name = _("Lax Mint"), + .name = ITEM_NAME("Lax Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Defense,\nbut " "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LAX, @@ -1674,13 +1740,14 @@ const struct Item gItemsInfo[] = [ITEM_RELAXED_MINT] = { - .name = _("Relaxed Mint"), + .name = ITEM_NAME("Relaxed Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Defense,\nbut " "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RELAXED, @@ -1691,13 +1758,14 @@ const struct Item gItemsInfo[] = [ITEM_MODEST_MINT] = { - .name = _("Modest Mint"), + .name = ITEM_NAME("Modest Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Atk,\nbut " "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MODEST, @@ -1708,13 +1776,14 @@ const struct Item gItemsInfo[] = [ITEM_MILD_MINT] = { - .name = _("Mild Mint"), + .name = ITEM_NAME("Mild Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Atk,\nbut " "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MILD, @@ -1725,13 +1794,14 @@ const struct Item gItemsInfo[] = [ITEM_RASH_MINT] = { - .name = _("Rash Mint"), + .name = ITEM_NAME("Rash Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Atk,\nbut " "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RASH, @@ -1742,13 +1812,14 @@ const struct Item gItemsInfo[] = [ITEM_QUIET_MINT] = { - .name = _("Quiet Mint"), + .name = ITEM_NAME("Quiet Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Atk,\nbut " "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_QUIET, @@ -1759,13 +1830,14 @@ const struct Item gItemsInfo[] = [ITEM_CALM_MINT] = { - .name = _("Calm Mint"), + .name = ITEM_NAME("Calm Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Def,\nbut " "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CALM, @@ -1776,13 +1848,14 @@ const struct Item gItemsInfo[] = [ITEM_GENTLE_MINT] = { - .name = _("Gentle Mint"), + .name = ITEM_NAME("Gentle Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Def,\nbut " "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_GENTLE, @@ -1793,13 +1866,14 @@ const struct Item gItemsInfo[] = [ITEM_CAREFUL_MINT] = { - .name = _("Careful Mint"), + .name = ITEM_NAME("Careful Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Def,\nbut " "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CAREFUL, @@ -1810,13 +1884,14 @@ const struct Item gItemsInfo[] = [ITEM_SASSY_MINT] = { - .name = _("Sassy Mint"), + .name = ITEM_NAME("Sassy Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Sp. Def,\nbut " "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SASSY, @@ -1827,13 +1902,14 @@ const struct Item gItemsInfo[] = [ITEM_TIMID_MINT] = { - .name = _("Timid Mint"), + .name = ITEM_NAME("Timid Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Speed, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_TIMID, @@ -1844,13 +1920,14 @@ const struct Item gItemsInfo[] = [ITEM_HASTY_MINT] = { - .name = _("Hasty Mint"), + .name = ITEM_NAME("Hasty Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Speed, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_HASTY, @@ -1861,13 +1938,14 @@ const struct Item gItemsInfo[] = [ITEM_JOLLY_MINT] = { - .name = _("Jolly Mint"), + .name = ITEM_NAME("Jolly Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Speed, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_JOLLY, @@ -1878,13 +1956,14 @@ const struct Item gItemsInfo[] = [ITEM_NAIVE_MINT] = { - .name = _("Naive Mint"), + .name = ITEM_NAME("Naive Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "ups Speed, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAIVE, @@ -1895,13 +1974,14 @@ const struct Item gItemsInfo[] = [ITEM_SERIOUS_MINT] = { - .name = _("Serious Mint"), + .name = ITEM_NAME("Serious Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It " "makes each\nstat " "grow equally."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SERIOUS, @@ -1914,14 +1994,15 @@ const struct Item gItemsInfo[] = [ITEM_RARE_CANDY] = { - .name = _("Rare Candy"), - .pluralName = _("Rare Candies"), + .name = ITEM_NAME("Rare Candy"), + .pluralName = ITEM_PLURAL_NAME("Rare Candies"), .price = (I_PRICE >= GEN_7) ? 10000 : 4800, .description = COMPOUND_STRING( "Raises the level " "of a Pokémon by\n" "one."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1932,8 +2013,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_XS] = { - .name = _("Exp. Candy XS"), - .pluralName = _("Exp. Candies XS"), + .name = ITEM_NAME("Exp. Candy XS"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies XS"), .price = 20, .holdEffectParam = EXP_100, .description = COMPOUND_STRING( @@ -1941,6 +2022,7 @@ const struct Item gItemsInfo[] = "amount of Exp.\nto " "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1951,8 +2033,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_S] = { - .name = _("Exp. Candy S"), - .pluralName = _("Exp. Candies S"), + .name = ITEM_NAME("Exp. Candy S"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies S"), .price = 240, .holdEffectParam = EXP_800, .description = COMPOUND_STRING( @@ -1960,6 +2042,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to " "a\nsingle Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1970,8 +2053,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_M] = { - .name = _("Exp. Candy M"), - .pluralName = _("Exp. Candies M"), + .name = ITEM_NAME("Exp. Candy M"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies M"), .price = 1000, .holdEffectParam = EXP_3000, .description = COMPOUND_STRING( @@ -1979,6 +2062,7 @@ const struct Item gItemsInfo[] = "amount of Exp.\nto " "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1989,8 +2073,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_L] = { - .name = _("Exp. Candy L"), - .pluralName = _("Exp. Candies L"), + .name = ITEM_NAME("Exp. Candy L"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies L"), .price = 3000, .holdEffectParam = EXP_10000, .description = COMPOUND_STRING( @@ -1998,6 +2082,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to " "a\nsingle Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -2008,8 +2093,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_XL] = { - .name = _("Exp. Candy XL"), - .pluralName = _("Exp. Candies XL"), + .name = ITEM_NAME("Exp. Candy XL"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies XL"), .price = 10000, .holdEffectParam = EXP_30000, .description = COMPOUND_STRING( @@ -2017,6 +2102,7 @@ const struct Item gItemsInfo[] = "amount of Exp.\nto " "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -2027,14 +2113,15 @@ const struct Item gItemsInfo[] = [ITEM_DYNAMAX_CANDY] = { - .name = _("Dynamax Candy"), - .pluralName = _("Dynamax Candies"), + .name = ITEM_NAME("Dynamax Candy"), + .pluralName = ITEM_PLURAL_NAME("Dynamax Candies"), .price = 0, .description = COMPOUND_STRING( "Raises the Dynamax " "Level of a\nsingle " "Pokémon by one."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_DynamaxCandy, .flingPower = 30, @@ -2046,7 +2133,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_FLUTE] = { - .name = _("Blue Flute"), + .name = ITEM_NAME("Blue Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 100, .description = COMPOUND_STRING( "A glass flute that " @@ -2054,6 +2141,7 @@ const struct Item gItemsInfo[] = "Pokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2065,7 +2153,7 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_FLUTE] = { - .name = _("Yellow Flute"), + .name = ITEM_NAME("Yellow Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 300, .description = COMPOUND_STRING( "A glass flute that " @@ -2073,6 +2161,7 @@ const struct Item gItemsInfo[] = "out of confusion."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2084,7 +2173,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_FLUTE] = { - .name = _("Red Flute"), + .name = ITEM_NAME("Red Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING( "A glass flute that " @@ -2092,6 +2181,7 @@ const struct Item gItemsInfo[] = "out of attraction."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2105,7 +2195,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_FLUTE] = { - .name = _("Black Flute"), + .name = ITEM_NAME("Black Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 400, .holdEffectParam = 50, .description = COMPOUND_STRING( @@ -2114,6 +2204,7 @@ const struct Item gItemsInfo[] = "Pokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2123,7 +2214,7 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_FLUTE] = { - .name = _("White Flute"), + .name = ITEM_NAME("White Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 500, .holdEffectParam = 150, .description = COMPOUND_STRING( @@ -2131,6 +2222,7 @@ const struct Item gItemsInfo[] = "lures wild\nPokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2142,7 +2234,7 @@ const struct Item gItemsInfo[] = [ITEM_REPEL] = { - .name = _("Repel"), + .name = ITEM_NAME("Repel"), .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -2150,6 +2242,7 @@ const struct Item gItemsInfo[] = "Pokémon for 100\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2159,7 +2252,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_REPEL] = { - .name = _("Super Repel"), + .name = ITEM_NAME("Super Repel"), .price = (I_PRICE >= GEN_7) ? 700 : 500, .holdEffectParam = 200, .description = COMPOUND_STRING( @@ -2167,6 +2260,7 @@ const struct Item gItemsInfo[] = "Pokémon for 200\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2176,7 +2270,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_REPEL] = { - .name = _("Max Repel"), + .name = ITEM_NAME("Max Repel"), .price = (I_PRICE >= GEN_7) ? 900 : 700, .holdEffectParam = 250, .description = COMPOUND_STRING( @@ -2184,6 +2278,7 @@ const struct Item gItemsInfo[] = "Pokémon for 250\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2193,7 +2288,7 @@ const struct Item gItemsInfo[] = [ITEM_LURE] = { - .name = _("Lure"), + .name = ITEM_NAME("Lure"), .price = 400, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -2201,6 +2296,7 @@ const struct Item gItemsInfo[] = "likely to\nappear " "for 100 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2211,7 +2307,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_LURE] = { - .name = _("Super Lure"), + .name = ITEM_NAME("Super Lure"), .price = 700, .holdEffectParam = 200, .description = COMPOUND_STRING( @@ -2219,6 +2315,7 @@ const struct Item gItemsInfo[] = "likely to\nappear " "for 200 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2229,7 +2326,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_LURE] = { - .name = _("Max Lure"), + .name = ITEM_NAME("Max Lure"), .price = 900, .holdEffectParam = 250, .description = COMPOUND_STRING( @@ -2237,6 +2334,7 @@ const struct Item gItemsInfo[] = "likely to\nappear " "for 250 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2247,7 +2345,7 @@ const struct Item gItemsInfo[] = [ITEM_ESCAPE_ROPE] = { - .name = _("Escape Rope"), + .name = ITEM_NAME("Escape Rope"), .description = COMPOUND_STRING( "Use to escape " "instantly from a " @@ -2259,6 +2357,7 @@ const struct Item gItemsInfo[] = #else .price = (I_PRICE >= GEN_7) ? 1000 : 550, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, #endif .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_EscapeRope, @@ -2271,7 +2370,7 @@ const struct Item gItemsInfo[] = [ITEM_X_ATTACK] = { - .name = _("X Attack"), + .name = ITEM_NAME("X Attack"), .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2285,6 +2384,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2296,7 +2396,7 @@ const struct Item gItemsInfo[] = [ITEM_X_DEFENSE] = { - .name = _("X Defense"), + .name = ITEM_NAME("X Defense"), .price = (I_PRICE >= GEN_7) ? 2000 : 550, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2310,6 +2410,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2321,7 +2422,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SP_ATK] = { - .name = _("X Sp. Atk"), + .name = ITEM_NAME("X Sp. Atk"), .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2335,6 +2436,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2346,7 +2448,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SP_DEF] = { - .name = _("X Sp. Def"), + .name = ITEM_NAME("X Sp. Def"), .price = (I_PRICE >= GEN_7) ? 2000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2360,6 +2462,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2371,7 +2474,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SPEED] = { - .name = _("X Speed"), + .name = ITEM_NAME("X Speed"), .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2385,6 +2488,7 @@ const struct Item gItemsInfo[] = "\nbattle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2396,8 +2500,8 @@ const struct Item gItemsInfo[] = [ITEM_X_ACCURACY] = { - .name = _("X Accuracy"), - .pluralName = _("X Accuracies"), + .name = ITEM_NAME("X Accuracy"), + .pluralName = ITEM_PLURAL_NAME("X Accuracies"), .price = (I_PRICE >= GEN_7) ? 1000 : 950, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2411,6 +2515,7 @@ const struct Item gItemsInfo[] = "\nduring one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2422,13 +2527,14 @@ const struct Item gItemsInfo[] = [ITEM_DIRE_HIT] = { - .name = _("Dire Hit"), + .name = ITEM_NAME("Dire Hit"), .price = (I_PRICE >= GEN_7) ? 1000 : 650, .description = COMPOUND_STRING( "Raises the " "critical-hit ratio " "\nduring one battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_FOCUS_ENERGY, @@ -2440,14 +2546,15 @@ const struct Item gItemsInfo[] = [ITEM_GUARD_SPEC] = { - .name = _("Guard Spec."), - .pluralName = _("Guard Specs."), + .name = ITEM_NAME("Guard Spec."), + .pluralName = ITEM_PLURAL_NAME("Guard Specs."), .price = (I_PRICE >= GEN_7) ? 1500 : 700, .description = COMPOUND_STRING( "Prevents stat " "reduction when " "used\nin battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_MIST, @@ -2459,10 +2566,11 @@ const struct Item gItemsInfo[] = [ITEM_POKE_DOLL] = { - .name = _("Poké Doll"), + .name = ITEM_NAME("Poké Doll"), .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE == GEN_7) ? 100 : 300), .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2473,10 +2581,11 @@ const struct Item gItemsInfo[] = [ITEM_FLUFFY_TAIL] = { - .name = _("Fluffy Tail"), + .name = ITEM_NAME("Fluffy Tail"), .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2487,10 +2596,11 @@ const struct Item gItemsInfo[] = [ITEM_POKE_TOY] = { - .name = _("Poké Toy"), + .name = ITEM_NAME("Poké Toy"), .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2501,14 +2611,15 @@ const struct Item gItemsInfo[] = [ITEM_MAX_MUSHROOMS] = { - .name = _("Max Mushrooms"), - .pluralName = _("Max Mushrooms"), + .name = ITEM_NAME("Max Mushrooms"), + .pluralName = ITEM_PLURAL_NAME("Max Mushrooms"), .price = 8000, .description = COMPOUND_STRING( "Raises every stat " "during one\nbattle " "by one stage."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_ALL_STATS, @@ -2521,13 +2632,14 @@ const struct Item gItemsInfo[] = [ITEM_BOTTLE_CAP] = { - .name = _("Bottle Cap"), + .name = ITEM_NAME("Bottle Cap"), .price = (I_PRICE >= GEN_9) ? 20000 : 5000, .description = COMPOUND_STRING( "A beautiful bottle " "cap that gives\noff " "a silver gleam."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2537,13 +2649,14 @@ const struct Item gItemsInfo[] = [ITEM_GOLD_BOTTLE_CAP] = { - .name = _("Gold Bottle Cap"), + .name = ITEM_NAME("Gold Bottle Cap"), .price = (I_PRICE >= GEN_9) ? 60000 : 10000, .description = COMPOUND_STRING( "A beautiful bottle " "cap that gives\noff " "a golden gleam."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2553,13 +2666,14 @@ const struct Item gItemsInfo[] = [ITEM_NUGGET] = { - .name = _("Nugget"), + .name = ITEM_NAME("Nugget"), .price = 10000 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A nugget of pure " "gold. Can be\nsold at " "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2569,13 +2683,14 @@ const struct Item gItemsInfo[] = [ITEM_BIG_NUGGET] = { - .name = _("Big Nugget"), + .name = ITEM_NAME("Big Nugget"), .price = (I_PRICE >= GEN_7) ? (40000 * TREASURE_FACTOR) : 20000, .description = COMPOUND_STRING( "A big nugget made " "of gold,\nsellable " "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -2585,13 +2700,14 @@ const struct Item gItemsInfo[] = [ITEM_TINY_MUSHROOM] = { - .name = _("Tiny Mushroom"), + .name = ITEM_NAME("Tiny Mushroom"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A plain mushroom " "that would sell " "\nat a cheap price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2601,10 +2717,11 @@ const struct Item gItemsInfo[] = [ITEM_BIG_MUSHROOM] = { - .name = _("Big Mushroom"), + .name = ITEM_NAME("Big Mushroom"), .price = 5000 * TREASURE_FACTOR, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2614,10 +2731,11 @@ const struct Item gItemsInfo[] = [ITEM_BALM_MUSHROOM] = { - .name = _("Balm Mushroom"), + .name = ITEM_NAME("Balm Mushroom"), .price = (I_PRICE >= GEN_7) ? 15000 * TREASURE_FACTOR: 12500, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2627,13 +2745,14 @@ const struct Item gItemsInfo[] = [ITEM_PEARL] = { - .name = _("Pearl"), + .name = ITEM_NAME("Pearl"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR: 1400, .description = COMPOUND_STRING( "A pretty pearl " "that would sell at\na " "cheap price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2643,13 +2762,14 @@ const struct Item gItemsInfo[] = [ITEM_BIG_PEARL] = { - .name = _("Big Pearl"), + .name = ITEM_NAME("Big Pearl"), .price = (I_PRICE >= GEN_7) ? 8000 * TREASURE_FACTOR: 7500, .description = COMPOUND_STRING( "A lovely large pearl " "that would\nsell at a " "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2659,13 +2779,14 @@ const struct Item gItemsInfo[] = [ITEM_PEARL_STRING] = { - .name = _("Pearl String"), + .name = ITEM_NAME("Pearl String"), .price = (I_PRICE >= GEN_8) ? 15000 * TREASURE_FACTOR: ((I_PRICE == GEN_7) ? 30000 : 15000), .description = COMPOUND_STRING( "Very large pearls " "that would sell\nat a " "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2675,14 +2796,15 @@ const struct Item gItemsInfo[] = [ITEM_STARDUST] = { - .name = _("Stardust"), - .pluralName = _("Stardust"), + .name = ITEM_NAME("Stardust"), + .pluralName = ITEM_PLURAL_NAME("Stardust"), .price = (I_PRICE >= GEN_7) ? 3000 * TREASURE_FACTOR: 2000, .description = COMPOUND_STRING( "Beautiful red sand. " "Can be sold\nat a " "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2692,13 +2814,14 @@ const struct Item gItemsInfo[] = [ITEM_STAR_PIECE] = { - .name = _("Star Piece"), + .name = ITEM_NAME("Star Piece"), .price = (I_PRICE >= GEN_7) ? 12000 * TREASURE_FACTOR: 9800, .description = COMPOUND_STRING( "A red gem shard. " "It would sell\nfor a " "very high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2708,13 +2831,14 @@ const struct Item gItemsInfo[] = [ITEM_COMET_SHARD] = { - .name = _("Comet Shard"), + .name = ITEM_NAME("Comet Shard"), .price = (I_PRICE <= GEN_5) ? 0 : ((I_PRICE == GEN_6) ? 30000 : ((I_PRICE == GEN_7) ? 60000 : 25000 * TREASURE_FACTOR)), .description = COMPOUND_STRING( "A comet's shard. " "It would sell\nfor a " "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2724,14 +2848,15 @@ const struct Item gItemsInfo[] = [ITEM_SHOAL_SALT] = { - .name = _("Shoal Salt"), - .pluralName = _("Shoal Salt"), + .name = ITEM_NAME("Shoal Salt"), + .pluralName = ITEM_PLURAL_NAME("Shoal Salt"), .price = 20, .description = COMPOUND_STRING( "Salt obtained from " "deep inside\nthe " "Shoal Cave."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2741,13 +2866,14 @@ const struct Item gItemsInfo[] = [ITEM_SHOAL_SHELL] = { - .name = _("Shoal Shell"), + .name = ITEM_NAME("Shoal Shell"), .price = 20, .description = COMPOUND_STRING( "A seashell found " "deep inside the " "\nShoal Cave."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2757,10 +2883,11 @@ const struct Item gItemsInfo[] = [ITEM_RED_SHARD] = { - .name = _("Red Shard"), + .name = ITEM_NAME("Red Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2770,10 +2897,11 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_SHARD] = { - .name = _("Blue Shard"), + .name = ITEM_NAME("Blue Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2783,10 +2911,11 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_SHARD] = { - .name = _("Yellow Shard"), + .name = ITEM_NAME("Yellow Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2796,10 +2925,11 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_SHARD] = { - .name = _("Green Shard"), + .name = ITEM_NAME("Green Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2809,13 +2939,14 @@ const struct Item gItemsInfo[] = [ITEM_HEART_SCALE] = { - .name = _("Heart Scale"), + .name = ITEM_NAME("Heart Scale"), .price = 100, .description = COMPOUND_STRING( "A lovely scale. " "It is coveted by " "\ncollectors."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2825,14 +2956,15 @@ const struct Item gItemsInfo[] = [ITEM_HONEY] = { - .name = _("Honey"), - .pluralName = _("Honey"), + .name = ITEM_NAME("Honey"), + .pluralName = ITEM_PLURAL_NAME("Honey"), .price = (I_PRICE < GEN_5) ? 100 : ((I_PRICE < GEN_8) ? 300 : 900), .description = COMPOUND_STRING( "Sweet honey that " "attracts wild " "\nPokémon when used."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_Honey, .flingPower = 30, @@ -2842,13 +2974,14 @@ const struct Item gItemsInfo[] = [ITEM_RARE_BONE] = { - .name = _("Rare Bone"), + .name = ITEM_NAME("Rare Bone"), .price = (I_PRICE >= GEN_7) ? 5000 * TREASURE_FACTOR: 10000, .description = COMPOUND_STRING( "A very rare bone. " "It can be sold\nat " "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -2858,13 +2991,14 @@ const struct Item gItemsInfo[] = [ITEM_ODD_KEYSTONE] = { - .name = _("Odd Keystone"), + .name = ITEM_NAME("Odd Keystone"), .price = 2100, .description = COMPOUND_STRING( "Voices can be heard " "from this odd\nstone " "occasionally."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -2874,13 +3008,14 @@ const struct Item gItemsInfo[] = [ITEM_PRETTY_FEATHER] = { - .name = _("Pretty Feather"), + .name = ITEM_NAME("Pretty Feather"), .price = (I_PRICE >= GEN_7) ? 1000 * TREASURE_FACTOR: 200, .description = COMPOUND_STRING( "A beautiful yet " "plain feather\nthat " "does nothing."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 20, @@ -2890,13 +3025,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_COPPER] = { - .name = _("Relic Copper"), + .name = ITEM_NAME("Relic Copper"), .price = 0, .description = COMPOUND_STRING( "A copper coin used " "long ago. It\nsells " "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2906,13 +3042,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_SILVER] = { - .name = _("Relic Silver"), + .name = ITEM_NAME("Relic Silver"), .price = 0, .description = COMPOUND_STRING( "A silver coin used " "long ago. It\nsells " "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2922,13 +3059,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_GOLD] = { - .name = _("Relic Gold"), + .name = ITEM_NAME("Relic Gold"), .price = 0, .description = COMPOUND_STRING( "A gold coin used " "long ago. It\nsells " "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2938,13 +3076,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_VASE] = { - .name = _("Relic Vase"), + .name = ITEM_NAME("Relic Vase"), .price = 0, .description = COMPOUND_STRING( "A vase made long " "ago. It sells at\n" "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2954,13 +3093,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_BAND] = { - .name = _("Relic Band"), + .name = ITEM_NAME("Relic Band"), .price = 0, .description = COMPOUND_STRING( "An old bracelet. " "It sells at a " "\nhigh price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2970,13 +3110,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_STATUE] = { - .name = _("Relic Statue"), + .name = ITEM_NAME("Relic Statue"), .price = 0, .description = COMPOUND_STRING( "An old statue. " "It sells at a " "high\nprice."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2986,13 +3127,14 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_CROWN] = { - .name = _("Relic Crown"), + .name = ITEM_NAME("Relic Crown"), .price = 0, .description = COMPOUND_STRING( "An old crown. " "It sells at a " "high\nprice."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3002,13 +3144,14 @@ const struct Item gItemsInfo[] = [ITEM_STRANGE_SOUVENIR] = { - .name = _("Strange Souvenir"), + .name = ITEM_NAME("Strange Souvenir"), .price = (I_PRICE >= GEN_7) ? 3000 : 10, .description = COMPOUND_STRING( "An ornament that " "depicts a\nPokémon " "from Alola."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3020,7 +3163,7 @@ const struct Item gItemsInfo[] = [ITEM_HELIX_FOSSIL] = { - .name = _("Helix Fossil"), + .name = ITEM_NAME("Helix Fossil"), .description = COMPOUND_STRING( "A piece of an " "ancient marine " @@ -3028,6 +3171,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3042,7 +3186,7 @@ const struct Item gItemsInfo[] = [ITEM_DOME_FOSSIL] = { - .name = _("Dome Fossil"), + .name = ITEM_NAME("Dome Fossil"), .description = COMPOUND_STRING( "A piece of an " "ancient marine " @@ -3050,6 +3194,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3064,7 +3209,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_AMBER] = { - .name = _("Old Amber"), + .name = ITEM_NAME("Old Amber"), .description = COMPOUND_STRING( "A stone containing " "the genes of\nan " @@ -3072,6 +3217,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3086,11 +3232,12 @@ const struct Item gItemsInfo[] = [ITEM_ROOT_FOSSIL] = { - .name = _("Root Fossil"), + .name = ITEM_NAME("Root Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3105,11 +3252,12 @@ const struct Item gItemsInfo[] = [ITEM_CLAW_FOSSIL] = { - .name = _("Claw Fossil"), + .name = ITEM_NAME("Claw Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3124,13 +3272,14 @@ const struct Item gItemsInfo[] = [ITEM_ARMOR_FOSSIL] = { - .name = _("Armor Fossil"), + .name = ITEM_NAME("Armor Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's head."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3140,13 +3289,14 @@ const struct Item gItemsInfo[] = [ITEM_SKULL_FOSSIL] = { - .name = _("Skull Fossil"), + .name = ITEM_NAME("Skull Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's collar."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3156,13 +3306,14 @@ const struct Item gItemsInfo[] = [ITEM_COVER_FOSSIL] = { - .name = _("Cover Fossil"), + .name = ITEM_NAME("Cover Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's back."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3172,13 +3323,14 @@ const struct Item gItemsInfo[] = [ITEM_PLUME_FOSSIL] = { - .name = _("Plume Fossil"), + .name = ITEM_NAME("Plume Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's wing."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3188,13 +3340,14 @@ const struct Item gItemsInfo[] = [ITEM_JAW_FOSSIL] = { - .name = _("Jaw Fossil"), + .name = ITEM_NAME("Jaw Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's large jaw."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3204,13 +3357,14 @@ const struct Item gItemsInfo[] = [ITEM_SAIL_FOSSIL] = { - .name = _("Sail Fossil"), + .name = ITEM_NAME("Sail Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a " "prehistoric Poké-" "\nmon's skin sail."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3220,13 +3374,14 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_BIRD] = { - .name = _("Fossilized Bird"), + .name = ITEM_NAME("Fossilized Bird"), .price = 5000, .description = COMPOUND_STRING( "A fossil of an " "ancient, sky-" "\nsoaring Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3236,11 +3391,12 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_FISH] = { - .name = _("Fossilized Fish"), - .pluralName = _("Fossilized Fishes"), + .name = ITEM_NAME("Fossilized Fish"), + .pluralName = ITEM_PLURAL_NAME("Fossilized Fishes"), .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3250,13 +3406,14 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_DRAKE] = { - .name = _("Fossilized Drake"), + .name = ITEM_NAME("Fossilized Drake"), .price = 5000, .description = COMPOUND_STRING( "A fossil of an " "ancient, land-" "\nroaming Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3266,10 +3423,11 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_DINO] = { - .name = _("Fossilized Dino"), + .name = ITEM_NAME("Fossilized Dino"), .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3281,8 +3439,8 @@ const struct Item gItemsInfo[] = [ITEM_GROWTH_MULCH] = { - .name = _("Growth Mulch"), - .pluralName = _("Growth Mulch"), + .name = ITEM_NAME("Growth Mulch"), + .pluralName = ITEM_PLURAL_NAME("Growth Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3293,6 +3451,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GROWTH_MULCH), @@ -3303,8 +3462,8 @@ const struct Item gItemsInfo[] = [ITEM_DAMP_MULCH] = { - .name = _("Damp Mulch"), - .pluralName = _("Damp Mulch"), + .name = ITEM_NAME("Damp Mulch"), + .pluralName = ITEM_PLURAL_NAME("Damp Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3315,6 +3474,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_DAMP_MULCH), @@ -3325,8 +3485,8 @@ const struct Item gItemsInfo[] = [ITEM_STABLE_MULCH] = { - .name = _("Stable Mulch"), - .pluralName = _("Stable Mulch"), + .name = ITEM_NAME("Stable Mulch"), + .pluralName = ITEM_PLURAL_NAME("Stable Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3337,6 +3497,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_STABLE_MULCH), @@ -3347,8 +3508,8 @@ const struct Item gItemsInfo[] = [ITEM_GOOEY_MULCH] = { - .name = _("Gooey Mulch"), - .pluralName = _("Gooey Mulch"), + .name = ITEM_NAME("Gooey Mulch"), + .pluralName = ITEM_PLURAL_NAME("Gooey Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3359,6 +3520,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GOOEY_MULCH), @@ -3369,8 +3531,8 @@ const struct Item gItemsInfo[] = [ITEM_RICH_MULCH] = { - .name = _("Rich Mulch"), - .pluralName = _("Rich Mulch"), + .name = ITEM_NAME("Rich Mulch"), + .pluralName = ITEM_PLURAL_NAME("Rich Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3381,6 +3543,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_RICH_MULCH), @@ -3391,8 +3554,8 @@ const struct Item gItemsInfo[] = [ITEM_SURPRISE_MULCH] = { - .name = _("Surprise Mulch"), - .pluralName = _("Surprise Mulch"), + .name = ITEM_NAME("Surprise Mulch"), + .pluralName = ITEM_PLURAL_NAME("Surprise Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3403,6 +3566,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_SURPRISE_MULCH), @@ -3413,8 +3577,8 @@ const struct Item gItemsInfo[] = [ITEM_BOOST_MULCH] = { - .name = _("Boost Mulch"), - .pluralName = _("Boost Mulch"), + .name = ITEM_NAME("Boost Mulch"), + .pluralName = ITEM_PLURAL_NAME("Boost Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3425,6 +3589,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_BOOST_MULCH), @@ -3435,8 +3600,8 @@ const struct Item gItemsInfo[] = [ITEM_AMAZE_MULCH] = { - .name = _("Amaze Mulch"), - .pluralName = _("Amaze Mulch"), + .name = ITEM_NAME("Amaze Mulch"), + .pluralName = ITEM_PLURAL_NAME("Amaze Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3447,6 +3612,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_AMAZE_MULCH), @@ -3459,13 +3625,14 @@ const struct Item gItemsInfo[] = [ITEM_RED_APRICORN] = { - .name = _("Red Apricorn"), + .name = ITEM_NAME("Red Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A red apricorn. " "It assails your " "\nnostrils."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedApricorn, @@ -3474,13 +3641,14 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_APRICORN] = { - .name = _("Blue Apricorn"), + .name = ITEM_NAME("Blue Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A blue apricorn. " "It smells a bit " "\nlike grass."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueApricorn, @@ -3489,13 +3657,14 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_APRICORN] = { - .name = _("Yellow Apricorn"), + .name = ITEM_NAME("Yellow Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A yellow apricorn. " "It has an\ninvigor-" "ating scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_YellowApricorn, @@ -3504,13 +3673,14 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_APRICORN] = { - .name = _("Green Apricorn"), + .name = ITEM_NAME("Green Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A green apricorn. " "It has a\nstrange, " "aromatic scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GreenApricorn, @@ -3519,13 +3689,14 @@ const struct Item gItemsInfo[] = [ITEM_PINK_APRICORN] = { - .name = _("Pink Apricorn"), + .name = ITEM_NAME("Pink Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A pink apricorn. " "It has a nice, " "\nsweet scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PinkApricorn, @@ -3534,13 +3705,14 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_APRICORN] = { - .name = _("White Apricorn"), + .name = ITEM_NAME("White Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A white apricorn. " "It doesn't\nsmell " "like anything."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WhiteApricorn, @@ -3549,13 +3721,14 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_APRICORN] = { - .name = _("Black Apricorn"), + .name = ITEM_NAME("Black Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A black apricorn. " "It has an inde-" "\nscribable scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlackApricorn, @@ -3564,13 +3737,14 @@ const struct Item gItemsInfo[] = [ITEM_WISHING_PIECE] = { - .name = _("Wishing Piece"), + .name = ITEM_NAME("Wishing Piece"), .price = 20, .description = COMPOUND_STRING( "Throw into a " "{PKMN} Den to\nattract " "Dynamax Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo .flingPower = 50, @@ -3580,13 +3754,14 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_TWIG] = { - .name = _("Galarica Twig"), + .name = ITEM_NAME("Galarica Twig"), .price = 20 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A twig from a tree " "in Galar\ncalled " "Galarica."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3596,14 +3771,15 @@ const struct Item gItemsInfo[] = [ITEM_ARMORITE_ORE] = { - .name = _("Armorite Ore"), - .pluralName = _("Armorite Ore"), + .name = ITEM_NAME("Armorite Ore"), + .pluralName = ITEM_PLURAL_NAME("Armorite Ore"), .price = 20, .description = COMPOUND_STRING( "A rare ore. Can be " "found in the\nIsle " "of Armor at Galar."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3613,14 +3789,15 @@ const struct Item gItemsInfo[] = [ITEM_DYNITE_ORE] = { - .name = _("Dynite Ore"), - .pluralName = _("Dynite Ore"), + .name = ITEM_NAME("Dynite Ore"), + .pluralName = ITEM_PLURAL_NAME("Dynite Ore"), .price = 20, .description = COMPOUND_STRING( "A mysterious ore. " "It can be found\nin " "Galar's Max Lair."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3632,14 +3809,15 @@ const struct Item gItemsInfo[] = [ITEM_ORANGE_MAIL] = { - .name = _("Orange Mail"), - .pluralName = _("Orange Mail"), + .name = ITEM_NAME("Orange Mail"), + .pluralName = ITEM_PLURAL_NAME("Orange Mail"), .price = 50, .description = COMPOUND_STRING( "A Zigzagoon-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_ORANGE_MAIL), @@ -3649,14 +3827,15 @@ const struct Item gItemsInfo[] = [ITEM_HARBOR_MAIL] = { - .name = _("Harbor Mail"), - .pluralName = _("Harbor Mail"), + .name = ITEM_NAME("Harbor Mail"), + .pluralName = ITEM_PLURAL_NAME("Harbor Mail"), .price = 50, .description = COMPOUND_STRING( "A Wingull-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_HARBOR_MAIL), @@ -3666,14 +3845,15 @@ const struct Item gItemsInfo[] = [ITEM_GLITTER_MAIL] = { - .name = _("Glitter Mail"), - .pluralName = _("Glitter Mail"), + .name = ITEM_NAME("Glitter Mail"), + .pluralName = ITEM_PLURAL_NAME("Glitter Mail"), .price = 50, .description = COMPOUND_STRING( "A Pikachu-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_GLITTER_MAIL), @@ -3683,14 +3863,15 @@ const struct Item gItemsInfo[] = [ITEM_MECH_MAIL] = { - .name = _("Mech Mail"), - .pluralName = _("Mech Mail"), + .name = ITEM_NAME("Mech Mail"), + .pluralName = ITEM_PLURAL_NAME("Mech Mail"), .price = 50, .description = COMPOUND_STRING( "A Magnemite-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_MECH_MAIL), @@ -3700,14 +3881,15 @@ const struct Item gItemsInfo[] = [ITEM_WOOD_MAIL] = { - .name = _("Wood Mail"), - .pluralName = _("Wood Mail"), + .name = ITEM_NAME("Wood Mail"), + .pluralName = ITEM_PLURAL_NAME("Wood Mail"), .price = 50, .description = COMPOUND_STRING( "A Slakoth-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WOOD_MAIL), @@ -3717,14 +3899,15 @@ const struct Item gItemsInfo[] = [ITEM_WAVE_MAIL] = { - .name = _("Wave Mail"), - .pluralName = _("Wave Mail"), + .name = ITEM_NAME("Wave Mail"), + .pluralName = ITEM_PLURAL_NAME("Wave Mail"), .price = 50, .description = COMPOUND_STRING( "A Wailmer-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WAVE_MAIL), @@ -3734,11 +3917,12 @@ const struct Item gItemsInfo[] = [ITEM_BEAD_MAIL] = { - .name = _("Bead Mail"), - .pluralName = _("Bead Mail"), + .name = ITEM_NAME("Bead Mail"), + .pluralName = ITEM_PLURAL_NAME("Bead Mail"), .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_BEAD_MAIL), @@ -3748,14 +3932,15 @@ const struct Item gItemsInfo[] = [ITEM_SHADOW_MAIL] = { - .name = _("Shadow Mail"), - .pluralName = _("Shadow Mail"), + .name = ITEM_NAME("Shadow Mail"), + .pluralName = ITEM_PLURAL_NAME("Shadow Mail"), .price = 50, .description = COMPOUND_STRING( "A Duskull-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_SHADOW_MAIL), @@ -3765,14 +3950,15 @@ const struct Item gItemsInfo[] = [ITEM_TROPIC_MAIL] = { - .name = _("Tropic Mail"), - .pluralName = _("Tropic Mail"), + .name = ITEM_NAME("Tropic Mail"), + .pluralName = ITEM_PLURAL_NAME("Tropic Mail"), .price = 50, .description = COMPOUND_STRING( "A Bellossom-print " "Mail to be held\nby " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_TROPIC_MAIL), @@ -3782,11 +3968,12 @@ const struct Item gItemsInfo[] = [ITEM_DREAM_MAIL] = { - .name = _("Dream Mail"), - .pluralName = _("Dream Mail"), + .name = ITEM_NAME("Dream Mail"), + .pluralName = ITEM_PLURAL_NAME("Dream Mail"), .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_DREAM_MAIL), @@ -3796,14 +3983,15 @@ const struct Item gItemsInfo[] = [ITEM_FAB_MAIL] = { - .name = _("Fab Mail"), - .pluralName = _("Fab Mail"), + .name = ITEM_NAME("Fab Mail"), + .pluralName = ITEM_PLURAL_NAME("Fab Mail"), .price = 50, .description = COMPOUND_STRING( "A gorgeous-print " "Mail to be held " "\nby a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_FAB_MAIL), @@ -3813,14 +4001,15 @@ const struct Item gItemsInfo[] = [ITEM_RETRO_MAIL] = { - .name = _("Retro Mail"), - .pluralName = _("Retro Mail"), + .name = ITEM_NAME("Retro Mail"), + .pluralName = ITEM_PLURAL_NAME("Retro Mail"), .price = 50, .description = COMPOUND_STRING( "Mail featuring the " "drawings of\nthree " "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_RETRO_MAIL), @@ -3832,10 +4021,11 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_STONE] = { - .name = _("Fire Stone"), + .name = ITEM_NAME("Fire Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3846,10 +4036,11 @@ const struct Item gItemsInfo[] = [ITEM_WATER_STONE] = { - .name = _("Water Stone"), + .name = ITEM_NAME("Water Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3860,10 +4051,11 @@ const struct Item gItemsInfo[] = [ITEM_THUNDER_STONE] = { - .name = _("Thunder Stone"), + .name = ITEM_NAME("Thunder Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3874,10 +4066,11 @@ const struct Item gItemsInfo[] = [ITEM_LEAF_STONE] = { - .name = _("Leaf Stone"), + .name = ITEM_NAME("Leaf Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3888,10 +4081,11 @@ const struct Item gItemsInfo[] = [ITEM_ICE_STONE] = { - .name = _("Ice Stone"), + .name = ITEM_NAME("Ice Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3902,10 +4096,11 @@ const struct Item gItemsInfo[] = [ITEM_SUN_STONE] = { - .name = _("Sun Stone"), + .name = ITEM_NAME("Sun Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3916,10 +4111,11 @@ const struct Item gItemsInfo[] = [ITEM_MOON_STONE] = { - .name = _("Moon Stone"), + .name = ITEM_NAME("Moon Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3930,10 +4126,11 @@ const struct Item gItemsInfo[] = [ITEM_SHINY_STONE] = { - .name = _("Shiny Stone"), + .name = ITEM_NAME("Shiny Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3944,10 +4141,11 @@ const struct Item gItemsInfo[] = [ITEM_DUSK_STONE] = { - .name = _("Dusk Stone"), + .name = ITEM_NAME("Dusk Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3958,10 +4156,11 @@ const struct Item gItemsInfo[] = [ITEM_DAWN_STONE] = { - .name = _("Dawn Stone"), + .name = ITEM_NAME("Dawn Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3972,13 +4171,14 @@ const struct Item gItemsInfo[] = [ITEM_SWEET_APPLE] = { - .name = _("Sweet Apple"), + .name = ITEM_NAME("Sweet Apple"), .price = 2200, .description = COMPOUND_STRING( "A very sweet apple " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3989,13 +4189,14 @@ const struct Item gItemsInfo[] = [ITEM_TART_APPLE] = { - .name = _("Tart Apple"), + .name = ITEM_NAME("Tart Apple"), .price = 2200, .description = COMPOUND_STRING( "A very tart apple " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4006,13 +4207,14 @@ const struct Item gItemsInfo[] = [ITEM_CRACKED_POT] = { - .name = _("Cracked Pot"), + .name = ITEM_NAME("Cracked Pot"), .price = 1600, .description = COMPOUND_STRING( "A cracked teapot " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4023,13 +4225,14 @@ const struct Item gItemsInfo[] = [ITEM_CHIPPED_POT] = { - .name = _("Chipped Pot"), + .name = ITEM_NAME("Chipped Pot"), .price = 38000, .description = COMPOUND_STRING( "A chipped teapot " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4040,13 +4243,14 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_CUFF] = { - .name = _("Galarica Cuff"), + .name = ITEM_NAME("Galarica Cuff"), .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING( "A cuff from Galar " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4057,14 +4261,15 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_WREATH] = { - .name = _("Galarica Wreath"), - .pluralName = _("Galarica Wreathes"), + .name = ITEM_NAME("Galarica Wreath"), + .pluralName = ITEM_PLURAL_NAME("Galarica Wreathes"), .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING( "A wreath made in " "Galar. Makes\nsome " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4075,7 +4280,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_SCALE] = { - .name = _("Dragon Scale"), + .name = ITEM_NAME("Dragon Scale"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_DRAGON_SCALE, .holdEffectParam = 10, @@ -4084,6 +4289,7 @@ const struct Item gItemsInfo[] = "held by Dragon-" "\ntype Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4094,13 +4300,14 @@ const struct Item gItemsInfo[] = [ITEM_UPGRADE] = { - .name = _("Upgrade"), + .name = ITEM_NAME("Upgrade"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_UPGRADE, .description = COMPOUND_STRING( "A peculiar box made " "by Silph Co."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4111,13 +4318,14 @@ const struct Item gItemsInfo[] = [ITEM_PROTECTOR] = { - .name = _("Protector"), + .name = ITEM_NAME("Protector"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain " "Pokémon. It's\nstiff " "and heavy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4128,13 +4336,14 @@ const struct Item gItemsInfo[] = [ITEM_ELECTIRIZER] = { - .name = _("Electirizer"), + .name = ITEM_NAME("Electirizer"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain " "Pokémon. It's\nfull " "of electric energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4145,13 +4354,14 @@ const struct Item gItemsInfo[] = [ITEM_MAGMARIZER] = { - .name = _("Magmarizer"), + .name = ITEM_NAME("Magmarizer"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain " "Pokémon. It's\nfull " "of magma energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4162,13 +4372,14 @@ const struct Item gItemsInfo[] = [ITEM_DUBIOUS_DISC] = { - .name = _("Dubious Disc"), + .name = ITEM_NAME("Dubious Disc"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A clear device " "overflowing with " "\ndubious data."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4179,14 +4390,15 @@ const struct Item gItemsInfo[] = [ITEM_REAPER_CLOTH] = { - .name = _("Reaper Cloth"), - .pluralName = _("Reaper Cloths"), + .name = ITEM_NAME("Reaper Cloth"), + .pluralName = ITEM_PLURAL_NAME("Reaper Cloths"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain " "Pokémon.\nImbued " "with spirit energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4197,13 +4409,14 @@ const struct Item gItemsInfo[] = [ITEM_PRISM_SCALE] = { - .name = _("Prism Scale"), + .name = ITEM_NAME("Prism Scale"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 500), .description = COMPOUND_STRING( "A mysterious scale " "that evolves a\n" "certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4214,14 +4427,15 @@ const struct Item gItemsInfo[] = [ITEM_WHIPPED_DREAM] = { - .name = _("Whipped Dream"), - .pluralName = _("Whipped Dream"), + .name = ITEM_NAME("Whipped Dream"), + .pluralName = ITEM_PLURAL_NAME("Whipped Dream"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A soft and sweet " "treat loved by " "a\ncertain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4232,13 +4446,14 @@ const struct Item gItemsInfo[] = [ITEM_SACHET] = { - .name = _("Sachet"), + .name = ITEM_NAME("Sachet"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A sachet of strong " "perfumes,\nloved by " "a certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4249,13 +4464,14 @@ const struct Item gItemsInfo[] = [ITEM_OVAL_STONE] = { - .name = _("Oval Stone"), + .name = ITEM_NAME("Oval Stone"), .price = (I_PRICE >= GEN_7) ? 2000 : 2100, .description = COMPOUND_STRING( "Peculiar stone " "that evolves a " "\ncertain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4266,13 +4482,14 @@ const struct Item gItemsInfo[] = [ITEM_STRAWBERRY_SWEET] = { - .name = _("Strawberry Sweet"), + .name = ITEM_NAME("Strawberry Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "Strawberry-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4282,13 +4499,14 @@ const struct Item gItemsInfo[] = [ITEM_LOVE_SWEET] = { - .name = _("Love Sweet"), + .name = ITEM_NAME("Love Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A heart-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4298,13 +4516,14 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_SWEET] = { - .name = _("Berry Sweet"), + .name = ITEM_NAME("Berry Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A berry-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4314,13 +4533,14 @@ const struct Item gItemsInfo[] = [ITEM_CLOVER_SWEET] = { - .name = _("Clover Sweet"), + .name = ITEM_NAME("Clover Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A clover-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4330,13 +4550,14 @@ const struct Item gItemsInfo[] = [ITEM_FLOWER_SWEET] = { - .name = _("Flower Sweet"), + .name = ITEM_NAME("Flower Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A flower-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4346,13 +4567,14 @@ const struct Item gItemsInfo[] = [ITEM_STAR_SWEET] = { - .name = _("Star Sweet"), + .name = ITEM_NAME("Star Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A star-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4362,13 +4584,14 @@ const struct Item gItemsInfo[] = [ITEM_RIBBON_SWEET] = { - .name = _("Ribbon Sweet"), + .name = ITEM_NAME("Ribbon Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A ribbon-shaped " "sweet loved by " "\nMilcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4378,7 +4601,7 @@ const struct Item gItemsInfo[] = [ITEM_EVERSTONE] = { - .name = _("Everstone"), + .name = ITEM_NAME("Everstone"), .price = (I_PRICE >= GEN_7) ? 3000 : 200, .holdEffect = HOLD_EFFECT_PREVENT_EVOLVE, .description = COMPOUND_STRING( @@ -4386,6 +4609,7 @@ const struct Item gItemsInfo[] = "item that\nprevents " "evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -4397,11 +4621,12 @@ const struct Item gItemsInfo[] = [ITEM_RED_NECTAR] = { - .name = _("Red Nectar"), + .name = ITEM_NAME("Red Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4411,11 +4636,12 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_NECTAR] = { - .name = _("Yellow Nectar"), + .name = ITEM_NAME("Yellow Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4425,11 +4651,12 @@ const struct Item gItemsInfo[] = [ITEM_PINK_NECTAR] = { - .name = _("Pink Nectar"), + .name = ITEM_NAME("Pink Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4439,11 +4666,12 @@ const struct Item gItemsInfo[] = [ITEM_PURPLE_NECTAR] = { - .name = _("Purple Nectar"), + .name = ITEM_NAME("Purple Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4455,7 +4683,7 @@ const struct Item gItemsInfo[] = [ITEM_FLAME_PLATE] = { - .name = _("Flame Plate"), + .name = ITEM_NAME("Flame Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4464,6 +4692,7 @@ const struct Item gItemsInfo[] = "the power of " "\nFire-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4474,7 +4703,7 @@ const struct Item gItemsInfo[] = [ITEM_SPLASH_PLATE] = { - .name = _("Splash Plate"), + .name = ITEM_NAME("Splash Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4483,6 +4712,7 @@ const struct Item gItemsInfo[] = "the power of " "\nWater-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4493,7 +4723,7 @@ const struct Item gItemsInfo[] = [ITEM_ZAP_PLATE] = { - .name = _("Zap Plate"), + .name = ITEM_NAME("Zap Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4502,6 +4732,7 @@ const struct Item gItemsInfo[] = "the power of\nElec-" "tric-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4512,7 +4743,7 @@ const struct Item gItemsInfo[] = [ITEM_MEADOW_PLATE] = { - .name = _("Meadow Plate"), + .name = ITEM_NAME("Meadow Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4521,6 +4752,7 @@ const struct Item gItemsInfo[] = "the power of " "\nGrass-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4531,7 +4763,7 @@ const struct Item gItemsInfo[] = [ITEM_ICICLE_PLATE] = { - .name = _("Icicle Plate"), + .name = ITEM_NAME("Icicle Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4540,6 +4772,7 @@ const struct Item gItemsInfo[] = "the power of " "\nIce-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4550,7 +4783,7 @@ const struct Item gItemsInfo[] = [ITEM_FIST_PLATE] = { - .name = _("Fist Plate"), + .name = ITEM_NAME("Fist Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4559,6 +4792,7 @@ const struct Item gItemsInfo[] = "the power of\nFight-" "ing-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4569,7 +4803,7 @@ const struct Item gItemsInfo[] = [ITEM_TOXIC_PLATE] = { - .name = _("Toxic Plate"), + .name = ITEM_NAME("Toxic Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4578,6 +4812,7 @@ const struct Item gItemsInfo[] = "the power of " "\nPoison-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -4588,7 +4823,7 @@ const struct Item gItemsInfo[] = [ITEM_EARTH_PLATE] = { - .name = _("Earth Plate"), + .name = ITEM_NAME("Earth Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4597,6 +4832,7 @@ const struct Item gItemsInfo[] = "the power of " "\nGround-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -4607,7 +4843,7 @@ const struct Item gItemsInfo[] = [ITEM_SKY_PLATE] = { - .name = _("Sky Plate"), + .name = ITEM_NAME("Sky Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4616,6 +4852,7 @@ const struct Item gItemsInfo[] = "the power of " "\nFlying-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -4626,7 +4863,7 @@ const struct Item gItemsInfo[] = [ITEM_MIND_PLATE] = { - .name = _("Mind Plate"), + .name = ITEM_NAME("Mind Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4635,6 +4872,7 @@ const struct Item gItemsInfo[] = "the power of\nPsy " "chic-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -4645,7 +4883,7 @@ const struct Item gItemsInfo[] = [ITEM_INSECT_PLATE] = { - .name = _("Insect Plate"), + .name = ITEM_NAME("Insect Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4654,6 +4892,7 @@ const struct Item gItemsInfo[] = "the power of " "\nBug-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -4664,7 +4903,7 @@ const struct Item gItemsInfo[] = [ITEM_STONE_PLATE] = { - .name = _("Stone Plate"), + .name = ITEM_NAME("Stone Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4673,6 +4912,7 @@ const struct Item gItemsInfo[] = "the power of " "\nRock-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -4683,7 +4923,7 @@ const struct Item gItemsInfo[] = [ITEM_SPOOKY_PLATE] = { - .name = _("Spooky Plate"), + .name = ITEM_NAME("Spooky Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4692,6 +4932,7 @@ const struct Item gItemsInfo[] = "the power of " "\nGhost-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -4702,7 +4943,7 @@ const struct Item gItemsInfo[] = [ITEM_DRACO_PLATE] = { - .name = _("Draco Plate"), + .name = ITEM_NAME("Draco Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4711,6 +4952,7 @@ const struct Item gItemsInfo[] = "the power of " "\nDragon-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -4721,7 +4963,7 @@ const struct Item gItemsInfo[] = [ITEM_DREAD_PLATE] = { - .name = _("Dread Plate"), + .name = ITEM_NAME("Dread Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4730,6 +4972,7 @@ const struct Item gItemsInfo[] = "the power of " "\nDark-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -4740,7 +4983,7 @@ const struct Item gItemsInfo[] = [ITEM_IRON_PLATE] = { - .name = _("Iron Plate"), + .name = ITEM_NAME("Iron Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4749,6 +4992,7 @@ const struct Item gItemsInfo[] = "the power of " "\nSteel-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -4759,7 +5003,7 @@ const struct Item gItemsInfo[] = [ITEM_PIXIE_PLATE] = { - .name = _("Pixie Plate"), + .name = ITEM_NAME("Pixie Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4768,6 +5012,7 @@ const struct Item gItemsInfo[] = "the power of " "\nFairy-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -4780,7 +5025,7 @@ const struct Item gItemsInfo[] = [ITEM_DOUSE_DRIVE] = { - .name = _("Douse Drive"), + .name = ITEM_NAME("Douse Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -4788,6 +5033,7 @@ const struct Item gItemsInfo[] = "Techno Blast\nto " "Water-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4798,7 +5044,7 @@ const struct Item gItemsInfo[] = [ITEM_SHOCK_DRIVE] = { - .name = _("Shock Drive"), + .name = ITEM_NAME("Shock Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -4806,6 +5052,7 @@ const struct Item gItemsInfo[] = "Techno Blast\nto " "Electric-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4816,7 +5063,7 @@ const struct Item gItemsInfo[] = [ITEM_BURN_DRIVE] = { - .name = _("Burn Drive"), + .name = ITEM_NAME("Burn Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -4824,6 +5071,7 @@ const struct Item gItemsInfo[] = "Techno Blast\nto " "Fire-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4834,7 +5082,7 @@ const struct Item gItemsInfo[] = [ITEM_CHILL_DRIVE] = { - .name = _("Chill Drive"), + .name = ITEM_NAME("Chill Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -4842,6 +5090,7 @@ const struct Item gItemsInfo[] = "Techno Blast\nto " "Ice-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4854,8 +5103,8 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_MEMORY] = { - .name = _("Fire Memory"), - .pluralName = _("Fire Memories"), + .name = ITEM_NAME("Fire Memory"), + .pluralName = ITEM_PLURAL_NAME("Fire Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4864,6 +5113,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4874,8 +5124,8 @@ const struct Item gItemsInfo[] = [ITEM_WATER_MEMORY] = { - .name = _("Water Memory"), - .pluralName = _("Water Memories"), + .name = ITEM_NAME("Water Memory"), + .pluralName = ITEM_PLURAL_NAME("Water Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4884,6 +5134,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4894,8 +5145,8 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_MEMORY] = { - .name = _("Electric Memory"), - .pluralName = _("Electric Memories"), + .name = ITEM_NAME("Electric Memory"), + .pluralName = ITEM_PLURAL_NAME("Electric Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4904,6 +5155,7 @@ const struct Item gItemsInfo[] = "type data.\nIt swaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4914,8 +5166,8 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_MEMORY] = { - .name = _("Grass Memory"), - .pluralName = _("Grass Memories"), + .name = ITEM_NAME("Grass Memory"), + .pluralName = ITEM_PLURAL_NAME("Grass Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4924,6 +5176,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4934,8 +5187,8 @@ const struct Item gItemsInfo[] = [ITEM_ICE_MEMORY] = { - .name = _("Ice Memory"), - .pluralName = _("Ice Memories"), + .name = ITEM_NAME("Ice Memory"), + .pluralName = ITEM_PLURAL_NAME("Ice Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4944,6 +5197,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4954,8 +5208,8 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_MEMORY] = { - .name = _("Fighting Memory"), - .pluralName = _("Fighting Memories"), + .name = ITEM_NAME("Fighting Memory"), + .pluralName = ITEM_PLURAL_NAME("Fighting Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4964,6 +5218,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4974,8 +5229,8 @@ const struct Item gItemsInfo[] = [ITEM_POISON_MEMORY] = { - .name = _("Poison Memory"), - .pluralName = _("Poison Memories"), + .name = ITEM_NAME("Poison Memory"), + .pluralName = ITEM_PLURAL_NAME("Poison Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -4984,6 +5239,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -4994,8 +5250,8 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_MEMORY] = { - .name = _("Ground Memory"), - .pluralName = _("Ground Memories"), + .name = ITEM_NAME("Ground Memory"), + .pluralName = ITEM_PLURAL_NAME("Ground Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5004,6 +5260,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -5014,8 +5271,8 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_MEMORY] = { - .name = _("Flying Memory"), - .pluralName = _("Flying Memories"), + .name = ITEM_NAME("Flying Memory"), + .pluralName = ITEM_PLURAL_NAME("Flying Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5024,6 +5281,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -5034,8 +5292,8 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_MEMORY] = { - .name = _("Psychic Memory"), - .pluralName = _("Psychic Memories"), + .name = ITEM_NAME("Psychic Memory"), + .pluralName = ITEM_PLURAL_NAME("Psychic Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5044,6 +5302,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -5054,8 +5313,8 @@ const struct Item gItemsInfo[] = [ITEM_BUG_MEMORY] = { - .name = _("Bug Memory"), - .pluralName = _("Bug Memories"), + .name = ITEM_NAME("Bug Memory"), + .pluralName = ITEM_PLURAL_NAME("Bug Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5064,6 +5323,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -5074,8 +5334,8 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_MEMORY] = { - .name = _("Rock Memory"), - .pluralName = _("Rock Memories"), + .name = ITEM_NAME("Rock Memory"), + .pluralName = ITEM_PLURAL_NAME("Rock Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5084,6 +5344,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -5094,8 +5355,8 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_MEMORY] = { - .name = _("Ghost Memory"), - .pluralName = _("Ghost Memories"), + .name = ITEM_NAME("Ghost Memory"), + .pluralName = ITEM_PLURAL_NAME("Ghost Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5104,6 +5365,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -5114,8 +5376,8 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_MEMORY] = { - .name = _("Dragon Memory"), - .pluralName = _("Dragon Memories"), + .name = ITEM_NAME("Dragon Memory"), + .pluralName = ITEM_PLURAL_NAME("Dragon Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5124,6 +5386,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -5134,8 +5397,8 @@ const struct Item gItemsInfo[] = [ITEM_DARK_MEMORY] = { - .name = _("Dark Memory"), - .pluralName = _("Dark Memories"), + .name = ITEM_NAME("Dark Memory"), + .pluralName = ITEM_PLURAL_NAME("Dark Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5144,6 +5407,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -5154,8 +5418,8 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_MEMORY] = { - .name = _("Steel Memory"), - .pluralName = _("Steel Memories"), + .name = ITEM_NAME("Steel Memory"), + .pluralName = ITEM_PLURAL_NAME("Steel Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5164,6 +5428,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -5174,8 +5439,8 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_MEMORY] = { - .name = _("Fairy Memory"), - .pluralName = _("Fairy Memories"), + .name = ITEM_NAME("Fairy Memory"), + .pluralName = ITEM_PLURAL_NAME("Fairy Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5184,6 +5449,7 @@ const struct Item gItemsInfo[] = "type data. It\nswaps " "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -5194,13 +5460,14 @@ const struct Item gItemsInfo[] = [ITEM_RUSTED_SWORD] = { - .name = _("Rusted Sword"), + .name = ITEM_NAME("Rusted Sword"), .price = 0, .description = COMPOUND_STRING( "A rusty sword. A " "hero used it to " "\nhalt a disaster."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedSword, @@ -5209,13 +5476,14 @@ const struct Item gItemsInfo[] = [ITEM_RUSTED_SHIELD] = { - .name = _("Rusted Shield"), + .name = ITEM_NAME("Rusted Shield"), .price = 0, .description = COMPOUND_STRING( "A rusty shield. A " "hero used it to\n" "halt a disaster."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedShield, @@ -5226,7 +5494,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_ORB] = { - .name = _("Red Orb"), + .name = ITEM_NAME("Red Orb"), .price = 0, .holdEffect = HOLD_EFFECT_PRIMAL_ORB, .description = COMPOUND_STRING( @@ -5234,6 +5502,7 @@ const struct Item gItemsInfo[] = "said to\ncontain an " "ancient power."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedOrb, @@ -5242,7 +5511,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_ORB] = { - .name = _("Blue Orb"), + .name = ITEM_NAME("Blue Orb"), .price = 0, .holdEffect = HOLD_EFFECT_PRIMAL_ORB, .description = COMPOUND_STRING( @@ -5250,6 +5519,7 @@ const struct Item gItemsInfo[] = "said to\ncontain an " "ancient power."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueOrb, @@ -5260,7 +5530,7 @@ const struct Item gItemsInfo[] = [ITEM_VENUSAURITE] = { - .name = _("Venusaurite"), + .name = ITEM_NAME("Venusaurite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5268,6 +5538,7 @@ const struct Item gItemsInfo[] = "Venusaur to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5277,12 +5548,13 @@ const struct Item gItemsInfo[] = [ITEM_CHARIZARDITE_X] = { - .name = _("Charizardite X"), - .pluralName = _("Charizardites X"), + .name = ITEM_NAME("Charizardite X"), + .pluralName = ITEM_PLURAL_NAME("Charizardites X"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5292,12 +5564,13 @@ const struct Item gItemsInfo[] = [ITEM_CHARIZARDITE_Y] = { - .name = _("Charizardite Y"), - .pluralName = _("Charizardites Y"), + .name = ITEM_NAME("Charizardite Y"), + .pluralName = ITEM_PLURAL_NAME("Charizardites Y"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5307,7 +5580,7 @@ const struct Item gItemsInfo[] = [ITEM_BLASTOISINITE] = { - .name = _("Blastoisinite"), + .name = ITEM_NAME("Blastoisinite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5315,6 +5588,7 @@ const struct Item gItemsInfo[] = "Blastoise to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5324,7 +5598,7 @@ const struct Item gItemsInfo[] = [ITEM_BEEDRILLITE] = { - .name = _("Beedrillite"), + .name = ITEM_NAME("Beedrillite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5332,6 +5606,7 @@ const struct Item gItemsInfo[] = "Beedrill to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5341,7 +5616,7 @@ const struct Item gItemsInfo[] = [ITEM_PIDGEOTITE] = { - .name = _("Pidgeotite"), + .name = ITEM_NAME("Pidgeotite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5349,6 +5624,7 @@ const struct Item gItemsInfo[] = "Pidgeot to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5358,7 +5634,7 @@ const struct Item gItemsInfo[] = [ITEM_ALAKAZITE] = { - .name = _("Alakazite"), + .name = ITEM_NAME("Alakazite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5366,6 +5642,7 @@ const struct Item gItemsInfo[] = "Alakazam to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5375,7 +5652,7 @@ const struct Item gItemsInfo[] = [ITEM_SLOWBRONITE] = { - .name = _("Slowbronite"), + .name = ITEM_NAME("Slowbronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5383,6 +5660,7 @@ const struct Item gItemsInfo[] = "Slowbro to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5392,7 +5670,7 @@ const struct Item gItemsInfo[] = [ITEM_GENGARITE] = { - .name = _("Gengarite"), + .name = ITEM_NAME("Gengarite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5400,6 +5678,7 @@ const struct Item gItemsInfo[] = "Gengar to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5409,7 +5688,7 @@ const struct Item gItemsInfo[] = [ITEM_KANGASKHANITE] = { - .name = _("Kangaskhanite"), + .name = ITEM_NAME("Kangaskhanite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5417,6 +5696,7 @@ const struct Item gItemsInfo[] = "Kangaskhan to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5426,7 +5706,7 @@ const struct Item gItemsInfo[] = [ITEM_PINSIRITE] = { - .name = _("Pinsirite"), + .name = ITEM_NAME("Pinsirite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5434,6 +5714,7 @@ const struct Item gItemsInfo[] = "Pinsir to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5443,7 +5724,7 @@ const struct Item gItemsInfo[] = [ITEM_GYARADOSITE] = { - .name = _("Gyaradosite"), + .name = ITEM_NAME("Gyaradosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5451,6 +5732,7 @@ const struct Item gItemsInfo[] = "Gyarados to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5460,7 +5742,7 @@ const struct Item gItemsInfo[] = [ITEM_AERODACTYLITE] = { - .name = _("Aerodactylite"), + .name = ITEM_NAME("Aerodactylite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5468,6 +5750,7 @@ const struct Item gItemsInfo[] = "Aerodactyl to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5477,12 +5760,13 @@ const struct Item gItemsInfo[] = [ITEM_MEWTWONITE_X] = { - .name = _("Mewtwonite X"), - .pluralName = _("Mewtwonites X"), + .name = ITEM_NAME("Mewtwonite X"), + .pluralName = ITEM_PLURAL_NAME("Mewtwonites X"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5492,12 +5776,13 @@ const struct Item gItemsInfo[] = [ITEM_MEWTWONITE_Y] = { - .name = _("Mewtwonite Y"), - .pluralName = _("Mewtwonites Y"), + .name = ITEM_NAME("Mewtwonite Y"), + .pluralName = ITEM_PLURAL_NAME("Mewtwonites Y"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5507,7 +5792,7 @@ const struct Item gItemsInfo[] = [ITEM_AMPHAROSITE] = { - .name = _("Ampharosite"), + .name = ITEM_NAME("Ampharosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5515,6 +5800,7 @@ const struct Item gItemsInfo[] = "Ampharos to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5524,7 +5810,7 @@ const struct Item gItemsInfo[] = [ITEM_STEELIXITE] = { - .name = _("Steelixite"), + .name = ITEM_NAME("Steelixite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5532,6 +5818,7 @@ const struct Item gItemsInfo[] = "Steelix to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5541,7 +5828,7 @@ const struct Item gItemsInfo[] = [ITEM_SCIZORITE] = { - .name = _("Scizorite"), + .name = ITEM_NAME("Scizorite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5549,6 +5836,7 @@ const struct Item gItemsInfo[] = "Scizor to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5558,7 +5846,7 @@ const struct Item gItemsInfo[] = [ITEM_HERACRONITE] = { - .name = _("Heracronite"), + .name = ITEM_NAME("Heracronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5566,6 +5854,7 @@ const struct Item gItemsInfo[] = "Heracross to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5575,7 +5864,7 @@ const struct Item gItemsInfo[] = [ITEM_HOUNDOOMINITE] = { - .name = _("Houndoominite"), + .name = ITEM_NAME("Houndoominite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5583,6 +5872,7 @@ const struct Item gItemsInfo[] = "Houndoom to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5592,7 +5882,7 @@ const struct Item gItemsInfo[] = [ITEM_TYRANITARITE] = { - .name = _("Tyranitarite"), + .name = ITEM_NAME("Tyranitarite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5600,6 +5890,7 @@ const struct Item gItemsInfo[] = "Tyranitar to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5609,7 +5900,7 @@ const struct Item gItemsInfo[] = [ITEM_SCEPTILITE] = { - .name = _("Sceptilite"), + .name = ITEM_NAME("Sceptilite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5617,6 +5908,7 @@ const struct Item gItemsInfo[] = "Sceptile to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5626,7 +5918,7 @@ const struct Item gItemsInfo[] = [ITEM_BLAZIKENITE] = { - .name = _("Blazikenite"), + .name = ITEM_NAME("Blazikenite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5634,6 +5926,7 @@ const struct Item gItemsInfo[] = "Blaziken to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5643,7 +5936,7 @@ const struct Item gItemsInfo[] = [ITEM_SWAMPERTITE] = { - .name = _("Swampertite"), + .name = ITEM_NAME("Swampertite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5651,6 +5944,7 @@ const struct Item gItemsInfo[] = "Swampert to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5660,7 +5954,7 @@ const struct Item gItemsInfo[] = [ITEM_GARDEVOIRITE] = { - .name = _("Gardevoirite"), + .name = ITEM_NAME("Gardevoirite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5668,6 +5962,7 @@ const struct Item gItemsInfo[] = "Gardevoir to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5677,7 +5972,7 @@ const struct Item gItemsInfo[] = [ITEM_SABLENITE] = { - .name = _("Sablenite"), + .name = ITEM_NAME("Sablenite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5685,6 +5980,7 @@ const struct Item gItemsInfo[] = "Sableye to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5694,7 +5990,7 @@ const struct Item gItemsInfo[] = [ITEM_MAWILITE] = { - .name = _("Mawilite"), + .name = ITEM_NAME("Mawilite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5702,6 +5998,7 @@ const struct Item gItemsInfo[] = "Mawile to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5711,7 +6008,7 @@ const struct Item gItemsInfo[] = [ITEM_AGGRONITE] = { - .name = _("Aggronite"), + .name = ITEM_NAME("Aggronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5719,6 +6016,7 @@ const struct Item gItemsInfo[] = "Aggron to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5728,7 +6026,7 @@ const struct Item gItemsInfo[] = [ITEM_MEDICHAMITE] = { - .name = _("Medichamite"), + .name = ITEM_NAME("Medichamite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5736,6 +6034,7 @@ const struct Item gItemsInfo[] = "Medicham to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5745,7 +6044,7 @@ const struct Item gItemsInfo[] = [ITEM_MANECTITE] = { - .name = _("Manectite"), + .name = ITEM_NAME("Manectite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5753,6 +6052,7 @@ const struct Item gItemsInfo[] = "Manectric to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5762,7 +6062,7 @@ const struct Item gItemsInfo[] = [ITEM_SHARPEDONITE] = { - .name = _("Sharpedonite"), + .name = ITEM_NAME("Sharpedonite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5770,6 +6070,7 @@ const struct Item gItemsInfo[] = "Sharpedo to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5779,7 +6080,7 @@ const struct Item gItemsInfo[] = [ITEM_CAMERUPTITE] = { - .name = _("Cameruptite"), + .name = ITEM_NAME("Cameruptite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5787,6 +6088,7 @@ const struct Item gItemsInfo[] = "Camerupt to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5796,7 +6098,7 @@ const struct Item gItemsInfo[] = [ITEM_ALTARIANITE] = { - .name = _("Altarianite"), + .name = ITEM_NAME("Altarianite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5804,6 +6106,7 @@ const struct Item gItemsInfo[] = "Altaria to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5813,7 +6116,7 @@ const struct Item gItemsInfo[] = [ITEM_BANETTITE] = { - .name = _("Banettite"), + .name = ITEM_NAME("Banettite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5821,6 +6124,7 @@ const struct Item gItemsInfo[] = "Banette to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5830,7 +6134,7 @@ const struct Item gItemsInfo[] = [ITEM_ABSOLITE] = { - .name = _("Absolite"), + .name = ITEM_NAME("Absolite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5838,6 +6142,7 @@ const struct Item gItemsInfo[] = "Absol to Mega " "\nEvolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5847,7 +6152,7 @@ const struct Item gItemsInfo[] = [ITEM_GLALITITE] = { - .name = _("Glalitite"), + .name = ITEM_NAME("Glalitite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5855,6 +6160,7 @@ const struct Item gItemsInfo[] = "Glalie to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5864,7 +6170,7 @@ const struct Item gItemsInfo[] = [ITEM_SALAMENCITE] = { - .name = _("Salamencite"), + .name = ITEM_NAME("Salamencite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5872,6 +6178,7 @@ const struct Item gItemsInfo[] = "Salamence to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5881,7 +6188,7 @@ const struct Item gItemsInfo[] = [ITEM_METAGROSSITE] = { - .name = _("Metagrossite"), + .name = ITEM_NAME("Metagrossite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5889,6 +6196,7 @@ const struct Item gItemsInfo[] = "Metagross to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5898,7 +6206,7 @@ const struct Item gItemsInfo[] = [ITEM_LATIASITE] = { - .name = _("Latiasite"), + .name = ITEM_NAME("Latiasite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5906,6 +6214,7 @@ const struct Item gItemsInfo[] = "Latias to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5915,7 +6224,7 @@ const struct Item gItemsInfo[] = [ITEM_LATIOSITE] = { - .name = _("Latiosite"), + .name = ITEM_NAME("Latiosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5923,6 +6232,7 @@ const struct Item gItemsInfo[] = "Latios to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5932,7 +6242,7 @@ const struct Item gItemsInfo[] = [ITEM_LOPUNNITE] = { - .name = _("Lopunnite"), + .name = ITEM_NAME("Lopunnite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5940,6 +6250,7 @@ const struct Item gItemsInfo[] = "Lopunny to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5949,7 +6260,7 @@ const struct Item gItemsInfo[] = [ITEM_GARCHOMPITE] = { - .name = _("Garchompite"), + .name = ITEM_NAME("Garchompite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5957,6 +6268,7 @@ const struct Item gItemsInfo[] = "Garchomp to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5966,7 +6278,7 @@ const struct Item gItemsInfo[] = [ITEM_LUCARIONITE] = { - .name = _("Lucarionite"), + .name = ITEM_NAME("Lucarionite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5974,6 +6286,7 @@ const struct Item gItemsInfo[] = "Lucario to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5983,7 +6296,7 @@ const struct Item gItemsInfo[] = [ITEM_ABOMASITE] = { - .name = _("Abomasite"), + .name = ITEM_NAME("Abomasite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5991,6 +6304,7 @@ const struct Item gItemsInfo[] = "Abomasnow to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6000,7 +6314,7 @@ const struct Item gItemsInfo[] = [ITEM_GALLADITE] = { - .name = _("Galladite"), + .name = ITEM_NAME("Galladite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6008,6 +6322,7 @@ const struct Item gItemsInfo[] = "Gallade to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6017,7 +6332,7 @@ const struct Item gItemsInfo[] = [ITEM_AUDINITE] = { - .name = _("Audinite"), + .name = ITEM_NAME("Audinite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6025,6 +6340,7 @@ const struct Item gItemsInfo[] = "Audino to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6034,7 +6350,7 @@ const struct Item gItemsInfo[] = [ITEM_DIANCITE] = { - .name = _("Diancite"), + .name = ITEM_NAME("Diancite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6042,6 +6358,7 @@ const struct Item gItemsInfo[] = "Diancie to\nMega " "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6053,7 +6370,7 @@ const struct Item gItemsInfo[] = [ITEM_NORMAL_GEM] = { - .name = _("Normal Gem"), + .name = ITEM_NAME("Normal Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6062,6 +6379,7 @@ const struct Item gItemsInfo[] = "power of Normal " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -6071,7 +6389,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_GEM] = { - .name = _("Fire Gem"), + .name = ITEM_NAME("Fire Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6080,6 +6398,7 @@ const struct Item gItemsInfo[] = "power of Fire " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -6089,7 +6408,7 @@ const struct Item gItemsInfo[] = [ITEM_WATER_GEM] = { - .name = _("Water Gem"), + .name = ITEM_NAME("Water Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6098,6 +6417,7 @@ const struct Item gItemsInfo[] = "power of Water " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -6107,7 +6427,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_GEM] = { - .name = _("Electric Gem"), + .name = ITEM_NAME("Electric Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6116,6 +6436,7 @@ const struct Item gItemsInfo[] = "power of Electric " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -6125,7 +6446,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_GEM] = { - .name = _("Grass Gem"), + .name = ITEM_NAME("Grass Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6134,6 +6455,7 @@ const struct Item gItemsInfo[] = "power of Grass " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6143,7 +6465,7 @@ const struct Item gItemsInfo[] = [ITEM_ICE_GEM] = { - .name = _("Ice Gem"), + .name = ITEM_NAME("Ice Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6152,6 +6474,7 @@ const struct Item gItemsInfo[] = "power of Ice " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6161,7 +6484,7 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_GEM] = { - .name = _("Fighting Gem"), + .name = ITEM_NAME("Fighting Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6170,6 +6493,7 @@ const struct Item gItemsInfo[] = "power of Fighting " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6179,7 +6503,7 @@ const struct Item gItemsInfo[] = [ITEM_POISON_GEM] = { - .name = _("Poison Gem"), + .name = ITEM_NAME("Poison Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6188,6 +6512,7 @@ const struct Item gItemsInfo[] = "power of Poison " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6197,7 +6522,7 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_GEM] = { - .name = _("Ground Gem"), + .name = ITEM_NAME("Ground Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6206,6 +6531,7 @@ const struct Item gItemsInfo[] = "power of Ground " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6215,7 +6541,7 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_GEM] = { - .name = _("Flying Gem"), + .name = ITEM_NAME("Flying Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6224,6 +6550,7 @@ const struct Item gItemsInfo[] = "power of Flying " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6233,7 +6560,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_GEM] = { - .name = _("Psychic Gem"), + .name = ITEM_NAME("Psychic Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6242,6 +6569,7 @@ const struct Item gItemsInfo[] = "power of Psychic " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6251,7 +6579,7 @@ const struct Item gItemsInfo[] = [ITEM_BUG_GEM] = { - .name = _("Bug Gem"), + .name = ITEM_NAME("Bug Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6260,6 +6588,7 @@ const struct Item gItemsInfo[] = "power of Bug " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6269,7 +6598,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_GEM] = { - .name = _("Rock Gem"), + .name = ITEM_NAME("Rock Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6278,6 +6607,7 @@ const struct Item gItemsInfo[] = "power of Rock " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6287,7 +6617,7 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_GEM] = { - .name = _("Ghost Gem"), + .name = ITEM_NAME("Ghost Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6296,6 +6626,7 @@ const struct Item gItemsInfo[] = "power of Ghost " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6305,7 +6636,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_GEM] = { - .name = _("Dragon Gem"), + .name = ITEM_NAME("Dragon Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6314,6 +6645,7 @@ const struct Item gItemsInfo[] = "power of Dragon " "\nType moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6323,7 +6655,7 @@ const struct Item gItemsInfo[] = [ITEM_DARK_GEM] = { - .name = _("Dark Gem"), + .name = ITEM_NAME("Dark Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6332,6 +6664,7 @@ const struct Item gItemsInfo[] = "power of Dark " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6341,7 +6674,7 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_GEM] = { - .name = _("Steel Gem"), + .name = ITEM_NAME("Steel Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6350,6 +6683,7 @@ const struct Item gItemsInfo[] = "power of Steel " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6359,7 +6693,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_GEM] = { - .name = _("Fairy Gem"), + .name = ITEM_NAME("Fairy Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6368,6 +6702,7 @@ const struct Item gItemsInfo[] = "power of Fairy " "Type\nmoves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6379,7 +6714,7 @@ const struct Item gItemsInfo[] = [ITEM_NORMALIUM_Z] = { - .name = _("Normalium Z"), + .name = ITEM_NAME("Normalium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6387,6 +6722,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -6396,7 +6732,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRIUM_Z] = { - .name = _("Firium Z"), + .name = ITEM_NAME("Firium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6404,6 +6740,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -6413,7 +6750,7 @@ const struct Item gItemsInfo[] = [ITEM_WATERIUM_Z] = { - .name = _("Waterium Z"), + .name = ITEM_NAME("Waterium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6421,6 +6758,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -6430,7 +6768,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIUM_Z] = { - .name = _("Electrium Z"), + .name = ITEM_NAME("Electrium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6438,6 +6776,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -6447,7 +6786,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASSIUM_Z] = { - .name = _("Grassium Z"), + .name = ITEM_NAME("Grassium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6455,6 +6794,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6464,7 +6804,7 @@ const struct Item gItemsInfo[] = [ITEM_ICIUM_Z] = { - .name = _("Icium Z"), + .name = ITEM_NAME("Icium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6472,6 +6812,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6481,7 +6822,7 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTINIUM_Z] = { - .name = _("Fightinium Z"), + .name = ITEM_NAME("Fightinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6489,6 +6830,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6498,7 +6840,7 @@ const struct Item gItemsInfo[] = [ITEM_POISONIUM_Z] = { - .name = _("Poisonium Z"), + .name = ITEM_NAME("Poisonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6506,6 +6848,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6515,7 +6858,7 @@ const struct Item gItemsInfo[] = [ITEM_GROUNDIUM_Z] = { - .name = _("Groundium Z"), + .name = ITEM_NAME("Groundium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6523,6 +6866,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6532,7 +6876,7 @@ const struct Item gItemsInfo[] = [ITEM_FLYINIUM_Z] = { - .name = _("Flyinium Z"), + .name = ITEM_NAME("Flyinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6540,6 +6884,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6549,7 +6894,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIUM_Z] = { - .name = _("Psychium Z"), + .name = ITEM_NAME("Psychium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6557,6 +6902,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6566,7 +6912,7 @@ const struct Item gItemsInfo[] = [ITEM_BUGINIUM_Z] = { - .name = _("Buginium Z"), + .name = ITEM_NAME("Buginium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6574,6 +6920,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6583,7 +6930,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCKIUM_Z] = { - .name = _("Rockium Z"), + .name = ITEM_NAME("Rockium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6591,6 +6938,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6600,7 +6948,7 @@ const struct Item gItemsInfo[] = [ITEM_GHOSTIUM_Z] = { - .name = _("Ghostium Z"), + .name = ITEM_NAME("Ghostium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6608,6 +6956,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6617,7 +6966,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGONIUM_Z] = { - .name = _("Dragonium Z"), + .name = ITEM_NAME("Dragonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6625,6 +6974,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6634,7 +6984,7 @@ const struct Item gItemsInfo[] = [ITEM_DARKINIUM_Z] = { - .name = _("Darkinium Z"), + .name = ITEM_NAME("Darkinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6642,6 +6992,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6651,7 +7002,7 @@ const struct Item gItemsInfo[] = [ITEM_STEELIUM_Z] = { - .name = _("Steelium Z"), + .name = ITEM_NAME("Steelium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6659,6 +7010,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6668,7 +7020,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRIUM_Z] = { - .name = _("Fairium Z"), + .name = ITEM_NAME("Fairium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6676,6 +7028,7 @@ const struct Item gItemsInfo[] = "type moves into " "\nZ-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6685,7 +7038,7 @@ const struct Item gItemsInfo[] = [ITEM_PIKANIUM_Z] = { - .name = _("Pikanium Z"), + .name = ITEM_NAME("Pikanium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6693,6 +7046,7 @@ const struct Item gItemsInfo[] = "Volt Tackle " "\ninto a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6702,7 +7056,7 @@ const struct Item gItemsInfo[] = [ITEM_EEVIUM_Z] = { - .name = _("Eevium Z"), + .name = ITEM_NAME("Eevium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6710,6 +7064,7 @@ const struct Item gItemsInfo[] = "Last Resort " "into\na Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6719,7 +7074,7 @@ const struct Item gItemsInfo[] = [ITEM_SNORLIUM_Z] = { - .name = _("Snorlium Z"), + .name = ITEM_NAME("Snorlium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6727,6 +7082,7 @@ const struct Item gItemsInfo[] = "Giga Impact " "\ninto a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6736,7 +7092,7 @@ const struct Item gItemsInfo[] = [ITEM_MEWNIUM_Z] = { - .name = _("Mewnium Z"), + .name = ITEM_NAME("Mewnium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6744,6 +7100,7 @@ const struct Item gItemsInfo[] = "Psychic into " "a\nZ-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6753,7 +7110,7 @@ const struct Item gItemsInfo[] = [ITEM_DECIDIUM_Z] = { - .name = _("Decidium Z"), + .name = ITEM_NAME("Decidium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6761,6 +7118,7 @@ const struct Item gItemsInfo[] = "eye's Spirit Sha-" "\nckle into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6770,7 +7128,7 @@ const struct Item gItemsInfo[] = [ITEM_INCINIUM_Z] = { - .name = _("Incinium Z"), + .name = ITEM_NAME("Incinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6778,6 +7136,7 @@ const struct Item gItemsInfo[] = "roar's Darkest La-" "\nriat into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6787,7 +7146,7 @@ const struct Item gItemsInfo[] = [ITEM_PRIMARIUM_Z] = { - .name = _("Primarium Z"), + .name = ITEM_NAME("Primarium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6795,6 +7154,7 @@ const struct Item gItemsInfo[] = "Sparkling\nAria " "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6804,7 +7164,7 @@ const struct Item gItemsInfo[] = [ITEM_LYCANIUM_Z] = { - .name = _("Lycanium Z"), + .name = ITEM_NAME("Lycanium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6812,6 +7172,7 @@ const struct Item gItemsInfo[] = "Stone Edge " "\ninto a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6821,7 +7182,7 @@ const struct Item gItemsInfo[] = [ITEM_MIMIKIUM_Z] = { - .name = _("Mimikium Z"), + .name = ITEM_NAME("Mimikium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6829,6 +7190,7 @@ const struct Item gItemsInfo[] = "Play Rough " "into\na Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6838,7 +7200,7 @@ const struct Item gItemsInfo[] = [ITEM_KOMMONIUM_Z] = { - .name = _("Kommonium Z"), + .name = ITEM_NAME("Kommonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6846,6 +7208,7 @@ const struct Item gItemsInfo[] = "Clanging Scales\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6855,7 +7218,7 @@ const struct Item gItemsInfo[] = [ITEM_TAPUNIUM_Z] = { - .name = _("Tapunium Z"), + .name = ITEM_NAME("Tapunium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6863,6 +7226,7 @@ const struct Item gItemsInfo[] = "Nature's\nMadness " "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6872,7 +7236,7 @@ const struct Item gItemsInfo[] = [ITEM_SOLGANIUM_Z] = { - .name = _("Solganium Z"), + .name = ITEM_NAME("Solganium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6880,6 +7244,7 @@ const struct Item gItemsInfo[] = "Sunsteel\nStrike " "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6889,7 +7254,7 @@ const struct Item gItemsInfo[] = [ITEM_LUNALIUM_Z] = { - .name = _("Lunalium Z"), + .name = ITEM_NAME("Lunalium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6897,6 +7262,7 @@ const struct Item gItemsInfo[] = "Moongeist Beam " "\ninto a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6906,7 +7272,7 @@ const struct Item gItemsInfo[] = [ITEM_MARSHADIUM_Z] = { - .name = _("Marshadium Z"), + .name = ITEM_NAME("Marshadium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6914,6 +7280,7 @@ const struct Item gItemsInfo[] = "dow's Spectral\nThi-" "ef into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6923,7 +7290,7 @@ const struct Item gItemsInfo[] = [ITEM_ALORAICHIUM_Z] = { - .name = _("Aloraichium Z"), + .name = ITEM_NAME("Aloraichium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6931,6 +7298,7 @@ const struct Item gItemsInfo[] = "Raichu's Thunder-" "\nbolt into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6940,7 +7308,7 @@ const struct Item gItemsInfo[] = [ITEM_PIKASHUNIUM_Z] = { - .name = _("Pikashunium Z"), + .name = ITEM_NAME("Pikashunium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6948,6 +7316,7 @@ const struct Item gItemsInfo[] = "a cap's\nThunderbolt " "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6957,7 +7326,7 @@ const struct Item gItemsInfo[] = [ITEM_ULTRANECROZIUM_Z] = { - .name = _("Ultranecrozium Z"), + .name = ITEM_NAME("Ultranecrozium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6965,6 +7334,7 @@ const struct Item gItemsInfo[] = "fused Necrozma " "\ninto a new form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6976,7 +7346,7 @@ const struct Item gItemsInfo[] = [ITEM_LIGHT_BALL] = { - .name = _("Light Ball"), + .name = ITEM_NAME("Light Ball"), .price = (I_PRICE >= GEN_7) ? 1000 : 100, .holdEffect = HOLD_EFFECT_LIGHT_BALL, .description = COMPOUND_STRING( @@ -6984,6 +7354,7 @@ const struct Item gItemsInfo[] = "raises the Atk\nand " "Sp. Atk of Pikachu."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -6993,7 +7364,7 @@ const struct Item gItemsInfo[] = [ITEM_LEEK] = { - .name = _("Leek"), + .name = ITEM_NAME("Leek"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .holdEffect = HOLD_EFFECT_LEEK, .description = COMPOUND_STRING( @@ -7001,6 +7372,7 @@ const struct Item gItemsInfo[] = "raises\nFarfetch'd's " "critical-hit ratio."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7010,7 +7382,7 @@ const struct Item gItemsInfo[] = [ITEM_THICK_CLUB] = { - .name = _("Thick Club"), + .name = ITEM_NAME("Thick Club"), .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffect = HOLD_EFFECT_THICK_CLUB, .description = COMPOUND_STRING( @@ -7018,6 +7390,7 @@ const struct Item gItemsInfo[] = "raises Cubone\nor " "Marowak's Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -7027,8 +7400,8 @@ const struct Item gItemsInfo[] = [ITEM_LUCKY_PUNCH] = { - .name = _("Lucky Punch"), - .pluralName = _("Lucky Punches"), + .name = ITEM_NAME("Lucky Punch"), + .pluralName = ITEM_PLURAL_NAME("Lucky Punches"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_LUCKY_PUNCH, .description = COMPOUND_STRING( @@ -7036,6 +7409,7 @@ const struct Item gItemsInfo[] = "raises Chansey's\n" "critical-hit rate."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -7045,8 +7419,8 @@ const struct Item gItemsInfo[] = [ITEM_METAL_POWDER] = { - .name = _("Metal Powder"), - .pluralName = _("Metal Powder"), + .name = ITEM_NAME("Metal Powder"), + .pluralName = ITEM_PLURAL_NAME("Metal Powder"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_METAL_POWDER, .description = COMPOUND_STRING( @@ -7054,6 +7428,7 @@ const struct Item gItemsInfo[] = "raises Ditto's " "\nDefense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7063,8 +7438,8 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_POWDER] = { - .name = _("Quick Powder"), - .pluralName = _("Quick Powder"), + .name = ITEM_NAME("Quick Powder"), + .pluralName = ITEM_PLURAL_NAME("Quick Powder"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_QUICK_POWDER, .description = COMPOUND_STRING( @@ -7072,6 +7447,7 @@ const struct Item gItemsInfo[] = "raises the Speed\n" "of Ditto."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7081,7 +7457,7 @@ const struct Item gItemsInfo[] = [ITEM_DEEP_SEA_SCALE] = { - .name = _("Deep Sea Scale"), + .name = ITEM_NAME("Deep Sea Scale"), .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_SCALE, .description = COMPOUND_STRING( @@ -7089,6 +7465,7 @@ const struct Item gItemsInfo[] = "raises the Sp.\nDef " "of Clamperl."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7099,8 +7476,8 @@ const struct Item gItemsInfo[] = [ITEM_DEEP_SEA_TOOTH] = { - .name = _("Deep Sea Tooth"), - .pluralName = _("Deep Sea Teeth"), + .name = ITEM_NAME("Deep Sea Tooth"), + .pluralName = ITEM_PLURAL_NAME("Deep Sea Teeth"), .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_TOOTH, .description = COMPOUND_STRING( @@ -7108,6 +7485,7 @@ const struct Item gItemsInfo[] = "raises the Sp.\nAtk " "of Clamperl."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7118,7 +7496,7 @@ const struct Item gItemsInfo[] = [ITEM_SOUL_DEW] = { - .name = _("Soul Dew"), + .name = ITEM_NAME("Soul Dew"), .price = (I_PRICE >= GEN_7) ? 0 : 200, .holdEffect = HOLD_EFFECT_SOUL_DEW, .holdEffectParam = B_SOUL_DEW_BOOST >= GEN_7 ? 20 : 50, @@ -7133,6 +7511,7 @@ const struct Item gItemsInfo[] = "Latios & Latias."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7142,7 +7521,7 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_ORB] = { - .name = _("Adamant Orb"), + .name = ITEM_NAME("Adamant Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, @@ -7151,6 +7530,7 @@ const struct Item gItemsInfo[] = "Dragon and\nSteel-" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7160,7 +7540,7 @@ const struct Item gItemsInfo[] = [ITEM_LUSTROUS_ORB] = { - .name = _("Lustrous Orb"), + .name = ITEM_NAME("Lustrous Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, @@ -7169,6 +7549,7 @@ const struct Item gItemsInfo[] = "Dragon and\nWater-" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7178,7 +7559,7 @@ const struct Item gItemsInfo[] = [ITEM_GRISEOUS_ORB] = { - .name = _("Griseous Orb"), + .name = ITEM_NAME("Griseous Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, @@ -7187,6 +7568,7 @@ const struct Item gItemsInfo[] = "Dragon and\nGhost-" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7198,12 +7580,13 @@ const struct Item gItemsInfo[] = [ITEM_SEA_INCENSE] = { - .name = _("Sea Incense"), + .name = ITEM_NAME("Sea Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7214,7 +7597,7 @@ const struct Item gItemsInfo[] = [ITEM_LAX_INCENSE] = { - .name = _("Lax Incense"), + .name = ITEM_NAME("Lax Incense"), .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, @@ -7223,6 +7606,7 @@ const struct Item gItemsInfo[] = "slightly lowers\nthe " "foe's accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7232,12 +7616,13 @@ const struct Item gItemsInfo[] = [ITEM_ODD_INCENSE] = { - .name = _("Odd Incense"), + .name = ITEM_NAME("Odd Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7248,12 +7633,13 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_INCENSE] = { - .name = _("Rock Incense"), + .name = ITEM_NAME("Rock Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7264,12 +7650,13 @@ const struct Item gItemsInfo[] = [ITEM_FULL_INCENSE] = { - .name = _("Full Incense"), + .name = ITEM_NAME("Full Incense"), .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .holdEffectParam = 5, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7279,12 +7666,13 @@ const struct Item gItemsInfo[] = [ITEM_WAVE_INCENSE] = { - .name = _("Wave Incense"), + .name = ITEM_NAME("Wave Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7295,12 +7683,13 @@ const struct Item gItemsInfo[] = [ITEM_ROSE_INCENSE] = { - .name = _("Rose Incense"), + .name = ITEM_NAME("Rose Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7311,11 +7700,12 @@ const struct Item gItemsInfo[] = [ITEM_LUCK_INCENSE] = { - .name = _("Luck Incense"), + .name = ITEM_NAME("Luck Incense"), .price = (I_PRICE >= GEN_7) ? 11000 : 9600, .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7325,11 +7715,12 @@ const struct Item gItemsInfo[] = [ITEM_PURE_INCENSE] = { - .name = _("Pure Incense"), + .name = ITEM_NAME("Pure Incense"), .price = (I_PRICE >= GEN_7) ? 6000 : 9600, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7341,14 +7732,15 @@ const struct Item gItemsInfo[] = [ITEM_RED_SCARF] = { - .name = _("Red Scarf"), - .pluralName = _("Red Scarves"), + .name = ITEM_NAME("Red Scarf"), + .pluralName = ITEM_PLURAL_NAME("Red Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that " "raises Cool in " "\nContests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7358,14 +7750,15 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_SCARF] = { - .name = _("Blue Scarf"), - .pluralName = _("Blue Scarves"), + .name = ITEM_NAME("Blue Scarf"), + .pluralName = ITEM_PLURAL_NAME("Blue Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that " "raises Beauty in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7375,14 +7768,15 @@ const struct Item gItemsInfo[] = [ITEM_PINK_SCARF] = { - .name = _("Pink Scarf"), - .pluralName = _("Pink Scarves"), + .name = ITEM_NAME("Pink Scarf"), + .pluralName = ITEM_PLURAL_NAME("Pink Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that " "raises Cute in " "\nContests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7392,14 +7786,15 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_SCARF] = { - .name = _("Green Scarf"), - .pluralName = _("Green Scarves"), + .name = ITEM_NAME("Green Scarf"), + .pluralName = ITEM_PLURAL_NAME("Green Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that " "raises Smart in " "\nContests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7409,14 +7804,15 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_SCARF] = { - .name = _("Yellow Scarf"), - .pluralName = _("Yellow Scarves"), + .name = ITEM_NAME("Yellow Scarf"), + .pluralName = ITEM_PLURAL_NAME("Yellow Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that " "raises Tough in " "\nContests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7428,7 +7824,7 @@ const struct Item gItemsInfo[] = [ITEM_MACHO_BRACE] = { - .name = _("Macho Brace"), + .name = ITEM_NAME("Macho Brace"), .price = 3000, .holdEffect = HOLD_EFFECT_MACHO_BRACE, .description = COMPOUND_STRING( @@ -7436,6 +7832,7 @@ const struct Item gItemsInfo[] = "promotes growth,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7445,7 +7842,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_WEIGHT] = { - .name = _("Power Weight"), + .name = ITEM_NAME("Power Weight"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7454,6 +7851,7 @@ const struct Item gItemsInfo[] = "promotes HP\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_HP, @@ -7464,7 +7862,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BRACER] = { - .name = _("Power Bracer"), + .name = ITEM_NAME("Power Bracer"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7473,6 +7871,7 @@ const struct Item gItemsInfo[] = "promotes Atk\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_ATK, @@ -7483,7 +7882,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BELT] = { - .name = _("Power Belt"), + .name = ITEM_NAME("Power Belt"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7492,6 +7891,7 @@ const struct Item gItemsInfo[] = "promotes Def\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_DEF, @@ -7502,8 +7902,8 @@ const struct Item gItemsInfo[] = [ITEM_POWER_LENS] = { - .name = _("Power Lens"), - .pluralName = _("Power Lenses"), + .name = ITEM_NAME("Power Lens"), + .pluralName = ITEM_PLURAL_NAME("Power Lenses"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7512,6 +7912,7 @@ const struct Item gItemsInfo[] = "motes Sp. Atk\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPATK, @@ -7522,7 +7923,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BAND] = { - .name = _("Power Band"), + .name = ITEM_NAME("Power Band"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7531,6 +7932,7 @@ const struct Item gItemsInfo[] = "motes Sp. Def\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPDEF, @@ -7541,7 +7943,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_ANKLET] = { - .name = _("Power Anklet"), + .name = ITEM_NAME("Power Anklet"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7550,6 +7952,7 @@ const struct Item gItemsInfo[] = "promotes Spd\ngain, " "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPEED, @@ -7562,8 +7965,8 @@ const struct Item gItemsInfo[] = [ITEM_SILK_SCARF] = { - .name = _("Silk Scarf"), - .pluralName = _("Silk Scarves"), + .name = ITEM_NAME("Silk Scarf"), + .pluralName = ITEM_PLURAL_NAME("Silk Scarves"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7572,6 +7975,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Normal-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -7582,7 +7986,7 @@ const struct Item gItemsInfo[] = [ITEM_CHARCOAL] = { - .name = _("Charcoal"), + .name = ITEM_NAME("Charcoal"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 9800), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7591,6 +7995,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Fire-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -7601,8 +8006,8 @@ const struct Item gItemsInfo[] = [ITEM_MYSTIC_WATER] = { - .name = _("Mystic Water"), - .pluralName = _("Mystic Water"), + .name = ITEM_NAME("Mystic Water"), + .pluralName = ITEM_PLURAL_NAME("Mystic Water"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7611,6 +8016,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Water-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7621,7 +8027,7 @@ const struct Item gItemsInfo[] = [ITEM_MAGNET] = { - .name = _("Magnet"), + .name = ITEM_NAME("Magnet"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7630,6 +8036,7 @@ const struct Item gItemsInfo[] = "boosts Electric-" "\ntype moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -7640,12 +8047,13 @@ const struct Item gItemsInfo[] = [ITEM_MIRACLE_SEED] = { - .name = _("Miracle Seed"), + .name = ITEM_NAME("Miracle Seed"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7656,8 +8064,8 @@ const struct Item gItemsInfo[] = [ITEM_NEVER_MELT_ICE] = { - .name = _("Never-Melt Ice"), - .pluralName = _("Never-Melt Ice"), + .name = ITEM_NAME("Never-Melt Ice"), + .pluralName = ITEM_PLURAL_NAME("Never-Melt Ice"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7666,6 +8074,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Ice-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -7676,7 +8085,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_BELT] = { - .name = _("Black Belt"), + .name = ITEM_NAME("Black Belt"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7685,6 +8094,7 @@ const struct Item gItemsInfo[] = "boosts Fighting-" "\ntype moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -7695,7 +8105,7 @@ const struct Item gItemsInfo[] = [ITEM_POISON_BARB] = { - .name = _("Poison Barb"), + .name = ITEM_NAME("Poison Barb"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7704,6 +8114,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Poison-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -7714,8 +8125,8 @@ const struct Item gItemsInfo[] = [ITEM_SOFT_SAND] = { - .name = _("Soft Sand"), - .pluralName = _("Soft Sand"), + .name = ITEM_NAME("Soft Sand"), + .pluralName = ITEM_PLURAL_NAME("Soft Sand"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7724,6 +8135,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Ground-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -7734,7 +8146,7 @@ const struct Item gItemsInfo[] = [ITEM_SHARP_BEAK] = { - .name = _("Sharp Beak"), + .name = ITEM_NAME("Sharp Beak"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7743,6 +8155,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Flying-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -7753,12 +8166,13 @@ const struct Item gItemsInfo[] = [ITEM_TWISTED_SPOON] = { - .name = _("Twisted Spoon"), + .name = ITEM_NAME("Twisted Spoon"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7769,8 +8183,8 @@ const struct Item gItemsInfo[] = [ITEM_SILVER_POWDER] = { - .name = _("Silver Powder"), - .pluralName = _("Silver Powder"), + .name = ITEM_NAME("Silver Powder"), + .pluralName = ITEM_PLURAL_NAME("Silver Powder"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7779,6 +8193,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Bug-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -7789,12 +8204,13 @@ const struct Item gItemsInfo[] = [ITEM_HARD_STONE] = { - .name = _("Hard Stone"), + .name = ITEM_NAME("Hard Stone"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7805,7 +8221,7 @@ const struct Item gItemsInfo[] = [ITEM_SPELL_TAG] = { - .name = _("Spell Tag"), + .name = ITEM_NAME("Spell Tag"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7814,6 +8230,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Ghost-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -7824,7 +8241,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_FANG] = { - .name = _("Dragon Fang"), + .name = ITEM_NAME("Dragon Fang"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7833,6 +8250,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Dragon-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -7843,8 +8261,8 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_GLASSES] = { - .name = _("Black Glasses"), - .pluralName = _("Black Glasses"), + .name = ITEM_NAME("Black Glasses"), + .pluralName = ITEM_PLURAL_NAME("Black Glasses"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7853,6 +8271,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Dark-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -7863,7 +8282,7 @@ const struct Item gItemsInfo[] = [ITEM_METAL_COAT] = { - .name = _("Metal Coat"), + .name = ITEM_NAME("Metal Coat"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7872,6 +8291,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Steel-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7885,7 +8305,7 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_BAND] = { - .name = _("Choice Band"), + .name = ITEM_NAME("Choice Band"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_BAND, .description = COMPOUND_STRING( @@ -7893,6 +8313,7 @@ const struct Item gItemsInfo[] = "allows the use\nof " "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7902,8 +8323,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_SPECS] = { - .name = _("Choice Specs"), - .pluralName = _("Choice Specs"), + .name = ITEM_NAME("Choice Specs"), + .pluralName = ITEM_PLURAL_NAME("Choice Specs"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SPECS, .description = COMPOUND_STRING( @@ -7911,6 +8332,7 @@ const struct Item gItemsInfo[] = "allows the\nuse of " "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7920,8 +8342,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_SCARF] = { - .name = _("Choice Scarf"), - .pluralName = _("Choice Scarves"), + .name = ITEM_NAME("Choice Scarf"), + .pluralName = ITEM_PLURAL_NAME("Choice Scarves"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SCARF, .description = COMPOUND_STRING( @@ -7929,6 +8351,7 @@ const struct Item gItemsInfo[] = "allows the use\nof " "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7940,7 +8363,7 @@ const struct Item gItemsInfo[] = [ITEM_FLAME_ORB] = { - .name = _("Flame Orb"), + .name = ITEM_NAME("Flame Orb"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLAME_ORB, .description = COMPOUND_STRING( @@ -7948,6 +8371,7 @@ const struct Item gItemsInfo[] = "inflicts a\nburn on " "holder in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7957,7 +8381,7 @@ const struct Item gItemsInfo[] = [ITEM_TOXIC_ORB] = { - .name = _("Toxic Orb"), + .name = ITEM_NAME("Toxic Orb"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_TOXIC_ORB, .description = COMPOUND_STRING( @@ -7965,6 +8389,7 @@ const struct Item gItemsInfo[] = "badly poisons\nthe " "holder in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7976,7 +8401,7 @@ const struct Item gItemsInfo[] = [ITEM_DAMP_ROCK] = { - .name = _("Damp Rock"), + .name = ITEM_NAME("Damp Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DAMP_ROCK, .description = COMPOUND_STRING( @@ -7984,6 +8409,7 @@ const struct Item gItemsInfo[] = "of Rain Dance\nif " "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7993,7 +8419,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAT_ROCK] = { - .name = _("Heat Rock"), + .name = ITEM_NAME("Heat Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_HEAT_ROCK, .description = COMPOUND_STRING( @@ -8001,6 +8427,7 @@ const struct Item gItemsInfo[] = "of Sunny Day\nif " "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8010,7 +8437,7 @@ const struct Item gItemsInfo[] = [ITEM_SMOOTH_ROCK] = { - .name = _("Smooth Rock"), + .name = ITEM_NAME("Smooth Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SMOOTH_ROCK, .description = COMPOUND_STRING( @@ -8018,6 +8445,7 @@ const struct Item gItemsInfo[] = "of Sandstorm\nif " "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8027,7 +8455,7 @@ const struct Item gItemsInfo[] = [ITEM_ICY_ROCK] = { - .name = _("Icy Rock"), + .name = ITEM_NAME("Icy Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ICY_ROCK, #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_HAIL @@ -8047,6 +8475,7 @@ const struct Item gItemsInfo[] = "used by the holder."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -8058,7 +8487,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_SEED] = { - .name = _("Electric Seed"), + .name = ITEM_NAME("Electric Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN, @@ -8067,6 +8496,7 @@ const struct Item gItemsInfo[] = "Electric\nTerrain, " "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8076,7 +8506,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_SEED] = { - .name = _("Psychic Seed"), + .name = ITEM_NAME("Psychic Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN, @@ -8085,6 +8515,7 @@ const struct Item gItemsInfo[] = "Psychic\nTerrain, " "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8094,7 +8525,7 @@ const struct Item gItemsInfo[] = [ITEM_MISTY_SEED] = { - .name = _("Misty Seed"), + .name = ITEM_NAME("Misty Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_MISTY_TERRAIN, @@ -8103,6 +8534,7 @@ const struct Item gItemsInfo[] = "Misty Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8112,7 +8544,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASSY_SEED] = { - .name = _("Grassy Seed"), + .name = ITEM_NAME("Grassy Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_GRASSY_TERRAIN, @@ -8121,6 +8553,7 @@ const struct Item gItemsInfo[] = "Grassy Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8132,7 +8565,7 @@ const struct Item gItemsInfo[] = [ITEM_ABSORB_BULB] = { - .name = _("Absorb Bulb"), + .name = ITEM_NAME("Absorb Bulb"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ABSORB_BULB, .holdEffectParam = 0, @@ -8141,6 +8574,7 @@ const struct Item gItemsInfo[] = "the holder is\nhit by " "a Water-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8150,8 +8584,8 @@ const struct Item gItemsInfo[] = [ITEM_CELL_BATTERY] = { - .name = _("Cell Battery"), - .pluralName = _("Cell Batteries"), + .name = ITEM_NAME("Cell Battery"), + .pluralName = ITEM_PLURAL_NAME("Cell Batteries"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CELL_BATTERY, .holdEffectParam = 0, @@ -8160,6 +8594,7 @@ const struct Item gItemsInfo[] = "the holder is\nhit by " "an Electric move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8169,8 +8604,8 @@ const struct Item gItemsInfo[] = [ITEM_LUMINOUS_MOSS] = { - .name = _("Luminous Moss"), - .pluralName = _("Luminous Moss"), + .name = ITEM_NAME("Luminous Moss"), + .pluralName = ITEM_PLURAL_NAME("Luminous Moss"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_LUMINOUS_MOSS, .holdEffectParam = 0, @@ -8179,6 +8614,7 @@ const struct Item gItemsInfo[] = "the holder is\nhit by " "a Water-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8188,7 +8624,7 @@ const struct Item gItemsInfo[] = [ITEM_SNOWBALL] = { - .name = _("Snowball"), + .name = ITEM_NAME("Snowball"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SNOWBALL, .holdEffectParam = 0, @@ -8197,6 +8633,7 @@ const struct Item gItemsInfo[] = "holder is hit\nby an " "Ice-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8208,8 +8645,8 @@ const struct Item gItemsInfo[] = [ITEM_BRIGHT_POWDER] = { - .name = _("Bright Powder"), - .pluralName = _("Bright Powder"), + .name = ITEM_NAME("Bright Powder"), + .pluralName = ITEM_PLURAL_NAME("Bright Powder"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 10), .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, @@ -8218,6 +8655,7 @@ const struct Item gItemsInfo[] = "casts a glare to\n" "reduce accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8227,7 +8665,7 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_HERB] = { - .name = _("White Herb"), + .name = ITEM_NAME("White Herb"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_WHITE_HERB, .description = COMPOUND_STRING( @@ -8235,6 +8673,7 @@ const struct Item gItemsInfo[] = "restores any " "\nlowered stat."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8244,7 +8683,7 @@ const struct Item gItemsInfo[] = [ITEM_EXP_SHARE] = { - .name = _("Exp. Share"), + .name = ITEM_NAME("Exp. Share"), .holdEffect = HOLD_EFFECT_EXP_SHARE, #if I_EXP_SHARE_ITEM >= GEN_6 .price = 0, @@ -8260,6 +8699,7 @@ const struct Item gItemsInfo[] = "from battles."), #endif .pocket = I_EXP_SHARE_ITEM >= GEN_6 ? POCKET_KEY_ITEMS : POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_ExpShare, .flingPower = 30, @@ -8269,7 +8709,7 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_CLAW] = { - .name = _("Quick Claw"), + .name = ITEM_NAME("Quick Claw"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_QUICK_CLAW, .holdEffectParam = 20, @@ -8278,6 +8718,7 @@ const struct Item gItemsInfo[] = "occasionally\nallows " "the first strike."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8287,7 +8728,7 @@ const struct Item gItemsInfo[] = [ITEM_SOOTHE_BELL] = { - .name = _("Soothe Bell"), + .name = ITEM_NAME("Soothe Bell"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_FRIENDSHIP_UP, .description = COMPOUND_STRING( @@ -8295,6 +8736,7 @@ const struct Item gItemsInfo[] = "calms spirits\nand " "fosters friendship."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8304,7 +8746,7 @@ const struct Item gItemsInfo[] = [ITEM_MENTAL_HERB] = { - .name = _("Mental Herb"), + .name = ITEM_NAME("Mental Herb"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_MENTAL_HERB, .description = COMPOUND_STRING( @@ -8318,6 +8760,7 @@ const struct Item gItemsInfo[] = "of infatuation."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8327,12 +8770,13 @@ const struct Item gItemsInfo[] = [ITEM_KINGS_ROCK] = { - .name = _("King's Rock"), + .name = ITEM_NAME("King's Rock"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 5000 : 100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8343,11 +8787,12 @@ const struct Item gItemsInfo[] = [ITEM_AMULET_COIN] = { - .name = _("Amulet Coin"), + .name = ITEM_NAME("Amulet Coin"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 10000 : 100), .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8357,11 +8802,12 @@ const struct Item gItemsInfo[] = [ITEM_CLEANSE_TAG] = { - .name = _("Cleanse Tag"), + .name = ITEM_NAME("Cleanse Tag"), .price = (I_PRICE >= GEN_7) ? 5000 : 200, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8371,7 +8817,7 @@ const struct Item gItemsInfo[] = [ITEM_SMOKE_BALL] = { - .name = _("Smoke Ball"), + .name = ITEM_NAME("Smoke Ball"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CAN_ALWAYS_RUN, .description = COMPOUND_STRING( @@ -8379,6 +8825,7 @@ const struct Item gItemsInfo[] = "assures fleeing " "\nfrom wild Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8388,7 +8835,7 @@ const struct Item gItemsInfo[] = [ITEM_FOCUS_BAND] = { - .name = _("Focus Band"), + .name = ITEM_NAME("Focus Band"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_BAND, .holdEffectParam = 10, @@ -8397,6 +8844,7 @@ const struct Item gItemsInfo[] = "occasionally " "\nprevents fainting."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8406,7 +8854,7 @@ const struct Item gItemsInfo[] = [ITEM_LUCKY_EGG] = { - .name = _("Lucky Egg"), + .name = ITEM_NAME("Lucky Egg"), .price = (I_PRICE >= GEN_7) ? 10000 : 200, .holdEffect = HOLD_EFFECT_LUCKY_EGG, .description = COMPOUND_STRING( @@ -8414,6 +8862,7 @@ const struct Item gItemsInfo[] = "boosts Exp.\npoints " "earned in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8423,8 +8872,8 @@ const struct Item gItemsInfo[] = [ITEM_SCOPE_LENS] = { - .name = _("Scope Lens"), - .pluralName = _("Scope Lenses"), + .name = ITEM_NAME("Scope Lens"), + .pluralName = ITEM_PLURAL_NAME("Scope Lenses"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING( @@ -8432,6 +8881,7 @@ const struct Item gItemsInfo[] = "improves the " "\ncritical-hit rate."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8441,8 +8891,8 @@ const struct Item gItemsInfo[] = [ITEM_LEFTOVERS] = { - .name = _("Leftovers"), - .pluralName = _("Leftovers"), + .name = ITEM_NAME("Leftovers"), + .pluralName = ITEM_PLURAL_NAME("Leftovers"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LEFTOVERS, .holdEffectParam = 10, @@ -8451,6 +8901,7 @@ const struct Item gItemsInfo[] = "gradually\nrestores " "HP in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8460,7 +8911,7 @@ const struct Item gItemsInfo[] = [ITEM_SHELL_BELL] = { - .name = _("Shell Bell"), + .name = ITEM_NAME("Shell Bell"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SHELL_BELL, .holdEffectParam = 8, @@ -8469,6 +8920,7 @@ const struct Item gItemsInfo[] = "restores HP upon\n" "striking the foe."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8478,8 +8930,8 @@ const struct Item gItemsInfo[] = [ITEM_WIDE_LENS] = { - .name = _("Wide Lens"), - .pluralName = _("Wide Lenses"), + .name = ITEM_NAME("Wide Lens"), + .pluralName = ITEM_PLURAL_NAME("Wide Lenses"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WIDE_LENS, .holdEffectParam = 10, @@ -8488,6 +8940,7 @@ const struct Item gItemsInfo[] = "that boosts the\n" "accuracy of moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8497,7 +8950,7 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_BAND] = { - .name = _("Muscle Band"), + .name = ITEM_NAME("Muscle Band"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_MUSCLE_BAND, .holdEffectParam = 10, @@ -8506,6 +8959,7 @@ const struct Item gItemsInfo[] = "boosts the power " "\nof physical moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8515,8 +8969,8 @@ const struct Item gItemsInfo[] = [ITEM_WISE_GLASSES] = { - .name = _("Wise Glasses"), - .pluralName = _("Wise Glasses"), + .name = ITEM_NAME("Wise Glasses"), + .pluralName = ITEM_PLURAL_NAME("Wise Glasses"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WISE_GLASSES, .holdEffectParam = 10, @@ -8525,6 +8979,7 @@ const struct Item gItemsInfo[] = "that ups the\npower " "of special moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8534,7 +8989,7 @@ const struct Item gItemsInfo[] = [ITEM_EXPERT_BELT] = { - .name = _("Expert Belt"), + .name = ITEM_NAME("Expert Belt"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EXPERT_BELT, .holdEffectParam = 20, @@ -8543,6 +8998,7 @@ const struct Item gItemsInfo[] = "the power of\nsuper " "effective moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8552,8 +9008,8 @@ const struct Item gItemsInfo[] = [ITEM_LIGHT_CLAY] = { - .name = _("Light Clay"), - .pluralName = _("Light Clay"), + .name = ITEM_NAME("Light Clay"), + .pluralName = ITEM_PLURAL_NAME("Light Clay"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIGHT_CLAY, .description = COMPOUND_STRING( @@ -8561,6 +9017,7 @@ const struct Item gItemsInfo[] = "of barrier\nmoves " "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8570,7 +9027,7 @@ const struct Item gItemsInfo[] = [ITEM_LIFE_ORB] = { - .name = _("Life Orb"), + .name = ITEM_NAME("Life Orb"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIFE_ORB, .description = COMPOUND_STRING( @@ -8578,6 +9035,7 @@ const struct Item gItemsInfo[] = "but holder\nloses HP " "with each attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8587,7 +9045,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_HERB] = { - .name = _("Power Herb"), + .name = ITEM_NAME("Power Herb"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_POWER_HERB, .description = COMPOUND_STRING( @@ -8595,6 +9053,7 @@ const struct Item gItemsInfo[] = "use of a move\nthat " "charges first."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8604,8 +9063,8 @@ const struct Item gItemsInfo[] = [ITEM_FOCUS_SASH] = { - .name = _("Focus Sash"), - .pluralName = _("Focus Sashes"), + .name = ITEM_NAME("Focus Sash"), + .pluralName = ITEM_PLURAL_NAME("Focus Sashes"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_SASH, .description = COMPOUND_STRING( @@ -8613,6 +9072,7 @@ const struct Item gItemsInfo[] = "full HP, it\nendures " "KO hits with 1 HP."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8622,8 +9082,8 @@ const struct Item gItemsInfo[] = [ITEM_ZOOM_LENS] = { - .name = _("Zoom Lens"), - .pluralName = _("Zoom Lenses"), + .name = ITEM_NAME("Zoom Lens"), + .pluralName = ITEM_PLURAL_NAME("Zoom Lenses"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ZOOM_LENS, .holdEffectParam = 20, @@ -8632,6 +9092,7 @@ const struct Item gItemsInfo[] = "after the\nfoe, it'll " "boost accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8641,7 +9102,7 @@ const struct Item gItemsInfo[] = [ITEM_METRONOME] = { - .name = _("Metronome"), + .name = ITEM_NAME("Metronome"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_METRONOME, .holdEffectParam = 20, @@ -8650,6 +9111,7 @@ const struct Item gItemsInfo[] = "boosts a move\nused " "consecutively."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8659,7 +9121,7 @@ const struct Item gItemsInfo[] = [ITEM_IRON_BALL] = { - .name = _("Iron Ball"), + .name = ITEM_NAME("Iron Ball"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_IRON_BALL, .description = COMPOUND_STRING( @@ -8667,6 +9129,7 @@ const struct Item gItemsInfo[] = "becomes vulnerable\n" "to Ground moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -8676,11 +9139,12 @@ const struct Item gItemsInfo[] = [ITEM_LAGGING_TAIL] = { - .name = _("Lagging Tail"), + .name = ITEM_NAME("Lagging Tail"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8690,7 +9154,7 @@ const struct Item gItemsInfo[] = [ITEM_DESTINY_KNOT] = { - .name = _("Destiny Knot"), + .name = ITEM_NAME("Destiny Knot"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DESTINY_KNOT, .description = COMPOUND_STRING( @@ -8698,6 +9162,7 @@ const struct Item gItemsInfo[] = "in love, the\nfoe " "does too."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8707,8 +9172,8 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_SLUDGE] = { - .name = _("Black Sludge"), - .pluralName = _("Black Sludge"), + .name = ITEM_NAME("Black Sludge"), + .pluralName = ITEM_PLURAL_NAME("Black Sludge"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BLACK_SLUDGE, .description = COMPOUND_STRING( @@ -8716,6 +9181,7 @@ const struct Item gItemsInfo[] = "Poison-types. " "\nDamages all others."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8725,7 +9191,7 @@ const struct Item gItemsInfo[] = [ITEM_GRIP_CLAW] = { - .name = _("Grip Claw"), + .name = ITEM_NAME("Grip Claw"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GRIP_CLAW, .description = COMPOUND_STRING( @@ -8733,6 +9199,7 @@ const struct Item gItemsInfo[] = "extends binding " "\nmoves like Wrap."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -8742,7 +9209,7 @@ const struct Item gItemsInfo[] = [ITEM_STICKY_BARB] = { - .name = _("Sticky Barb"), + .name = ITEM_NAME("Sticky Barb"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_STICKY_BARB, .description = COMPOUND_STRING( @@ -8750,6 +9217,7 @@ const struct Item gItemsInfo[] = "each turn. May\n" "latch on to foes."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8759,7 +9227,7 @@ const struct Item gItemsInfo[] = [ITEM_SHED_SHELL] = { - .name = _("Shed Shell"), + .name = ITEM_NAME("Shed Shell"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SHED_SHELL, .description = COMPOUND_STRING( @@ -8767,6 +9235,7 @@ const struct Item gItemsInfo[] = "to switch out " "\nwithout fail."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8776,7 +9245,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_ROOT] = { - .name = _("Big Root"), + .name = ITEM_NAME("Big Root"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BIG_ROOT, .holdEffectParam = 30, @@ -8785,6 +9254,7 @@ const struct Item gItemsInfo[] = "ups the power of\n" "HP-stealing moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8794,7 +9264,7 @@ const struct Item gItemsInfo[] = [ITEM_RAZOR_CLAW] = { - .name = _("Razor Claw"), + .name = ITEM_NAME("Razor Claw"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING( @@ -8802,6 +9272,7 @@ const struct Item gItemsInfo[] = "ups the\nholder's " "critical-hit ratio."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8812,12 +9283,13 @@ const struct Item gItemsInfo[] = [ITEM_RAZOR_FANG] = { - .name = _("Razor Fang"), + .name = ITEM_NAME("Razor Fang"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8828,7 +9300,7 @@ const struct Item gItemsInfo[] = [ITEM_EVIOLITE] = { - .name = _("Eviolite"), + .name = ITEM_NAME("Eviolite"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EVIOLITE, .holdEffectParam = 50, @@ -8837,6 +9309,7 @@ const struct Item gItemsInfo[] = "Sp. Def of\nPokémon " "that can evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -8846,7 +9319,7 @@ const struct Item gItemsInfo[] = [ITEM_FLOAT_STONE] = { - .name = _("Float Stone"), + .name = ITEM_NAME("Float Stone"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLOAT_STONE, .description = COMPOUND_STRING( @@ -8854,6 +9327,7 @@ const struct Item gItemsInfo[] = "when held, it\nhalves " "a Pokémon's weight."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8863,7 +9337,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCKY_HELMET] = { - .name = _("Rocky Helmet"), + .name = ITEM_NAME("Rocky Helmet"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ROCKY_HELMET, .holdEffectParam = 0, @@ -8872,6 +9346,7 @@ const struct Item gItemsInfo[] = "they touch its " "\nholder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8881,7 +9356,7 @@ const struct Item gItemsInfo[] = [ITEM_AIR_BALLOON] = { - .name = _("Air Balloon"), + .name = ITEM_NAME("Air Balloon"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_AIR_BALLOON, .holdEffectParam = 0, @@ -8890,6 +9365,7 @@ const struct Item gItemsInfo[] = "float but bursts\n" "if hit by an attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8899,7 +9375,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_CARD] = { - .name = _("Red Card"), + .name = ITEM_NAME("Red Card"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RED_CARD, .holdEffectParam = 0, @@ -8908,6 +9384,7 @@ const struct Item gItemsInfo[] = "foe if they hit\nthe " "holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8917,7 +9394,7 @@ const struct Item gItemsInfo[] = [ITEM_RING_TARGET] = { - .name = _("Ring Target"), + .name = ITEM_NAME("Ring Target"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RING_TARGET, .holdEffectParam = 0, @@ -8926,6 +9403,7 @@ const struct Item gItemsInfo[] = "have no effect\nwill " "hit the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8935,7 +9413,7 @@ const struct Item gItemsInfo[] = [ITEM_BINDING_BAND] = { - .name = _("Binding Band"), + .name = ITEM_NAME("Binding Band"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BINDING_BAND, .description = COMPOUND_STRING( @@ -8943,6 +9421,7 @@ const struct Item gItemsInfo[] = "power of binding " "\nmoves when held."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8952,7 +9431,7 @@ const struct Item gItemsInfo[] = [ITEM_EJECT_BUTTON] = { - .name = _("Eject Button"), + .name = ITEM_NAME("Eject Button"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EJECT_BUTTON, .holdEffectParam = 0, @@ -8961,6 +9440,7 @@ const struct Item gItemsInfo[] = "user if they're\nhit " "by the foe."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8970,8 +9450,8 @@ const struct Item gItemsInfo[] = [ITEM_WEAKNESS_POLICY] = { - .name = _("Weakness Policy"), - .pluralName = _("Weakness Policies"), + .name = ITEM_NAME("Weakness Policy"), + .pluralName = ITEM_PLURAL_NAME("Weakness Policies"), .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_WEAKNESS_POLICY, .holdEffectParam = 0, @@ -8980,6 +9460,7 @@ const struct Item gItemsInfo[] = "effective move,\n" "ups Atk and Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8989,7 +9470,7 @@ const struct Item gItemsInfo[] = [ITEM_ASSAULT_VEST] = { - .name = _("Assault Vest"), + .name = ITEM_NAME("Assault Vest"), .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_ASSAULT_VEST, .holdEffectParam = 50, @@ -8998,6 +9479,7 @@ const struct Item gItemsInfo[] = "prevents the\nuse " "of status moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9007,8 +9489,8 @@ const struct Item gItemsInfo[] = [ITEM_SAFETY_GOGGLES] = { - .name = _("Safety Goggles"), - .pluralName = _("Safety Goggles"), + .name = ITEM_NAME("Safety Goggles"), + .pluralName = ITEM_PLURAL_NAME("Safety Goggles"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_SAFETY_GOGGLES, .description = COMPOUND_STRING( @@ -9016,6 +9498,7 @@ const struct Item gItemsInfo[] = "weather damage and " "\npowder moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9025,7 +9508,7 @@ const struct Item gItemsInfo[] = [ITEM_ADRENALINE_ORB] = { - .name = _("Adrenaline Orb"), + .name = ITEM_NAME("Adrenaline Orb"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_8) ? 4000 : 300), .holdEffect = HOLD_EFFECT_ADRENALINE_ORB, .description = COMPOUND_STRING( @@ -9033,6 +9516,7 @@ const struct Item gItemsInfo[] = "Speed if the\nholder " "is intimidated."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9042,7 +9526,7 @@ const struct Item gItemsInfo[] = [ITEM_TERRAIN_EXTENDER] = { - .name = _("Terrain Extender"), + .name = ITEM_NAME("Terrain Extender"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_TERRAIN_EXTENDER, .description = COMPOUND_STRING( @@ -9050,6 +9534,7 @@ const struct Item gItemsInfo[] = "of the active " "\nbattle terrain."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -9059,8 +9544,8 @@ const struct Item gItemsInfo[] = [ITEM_PROTECTIVE_PADS] = { - .name = _("Protective Pads"), - .pluralName = _("Protective Pads"), + .name = ITEM_NAME("Protective Pads"), + .pluralName = ITEM_PLURAL_NAME("Protective Pads"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_PROTECTIVE_PADS, .description = COMPOUND_STRING( @@ -9068,6 +9553,7 @@ const struct Item gItemsInfo[] = "from contact\nmove " "effects."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9077,7 +9563,7 @@ const struct Item gItemsInfo[] = [ITEM_THROAT_SPRAY] = { - .name = _("Throat Spray"), + .name = ITEM_NAME("Throat Spray"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_THROAT_SPRAY, .description = COMPOUND_STRING( @@ -9085,6 +9571,7 @@ const struct Item gItemsInfo[] = "the holder\nuses a " "sound-based move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9094,7 +9581,7 @@ const struct Item gItemsInfo[] = [ITEM_EJECT_PACK] = { - .name = _("Eject Pack"), + .name = ITEM_NAME("Eject Pack"), .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_EJECT_PACK, .description = COMPOUND_STRING( @@ -9102,6 +9589,7 @@ const struct Item gItemsInfo[] = "switch if its\nstats " "are lowered."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 50, @@ -9111,8 +9599,8 @@ const struct Item gItemsInfo[] = [ITEM_HEAVY_DUTY_BOOTS] = { - .name = _("Heavy-Duty Boots"), - .pluralName = _("Heavy-Duty Boots"), + .name = ITEM_NAME("Heavy-Duty Boots"), + .pluralName = ITEM_PLURAL_NAME("Heavy-Duty Boots"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_HEAVY_DUTY_BOOTS, .description = COMPOUND_STRING( @@ -9120,6 +9608,7 @@ const struct Item gItemsInfo[] = "effects of\ntraps " "set in the field."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9129,8 +9618,8 @@ const struct Item gItemsInfo[] = [ITEM_BLUNDER_POLICY] = { - .name = _("Blunder Policy"), - .pluralName = _("Blunder Policies"), + .name = ITEM_NAME("Blunder Policy"), + .pluralName = ITEM_PLURAL_NAME("Blunder Policies"), .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_BLUNDER_POLICY, .description = COMPOUND_STRING( @@ -9138,6 +9627,7 @@ const struct Item gItemsInfo[] = "the user misses " "\ndue to Accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9147,7 +9637,7 @@ const struct Item gItemsInfo[] = [ITEM_ROOM_SERVICE] = { - .name = _("Room Service"), + .name = ITEM_NAME("Room Service"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_ROOM_SERVICE, .description = COMPOUND_STRING( @@ -9155,6 +9645,7 @@ const struct Item gItemsInfo[] = "Trick Room is " "\nactive."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -9164,7 +9655,7 @@ const struct Item gItemsInfo[] = [ITEM_UTILITY_UMBRELLA] = { - .name = _("Utility Umbrella"), + .name = ITEM_NAME("Utility Umbrella"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_UTILITY_UMBRELLA, .description = COMPOUND_STRING( @@ -9172,6 +9663,7 @@ const struct Item gItemsInfo[] = "protects from " "\nweather effects."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -9183,8 +9675,8 @@ const struct Item gItemsInfo[] = [ITEM_CHERI_BERRY] = { - .name = _("Cheri Berry"), - .pluralName = _("Cheri Berries"), + .name = ITEM_NAME("Cheri Berry"), + .pluralName = ITEM_PLURAL_NAME("Cheri Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PAR, .description = COMPOUND_STRING( @@ -9203,8 +9695,8 @@ const struct Item gItemsInfo[] = [ITEM_CHESTO_BERRY] = { - .name = _("Chesto Berry"), - .pluralName = _("Chesto Berries"), + .name = ITEM_NAME("Chesto Berry"), + .pluralName = ITEM_PLURAL_NAME("Chesto Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_SLP, .description = COMPOUND_STRING( @@ -9223,8 +9715,8 @@ const struct Item gItemsInfo[] = [ITEM_PECHA_BERRY] = { - .name = _("Pecha Berry"), - .pluralName = _("Pecha Berries"), + .name = ITEM_NAME("Pecha Berry"), + .pluralName = ITEM_PLURAL_NAME("Pecha Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PSN, .description = COMPOUND_STRING( @@ -9243,8 +9735,8 @@ const struct Item gItemsInfo[] = [ITEM_RAWST_BERRY] = { - .name = _("Rawst Berry"), - .pluralName = _("Rawst Berries"), + .name = ITEM_NAME("Rawst Berry"), + .pluralName = ITEM_PLURAL_NAME("Rawst Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_BRN, .description = COMPOUND_STRING( @@ -9263,8 +9755,8 @@ const struct Item gItemsInfo[] = [ITEM_ASPEAR_BERRY] = { - .name = _("Aspear Berry"), - .pluralName = _("Aspear Berries"), + .name = ITEM_NAME("Aspear Berry"), + .pluralName = ITEM_PLURAL_NAME("Aspear Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_FRZ, .description = COMPOUND_STRING( @@ -9283,8 +9775,8 @@ const struct Item gItemsInfo[] = [ITEM_LEPPA_BERRY] = { - .name = _("Leppa Berry"), - .pluralName = _("Leppa Berries"), + .name = ITEM_NAME("Leppa Berry"), + .pluralName = ITEM_PLURAL_NAME("Leppa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_PP, .holdEffectParam = 10, @@ -9304,8 +9796,8 @@ const struct Item gItemsInfo[] = [ITEM_ORAN_BERRY] = { - .name = _("Oran Berry"), - .pluralName = _("Oran Berries"), + .name = ITEM_NAME("Oran Berry"), + .pluralName = ITEM_PLURAL_NAME("Oran Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 10, @@ -9325,8 +9817,8 @@ const struct Item gItemsInfo[] = [ITEM_PERSIM_BERRY] = { - .name = _("Persim Berry"), - .pluralName = _("Persim Berries"), + .name = ITEM_NAME("Persim Berry"), + .pluralName = ITEM_PLURAL_NAME("Persim Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_CONFUSION, .description = COMPOUND_STRING( @@ -9345,8 +9837,8 @@ const struct Item gItemsInfo[] = [ITEM_LUM_BERRY] = { - .name = _("Lum Berry"), - .pluralName = _("Lum Berries"), + .name = ITEM_NAME("Lum Berry"), + .pluralName = ITEM_PLURAL_NAME("Lum Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_STATUS, .description = COMPOUND_STRING( @@ -9365,16 +9857,16 @@ const struct Item gItemsInfo[] = [ITEM_SITRUS_BERRY] = { - .name = _("Sitrus Berry"), - .pluralName = _("Sitrus Berries"), + .name = ITEM_NAME("Sitrus Berry"), + .pluralName = ITEM_PLURAL_NAME("Sitrus Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, #if I_SITRUS_BERRY_HEAL >= GEN_4 .holdEffect = HOLD_EFFECT_RESTORE_PCT_HP, .holdEffectParam = 25, .description = COMPOUND_STRING( - "A hold item that " - "restores the\nuser's " - "HP a little."), + "A hold item\nthat " + "restores the user's " + "HP a\nlittle."), #else .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 30, @@ -9395,8 +9887,8 @@ const struct Item gItemsInfo[] = [ITEM_FIGY_BERRY] = { - .name = _("Figy Berry"), - .pluralName = _("Figy Berries"), + .name = ITEM_NAME("Figy Berry"), + .pluralName = ITEM_PLURAL_NAME("Figy Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SPICY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9411,8 +9903,8 @@ const struct Item gItemsInfo[] = [ITEM_WIKI_BERRY] = { - .name = _("Wiki Berry"), - .pluralName = _("Wiki Berries"), + .name = ITEM_NAME("Wiki Berry"), + .pluralName = ITEM_PLURAL_NAME("Wiki Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_DRY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9427,8 +9919,8 @@ const struct Item gItemsInfo[] = [ITEM_MAGO_BERRY] = { - .name = _("Mago Berry"), - .pluralName = _("Mago Berries"), + .name = ITEM_NAME("Mago Berry"), + .pluralName = ITEM_PLURAL_NAME("Mago Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SWEET, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9443,8 +9935,8 @@ const struct Item gItemsInfo[] = [ITEM_AGUAV_BERRY] = { - .name = _("Aguav Berry"), - .pluralName = _("Aguav Berries"), + .name = ITEM_NAME("Aguav Berry"), + .pluralName = ITEM_PLURAL_NAME("Aguav Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_BITTER, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9459,8 +9951,8 @@ const struct Item gItemsInfo[] = [ITEM_IAPAPA_BERRY] = { - .name = _("Iapapa Berry"), - .pluralName = _("Iapapa Berries"), + .name = ITEM_NAME("Iapapa Berry"), + .pluralName = ITEM_PLURAL_NAME("Iapapa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SOUR, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9475,8 +9967,8 @@ const struct Item gItemsInfo[] = [ITEM_RAZZ_BERRY] = { - .name = _("Razz Berry"), - .pluralName = _("Razz Berries"), + .name = ITEM_NAME("Razz Berry"), + .pluralName = ITEM_PLURAL_NAME("Razz Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9492,8 +9984,8 @@ const struct Item gItemsInfo[] = [ITEM_BLUK_BERRY] = { - .name = _("Bluk Berry"), - .pluralName = _("Bluk Berries"), + .name = ITEM_NAME("Bluk Berry"), + .pluralName = ITEM_PLURAL_NAME("Bluk Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9509,8 +10001,8 @@ const struct Item gItemsInfo[] = [ITEM_NANAB_BERRY] = { - .name = _("Nanab Berry"), - .pluralName = _("Nanab Berries"), + .name = ITEM_NAME("Nanab Berry"), + .pluralName = ITEM_PLURAL_NAME("Nanab Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9526,8 +10018,8 @@ const struct Item gItemsInfo[] = [ITEM_WEPEAR_BERRY] = { - .name = _("Wepear Berry"), - .pluralName = _("Wepear Berries"), + .name = ITEM_NAME("Wepear Berry"), + .pluralName = ITEM_PLURAL_NAME("Wepear Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9543,8 +10035,8 @@ const struct Item gItemsInfo[] = [ITEM_PINAP_BERRY] = { - .name = _("Pinap Berry"), - .pluralName = _("Pinap Berries"), + .name = ITEM_NAME("Pinap Berry"), + .pluralName = ITEM_PLURAL_NAME("Pinap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9560,8 +10052,8 @@ const struct Item gItemsInfo[] = [ITEM_POMEG_BERRY] = { - .name = _("Pomeg Berry"), - .pluralName = _("Pomeg Berries"), + .name = ITEM_NAME("Pomeg Berry"), + .pluralName = ITEM_PLURAL_NAME("Pomeg Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9578,8 +10070,8 @@ const struct Item gItemsInfo[] = [ITEM_KELPSY_BERRY] = { - .name = _("Kelpsy Berry"), - .pluralName = _("Kelpsy Berries"), + .name = ITEM_NAME("Kelpsy Berry"), + .pluralName = ITEM_PLURAL_NAME("Kelpsy Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9596,8 +10088,8 @@ const struct Item gItemsInfo[] = [ITEM_QUALOT_BERRY] = { - .name = _("Qualot Berry"), - .pluralName = _("Qualot Berries"), + .name = ITEM_NAME("Qualot Berry"), + .pluralName = ITEM_PLURAL_NAME("Qualot Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9614,8 +10106,8 @@ const struct Item gItemsInfo[] = [ITEM_HONDEW_BERRY] = { - .name = _("Hondew Berry"), - .pluralName = _("Hondew Berries"), + .name = ITEM_NAME("Hondew Berry"), + .pluralName = ITEM_PLURAL_NAME("Hondew Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9632,8 +10124,8 @@ const struct Item gItemsInfo[] = [ITEM_GREPA_BERRY] = { - .name = _("Grepa Berry"), - .pluralName = _("Grepa Berries"), + .name = ITEM_NAME("Grepa Berry"), + .pluralName = ITEM_PLURAL_NAME("Grepa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9650,8 +10142,8 @@ const struct Item gItemsInfo[] = [ITEM_TAMATO_BERRY] = { - .name = _("Tamato Berry"), - .pluralName = _("Tamato Berries"), + .name = ITEM_NAME("Tamato Berry"), + .pluralName = ITEM_PLURAL_NAME("Tamato Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon " @@ -9668,8 +10160,8 @@ const struct Item gItemsInfo[] = [ITEM_CORNN_BERRY] = { - .name = _("Cornn Berry"), - .pluralName = _("Cornn Berries"), + .name = ITEM_NAME("Cornn Berry"), + .pluralName = ITEM_PLURAL_NAME("Cornn Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9685,8 +10177,8 @@ const struct Item gItemsInfo[] = [ITEM_MAGOST_BERRY] = { - .name = _("Magost Berry"), - .pluralName = _("Magost Berries"), + .name = ITEM_NAME("Magost Berry"), + .pluralName = ITEM_PLURAL_NAME("Magost Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9702,8 +10194,8 @@ const struct Item gItemsInfo[] = [ITEM_RABUTA_BERRY] = { - .name = _("Rabuta Berry"), - .pluralName = _("Rabuta Berries"), + .name = ITEM_NAME("Rabuta Berry"), + .pluralName = ITEM_PLURAL_NAME("Rabuta Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9719,8 +10211,8 @@ const struct Item gItemsInfo[] = [ITEM_NOMEL_BERRY] = { - .name = _("Nomel Berry"), - .pluralName = _("Nomel Berries"), + .name = ITEM_NAME("Nomel Berry"), + .pluralName = ITEM_PLURAL_NAME("Nomel Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9736,8 +10228,8 @@ const struct Item gItemsInfo[] = [ITEM_SPELON_BERRY] = { - .name = _("Spelon Berry"), - .pluralName = _("Spelon Berries"), + .name = ITEM_NAME("Spelon Berry"), + .pluralName = ITEM_PLURAL_NAME("Spelon Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9753,8 +10245,8 @@ const struct Item gItemsInfo[] = [ITEM_PAMTRE_BERRY] = { - .name = _("Pamtre Berry"), - .pluralName = _("Pamtre Berries"), + .name = ITEM_NAME("Pamtre Berry"), + .pluralName = ITEM_PLURAL_NAME("Pamtre Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9770,8 +10262,8 @@ const struct Item gItemsInfo[] = [ITEM_WATMEL_BERRY] = { - .name = _("Watmel Berry"), - .pluralName = _("Watmel Berries"), + .name = ITEM_NAME("Watmel Berry"), + .pluralName = ITEM_PLURAL_NAME("Watmel Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9787,8 +10279,8 @@ const struct Item gItemsInfo[] = [ITEM_DURIN_BERRY] = { - .name = _("Durin Berry"), - .pluralName = _("Durin Berries"), + .name = ITEM_NAME("Durin Berry"), + .pluralName = ITEM_PLURAL_NAME("Durin Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9804,8 +10296,8 @@ const struct Item gItemsInfo[] = [ITEM_BELUE_BERRY] = { - .name = _("Belue Berry"), - .pluralName = _("Belue Berries"), + .name = ITEM_NAME("Belue Berry"), + .pluralName = ITEM_PLURAL_NAME("Belue Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -9821,8 +10313,8 @@ const struct Item gItemsInfo[] = [ITEM_CHILAN_BERRY] = { - .name = _("Chilan Berry"), - .pluralName = _("Chilan Berries"), + .name = ITEM_NAME("Chilan Berry"), + .pluralName = ITEM_PLURAL_NAME("Chilan Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_NORMAL, @@ -9840,8 +10332,8 @@ const struct Item gItemsInfo[] = [ITEM_OCCA_BERRY] = { - .name = _("Occa Berry"), - .pluralName = _("Occa Berries"), + .name = ITEM_NAME("Occa Berry"), + .pluralName = ITEM_PLURAL_NAME("Occa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIRE, @@ -9859,8 +10351,8 @@ const struct Item gItemsInfo[] = [ITEM_PASSHO_BERRY] = { - .name = _("Passho Berry"), - .pluralName = _("Passho Berries"), + .name = ITEM_NAME("Passho Berry"), + .pluralName = ITEM_PLURAL_NAME("Passho Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_WATER, @@ -9878,8 +10370,8 @@ const struct Item gItemsInfo[] = [ITEM_WACAN_BERRY] = { - .name = _("Wacan Berry"), - .pluralName = _("Wacan Berries"), + .name = ITEM_NAME("Wacan Berry"), + .pluralName = ITEM_PLURAL_NAME("Wacan Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ELECTRIC, @@ -9897,8 +10389,8 @@ const struct Item gItemsInfo[] = [ITEM_RINDO_BERRY] = { - .name = _("Rindo Berry"), - .pluralName = _("Rindo Berries"), + .name = ITEM_NAME("Rindo Berry"), + .pluralName = ITEM_PLURAL_NAME("Rindo Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GRASS, @@ -9916,8 +10408,8 @@ const struct Item gItemsInfo[] = [ITEM_YACHE_BERRY] = { - .name = _("Yache Berry"), - .pluralName = _("Yache Berries"), + .name = ITEM_NAME("Yache Berry"), + .pluralName = ITEM_PLURAL_NAME("Yache Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ICE, @@ -9935,8 +10427,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOPLE_BERRY] = { - .name = _("Chople Berry"), - .pluralName = _("Chople Berries"), + .name = ITEM_NAME("Chople Berry"), + .pluralName = ITEM_PLURAL_NAME("Chople Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIGHTING, @@ -9954,8 +10446,8 @@ const struct Item gItemsInfo[] = [ITEM_KEBIA_BERRY] = { - .name = _("Kebia Berry"), - .pluralName = _("Kebia Berries"), + .name = ITEM_NAME("Kebia Berry"), + .pluralName = ITEM_PLURAL_NAME("Kebia Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_POISON, @@ -9973,8 +10465,8 @@ const struct Item gItemsInfo[] = [ITEM_SHUCA_BERRY] = { - .name = _("Shuca Berry"), - .pluralName = _("Shuca Berries"), + .name = ITEM_NAME("Shuca Berry"), + .pluralName = ITEM_PLURAL_NAME("Shuca Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GROUND, @@ -9992,8 +10484,8 @@ const struct Item gItemsInfo[] = [ITEM_COBA_BERRY] = { - .name = _("Coba Berry"), - .pluralName = _("Coba Berries"), + .name = ITEM_NAME("Coba Berry"), + .pluralName = ITEM_PLURAL_NAME("Coba Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FLYING, @@ -10011,8 +10503,8 @@ const struct Item gItemsInfo[] = [ITEM_PAYAPA_BERRY] = { - .name = _("Payapa Berry"), - .pluralName = _("Payapa Berries"), + .name = ITEM_NAME("Payapa Berry"), + .pluralName = ITEM_PLURAL_NAME("Payapa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_PSYCHIC, @@ -10030,8 +10522,8 @@ const struct Item gItemsInfo[] = [ITEM_TANGA_BERRY] = { - .name = _("Tanga Berry"), - .pluralName = _("Tanga Berries"), + .name = ITEM_NAME("Tanga Berry"), + .pluralName = ITEM_PLURAL_NAME("Tanga Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_BUG, @@ -10049,8 +10541,8 @@ const struct Item gItemsInfo[] = [ITEM_CHARTI_BERRY] = { - .name = _("Charti Berry"), - .pluralName = _("Charti Berries"), + .name = ITEM_NAME("Charti Berry"), + .pluralName = ITEM_PLURAL_NAME("Charti Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ROCK, @@ -10068,8 +10560,8 @@ const struct Item gItemsInfo[] = [ITEM_KASIB_BERRY] = { - .name = _("Kasib Berry"), - .pluralName = _("Kasib Berries"), + .name = ITEM_NAME("Kasib Berry"), + .pluralName = ITEM_PLURAL_NAME("Kasib Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GHOST, @@ -10087,8 +10579,8 @@ const struct Item gItemsInfo[] = [ITEM_HABAN_BERRY] = { - .name = _("Haban Berry"), - .pluralName = _("Haban Berries"), + .name = ITEM_NAME("Haban Berry"), + .pluralName = ITEM_PLURAL_NAME("Haban Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DRAGON, @@ -10106,8 +10598,8 @@ const struct Item gItemsInfo[] = [ITEM_COLBUR_BERRY] = { - .name = _("Colbur Berry"), - .pluralName = _("Colbur Berries"), + .name = ITEM_NAME("Colbur Berry"), + .pluralName = ITEM_PLURAL_NAME("Colbur Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DARK, @@ -10125,8 +10617,8 @@ const struct Item gItemsInfo[] = [ITEM_BABIRI_BERRY] = { - .name = _("Babiri Berry"), - .pluralName = _("Babiri Berries"), + .name = ITEM_NAME("Babiri Berry"), + .pluralName = ITEM_PLURAL_NAME("Babiri Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_STEEL, @@ -10144,8 +10636,8 @@ const struct Item gItemsInfo[] = [ITEM_ROSELI_BERRY] = { - .name = _("Roseli Berry"), - .pluralName = _("Roseli Berries"), + .name = ITEM_NAME("Roseli Berry"), + .pluralName = ITEM_PLURAL_NAME("Roseli Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FAIRY, @@ -10163,8 +10655,8 @@ const struct Item gItemsInfo[] = [ITEM_LIECHI_BERRY] = { - .name = _("Liechi Berry"), - .pluralName = _("Liechi Berries"), + .name = ITEM_NAME("Liechi Berry"), + .pluralName = ITEM_PLURAL_NAME("Liechi Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ATTACK_UP, .holdEffectParam = 4, @@ -10182,8 +10674,8 @@ const struct Item gItemsInfo[] = [ITEM_GANLON_BERRY] = { - .name = _("Ganlon Berry"), - .pluralName = _("Ganlon Berries"), + .name = ITEM_NAME("Ganlon Berry"), + .pluralName = ITEM_PLURAL_NAME("Ganlon Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_DEFENSE_UP, .holdEffectParam = 4, @@ -10201,8 +10693,8 @@ const struct Item gItemsInfo[] = [ITEM_SALAC_BERRY] = { - .name = _("Salac Berry"), - .pluralName = _("Salac Berries"), + .name = ITEM_NAME("Salac Berry"), + .pluralName = ITEM_PLURAL_NAME("Salac Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SPEED_UP, .holdEffectParam = 4, @@ -10220,8 +10712,8 @@ const struct Item gItemsInfo[] = [ITEM_PETAYA_BERRY] = { - .name = _("Petaya Berry"), - .pluralName = _("Petaya Berries"), + .name = ITEM_NAME("Petaya Berry"), + .pluralName = ITEM_PLURAL_NAME("Petaya Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_ATTACK_UP, .holdEffectParam = 4, @@ -10239,8 +10731,8 @@ const struct Item gItemsInfo[] = [ITEM_APICOT_BERRY] = { - .name = _("Apicot Berry"), - .pluralName = _("Apicot Berries"), + .name = ITEM_NAME("Apicot Berry"), + .pluralName = ITEM_PLURAL_NAME("Apicot Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_DEFENSE_UP, .holdEffectParam = 4, @@ -10258,8 +10750,8 @@ const struct Item gItemsInfo[] = [ITEM_LANSAT_BERRY] = { - .name = _("Lansat Berry"), - .pluralName = _("Lansat Berries"), + .name = ITEM_NAME("Lansat Berry"), + .pluralName = ITEM_PLURAL_NAME("Lansat Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CRITICAL_UP, .holdEffectParam = 4, @@ -10277,8 +10769,8 @@ const struct Item gItemsInfo[] = [ITEM_STARF_BERRY] = { - .name = _("Starf Berry"), - .pluralName = _("Starf Berries"), + .name = ITEM_NAME("Starf Berry"), + .pluralName = ITEM_PLURAL_NAME("Starf Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RANDOM_STAT_UP, .holdEffectParam = 4, @@ -10296,8 +10788,8 @@ const struct Item gItemsInfo[] = [ITEM_ENIGMA_BERRY] = { - .name = _("Enigma Berry"), - .pluralName = _("Enigma Berries"), + .name = ITEM_NAME("Enigma Berry"), + .pluralName = ITEM_PLURAL_NAME("Enigma Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ENIGMA_BERRY, .description = COMPOUND_STRING( @@ -10314,8 +10806,8 @@ const struct Item gItemsInfo[] = [ITEM_MICLE_BERRY] = { - .name = _("Micle Berry"), - .pluralName = _("Micle Berries"), + .name = ITEM_NAME("Micle Berry"), + .pluralName = ITEM_PLURAL_NAME("Micle Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MICLE_BERRY, .holdEffectParam = 4, @@ -10333,8 +10825,8 @@ const struct Item gItemsInfo[] = [ITEM_CUSTAP_BERRY] = { - .name = _("Custap Berry"), - .pluralName = _("Custap Berries"), + .name = ITEM_NAME("Custap Berry"), + .pluralName = ITEM_PLURAL_NAME("Custap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CUSTAP_BERRY, .holdEffectParam = 4, @@ -10352,8 +10844,8 @@ const struct Item gItemsInfo[] = [ITEM_JABOCA_BERRY] = { - .name = _("Jaboca Berry"), - .pluralName = _("Jaboca Berries"), + .name = ITEM_NAME("Jaboca Berry"), + .pluralName = ITEM_PLURAL_NAME("Jaboca Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_JABOCA_BERRY, .description = COMPOUND_STRING( @@ -10370,8 +10862,8 @@ const struct Item gItemsInfo[] = [ITEM_ROWAP_BERRY] = { - .name = _("Rowap Berry"), - .pluralName = _("Rowap Berries"), + .name = ITEM_NAME("Rowap Berry"), + .pluralName = ITEM_PLURAL_NAME("Rowap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ROWAP_BERRY, .description = COMPOUND_STRING( @@ -10388,8 +10880,8 @@ const struct Item gItemsInfo[] = [ITEM_KEE_BERRY] = { - .name = _("Kee Berry"), - .pluralName = _("Kee Berries"), + .name = ITEM_NAME("Kee Berry"), + .pluralName = ITEM_PLURAL_NAME("Kee Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_KEE_BERRY, .description = COMPOUND_STRING( @@ -10406,8 +10898,8 @@ const struct Item gItemsInfo[] = [ITEM_MARANGA_BERRY] = { - .name = _("Maranga Berry"), - .pluralName = _("Maranga Berries"), + .name = ITEM_NAME("Maranga Berry"), + .pluralName = ITEM_PLURAL_NAME("Maranga Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MARANGA_BERRY, .description = COMPOUND_STRING( @@ -10424,8 +10916,8 @@ const struct Item gItemsInfo[] = [ITEM_ENIGMA_BERRY_E_READER] = { - .name = _("Enigma Berry"), - .pluralName = _("Enigma Berries"), + .name = ITEM_NAME("Enigma Berry"), + .pluralName = ITEM_PLURAL_NAME("Enigma Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient. " @@ -10444,7 +10936,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FOCUS_PUNCH] = { - .name = _("TM01"), + .name = ITEM_NAME("TM01"), .price = 3000, .description = COMPOUND_STRING( "Powerful, but makes " @@ -10454,12 +10946,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FOCUS_PUNCH, }, [ITEM_TM_DRAGON_CLAW] = { - .name = _("TM02"), + .name = ITEM_NAME("TM02"), .price = 3000, .description = COMPOUND_STRING( "Hooks and slashes " @@ -10469,12 +10960,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_DRAGON_CLAW, }, [ITEM_TM_WATER_PULSE] = { - .name = _("TM03"), + .name = ITEM_NAME("TM03"), .price = 3000, .description = COMPOUND_STRING( "Generates an " @@ -10484,12 +10974,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_WATER_PULSE, }, [ITEM_TM_CALM_MIND] = { - .name = _("TM04"), + .name = ITEM_NAME("TM04"), .price = 3000, .description = COMPOUND_STRING( "Raises Sp. Atk and " @@ -10499,12 +10988,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_CALM_MIND, }, [ITEM_TM_ROAR] = { - .name = _("TM05"), + .name = ITEM_NAME("TM05"), .price = 1000, .description = COMPOUND_STRING( "A savage roar that " @@ -10514,12 +11002,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_ROAR, }, [ITEM_TM_TOXIC] = { - .name = _("TM06"), + .name = ITEM_NAME("TM06"), .price = 3000, .description = COMPOUND_STRING( "Poisons the foe " @@ -10529,12 +11016,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_TOXIC, }, [ITEM_TM_HAIL] = { - .name = _("TM07"), + .name = ITEM_NAME("TM07"), .price = 3000, #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_SNOW .description = COMPOUND_STRING( @@ -10551,12 +11037,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_HAIL, }, [ITEM_TM_BULK_UP] = { - .name = _("TM08"), + .name = ITEM_NAME("TM08"), .price = 3000, .description = COMPOUND_STRING( "Bulks up the body " @@ -10566,12 +11051,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_BULK_UP, }, [ITEM_TM_BULLET_SEED] = { - .name = _("TM09"), + .name = ITEM_NAME("TM09"), .price = 3000, .description = COMPOUND_STRING( "Shoots 2 to 5 seeds " @@ -10581,12 +11065,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_BULLET_SEED, }, [ITEM_TM_HIDDEN_POWER] = { - .name = _("TM10"), + .name = ITEM_NAME("TM10"), .price = 3000, .description = COMPOUND_STRING( "The attack power " @@ -10596,12 +11079,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_HIDDEN_POWER, }, [ITEM_TM_SUNNY_DAY] = { - .name = _("TM11"), + .name = ITEM_NAME("TM11"), .price = 2000, .description = COMPOUND_STRING( "Raises the power of " @@ -10611,12 +11093,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SUNNY_DAY, }, [ITEM_TM_TAUNT] = { - .name = _("TM12"), + .name = ITEM_NAME("TM12"), .price = 3000, .description = COMPOUND_STRING( "Enrages the foe so " @@ -10626,12 +11107,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_TAUNT, }, [ITEM_TM_ICE_BEAM] = { - .name = _("TM13"), + .name = ITEM_NAME("TM13"), .price = 3000, .description = COMPOUND_STRING( "Fires an icy cold " @@ -10645,12 +11125,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_ICE_BEAM, }, [ITEM_TM_BLIZZARD] = { - .name = _("TM14"), + .name = ITEM_NAME("TM14"), .price = 5500, .description = COMPOUND_STRING( #if B_USE_FROSTBITE == TRUE @@ -10666,12 +11145,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_BLIZZARD, }, [ITEM_TM_HYPER_BEAM] = { - .name = _("TM15"), + .name = ITEM_NAME("TM15"), .price = 7500, .description = COMPOUND_STRING( "Powerful, but needs " @@ -10681,12 +11159,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_HYPER_BEAM, }, [ITEM_TM_LIGHT_SCREEN] = { - .name = _("TM16"), + .name = ITEM_NAME("TM16"), .price = 3000, .description = COMPOUND_STRING( "Creates a wall of " @@ -10696,12 +11173,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_LIGHT_SCREEN, }, [ITEM_TM_PROTECT] = { - .name = _("TM17"), + .name = ITEM_NAME("TM17"), .price = 3000, .description = COMPOUND_STRING( "Negates all damage, " @@ -10711,12 +11187,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_PROTECT, }, [ITEM_TM_RAIN_DANCE] = { - .name = _("TM18"), + .name = ITEM_NAME("TM18"), .price = 2000, .description = COMPOUND_STRING( "Raises the power of " @@ -10726,12 +11201,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_RAIN_DANCE, }, [ITEM_TM_GIGA_DRAIN] = { - .name = _("TM19"), + .name = ITEM_NAME("TM19"), .price = 3000, .description = COMPOUND_STRING( "Recovers half the " @@ -10741,12 +11215,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_GIGA_DRAIN, }, [ITEM_TM_SAFEGUARD] = { - .name = _("TM20"), + .name = ITEM_NAME("TM20"), .price = 3000, .description = COMPOUND_STRING( "Prevents status " @@ -10756,12 +11229,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SAFEGUARD, }, [ITEM_TM_FRUSTRATION] = { - .name = _("TM21"), + .name = ITEM_NAME("TM21"), .price = 1000, .description = COMPOUND_STRING( "The less the user " @@ -10771,12 +11243,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FRUSTRATION, }, [ITEM_TM_SOLAR_BEAM] = { - .name = _("TM22"), + .name = ITEM_NAME("TM22"), .price = 3000, .description = COMPOUND_STRING( "Absorbs sunlight in " @@ -10786,12 +11257,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SOLAR_BEAM, }, [ITEM_TM_IRON_TAIL] = { - .name = _("TM23"), + .name = ITEM_NAME("TM23"), .price = 3000, .description = COMPOUND_STRING( "Slams the foe with " @@ -10801,12 +11271,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_IRON_TAIL, }, [ITEM_TM_THUNDERBOLT] = { - .name = _("TM24"), + .name = ITEM_NAME("TM24"), .price = 3000, .description = COMPOUND_STRING( "A powerful electric " @@ -10816,12 +11285,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_THUNDERBOLT, }, [ITEM_TM_THUNDER] = { - .name = _("TM25"), + .name = ITEM_NAME("TM25"), .price = 5500, .description = COMPOUND_STRING( "Strikes the foe " @@ -10831,12 +11299,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_THUNDER, }, [ITEM_TM_EARTHQUAKE] = { - .name = _("TM26"), + .name = ITEM_NAME("TM26"), .price = 3000, .description = COMPOUND_STRING( "Causes a quake " @@ -10846,12 +11313,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_EARTHQUAKE, }, [ITEM_TM_RETURN] = { - .name = _("TM27"), + .name = ITEM_NAME("TM27"), .price = 1000, .description = COMPOUND_STRING( "The more the user " @@ -10861,12 +11327,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_RETURN, }, [ITEM_TM_DIG] = { - .name = _("TM28"), + .name = ITEM_NAME("TM28"), .price = 2000, .description = COMPOUND_STRING( "Digs underground " @@ -10876,12 +11341,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_DIG, }, [ITEM_TM_PSYCHIC] = { - .name = _("TM29"), + .name = ITEM_NAME("TM29"), .price = 2000, .description = COMPOUND_STRING( "A powerful psychic " @@ -10891,12 +11355,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_PSYCHIC, }, [ITEM_TM_SHADOW_BALL] = { - .name = _("TM30"), + .name = ITEM_NAME("TM30"), .price = 3000, .description = COMPOUND_STRING( "Hurls a dark lump " @@ -10906,12 +11369,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SHADOW_BALL, }, [ITEM_TM_BRICK_BREAK] = { - .name = _("TM31"), + .name = ITEM_NAME("TM31"), .price = 3000, .description = COMPOUND_STRING( "Destroys barriers " @@ -10921,12 +11383,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_BRICK_BREAK, }, [ITEM_TM_DOUBLE_TEAM] = { - .name = _("TM32"), + .name = ITEM_NAME("TM32"), .price = 2000, .description = COMPOUND_STRING( "Creates illusory " @@ -10936,12 +11397,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_DOUBLE_TEAM, }, [ITEM_TM_REFLECT] = { - .name = _("TM33"), + .name = ITEM_NAME("TM33"), .price = 3000, .description = COMPOUND_STRING( "Creates a wall of " @@ -10951,12 +11411,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_REFLECT, }, [ITEM_TM_SHOCK_WAVE] = { - .name = _("TM34"), + .name = ITEM_NAME("TM34"), .price = 3000, .description = COMPOUND_STRING( "Zaps the foe with a " @@ -10966,12 +11425,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SHOCK_WAVE, }, [ITEM_TM_FLAMETHROWER] = { - .name = _("TM35"), + .name = ITEM_NAME("TM35"), .price = 3000, .description = COMPOUND_STRING( "Looses a stream of " @@ -10981,12 +11439,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FLAMETHROWER, }, [ITEM_TM_SLUDGE_BOMB] = { - .name = _("TM36"), + .name = ITEM_NAME("TM36"), .price = 1000, .description = COMPOUND_STRING( "Hurls sludge at the " @@ -10996,12 +11453,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SLUDGE_BOMB, }, [ITEM_TM_SANDSTORM] = { - .name = _("TM37"), + .name = ITEM_NAME("TM37"), .price = 2000, .description = COMPOUND_STRING( "Causes a sandstorm " @@ -11011,12 +11467,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SANDSTORM, }, [ITEM_TM_FIRE_BLAST] = { - .name = _("TM38"), + .name = ITEM_NAME("TM38"), .price = 5500, .description = COMPOUND_STRING( "A powerful fire " @@ -11026,12 +11481,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FIRE_BLAST, }, [ITEM_TM_ROCK_TOMB] = { - .name = _("TM39"), + .name = ITEM_NAME("TM39"), .price = 3000, .description = COMPOUND_STRING( "Stops the foe from " @@ -11041,12 +11495,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_ROCK_TOMB, }, [ITEM_TM_AERIAL_ACE] = { - .name = _("TM40"), + .name = ITEM_NAME("TM40"), .price = 3000, .description = COMPOUND_STRING( "An extremely fast " @@ -11056,12 +11509,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_AERIAL_ACE, }, [ITEM_TM_TORMENT] = { - .name = _("TM41"), + .name = ITEM_NAME("TM41"), .price = 3000, .description = COMPOUND_STRING( "Prevents the foe " @@ -11071,12 +11523,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_TORMENT, }, [ITEM_TM_FACADE] = { - .name = _("TM42"), + .name = ITEM_NAME("TM42"), .price = 3000, .description = COMPOUND_STRING( "Raises Attack when " @@ -11086,12 +11537,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FACADE, }, [ITEM_TM_SECRET_POWER] = { - .name = _("TM43"), + .name = ITEM_NAME("TM43"), .price = 3000, .description = COMPOUND_STRING( "Adds an effect to " @@ -11101,12 +11551,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SECRET_POWER, }, [ITEM_TM_REST] = { - .name = _("TM44"), + .name = ITEM_NAME("TM44"), .price = 3000, .description = COMPOUND_STRING( "The user sleeps for " @@ -11116,12 +11565,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_REST, }, [ITEM_TM_ATTRACT] = { - .name = _("TM45"), + .name = ITEM_NAME("TM45"), .price = 3000, .description = COMPOUND_STRING( "Makes it tough to " @@ -11131,12 +11579,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_ATTRACT, }, [ITEM_TM_THIEF] = { - .name = _("TM46"), + .name = ITEM_NAME("TM46"), .price = 3000, .description = COMPOUND_STRING( "While attacking, " @@ -11146,12 +11593,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_THIEF, }, [ITEM_TM_STEEL_WING] = { - .name = _("TM47"), + .name = ITEM_NAME("TM47"), .price = 3000, .description = COMPOUND_STRING( "Spreads hard-" @@ -11161,12 +11607,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_STEEL_WING, }, [ITEM_TM_SKILL_SWAP] = { - .name = _("TM48"), + .name = ITEM_NAME("TM48"), .price = 3000, .description = COMPOUND_STRING( "Switches abilities " @@ -11176,12 +11621,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SKILL_SWAP, }, [ITEM_TM_SNATCH] = { - .name = _("TM49"), + .name = ITEM_NAME("TM49"), .price = 3000, .description = COMPOUND_STRING( "Steals the effects " @@ -11191,12 +11635,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SNATCH, }, [ITEM_TM_OVERHEAT] = { - .name = _("TM50"), + .name = ITEM_NAME("TM50"), .price = 3000, .description = COMPOUND_STRING( "Enables full-power " @@ -11206,612 +11649,561 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_OVERHEAT, }, [ITEM_TM51] = { - .name = _("TM51"), + .name = ITEM_NAME("TM51"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM52] = { - .name = _("TM52"), + .name = ITEM_NAME("TM52"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM53] = { - .name = _("TM53"), + .name = ITEM_NAME("TM53"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM54] = { - .name = _("TM54"), + .name = ITEM_NAME("TM54"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM55] = { - .name = _("TM55"), + .name = ITEM_NAME("TM55"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM56] = { - .name = _("TM56"), + .name = ITEM_NAME("TM56"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM57] = { - .name = _("TM57"), + .name = ITEM_NAME("TM57"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM58] = { - .name = _("TM58"), + .name = ITEM_NAME("TM58"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM59] = { - .name = _("TM59"), + .name = ITEM_NAME("TM59"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM60] = { - .name = _("TM60"), + .name = ITEM_NAME("TM60"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM61] = { - .name = _("TM61"), + .name = ITEM_NAME("TM61"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM62] = { - .name = _("TM62"), + .name = ITEM_NAME("TM62"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM63] = { - .name = _("TM63"), + .name = ITEM_NAME("TM63"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM64] = { - .name = _("TM64"), + .name = ITEM_NAME("TM64"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM65] = { - .name = _("TM65"), + .name = ITEM_NAME("TM65"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM66] = { - .name = _("TM66"), + .name = ITEM_NAME("TM66"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM67] = { - .name = _("TM67"), + .name = ITEM_NAME("TM67"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM68] = { - .name = _("TM68"), + .name = ITEM_NAME("TM68"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM69] = { - .name = _("TM69"), + .name = ITEM_NAME("TM69"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM70] = { - .name = _("TM70"), + .name = ITEM_NAME("TM70"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM71] = { - .name = _("TM71"), + .name = ITEM_NAME("TM71"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM72] = { - .name = _("TM72"), + .name = ITEM_NAME("TM72"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM73] = { - .name = _("TM73"), + .name = ITEM_NAME("TM73"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM74] = { - .name = _("TM74"), + .name = ITEM_NAME("TM74"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM75] = { - .name = _("TM75"), + .name = ITEM_NAME("TM75"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM76] = { - .name = _("TM76"), + .name = ITEM_NAME("TM76"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM77] = { - .name = _("TM77"), + .name = ITEM_NAME("TM77"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM78] = { - .name = _("TM78"), + .name = ITEM_NAME("TM78"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM79] = { - .name = _("TM79"), + .name = ITEM_NAME("TM79"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM80] = { - .name = _("TM80"), + .name = ITEM_NAME("TM80"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM81] = { - .name = _("TM81"), + .name = ITEM_NAME("TM81"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM82] = { - .name = _("TM82"), + .name = ITEM_NAME("TM82"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM83] = { - .name = _("TM83"), + .name = ITEM_NAME("TM83"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM84] = { - .name = _("TM84"), + .name = ITEM_NAME("TM84"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM85] = { - .name = _("TM85"), + .name = ITEM_NAME("TM85"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM86] = { - .name = _("TM86"), + .name = ITEM_NAME("TM86"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM87] = { - .name = _("TM87"), + .name = ITEM_NAME("TM87"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM88] = { - .name = _("TM88"), + .name = ITEM_NAME("TM88"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM89] = { - .name = _("TM89"), + .name = ITEM_NAME("TM89"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM90] = { - .name = _("TM90"), + .name = ITEM_NAME("TM90"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM91] = { - .name = _("TM91"), + .name = ITEM_NAME("TM91"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM92] = { - .name = _("TM92"), + .name = ITEM_NAME("TM92"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM93] = { - .name = _("TM93"), + .name = ITEM_NAME("TM93"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM94] = { - .name = _("TM94"), + .name = ITEM_NAME("TM94"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM95] = { - .name = _("TM95"), + .name = ITEM_NAME("TM95"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM96] = { - .name = _("TM96"), + .name = ITEM_NAME("TM96"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM97] = { - .name = _("TM97"), + .name = ITEM_NAME("TM97"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM98] = { - .name = _("TM98"), + .name = ITEM_NAME("TM98"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM99] = { - .name = _("TM99"), + .name = ITEM_NAME("TM99"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM100] = { - .name = _("TM100"), + .name = ITEM_NAME("TM100"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_HM_CUT] = { - .name = _("HM01"), + .name = ITEM_NAME("HM01"), .price = 0, .description = COMPOUND_STRING( "Attacks the foe " @@ -11821,12 +12213,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_CUT, }, [ITEM_HM_FLY] = { - .name = _("HM02"), + .name = ITEM_NAME("HM02"), .price = 0, .description = COMPOUND_STRING( "Flies up on the " @@ -11836,12 +12227,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FLY, }, [ITEM_HM_SURF] = { - .name = _("HM03"), + .name = ITEM_NAME("HM03"), .price = 0, .description = COMPOUND_STRING( "Creates a huge " @@ -11851,12 +12241,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_SURF, }, [ITEM_HM_STRENGTH] = { - .name = _("HM04"), + .name = ITEM_NAME("HM04"), .price = 0, .description = COMPOUND_STRING( "Builds enormous " @@ -11866,12 +12255,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_STRENGTH, }, [ITEM_HM_FLASH] = { - .name = _("HM05"), + .name = ITEM_NAME("HM05"), .price = 0, .description = COMPOUND_STRING( "Looses a powerful " @@ -11881,12 +12269,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_FLASH, }, [ITEM_HM_ROCK_SMASH] = { - .name = _("HM06"), + .name = ITEM_NAME("HM06"), .price = 0, .description = COMPOUND_STRING( "A rock-crushingly " @@ -11896,12 +12283,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_ROCK_SMASH, }, [ITEM_HM_WATERFALL] = { - .name = _("HM07"), + .name = ITEM_NAME("HM07"), .price = 0, .description = COMPOUND_STRING( "Attacks the foe " @@ -11911,12 +12297,11 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_WATERFALL, }, [ITEM_HM_DIVE] = { - .name = _("HM08"), + .name = ITEM_NAME("HM08"), .price = 0, .description = COMPOUND_STRING( "Dives underwater " @@ -11926,7 +12311,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = NULL, - .secondaryId = MOVE_DIVE, }, @@ -11934,7 +12318,7 @@ const struct Item gItemsInfo[] = [ITEM_OVAL_CHARM] = { - .name = _("Oval Charm"), + .name = ITEM_NAME("Oval Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -11950,7 +12334,7 @@ const struct Item gItemsInfo[] = [ITEM_SHINY_CHARM] = { - .name = _("Shiny Charm"), + .name = ITEM_NAME("Shiny Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -11966,7 +12350,7 @@ const struct Item gItemsInfo[] = [ITEM_CATCHING_CHARM] = { - .name = _("Catching Charm"), + .name = ITEM_NAME("Catching Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -11982,7 +12366,7 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CHARM] = { - .name = _("Exp. Charm"), + .name = ITEM_NAME("Exp. Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12000,7 +12384,7 @@ const struct Item gItemsInfo[] = [ITEM_ROTOM_CATALOG] = { - .name = _("Rotom Catalog"), + .name = ITEM_NAME("Rotom Catalog"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12016,7 +12400,7 @@ const struct Item gItemsInfo[] = [ITEM_GRACIDEA] = { - .name = _("Gracidea"), + .name = ITEM_NAME("Gracidea"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12032,8 +12416,8 @@ const struct Item gItemsInfo[] = [ITEM_REVEAL_GLASS] = { - .name = _("Reveal Glass"), - .pluralName = _("Reveal Glasses"), + .name = ITEM_NAME("Reveal Glass"), + .pluralName = ITEM_PLURAL_NAME("Reveal Glasses"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12049,8 +12433,8 @@ const struct Item gItemsInfo[] = [ITEM_DNA_SPLICERS] = { - .name = _("DNA Splicers"), - .pluralName = _("DNA Splicers"), + .name = ITEM_NAME("DNA Splicers"), + .pluralName = ITEM_PLURAL_NAME("DNA Splicers"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12066,7 +12450,7 @@ const struct Item gItemsInfo[] = [ITEM_ZYGARDE_CUBE] = { - .name = _("Zygarde Cube"), + .name = ITEM_NAME("Zygarde Cube"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12082,7 +12466,7 @@ const struct Item gItemsInfo[] = [ITEM_PRISON_BOTTLE] = { - .name = _("Prison Bottle"), + .name = ITEM_NAME("Prison Bottle"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12098,7 +12482,7 @@ const struct Item gItemsInfo[] = [ITEM_N_SOLARIZER] = { - .name = _("N-Solarizer"), + .name = ITEM_NAME("N-Solarizer"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12114,7 +12498,7 @@ const struct Item gItemsInfo[] = [ITEM_N_LUNARIZER] = { - .name = _("N-Lunarizer"), + .name = ITEM_NAME("N-Lunarizer"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12130,8 +12514,8 @@ const struct Item gItemsInfo[] = [ITEM_REINS_OF_UNITY] = { - .name = _("Reins of Unity"), - .pluralName = _("Reins of Unity"), + .name = ITEM_NAME("Reins of Unity"), + .pluralName = ITEM_PLURAL_NAME("Reins of Unity"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12149,7 +12533,7 @@ const struct Item gItemsInfo[] = [ITEM_MEGA_RING] = { - .name = _("Mega Ring"), + .name = ITEM_NAME("Mega Ring"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12165,7 +12549,7 @@ const struct Item gItemsInfo[] = [ITEM_Z_POWER_RING] = { - .name = _("Z-Power Ring"), + .name = ITEM_NAME("Z-Power Ring"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12181,7 +12565,7 @@ const struct Item gItemsInfo[] = [ITEM_DYNAMAX_BAND] = { - .name = _("Dynamax Band"), + .name = ITEM_NAME("Dynamax Band"), .price = 0, .description = COMPOUND_STRING( "A band carrying a " @@ -12198,7 +12582,7 @@ const struct Item gItemsInfo[] = [ITEM_BICYCLE] = { - .name = _("Bicycle"), + .name = ITEM_NAME("Bicycle"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle " @@ -12214,7 +12598,7 @@ const struct Item gItemsInfo[] = [ITEM_MACH_BIKE] = { - .name = _("Mach Bike"), + .name = ITEM_NAME("Mach Bike"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle " @@ -12231,7 +12615,7 @@ const struct Item gItemsInfo[] = [ITEM_ACRO_BIKE] = { - .name = _("Acro Bike"), + .name = ITEM_NAME("Acro Bike"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle " @@ -12248,7 +12632,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_ROD] = { - .name = _("Old Rod"), + .name = ITEM_NAME("Old Rod"), .price = 0, .description = COMPOUND_STRING( "Use by any body of " @@ -12265,7 +12649,7 @@ const struct Item gItemsInfo[] = [ITEM_GOOD_ROD] = { - .name = _("Good Rod"), + .name = ITEM_NAME("Good Rod"), .price = 0, .description = COMPOUND_STRING( "A decent fishing " @@ -12282,7 +12666,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_ROD] = { - .name = _("Super Rod"), + .name = ITEM_NAME("Super Rod"), .price = 0, .description = COMPOUND_STRING( "The best fishing " @@ -12299,7 +12683,7 @@ const struct Item gItemsInfo[] = [ITEM_DOWSING_MACHINE] = { - .name = _("Dowsing Machine"), + .name = ITEM_NAME("Dowsing Machine"), .price = 0, .description = COMPOUND_STRING( "A device that " @@ -12315,7 +12699,7 @@ const struct Item gItemsInfo[] = [ITEM_TOWN_MAP] = { - .name = _("Town Map"), + .name = ITEM_NAME("Town Map"), .price = 0, .description = COMPOUND_STRING( "Can be viewed " @@ -12331,7 +12715,7 @@ const struct Item gItemsInfo[] = [ITEM_VS_SEEKER] = { - .name = _("Vs. Seeker"), + .name = ITEM_NAME("Vs. Seeker"), .price = 0, .description = COMPOUND_STRING( "A rechargeable unit " @@ -12347,7 +12731,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_CASE] = { - .name = _("TM Case"), + .name = ITEM_NAME("TM Case"), .price = 0, .description = COMPOUND_STRING( "A convenient case " @@ -12363,8 +12747,8 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_POUCH] = { - .name = _("Berry Pouch"), - .pluralName = _("Berry Pouches"), + .name = ITEM_NAME("Berry Pouch"), + .pluralName = ITEM_PLURAL_NAME("Berry Pouches"), .price = 0, .description = COMPOUND_STRING( "A convenient " @@ -12381,7 +12765,7 @@ const struct Item gItemsInfo[] = [ITEM_POKEMON_BOX_LINK] = { - .name = _("{PKMN} Box Link"), + .name = ITEM_NAME("{PKMN} Box Link"), .price = 0, .description = COMPOUND_STRING( "This device grants " @@ -12397,7 +12781,7 @@ const struct Item gItemsInfo[] = [ITEM_COIN_CASE] = { - .name = _("Coin Case"), + .name = ITEM_NAME("Coin Case"), .price = 0, .description = COMPOUND_STRING( "A case that holds " @@ -12412,7 +12796,7 @@ const struct Item gItemsInfo[] = [ITEM_POWDER_JAR] = { - .name = _("Powder Jar"), + .name = ITEM_NAME("Powder Jar"), .price = 0, .description = COMPOUND_STRING( "Stores Berry " @@ -12428,7 +12812,7 @@ const struct Item gItemsInfo[] = [ITEM_WAILMER_PAIL] = { - .name = _("Wailmer Pail"), + .name = ITEM_NAME("Wailmer Pail"), .price = 0, .description = COMPOUND_STRING( "A tool used for " @@ -12444,7 +12828,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_RADAR] = { - .name = _("Poké Radar"), + .name = ITEM_NAME("Poké Radar"), .price = 0, .description = COMPOUND_STRING( "A tool used to " @@ -12460,7 +12844,7 @@ const struct Item gItemsInfo[] = [ITEM_POKEBLOCK_CASE] = { - .name = _("{POKEBLOCK} Case"), + .name = ITEM_NAME("{POKEBLOCK} Case"), .price = 0, .description = COMPOUND_STRING( "A case for holding " @@ -12476,7 +12860,7 @@ const struct Item gItemsInfo[] = [ITEM_SOOT_SACK] = { - .name = _("Soot Sack"), + .name = ITEM_NAME("Soot Sack"), .price = 0, .description = COMPOUND_STRING( "A sack used to " @@ -12492,7 +12876,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_FLUTE] = { - .name = _("Poké Flute"), + .name = ITEM_NAME("Poké Flute"), .price = 0, .description = COMPOUND_STRING( "A sweet-sounding " @@ -12509,7 +12893,7 @@ const struct Item gItemsInfo[] = [ITEM_FAME_CHECKER] = { - .name = _("Fame Checker"), + .name = ITEM_NAME("Fame Checker"), .price = 0, .description = COMPOUND_STRING( "Stores information " @@ -12525,7 +12909,7 @@ const struct Item gItemsInfo[] = [ITEM_TEACHY_TV] = { - .name = _("Teachy TV"), + .name = ITEM_NAME("Teachy TV"), .price = 0, .description = COMPOUND_STRING( "A TV set tuned to " @@ -12543,7 +12927,7 @@ const struct Item gItemsInfo[] = [ITEM_SS_TICKET] = { - .name = _("S.S. Ticket"), + .name = ITEM_NAME("S.S. Ticket"), .price = 0, .description = COMPOUND_STRING( "The ticket required " @@ -12559,7 +12943,7 @@ const struct Item gItemsInfo[] = [ITEM_EON_TICKET] = { - .name = _("Eon Ticket"), + .name = ITEM_NAME("Eon Ticket"), .price = 0, .description = COMPOUND_STRING( "The ticket for a " @@ -12576,7 +12960,7 @@ const struct Item gItemsInfo[] = [ITEM_MYSTIC_TICKET] = { - .name = _("Mystic Ticket"), + .name = ITEM_NAME("Mystic Ticket"), .price = 0, .description = COMPOUND_STRING( "A ticket required " @@ -12592,7 +12976,7 @@ const struct Item gItemsInfo[] = [ITEM_AURORA_TICKET] = { - .name = _("Aurora Ticket"), + .name = ITEM_NAME("Aurora Ticket"), .price = 0, .description = COMPOUND_STRING( "A ticket required " @@ -12608,7 +12992,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_SEA_MAP] = { - .name = _("Old Sea Map"), + .name = ITEM_NAME("Old Sea Map"), .price = 0, .description = COMPOUND_STRING( "A faded sea chart " @@ -12624,7 +13008,7 @@ const struct Item gItemsInfo[] = [ITEM_LETTER] = { - .name = _("Letter"), + .name = ITEM_NAME("Letter"), .price = 0, .description = COMPOUND_STRING( "A letter to Steven " @@ -12640,8 +13024,8 @@ const struct Item gItemsInfo[] = [ITEM_DEVON_PARTS] = { - .name = _("Devon Parts"), - .pluralName = _("Devon Parts"), + .name = ITEM_NAME("Devon Parts"), + .pluralName = ITEM_PLURAL_NAME("Devon Parts"), .price = 0, .description = COMPOUND_STRING( "A package that " @@ -12657,8 +13041,8 @@ const struct Item gItemsInfo[] = [ITEM_GO_GOGGLES] = { - .name = _("Go-Goggles"), - .pluralName = _("Go-Goggles"), + .name = ITEM_NAME("Go-Goggles"), + .pluralName = ITEM_PLURAL_NAME("Go-Goggles"), .price = 0, .description = COMPOUND_STRING( "Nifty goggles that " @@ -12674,7 +13058,7 @@ const struct Item gItemsInfo[] = [ITEM_DEVON_SCOPE] = { - .name = _("Devon Scope"), + .name = ITEM_NAME("Devon Scope"), .price = 0, .description = COMPOUND_STRING( "A device by Devon " @@ -12690,7 +13074,7 @@ const struct Item gItemsInfo[] = [ITEM_BASEMENT_KEY] = { - .name = _("Basement Key"), + .name = ITEM_NAME("Basement Key"), .price = 0, .description = COMPOUND_STRING( "The key for New " @@ -12706,7 +13090,7 @@ const struct Item gItemsInfo[] = [ITEM_SCANNER] = { - .name = _("Scanner"), + .name = ITEM_NAME("Scanner"), .price = 0, .description = COMPOUND_STRING( "A device found " @@ -12722,7 +13106,7 @@ const struct Item gItemsInfo[] = [ITEM_STORAGE_KEY] = { - .name = _("Storage Key"), + .name = ITEM_NAME("Storage Key"), .price = 0, .description = COMPOUND_STRING( "The key to the " @@ -12738,8 +13122,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_1] = { - .name = _("Key to Room 1"), - .pluralName = _("Keys to Room 1"), + .name = ITEM_NAME("Key to Room 1"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 1"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -12752,8 +13136,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_2] = { - .name = _("Key to Room 2"), - .pluralName = _("Keys to Room 2"), + .name = ITEM_NAME("Key to Room 2"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 2"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -12766,8 +13150,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_4] = { - .name = _("Key to Room 4"), - .pluralName = _("Keys to Room 4"), + .name = ITEM_NAME("Key to Room 4"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 4"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -12780,8 +13164,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_6] = { - .name = _("Key to Room 6"), - .pluralName = _("Keys to Room 6"), + .name = ITEM_NAME("Key to Room 6"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 6"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -12794,7 +13178,7 @@ const struct Item gItemsInfo[] = [ITEM_METEORITE] = { - .name = _("Meteorite"), + .name = ITEM_NAME("Meteorite"), .price = 0, .description = COMPOUND_STRING( "A meteorite found " @@ -12809,7 +13193,7 @@ const struct Item gItemsInfo[] = [ITEM_MAGMA_EMBLEM] = { - .name = _("Magma Emblem"), + .name = ITEM_NAME("Magma Emblem"), .price = 0, .description = COMPOUND_STRING( "A medal-like item in " @@ -12825,8 +13209,8 @@ const struct Item gItemsInfo[] = [ITEM_CONTEST_PASS] = { - .name = _("Contest Pass"), - .pluralName = _("Contest Passes"), + .name = ITEM_NAME("Contest Pass"), + .pluralName = ITEM_PLURAL_NAME("Contest Passes"), .price = 0, .description = COMPOUND_STRING( "The pass required " @@ -12842,7 +13226,7 @@ const struct Item gItemsInfo[] = [ITEM_PARCEL] = { - .name = _("Parcel"), + .name = ITEM_NAME("Parcel"), .price = 0, .description = COMPOUND_STRING( "A parcel for Prof. " @@ -12858,7 +13242,7 @@ const struct Item gItemsInfo[] = [ITEM_SECRET_KEY] = { - .name = _("Secret Key"), + .name = ITEM_NAME("Secret Key"), .price = 0, .description = COMPOUND_STRING( "The key to the " @@ -12874,7 +13258,7 @@ const struct Item gItemsInfo[] = [ITEM_BIKE_VOUCHER] = { - .name = _("Bike Voucher"), + .name = ITEM_NAME("Bike Voucher"), .price = 0, .description = COMPOUND_STRING( "A voucher for " @@ -12890,8 +13274,8 @@ const struct Item gItemsInfo[] = [ITEM_GOLD_TEETH] = { - .name = _("Gold Teeth"), - .pluralName = _("Gold Teeth"), + .name = ITEM_NAME("Gold Teeth"), + .pluralName = ITEM_PLURAL_NAME("Gold Teeth"), .price = 0, .description = COMPOUND_STRING( "Gold dentures lost " @@ -12907,7 +13291,7 @@ const struct Item gItemsInfo[] = [ITEM_CARD_KEY] = { - .name = _("Card Key"), + .name = ITEM_NAME("Card Key"), .price = 0, .description = COMPOUND_STRING( "A card-type door " @@ -12923,7 +13307,7 @@ const struct Item gItemsInfo[] = [ITEM_LIFT_KEY] = { - .name = _("Lift Key"), + .name = ITEM_NAME("Lift Key"), .price = 0, .description = COMPOUND_STRING( "An elevator key " @@ -12939,7 +13323,7 @@ const struct Item gItemsInfo[] = [ITEM_SILPH_SCOPE] = { - .name = _("Silph Scope"), + .name = ITEM_NAME("Silph Scope"), .price = 0, .description = COMPOUND_STRING( "Silph Co's scope " @@ -12955,8 +13339,8 @@ const struct Item gItemsInfo[] = [ITEM_TRI_PASS] = { - .name = _("Tri-Pass"), - .pluralName = _("Tri-Passes"), + .name = ITEM_NAME("Tri-Pass"), + .pluralName = ITEM_PLURAL_NAME("Tri-Passes"), .price = 0, .description = COMPOUND_STRING( "A pass for ferries " @@ -12972,8 +13356,8 @@ const struct Item gItemsInfo[] = [ITEM_RAINBOW_PASS] = { - .name = _("Rainbow Pass"), - .pluralName = _("Rainbow Passes"), + .name = ITEM_NAME("Rainbow Pass"), + .pluralName = ITEM_PLURAL_NAME("Rainbow Passes"), .price = 0, .description = COMPOUND_STRING( "For ferries serving " @@ -12989,8 +13373,8 @@ const struct Item gItemsInfo[] = [ITEM_TEA] = { - .name = _("Tea"), - .pluralName = _("Tea"), + .name = ITEM_NAME("Tea"), + .pluralName = ITEM_PLURAL_NAME("Tea"), .price = 0, .description = COMPOUND_STRING( "A thirst-quenching " @@ -13006,8 +13390,8 @@ const struct Item gItemsInfo[] = [ITEM_RUBY] = { - .name = _("Ruby"), - .pluralName = _("Rubies"), + .name = ITEM_NAME("Ruby"), + .pluralName = ITEM_PLURAL_NAME("Rubies"), .price = 0, .description = COMPOUND_STRING( "An exquisite, red-" @@ -13023,7 +13407,7 @@ const struct Item gItemsInfo[] = [ITEM_SAPPHIRE] = { - .name = _("Sapphire"), + .name = ITEM_NAME("Sapphire"), .price = 0, .description = COMPOUND_STRING( "A brilliant blue gem " @@ -13039,7 +13423,7 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_SHIELD] = { - .name = _("Ability Shield"), + .name = ITEM_NAME("Ability Shield"), .price = 20000, .holdEffect = HOLD_EFFECT_ABILITY_SHIELD, .description = COMPOUND_STRING( @@ -13058,7 +13442,7 @@ const struct Item gItemsInfo[] = [ITEM_CLEAR_AMULET] = { - .name = _("Clear Amulet"), + .name = ITEM_NAME("Clear Amulet"), .price = 30000, .holdEffect = HOLD_EFFECT_CLEAR_AMULET, .description = COMPOUND_STRING( @@ -13066,6 +13450,7 @@ const struct Item gItemsInfo[] = "prevented for\nthis " "items's holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13075,7 +13460,7 @@ const struct Item gItemsInfo[] = [ITEM_PUNCHING_GLOVE] = { - .name = _("Punching Glove"), + .name = ITEM_NAME("Punching Glove"), .price = 15000, .holdEffect = HOLD_EFFECT_PUNCHING_GLOVE, .description = COMPOUND_STRING( @@ -13083,6 +13468,7 @@ const struct Item gItemsInfo[] = "moves and\nremoves " "their contact."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13092,7 +13478,7 @@ const struct Item gItemsInfo[] = [ITEM_COVERT_CLOAK] = { - .name = _("Covert Cloak"), + .name = ITEM_NAME("Covert Cloak"), .price = 20000, .holdEffect = HOLD_EFFECT_COVERT_CLOAK, .description = COMPOUND_STRING( @@ -13100,6 +13486,7 @@ const struct Item gItemsInfo[] = "from additional " "\neffects of moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13109,8 +13496,8 @@ const struct Item gItemsInfo[] = [ITEM_LOADED_DICE] = { - .name = _("Loaded Dice"), - .pluralName = _("Loaded Dice"), + .name = ITEM_NAME("Loaded Dice"), + .pluralName = ITEM_PLURAL_NAME("Loaded Dice"), .price = 20000, .holdEffect = HOLD_EFFECT_LOADED_DICE, .description = COMPOUND_STRING( @@ -13118,6 +13505,7 @@ const struct Item gItemsInfo[] = "Multihit\nstrikes " "hit more times."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13127,13 +13515,14 @@ const struct Item gItemsInfo[] = [ITEM_AUSPICIOUS_ARMOR] = { - .name = _("Auspicious Armor"), + .name = ITEM_NAME("Auspicious Armor"), .price = 3000, .description = COMPOUND_STRING( "Armor inhabited by " "auspicious\nwishes. " "Causes evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13144,8 +13533,8 @@ const struct Item gItemsInfo[] = [ITEM_BOOSTER_ENERGY] = { - .name = _("Booster Energy"), - .pluralName = _("Booster Energies"), + .name = ITEM_NAME("Booster Energy"), + .pluralName = ITEM_PLURAL_NAME("Booster Energies"), .price = 0, .holdEffect = HOLD_EFFECT_BOOSTER_ENERGY, .description = COMPOUND_STRING( @@ -13153,6 +13542,7 @@ const struct Item gItemsInfo[] = "ups Pokémon\nwith " "certain Abilities."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13162,13 +13552,14 @@ const struct Item gItemsInfo[] = [ITEM_BIG_BAMBOO_SHOOT] = { - .name = _("Big Bamboo Shoot"), + .name = ITEM_NAME("Big Bamboo Shoot"), .price = 3000, .description = COMPOUND_STRING( "A large and rare " "bamboo shoot.\nBest " "sold to gourmands."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13178,13 +13569,14 @@ const struct Item gItemsInfo[] = [ITEM_GIMMIGHOUL_COIN] = { - .name = _("Gimmighoul Coin"), + .name = ITEM_NAME("Gimmighoul Coin"), .price = 400, .description = COMPOUND_STRING( "Gimmighoul hoard " "and treasure\nthese " "curious coins."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GimmighoulCoin, @@ -13193,13 +13585,14 @@ const struct Item gItemsInfo[] = [ITEM_LEADERS_CREST] = { - .name = _("Leader's Crest"), + .name = ITEM_NAME("Leader's Crest"), .price = 3000, .description = COMPOUND_STRING( "A shard of an old " "blade of some\nsort. " "Held by Bisharp."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_LeadersCrest, @@ -13208,13 +13601,14 @@ const struct Item gItemsInfo[] = [ITEM_MALICIOUS_ARMOR] = { - .name = _("Malicious Armor"), + .name = ITEM_NAME("Malicious Armor"), .price = 3000, .description = COMPOUND_STRING( "Armor inhabited by " "malicious\nwill. " "Causes evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13225,7 +13619,7 @@ const struct Item gItemsInfo[] = [ITEM_MIRROR_HERB] = { - .name = _("Mirror Herb"), + .name = ITEM_NAME("Mirror Herb"), .price = 30000, .holdEffect = HOLD_EFFECT_MIRROR_HERB, .description = COMPOUND_STRING( @@ -13233,6 +13627,7 @@ const struct Item gItemsInfo[] = "stat increases\n" "but only once."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13242,8 +13637,8 @@ const struct Item gItemsInfo[] = [ITEM_SCROLL_OF_DARKNESS] = { - .name = _("Scroll of Darkness"), - .pluralName = _("Scrolls of Darkness"), + .name = ITEM_NAME("Scroll of Darkness"), + .pluralName = ITEM_PLURAL_NAME("Scrolls of Darkness"), .price = 0, .description = COMPOUND_STRING( "A peculiar scroll " @@ -13251,6 +13646,7 @@ const struct Item gItemsInfo[] = "the dark path."), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13260,8 +13656,8 @@ const struct Item gItemsInfo[] = [ITEM_SCROLL_OF_WATERS] = { - .name = _("Scroll of Waters"), - .pluralName = _("Scrolls of Waters"), + .name = ITEM_NAME("Scroll of Waters"), + .pluralName = ITEM_PLURAL_NAME("Scrolls of Waters"), .price = 0, .description = COMPOUND_STRING( "A peculiar scroll " @@ -13269,6 +13665,7 @@ const struct Item gItemsInfo[] = "the water path."), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13278,7 +13675,7 @@ const struct Item gItemsInfo[] = [ITEM_TERA_ORB] = { - .name = _("Tera Orb"), + .name = ITEM_NAME("Tera Orb"), .price = 0, .description = COMPOUND_STRING( "Energy charges can " @@ -13294,13 +13691,14 @@ const struct Item gItemsInfo[] = [ITEM_TINY_BAMBOO_SHOOT] = { - .name = _("Tiny Bamboo Shoot"), + .name = ITEM_NAME("Tiny Bamboo Shoot"), .price = 750, .description = COMPOUND_STRING( "A small and rare " "bamboo shoot.\nBest " "sold to gourmands."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13310,10 +13708,11 @@ const struct Item gItemsInfo[] = [ITEM_BUG_TERA_SHARD] = { - .name = _("Bug Tera Shard"), + .name = ITEM_NAME("Bug Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13322,10 +13721,11 @@ const struct Item gItemsInfo[] = [ITEM_DARK_TERA_SHARD] = { - .name = _("Dark Tera Shard"), + .name = ITEM_NAME("Dark Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13334,10 +13734,11 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_TERA_SHARD] = { - .name = _("Dragon Tera Shard"), + .name = ITEM_NAME("Dragon Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13346,10 +13747,11 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_TERA_SHARD] = { - .name = _("Electric Tera Shard"), + .name = ITEM_NAME("Electric Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13358,10 +13760,11 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_TERA_SHARD] = { - .name = _("Fairy Tera Shard"), + .name = ITEM_NAME("Fairy Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13370,10 +13773,11 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_TERA_SHARD] = { - .name = _("Fighting Tera Shard"), + .name = ITEM_NAME("Fighting Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13382,10 +13786,11 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_TERA_SHARD] = { - .name = _("Fire Tera Shard"), + .name = ITEM_NAME("Fire Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13394,10 +13799,11 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_TERA_SHARD] = { - .name = _("Flying Tera Shard"), + .name = ITEM_NAME("Flying Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13406,10 +13812,11 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_TERA_SHARD] = { - .name = _("Ghost Tera Shard"), + .name = ITEM_NAME("Ghost Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13418,10 +13825,11 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_TERA_SHARD] = { - .name = _("Grass Tera Shard"), + .name = ITEM_NAME("Grass Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13430,10 +13838,11 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_TERA_SHARD] = { - .name = _("Ground Tera Shard"), + .name = ITEM_NAME("Ground Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13442,10 +13851,11 @@ const struct Item gItemsInfo[] = [ITEM_ICE_TERA_SHARD] = { - .name = _("Ice Tera Shard"), + .name = ITEM_NAME("Ice Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13454,10 +13864,11 @@ const struct Item gItemsInfo[] = [ITEM_NORMAL_TERA_SHARD] = { - .name = _("Normal Tera Shard"), + .name = ITEM_NAME("Normal Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13466,10 +13877,11 @@ const struct Item gItemsInfo[] = [ITEM_POISON_TERA_SHARD] = { - .name = _("Poison Tera Shard"), + .name = ITEM_NAME("Poison Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13478,10 +13890,11 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_TERA_SHARD] = { - .name = _("Psychic Tera Shard"), + .name = ITEM_NAME("Psychic Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13490,10 +13903,11 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_TERA_SHARD] = { - .name = _("Rock Tera Shard"), + .name = ITEM_NAME("Rock Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13502,10 +13916,11 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_TERA_SHARD] = { - .name = _("Steel Tera Shard"), + .name = ITEM_NAME("Steel Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13514,10 +13929,11 @@ const struct Item gItemsInfo[] = [ITEM_WATER_TERA_SHARD] = { - .name = _("Water Tera Shard"), + .name = ITEM_NAME("Water Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13526,7 +13942,7 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_CRYSTAL] = { - .name = _("Adamant Crystal"), + .name = ITEM_NAME("Adamant Crystal"), .price = 0, .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, @@ -13535,6 +13951,7 @@ const struct Item gItemsInfo[] = "that lets\nDialga " "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13544,7 +13961,7 @@ const struct Item gItemsInfo[] = [ITEM_GRISEOUS_CORE] = { - .name = _("Griseous Core"), + .name = ITEM_NAME("Griseous Core"), .price = 0, .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, @@ -13553,6 +13970,7 @@ const struct Item gItemsInfo[] = "that lets\nGiratina " "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13562,7 +13980,7 @@ const struct Item gItemsInfo[] = [ITEM_LUSTROUS_GLOBE] = { - .name = _("Lustrous Globe"), + .name = ITEM_NAME("Lustrous Globe"), .price = 0, .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, @@ -13571,6 +13989,7 @@ const struct Item gItemsInfo[] = "that lets\nPalkia " "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13580,13 +13999,14 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_AUGURITE] = { - .name = _("Black Augurite"), + .name = ITEM_NAME("Black Augurite"), .price = 8000, .description = COMPOUND_STRING( "A black stone that " "makes some\nPokémon " "evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13597,13 +14017,14 @@ const struct Item gItemsInfo[] = [ITEM_LINKING_CORD] = { - .name = _("Linking Cord"), + .name = ITEM_NAME("Linking Cord"), .price = 8000, .description = COMPOUND_STRING( "A mysterious string " "that makes\nsome " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13614,13 +14035,14 @@ const struct Item gItemsInfo[] = [ITEM_PEAT_BLOCK] = { - .name = _("Peat Block"), + .name = ITEM_NAME("Peat Block"), .price = 10000, .description = COMPOUND_STRING( "A block of material " "that makes\nsome " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13631,7 +14053,7 @@ const struct Item gItemsInfo[] = [ITEM_BERSERK_GENE] = { - .name = _("Berserk Gene"), + .name = ITEM_NAME("Berserk Gene"), .price = 20, .holdEffect = HOLD_EFFECT_BERSERK_GENE, .description = COMPOUND_STRING( @@ -13639,6 +14061,7 @@ const struct Item gItemsInfo[] = "Attack, but causes\n" "lasting confusion."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -13648,7 +14071,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_FEATHER] = { - .name = _("Fairy Feather"), + .name = ITEM_NAME("Fairy Feather"), .price = 1000, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -13657,6 +14080,7 @@ const struct Item gItemsInfo[] = "raises the power\nof " "Fairy-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -13667,13 +14091,14 @@ const struct Item gItemsInfo[] = [ITEM_SYRUPY_APPLE] = { - .name = _("Syrupy Apple"), + .name = ITEM_NAME("Syrupy Apple"), .price = 2200, .description = COMPOUND_STRING( "A very syrupy apple " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13684,13 +14109,14 @@ const struct Item gItemsInfo[] = [ITEM_UNREMARKABLE_TEACUP] = { - .name = _("Unremarkable Teacup"), + .name = ITEM_NAME("Unremarkable Teacup"), .price = 1600, .description = COMPOUND_STRING( "A cracked teacup " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13701,13 +14127,14 @@ const struct Item gItemsInfo[] = [ITEM_MASTERPIECE_TEACUP] = { - .name = _("Masterpiece Teacup"), + .name = ITEM_NAME("Masterpiece Teacup"), .price = 38000, .description = COMPOUND_STRING( "A chipped teacup " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13718,7 +14145,7 @@ const struct Item gItemsInfo[] = [ITEM_CORNERSTONE_MASK] = { - .name = _("Cornerstone Mask"), + .name = ITEM_NAME("Cornerstone Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -13727,6 +14154,7 @@ const struct Item gItemsInfo[] = "wield the Rock-" "\ntype in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_CornerstoneMask, @@ -13735,7 +14163,7 @@ const struct Item gItemsInfo[] = [ITEM_WELLSPRING_MASK] = { - .name = _("Wellspring Mask"), + .name = ITEM_NAME("Wellspring Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -13744,6 +14172,7 @@ const struct Item gItemsInfo[] = "wield the\nWater-" "type in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WellspringMask, @@ -13752,7 +14181,7 @@ const struct Item gItemsInfo[] = [ITEM_HEARTHFLAME_MASK] = { - .name = _("Hearthflame Mask"), + .name = ITEM_NAME("Hearthflame Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -13761,6 +14190,7 @@ const struct Item gItemsInfo[] = "wield the Fire-" "\ntype in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_HearthflameMask, @@ -13769,11 +14199,12 @@ const struct Item gItemsInfo[] = [ITEM_HEALTH_MOCHI] = { - .name = _("Health Mochi"), - .pluralName = _("Health Mochi"), + .name = ITEM_NAME("Health Mochi"), + .pluralName = ITEM_PLURAL_NAME("Health Mochi"), .price = 500, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpMochi, @@ -13784,11 +14215,12 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_MOCHI] = { - .name = _("Muscle Mochi"), - .pluralName = _("Muscle Mochi"), + .name = ITEM_NAME("Muscle Mochi"), + .pluralName = ITEM_PLURAL_NAME("Muscle Mochi"), .price = 500, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkMochi, @@ -13799,11 +14231,12 @@ const struct Item gItemsInfo[] = [ITEM_RESIST_MOCHI] = { - .name = _("Resist Mochi"), - .pluralName = _("Resist Mochi"), + .name = ITEM_NAME("Resist Mochi"), + .pluralName = ITEM_PLURAL_NAME("Resist Mochi"), .price = 500, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefMochi, @@ -13814,11 +14247,12 @@ const struct Item gItemsInfo[] = [ITEM_GENIUS_MOCHI] = { - .name = _("Genius Mochi"), - .pluralName = _("Genius Mochi"), + .name = ITEM_NAME("Genius Mochi"), + .pluralName = ITEM_PLURAL_NAME("Genius Mochi"), .price = 500, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkMochi, @@ -13829,11 +14263,12 @@ const struct Item gItemsInfo[] = [ITEM_CLEVER_MOCHI] = { - .name = _("Clever Mochi"), - .pluralName = _("Clever Mochi"), + .name = ITEM_NAME("Clever Mochi"), + .pluralName = ITEM_PLURAL_NAME("Clever Mochi"), .price = 500, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefMochi, @@ -13844,11 +14279,12 @@ const struct Item gItemsInfo[] = [ITEM_SWIFT_MOCHI] = { - .name = _("Swift Mochi"), - .pluralName = _("Swift Mochi"), + .name = ITEM_NAME("Swift Mochi"), + .pluralName = ITEM_PLURAL_NAME("Swift Mochi"), .price = 500, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedMochi, @@ -13859,14 +14295,15 @@ const struct Item gItemsInfo[] = [ITEM_FRESH_START_MOCHI] = { - .name = _("Fresh Start Mochi"), - .pluralName = _("Fresh Start Mochi"), + .name = ITEM_NAME("Fresh Start Mochi"), + .pluralName = ITEM_PLURAL_NAME("Fresh Start Mochi"), .price = 300, .description = COMPOUND_STRING( "An item that resets " "all base\npoints of " "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_ResetEVs, .effect = gItemEffect_ResetMochi, @@ -13877,7 +14314,7 @@ const struct Item gItemsInfo[] = [ITEM_GLIMMERING_CHARM] = { - .name = _("Glimmering Charm"), + .name = ITEM_NAME("Glimmering Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -13893,13 +14330,14 @@ const struct Item gItemsInfo[] = [ITEM_METAL_ALLOY] = { - .name = _("Metal Alloy"), + .name = ITEM_NAME("Metal Alloy"), .price = 6000, .description = COMPOUND_STRING( "A peculiar metal " "that makes\ncertain " "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13909,10 +14347,11 @@ const struct Item gItemsInfo[] = [ITEM_STELLAR_TERA_SHARD] = { - .name = _("Stellar Tera Shard"), + .name = ITEM_NAME("Stellar Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_StellarTeraShard, @@ -13921,10 +14360,11 @@ const struct Item gItemsInfo[] = [ITEM_JUBILIFE_MUFFIN] = { - .name = _("Jubilife Muffin"), + .name = ITEM_NAME("Jubilife Muffin"), .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -13936,13 +14376,14 @@ const struct Item gItemsInfo[] = [ITEM_REMEDY] = { - .name = _("Remedy"), + .name = ITEM_NAME("Remedy"), .price = 150, .description = COMPOUND_STRING( "A bitter powder " "that restores HP " "\nby 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13954,7 +14395,7 @@ const struct Item gItemsInfo[] = [ITEM_FINE_REMEDY] = { - .name = _("Fine Remedy"), + .name = ITEM_NAME("Fine Remedy"), .price = 150, .description = COMPOUND_STRING( "A bitter powder " @@ -13965,6 +14406,7 @@ const struct Item gItemsInfo[] = "\nby 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13976,7 +14418,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPERB_REMEDY] = { - .name = _("Superb Remedy"), + .name = ITEM_NAME("Superb Remedy"), .price = 750, .description = COMPOUND_STRING( "A bitter powder " @@ -13987,6 +14429,7 @@ const struct Item gItemsInfo[] = "\nby 200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13998,7 +14441,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_EVASION] = { - .name = _("Aux Evasion"), + .name = ITEM_NAME("Aux Evasion"), .price = 800, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14011,6 +14454,7 @@ const struct Item gItemsInfo[] = "during one\nbattle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -14020,7 +14464,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_GUARD] = { - .name = _("Aux Guard"), + .name = ITEM_NAME("Aux Guard"), .price = 400, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14033,6 +14477,7 @@ const struct Item gItemsInfo[] = "during one\nbattle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -14042,7 +14487,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_POWER] = { - .name = _("Aux Power"), + .name = ITEM_NAME("Aux Power"), .price = 400, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14055,6 +14500,7 @@ const struct Item gItemsInfo[] = "during one\nbattle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -14064,7 +14510,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_POWERGUARD] = { - .name = _("Aux Powerguard"), + .name = ITEM_NAME("Aux Powerguard"), .price = 1200, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14078,6 +14524,7 @@ const struct Item gItemsInfo[] = "one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -14087,7 +14534,7 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_DUMPLING] = { - .name = _("Choice Dumpling"), + .name = ITEM_NAME("Choice Dumpling"), .price = 1200, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14100,7 +14547,7 @@ const struct Item gItemsInfo[] = [ITEM_SWAP_SNACK] = { - .name = _("Swap Snack"), + .name = ITEM_NAME("Swap Snack"), .price = 1200, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14113,7 +14560,7 @@ const struct Item gItemsInfo[] = [ITEM_TWICE_SPICED_RADISH] = { - .name = _("Twice-Spiced Radish"), + .name = ITEM_NAME("Twice-Spiced Radish"), .price = 1600, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14126,16 +14573,20 @@ const struct Item gItemsInfo[] = [ITEM_POKESHI_DOLL] = { - .name = _("Pokéshi Doll"), + .name = ITEM_NAME("Pokéshi Doll"), .price = 2000, .description = COMPOUND_STRING( "A wooden toy " "resembling a Poké-.\n" "mon. Can be sold."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PokeshiDoll, .iconPalette = gItemIconPalette_PokeshiDoll, }, }; + +#undef ITEM_NAME +#undef ITEM_PLURAL_NAME diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 881840b6d..fb5dbeb3e 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -20,104 +20,104 @@ // Shared Move Description entries const u8 gNotDoneYetDescription[] = _( - "This move can't be\nused. Its " - "effect\nis in development."); + "This move can't be used. Its\n" + "effect is in development."); static const u8 sNullDescription[] = _(""); static const u8 sMegaDrainDescription[] = _( - "An attack that\nabsorbs " - "half the\ndamage inflicted."); + "An attack that absorbs\n" + "half the damage inflicted."); #if B_SKIP_RECHARGE != GEN_1 static const u8 sHyperBeamDescription[] = _( - "\nPowerful, but\nleaves the " - "user\nimmobile the next\nturn."); + "Powerful, but leaves the\n" + "user immobile the next turn."); #else static const u8 sHyperBeamDescription[] = _( - "Leaves the user\nimmobile " - "if target\nis not KO'd."); + "Leaves the user immobile\n" + "if target is not KO'd."); #endif static const u8 sRevengeDescription[] = _( - "An attack that\nmoves last " - "and\ngains power if\nhit."); + "An attack that moves last\n" + "and gains power if hit."); static const u8 sPluckDescription[] = _( - "Eats the foe's\nheld Berry " - "gaining\nits effect."); + "Eats the foe's held Berry\n" + "gaining its effect."); static const u8 sHealingWishDescription[] = _( - "The user faints to\nheal up " - "the\nrecipient."); + "The user faints to heal up\n" + "the recipient."); static const u8 sWringOutDescription[] = _( - "The higher the\nfoe's HP " - "the more\ndamage caused."); + "The higher the foe's HP\n" + "the more damage caused."); static const u8 sUTurnDescription[] = _( - "Does damage then\nswitches " - "out the\nuser."); + "Does damage then switches\n" + "out the user."); static const u8 sStormThrowDescription[] = _( - "This attack always\nresults " - "in a\ncritical hit."); + "This attack always results\n" + "in a critical hit."); static const u8 sCircleThrowDescription[] = _( - "Knocks foe away to\nswitch " - "it out or\nend wild battle."); + "Knocks foe away to switch\n" + "it out or end wild battle."); static const u8 sChipAwayDescription[] = _( - "Strikes through\nthe foe's " - "stat\nchanges."); + "Strikes through the foe's\n" + "stat changes."); static const u8 sHeavySlamDescription[] = _( - "Does more damage\nif the " - "user\noutweighs the foe."); + "Does more damage if the\n" + "user outweighs the foe."); static const u8 sPsyshockDescription[] = _( - "Attacks with a\npsychic wave " - "that\ndoes physical\ndamage."); + "Attacks with a psychic wave\n" + "that does physical damage."); static const u8 sLavaPlumeDescription[] = _( - "Scarlet flames\ntorch " - "everything\naround the user."); + "Scarlet flames torch\n" + "everything around the user."); static const u8 sShadowForceDescription[] = _( - "Vanishes on the\nfirst turn " - "then\nstrikes the next\nturn."); + "Vanishes on the first turn\n" + "then strikes the next turn."); static const u8 sFalseSwipeDescription[] = _( - "An attack that\nleaves the " - "foe\nwith at least 1\nHP."); + "An attack that leaves the\n" + "foe with at least 1 HP."); static const u8 sDrainingKissDescription[] = _( - "An attack that\nabsorbs over " - "half\nthe damage\ninflicted."); + "An attack that absorbs over\n" + "half the damage inflicted."); static const u8 sCloseCombatDescription[] = _( - "A strong attack\nbut lowers " - "the\ndefensive stats."); + "A strong attack but lowers\n" + "the defensive stats."); static const u8 sHyperspaceHoleDescription[] = _( - "Uses a warp hole\nto attack. " - "Can't\nbe evaded."); + "Uses a warp hole to attack.\n" + "Can't be evaded."); static const u8 sSuckerPunchDescription[] = _( - "Strikes first if\nthe foe " - "is\npreparing an\nattack."); + "Strikes first if the foe\n" + "is preparing an attack."); static const u8 sFeintDescription[] = _( - "An attack that\nhits foes " - "using\nmoves like\nProtect."); + "An attack that hits foes\n" + "using moves like Protect."); static const u8 sProtectDescription[] = _( - "Evades attack, but\nmay fail " - "if used\nin succession."); + "Evades attack, but may fail\n" + "if used in succession."); static const u8 sGMaxOneBlowDescription[] = _( - "G-max Urshifu\nattack. " - "Ignores\nMax Guard."); + "G-max Urshifu attack.\n" + "Ignores Max Guard."); const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { @@ -144,8 +144,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pound"), .description = COMPOUND_STRING( - "Pounds the foe\nwith " - "forelegs or\ntail."), + "Pounds the foe with\n" + "forelegs or tail."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_NORMAL, @@ -167,8 +167,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Karate Chop"), .description = COMPOUND_STRING( - "A chopping attack\nwith a " - "high\ncritical-hit\nratio."), + "A chopping attack with a\n" + "high critical-hit ratio."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_FIGHTING, @@ -191,8 +191,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Slap"), .description = COMPOUND_STRING( - "Repeatedly slaps\nthe foe " - "2 to 5\ntimes."), + "Repeatedly slaps the foe\n" + "2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 15, .type = TYPE_NORMAL, @@ -214,8 +214,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Comet Punch"), .description = COMPOUND_STRING( - "Repeatedly punches\nthe foe " - "2 to 5\ntimes."), + "Repeatedly punches the foe\n" + "2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 18, .type = TYPE_NORMAL, @@ -237,8 +237,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mega Punch"), .description = COMPOUND_STRING( - "A strong punch\nthrown with " - "\nincredible power."), + "A strong punch thrown with\n" + "incredible power."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_NORMAL, @@ -261,8 +261,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pay Day"), .description = COMPOUND_STRING( - "Throws coins at\nthe foe. " - "Money is\nrecovered after."), + "Throws coins at the foe.\n" + "Money is recovered after."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_NORMAL, @@ -285,7 +285,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Punch"), .description = COMPOUND_STRING( - "A fiery punch that\nmay burn " + "A fiery punch that may burn\n" "the foe."), .effect = EFFECT_HIT, .power = 75, @@ -313,11 +313,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Punch"), .description = COMPOUND_STRING( - "An icy punch that\nmay " + "An icy punch that may\n" #if B_USE_FROSTBITE == TRUE - "leave the foe\nwith frostbite."), + "leave the foe with frostbite."), #else - "freeze the\nfoe."), + "freeze the foe."), #endif .effect = EFFECT_HIT, .power = 75, @@ -345,8 +345,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder Punch"), .description = COMPOUND_STRING( - "An electrified\npunch that " - "may\nparalyze the foe."), + "An electrified punch that\n" + "may paralyze the foe."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_ELECTRIC, @@ -373,7 +373,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Scratch"), .description = COMPOUND_STRING( - "Scratches the foe\nwith " + "Scratches the foe with\n" "sharp claws."), .effect = EFFECT_HIT, .power = 40, @@ -395,8 +395,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Vise Grip"), .description = COMPOUND_STRING( - "Grips the foe with\nlarge and " - "powerful\npincers."), + "Grips the foe with large and\n" + "powerful pincers."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_NORMAL, @@ -417,8 +417,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Guillotine"), .description = COMPOUND_STRING( - "A powerful pincer\nattack " - "that KOs if\nit hits."), + "A powerful pincer attack\n" + "that KOs if it hits."), .effect = EFFECT_OHKO, .power = 1, .type = TYPE_NORMAL, @@ -440,8 +440,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Razor Wind"), .description = COMPOUND_STRING( - "A 2-turn move with\na high " - "\ncritical-hit ratio."), + "A 2-turn move with a high\n" + "critical-hit ratio."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 80, .type = TYPE_NORMAL, @@ -466,8 +466,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Swords Dance"), .description = COMPOUND_STRING( - "A fighting dance\nthat " - "sharply\nraises Attack."), + "A fighting dance that\n" + "sharply raises Attack."), .effect = EFFECT_ATTACK_UP_2, .power = 0, .type = TYPE_NORMAL, @@ -491,8 +491,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Cut"), .description = COMPOUND_STRING( - "Cuts the foe with\nsharp " - "scythes,\nclaws, etc."), + "Cuts the foe with sharp\n" + "scythes, claws, etc."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_NORMAL, @@ -514,8 +514,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gust"), .description = COMPOUND_STRING( - "Strikes the foe\nwith a gust " - "of\nwind whipped up by\nwings."), + "Strikes the foe with a gust\n" + "of wind whipped up by wings."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FLYING, @@ -538,8 +538,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wing Attack"), .description = COMPOUND_STRING( - "Strikes the foe\nwith wings " - "spread\nwide."), + "Strikes the foe with wings\n" + "spread wide."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_FLYING, @@ -560,8 +560,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Whirlwind"), .description = COMPOUND_STRING( - "Blows away the\nfoe, switches " - "it\nout or ends wild\nbattle."), + "Blows away the foe, switches\n" + "it out or ends wild battle."), .effect = EFFECT_ROAR, .power = 0, .type = TYPE_NORMAL, @@ -589,8 +589,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fly"), .description = COMPOUND_STRING( - "Flies up on the\nfirst turn, " - "then\nstrikes the next\nturn."), + "Flies up on the first turn,\n" + "then strikes the next turn."), .effect = EFFECT_SEMI_INVULNERABLE, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 90 : 70, .type = TYPE_FLYING, @@ -604,7 +604,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = STATE_ON_AIR }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -617,8 +617,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bind"), .description = COMPOUND_STRING( - "Binds and squeezes\nthe foe " - "for "BINDING_TURNS"\nturns."), + "Binds and squeezes the foe\n" + "for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = 15, .type = TYPE_NORMAL, @@ -631,6 +631,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_BIND, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -644,8 +645,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Slam"), .description = COMPOUND_STRING( - "Slams the foe with\na long " - "tail, vine,\netc."), + "Slams the foe with a long\n" + "tail, vine, etc."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_NORMAL, @@ -668,8 +669,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Vine Whip"), .description = COMPOUND_STRING( - "Strikes the foe\nwith " - "slender,\nwhiplike vines."), + "Strikes the foe with\n" + "slender, whiplike vines."), #if B_UPDATED_MOVE_DATA >= GEN_6 .pp = 25, #elif B_UPDATED_MOVE_DATA >= GEN_4 @@ -696,8 +697,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stomp"), .description = COMPOUND_STRING( - "Stomps the enemy\nwith a big " - "foot.\nMay cause\nflinching."), + "Stomps the enemy with a big\n" + "foot. May cause flinching."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_NORMAL, @@ -725,8 +726,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Kick"), .description = COMPOUND_STRING( - "A double-kicking\nattack " - "that\nstrikes the foe\ntwice."), + "A double-kicking attack\n" + "that strikes the foe twice."), .effect = EFFECT_HIT, .power = 30, .type = TYPE_FIGHTING, @@ -749,8 +750,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mega Kick"), .description = COMPOUND_STRING( - "An extremely\npowerful kick " - "with\nintense force."), + "An extremely powerful kick\n" + "with intense force."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_NORMAL, @@ -772,8 +773,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Jump Kick"), .description = COMPOUND_STRING( - "A strong jumping\nkick. May " - "miss and\nhurt the kicker."), + "A strong jumping kick. May\n" + "miss and hurt the kicker."), #if B_UPDATED_MOVE_DATA >= GEN_5 .power = 100, #elif B_UPDATED_MOVE_DATA >= GEN_4 @@ -802,8 +803,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rolling Kick"), .description = COMPOUND_STRING( - "A fast kick\ndelivered from " - "a\nrapid spin. May\nflinch."), + "A fast kick delivered from\n" + "a rapid spin. May flinch."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_FIGHTING, @@ -830,8 +831,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sand Attack"), .description = COMPOUND_STRING( - "Reduces the foe's\naccuracy " - "by\nhurling sand in\nits face."), + "Reduces the foe's accuracy\n" + "by hurling sand in its face."), .effect = EFFECT_ACCURACY_DOWN, .power = 0, .type = TYPE_GROUND, @@ -854,8 +855,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Headbutt"), .description = COMPOUND_STRING( - "A ramming attack\nthat may " - "cause\nflinching."), + "A ramming attack that may\n" + "cause flinching."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_NORMAL, @@ -881,7 +882,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Horn Attack"), .description = COMPOUND_STRING( - "Jabs the foe with\nsharp " + "Jabs the foe with sharp\n" "horns."), .effect = EFFECT_HIT, .power = 65, @@ -903,8 +904,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fury Attack"), .description = COMPOUND_STRING( - "Jabs the foe 2 to\n5 times " - "with sharp\nhorns, etc."), + "Jabs the foe 2 to 5 times\n" + "with sharp horns, etc."), .effect = EFFECT_MULTI_HIT, .power = 15, .type = TYPE_NORMAL, @@ -925,8 +926,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Horn Drill"), .description = COMPOUND_STRING( - "A one-hit KO\nattack that " - "uses a\nhorn like a drill."), + "A one-hit KO attack that\n" + "uses a horn like a drill."), .effect = EFFECT_OHKO, .power = 1, .type = TYPE_NORMAL, @@ -948,8 +949,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tackle"), .description = COMPOUND_STRING( - "Charges the foe\nwith a full- " - "body\ntackle."), + "Charges the foe with a full-\n" + "body tackle."), #if B_UPDATED_MOVE_DATA >= GEN_7 .power = 40, #elif B_UPDATED_MOVE_DATA >= GEN_5 @@ -976,8 +977,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Body Slam"), .description = COMPOUND_STRING( - "A full-body slam\nthat may " - "cause\nparalysis."), + "A full-body slam that may\n" + "cause paralysis."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_NORMAL, @@ -1005,8 +1006,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wrap"), .description = COMPOUND_STRING( - "Wraps and squeezes\nthe foe " - BINDING_TURNS"\ntimes with vines,\netc."), + "Wraps and squeezes the foe\n" + BINDING_TURNS" times with vines, etc."), .effect = EFFECT_HIT, .power = 15, .type = TYPE_NORMAL, @@ -1018,6 +1019,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_WRAP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -1031,8 +1033,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Take Down"), .description = COMPOUND_STRING( - "A reckless charge\nattack " - "that also\nhurts the user."), + "A reckless charge attack\n" + "that also hurts the user."), .effect = EFFECT_RECOIL, .power = 90, .type = TYPE_NORMAL, @@ -1055,8 +1057,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thrash"), .description = COMPOUND_STRING( - "A rampage of 2 to\n3 turns " - "that\nconfuses the user."), + "A rampage of 2 to 3 turns\n" + "that confuses the user."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 120 : 90, .type = TYPE_NORMAL, @@ -1083,8 +1085,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double-Edge"), .description = COMPOUND_STRING( - "A life-risking\ntackle that " - "also\nhurts the user."), + "A life-risking tackle that\n" + "also hurts the user."), .effect = EFFECT_RECOIL, .power = 120, .type = TYPE_NORMAL, @@ -1107,8 +1109,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tail Whip"), .description = COMPOUND_STRING( - "Wags the tail to\nlower the " - "foe's\nDefense."), + "Wags the tail to lower the\n" + "foe's Defense."), .effect = EFFECT_DEFENSE_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -1130,8 +1132,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poison Sting"), .description = COMPOUND_STRING( - "A toxic attack\nwith barbs, " - "etc.,\nthat may poison."), + "A toxic attack with barbs,\n" + "etc., that may poison."), .effect = EFFECT_HIT, .power = 15, .type = TYPE_POISON, @@ -1155,8 +1157,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Twineedle"), .description = COMPOUND_STRING( - "Foreleg stingers\njab foe " - "twice. May\npoison."), + "Foreleg stingers jab foe\n" + "twice. May poison."), .effect = EFFECT_HIT, .power = 25, .type = TYPE_BUG, @@ -1183,8 +1185,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pin Missile"), .description = COMPOUND_STRING( - "Sharp pins are\nfired to " - "strike 2\nto 5 times."), + "Sharp pins are fired to\n" + "strike 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 25 : 14, .type = TYPE_BUG, @@ -1204,8 +1206,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leer"), .description = COMPOUND_STRING( - "Frightens the foes\nwith a " - "leer to\nlower Defense."), + "Frightens the foes with a\n" + "leer to lower Defense."), .effect = EFFECT_DEFENSE_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -1227,8 +1229,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bite"), .description = COMPOUND_STRING( - "Bites with vicious\nfangs. " - "May cause\nflinching."), + "Bites with vicious fangs.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_DARK, @@ -1255,8 +1257,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Growl"), .description = COMPOUND_STRING( - "Growls cutely to\nreduce the " - "foe's\nAttack."), + "Growls cutely to reduce the\n" + "foe's Attack."), .effect = EFFECT_ATTACK_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -1280,8 +1282,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Roar"), .description = COMPOUND_STRING( - "Switches the foe\nout " - "or ends wild\nbattle."), + "Switches the foe out\n" + "or ends wild battle."), .effect = EFFECT_ROAR, .power = 0, .type = TYPE_NORMAL, @@ -1309,8 +1311,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sing"), .description = COMPOUND_STRING( - "A soothing song\nlulls the " - "foe into\na deep slumber."), + "A soothing song lulls the\n" + "foe into a deep slumber."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_NORMAL, @@ -1336,8 +1338,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Supersonic"), .description = COMPOUND_STRING( - "Emits bizarre\nsound waves " - "that\nmay confuse the\nfoe."), + "Emits bizarre sound waves\n" + "that may confuse the foe."), .effect = EFFECT_CONFUSE, .power = 0, .type = TYPE_NORMAL, @@ -1362,8 +1364,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sonic Boom"), .description = COMPOUND_STRING( - "Launches shock\nwaves that " - "always\ninflict 20 HP\ndamage."), + "Launches shock waves that\n" + "always inflict 20 HP damage."), .effect = EFFECT_FIXED_HP_DAMAGE, .power = 1, .type = TYPE_NORMAL, @@ -1386,13 +1388,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Disable"), .description = COMPOUND_STRING( #if B_DISABLE_TURNS >= GEN_5 - "For 4 turns,\nprevents foe " + "For 4 turns, prevents foe\n" #elif B_DISABLE_TURNS == GEN_4 - "For\n4-7 turns,\nprevents foe " + "For 4-7 turns, prevents foe\n" #else - "For 2-5 turns,\nprevents foe " + "For 2-5 turns, prevents foe\n" #endif - "from using last\nused move."), + "from using last used move."), #if B_UPDATED_MOVE_DATA >= GEN_5 .accuracy = 100, #elif B_UPDATED_MOVE_DATA == GEN_4 @@ -1422,7 +1424,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acid"), .description = COMPOUND_STRING( - "Sprays a\nhide-melting acid.\n" + "Sprays a hide-melting acid.\n" #if B_UPDATED_MOVE_DATA >= GEN_4 "May lower Sp. Def."), #else @@ -1451,8 +1453,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ember"), .description = COMPOUND_STRING( - "A weak fire attack\nthat may " - "inflict a\nburn."), + "A weak fire attack that may\n" + "inflict a burn."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FIRE, @@ -1476,8 +1478,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flamethrower"), .description = COMPOUND_STRING( - "A powerful fire\nattack that " - "may\ninflict a burn."), + "A powerful fire attack that\n" + "may inflict a burn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 95, .type = TYPE_FIRE, @@ -1502,8 +1504,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mist"), .description = COMPOUND_STRING( - "Creates a mist\nthat stops " - "\nreduction of stats."), + "Creates a mist that stops\n" + "reduction of stats."), .effect = EFFECT_MIST, .power = 0, .type = TYPE_ICE, @@ -1528,7 +1530,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Gun"), .description = COMPOUND_STRING( - "Squirts water to\nattack " + "Squirts water to attack\n" "the foe."), .effect = EFFECT_HIT, .power = 40, @@ -1549,8 +1551,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hydro Pump"), .description = COMPOUND_STRING( - "Blasts water at\nhigh power " - "to\nstrike the foe."), + "Blasts water at high power\n" + "to strike the foe."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, .type = TYPE_WATER, @@ -1571,11 +1573,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Surf"), .description = COMPOUND_STRING( - "Creates a huge\nwave, then " + "Creates a huge wave, then\n" #if B_UPDATED_MOVE_DATA >= GEN_4 - "crashes\nit down on the\nfield."), + "crashes it down on the field."), #else - "crashes\nit down on the\nfoes."), + "crashes it down on the foes."), #endif .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 95, @@ -1599,11 +1601,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Beam"), .description = COMPOUND_STRING( - "Blasts the foe\nwith an icy " + "Blasts the foe with an icy\n" #if B_USE_FROSTBITE == TRUE - "beam.\nMay cause\nfrostbite."), + "beam. May cause frostbite."), #else - "beam\nthat may freeze\nit."), + "beam that may freeze it."), #endif .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 95, @@ -1631,11 +1633,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Blizzard"), .description = COMPOUND_STRING( - "Hits the foes with\nan icy " + "Hits the foes with an icy\n" #if B_USE_FROSTBITE == TRUE - "storm. May\ncause frostbite."), + "storm. May cause frostbite."), #else - "storm that\nmay freeze it."), + "storm that may freeze it."), #endif .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, @@ -1663,8 +1665,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psybeam"), .description = COMPOUND_STRING( - "Fires a peculiar\nray that " - "may\nconfuse the foe."), + "Fires a peculiar ray that\n" + "may confuse the foe."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_PSYCHIC, @@ -1689,8 +1691,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bubble Beam"), .description = COMPOUND_STRING( - "Forcefully sprays\nbubbles " - "that may\nlower Speed."), + "Forcefully sprays bubbles\n" + "that may lower Speed."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_WATER, @@ -1714,8 +1716,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aurora Beam"), .description = COMPOUND_STRING( - "Fires a\nrainbow-colored " - "\nbeam that may\nlower Attack."), + "Fires a rainbow-colored\n" + "beam that may lower Attack."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_ICE, @@ -1764,8 +1766,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Peck"), .description = COMPOUND_STRING( - "Attacks the foe\nwith a " - "jabbing\nbeak, etc."), + "Attacks the foe with a\n" + "jabbing beak, etc."), .effect = EFFECT_HIT, .power = 35, .type = TYPE_FLYING, @@ -1786,8 +1788,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Drill Peck"), .description = COMPOUND_STRING( - "A corkscrewing\nattack with " - "the\nbeak acting as a\ndrill."), + "A corkscrewing attack with\n" + "the beak acting as a drill."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FLYING, @@ -1809,8 +1811,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Submission"), .description = COMPOUND_STRING( - "A reckless body\nslam that " - "also\nhurts the user."), + "A reckless body slam that\n" + "also hurts the user."), .effect = EFFECT_RECOIL, .power = 80, .type = TYPE_FIGHTING, @@ -1833,8 +1835,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Low Kick"), .description = COMPOUND_STRING( - "A kick that\ninflicts more " - "\ndamage on heavier\nfoes."), + "A kick that inflicts more\n" + "damage on heavier foes."), .effect = EFFECT_LOW_KICK, .power = 1, .type = TYPE_FIGHTING, @@ -1856,8 +1858,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Counter"), .description = COMPOUND_STRING( - "Retaliates any\nphysical hit " - "with\ndouble the power."), + "Retaliates any physical hit\n" + "with double the power."), .effect = EFFECT_COUNTER, .power = 1, .type = TYPE_FIGHTING, @@ -1884,8 +1886,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Seismic Toss"), .description = COMPOUND_STRING( - "Inflicts damage\nidentical " - "to the\nuser's level."), + "Inflicts damage identical\n" + "to the user's level."), .effect = EFFECT_LEVEL_DAMAGE, .power = 1, .type = TYPE_FIGHTING, @@ -1908,8 +1910,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Strength"), .description = COMPOUND_STRING( - "Builds enormous\npower, " - "then slams\nthe foe."), + "Builds enormous power,\n" + "then slams the foe."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_NORMAL, @@ -1931,8 +1933,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Absorb"), .description = COMPOUND_STRING( - "An attack that\nabsorbs " - "half the\ndamage inflicted."), + "An attack that absorbs\n" + "half the damage inflicted."), .effect = EFFECT_ABSORB, .power = 20, .type = TYPE_GRASS, @@ -1978,8 +1980,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leech Seed"), .description = COMPOUND_STRING( - "Plants a seed on\nthe foe to " - "steal\nHP on every turn."), + "Plants a seed on the foe to\n" + "steal HP on every turn."), .effect = EFFECT_LEECH_SEED, .power = 0, .type = TYPE_GRASS, @@ -2003,11 +2005,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Growth"), .description = COMPOUND_STRING( #if B_GROWTH_STAT_RAISE >= GEN_5 - "Forces the body to\ngrow, " - "raising\nAttack and Sp.\nAtk."), + "Forces the body to grow,\n" + "raising Attack and Sp. Atk."), #else - "Forces the body to\ngrow " - "and heightens\nSp. Atk."), + "Forces the body to grow\n" + "and heightens Sp. Atk."), #endif .effect = B_GROWTH_STAT_RAISE >= GEN_5 ? EFFECT_GROWTH : EFFECT_SPECIAL_ATTACK_UP, .power = 0, @@ -2033,8 +2035,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Razor Leaf"), .description = COMPOUND_STRING( - "Cuts enemies with\nleaves. " - "High\ncritical-hit\nratio."), + "Cuts enemies with leaves.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_GRASS, @@ -2057,8 +2059,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Solar Beam"), .description = COMPOUND_STRING( - "Absorbs light in\none turn, " - "then\nattacks next turn."), + "Absorbs light in one turn,\n" + "then attacks next turn."), .effect = EFFECT_SOLAR_BEAM, .power = 120, .type = TYPE_GRASS, @@ -2082,8 +2084,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poison Powder"), .description = COMPOUND_STRING( - "Scatters a toxic\npowder " - "that may\npoison the foe."), + "Scatters a toxic powder\n" + "that may poison the foe."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_POISON, @@ -2108,8 +2110,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stun Spore"), .description = COMPOUND_STRING( - "Scatters a powder\nthat may " - "paralyze\nthe foe."), + "Scatters a powder that may\n" + "paralyze the foe."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_GRASS, @@ -2134,8 +2136,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sleep Powder"), .description = COMPOUND_STRING( - "Scatters a powder\nthat may " - "cause the\nfoe to sleep."), + "Scatters a powder that may\n" + "cause the foe to sleep."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_GRASS, @@ -2160,8 +2162,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Petal Dance"), .description = COMPOUND_STRING( - "A rampage of 2 to\n3 turns " - "that\nconfuses the user."), + "A rampage of 2 to 3 turns\n" + "that confuses the user."), #if B_UPDATED_MOVE_DATA >= GEN_5 .power = 120, #elif B_UPDATED_MOVE_DATA == GEN_4 @@ -2195,8 +2197,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("String Shot"), .description = COMPOUND_STRING( - "Binds the foe with\nstring " - "to reduce\nits Speed."), + "Binds the foe with string\n" + "to reduce its Speed."), .effect = B_UPDATED_MOVE_DATA >= GEN_6 ? EFFECT_SPEED_DOWN_2 : EFFECT_SPEED_DOWN, .power = 0, .type = TYPE_BUG, @@ -2218,8 +2220,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Rage"), .description = COMPOUND_STRING( - "Launches shock\nwaves that " - "always\ninflict 40 HP\ndamage."), + "Launches shock waves that\n" + "always inflict 40 HP damage."), .effect = EFFECT_FIXED_HP_DAMAGE, .power = 1, .type = TYPE_DRAGON, @@ -2242,8 +2244,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Spin"), .description = COMPOUND_STRING( - "Traps the foe in a\nring of " - "fire for\n"BINDING_TURNS" turns."), + "Traps the foe in a ring of\n" + "fire for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 35 : 15, .type = TYPE_FIRE, @@ -2255,6 +2257,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_FIRE_SPIN, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -2268,8 +2271,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder Shock"), .description = COMPOUND_STRING( - "An electrical\nattack that " - "may\nparalyze the foe."), + "An electrical attack that\n" + "may paralyze the foe."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_ELECTRIC, @@ -2293,8 +2296,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunderbolt"), .description = COMPOUND_STRING( - "A strong\nelectrical attack " - "\nthat may paralyze\nthe foe."), + "A strong electrical attack\n" + "that may paralyze the foe."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 95, .type = TYPE_ELECTRIC, @@ -2319,8 +2322,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder Wave"), .description = COMPOUND_STRING( - "A weak jolt of\nelectricity " - "that\nparalyzes the foe."), + "A weak jolt of electricity\n" + "that paralyzes the foe."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_ELECTRIC, @@ -2344,8 +2347,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder"), .description = COMPOUND_STRING( - "A lightning attack\nthat may " - "cause\nparalysis."), + "A lightning attack that may\n" + "cause paralysis."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, .type = TYPE_ELECTRIC, @@ -2373,7 +2376,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Throw"), .description = COMPOUND_STRING( - "Throws small rocks\nto " + "Throws small rocks to\n" "strike the foe."), .effect = EFFECT_HIT, .power = 50, @@ -2394,8 +2397,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Earthquake"), .description = COMPOUND_STRING( - "A powerful quake\nthat " - "hits all\nother POKéMON."), + "A powerful quake that\n" + "hits all other POKéMON."), .effect = EFFECT_EARTHQUAKE, .power = 100, .type = TYPE_GROUND, @@ -2419,8 +2422,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fissure"), .description = COMPOUND_STRING( - "A one-hit KO move\nthat " - "drops the foe\nin a fissure."), + "A one-hit KO move that\n" + "drops the foe in a fissure."), .effect = EFFECT_OHKO, .power = 1, .type = TYPE_GROUND, @@ -2443,8 +2446,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dig"), .description = COMPOUND_STRING( - "Digs underground\nthe first " - "turn and\nstrikes next turn."), + "Digs underground the first\n" + "turn and strikes next turn."), .effect = EFFECT_SEMI_INVULNERABLE, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 80 : 60, .type = TYPE_GROUND, @@ -2458,7 +2461,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = COMPRESS_BITS(STATUS3_UNDERGROUND) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = STATE_UNDERGROUND }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -2471,8 +2474,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Toxic"), .description = COMPOUND_STRING( - "Poisons the foe\nwith an " - "\nintensifying toxin."), + "Poisons the foe with an\n" + "intensifying toxin."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_POISON, @@ -2496,8 +2499,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Confusion"), .description = COMPOUND_STRING( - "A psychic attack\nthat may " - "cause\nconfusion."), + "A psychic attack that may\n" + "cause confusion."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_PSYCHIC, @@ -2521,8 +2524,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psychic"), .description = COMPOUND_STRING( - "A powerful psychic\nattack " - "that may\nlower Sp. Def."), + "A powerful psychic attack\n" + "that may lower Sp. Def."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_PSYCHIC, @@ -2547,8 +2550,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hypnosis"), .description = COMPOUND_STRING( - "A hypnotizing move\nthat " - "may induce\nsleep."), + "A hypnotizing move that\n" + "may induce sleep."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_PSYCHIC, @@ -2572,8 +2575,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Meditate"), .description = COMPOUND_STRING( - "Meditates in a\npeaceful " - "fashion\nto raise Attack."), + "Meditates in a peaceful\n" + "fashion to raise Attack."), .effect = EFFECT_ATTACK_UP, .power = 0, .type = TYPE_PSYCHIC, @@ -2598,8 +2601,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Agility"), .description = COMPOUND_STRING( - "Relaxes the body\nto sharply " - "boost\nSpeed."), + "Relaxes the body to sharply\n" + "boost Speed."), .effect = EFFECT_SPEED_UP_2, .power = 0, .type = TYPE_PSYCHIC, @@ -2624,8 +2627,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Quick Attack"), .description = COMPOUND_STRING( - "An extremely fast\nattack " - "that always\nstrikes first."), + "An extremely fast attack\n" + "that always strikes first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_NORMAL, @@ -2647,8 +2650,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rage"), .description = COMPOUND_STRING( - "Raises the user's\nAttack " - "every time\nit is hit."), + "Raises the user's Attack\n" + "every time it is hit."), .effect = EFFECT_RAGE, .power = 20, .type = TYPE_NORMAL, @@ -2668,14 +2671,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = [MOVE_TELEPORT] = { .name = COMPOUND_STRING("Teleport"), - #if B_TELEPORT_BEHAVIOUR >= GEN_8 + #if B_TELEPORT_BEHAVIOR >= GEN_8 .description = COMPOUND_STRING( - "Switches\nthe user out last.\n" - "Flees when used by\nwild {PKMN}.") + "Switches the user out last.\n" + "Flees when used by wild {PKMN}."), #else .description = COMPOUND_STRING( - "A psychic move for\nfleeing " - "from\nbattle instantly."), + "A psychic move for fleeing\n" + "from battle instantly."), #endif .effect = EFFECT_TELEPORT, .power = 0, @@ -2699,8 +2702,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Night Shade"), .description = COMPOUND_STRING( - "Inflicts damage\nidentical " - "to the\nuser's level."), + "Inflicts damage identical\n" + "to the user's level."), .effect = EFFECT_LEVEL_DAMAGE, .power = 1, .type = TYPE_GHOST, @@ -2721,8 +2724,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mimic"), .description = COMPOUND_STRING( - "Copies last move\nused by the " - "foe\nduring one battle."), + "Copies last move used by the\n" + "foe during one battle."), .effect = EFFECT_MIMIC, .power = 0, .type = TYPE_NORMAL, @@ -2752,8 +2755,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Screech"), .description = COMPOUND_STRING( - "Emits a screech to\nsharply " - "reduce the\nfoe's Defense."), + "Emits a screech to sharply\n" + "reduce the foe's Defense."), .effect = EFFECT_DEFENSE_DOWN_2, .power = 0, .type = TYPE_NORMAL, @@ -2778,8 +2781,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Team"), .description = COMPOUND_STRING( - "Creates illusory\ncopies to " - "raise\nevasiveness."), + "Creates illusory copies to\n" + "raise evasiveness."), .effect = EFFECT_EVASION_UP, .power = 0, .type = TYPE_NORMAL, @@ -2804,8 +2807,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Recover"), .description = COMPOUND_STRING( - "Recovers up to\nhalf the " - "user's\nmaximum HP."), + "Recovers up to half the\n" + "user's maximum HP."), #if B_UPDATED_MOVE_DATA >= GEN_9 .pp = 5, #elif B_UPDATED_MOVE_DATA >= GEN_4 @@ -2837,8 +2840,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Harden"), .description = COMPOUND_STRING( - "Stiffens the\nbody's " - "muscles to\nraise Defense."), + "Stiffens the body's \n" + "muscles to raise Defense."), .effect = EFFECT_DEFENSE_UP, .power = 0, .type = TYPE_NORMAL, @@ -2863,11 +2866,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Minimize"), .description = COMPOUND_STRING( - "Minimizes the\nuser's size to " + "Minimizes the user's size to\n" #if B_MINIMIZE_EVASION >= GEN_5 - "\nsharply raise\nevasiveness."), + "sharply raise evasiveness."), #else - "\nraise evasiveness."), + "raise evasiveness."), #endif .effect = EFFECT_MINIMIZE, .power = 0, @@ -2893,8 +2896,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Smokescreen"), .description = COMPOUND_STRING( - "Lowers the foe's\naccuracy " - "using\nsmoke, ink, etc."), + "Lowers the foe's accuracy\n" + "using smoke, ink, etc."), .effect = EFFECT_ACCURACY_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -2917,8 +2920,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Confuse Ray"), .description = COMPOUND_STRING( - "A sinister ray\nthat " - "confuses the\nfoe."), + "A sinister ray that\n" + "confuses the foe."), .effect = EFFECT_CONFUSE, .power = 0, .type = TYPE_GHOST, @@ -2941,8 +2944,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Withdraw"), .description = COMPOUND_STRING( - "Withdraws the body\ninto its " - "hard\nshell to raise\nDefense."), + "Withdraws the body into its\n" + "hard shell to raise Defense."), .effect = EFFECT_DEFENSE_UP, .power = 0, .type = TYPE_WATER, @@ -2967,8 +2970,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Defense Curl"), .description = COMPOUND_STRING( - "Curls up to\nconceal weak " - "spots\nand raise Defense."), + "Curls up to conceal weak\n" + "spots and raise Defense."), .effect = EFFECT_DEFENSE_CURL, .power = 0, .type = TYPE_NORMAL, @@ -2993,8 +2996,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Barrier"), .description = COMPOUND_STRING( - "Creates a barrier\nthat " - "sharply\nraises Defense."), + "Creates a barrier that\n" + "sharply raises Defense."), .effect = EFFECT_DEFENSE_UP_2, .power = 0, .type = TYPE_PSYCHIC, @@ -3019,8 +3022,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Light Screen"), .description = COMPOUND_STRING( - "Wall of light cuts\nspecial " - "damage for\n5 turns."), + "Wall of light cuts special\n" + "damage for 5 turns."), .effect = EFFECT_LIGHT_SCREEN, .power = 0, .type = TYPE_PSYCHIC, @@ -3045,8 +3048,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Haze"), .description = COMPOUND_STRING( - "Creates a black\nhaze that " - "\neliminates all\nstat changes."), + "Creates a black haze that\n" + "eliminates all stat changes."), .effect = EFFECT_HAZE, .power = 0, .type = TYPE_ICE, @@ -3071,8 +3074,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Reflect"), .description = COMPOUND_STRING( - "Wall of light cuts\nphysical " - "damage\nfor 5 turns."), + "Wall of light cuts physical\n" + "damage for 5 turns."), .effect = EFFECT_REFLECT, .power = 0, .type = TYPE_PSYCHIC, @@ -3097,8 +3100,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Focus Energy"), .description = COMPOUND_STRING( - "Focuses power to\nraise the " - "\ncritical-hit ratio."), + "Focuses power to raise the\n" + "critical-hit ratio."), .effect = EFFECT_FOCUS_ENERGY, .power = 0, .type = TYPE_NORMAL, @@ -3108,7 +3111,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, - .argument = { .status = STATUS2_FOCUS_ENERGY }, + .argument = { .status = VOLATILE_FOCUS_ENERGY }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, @@ -3124,8 +3127,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bide"), .description = COMPOUND_STRING( - "Endures attack for\n2 " - "turns to\nretaliate double."), + "Endures attack for 2\n" + "turns to retaliate double."), .effect = EFFECT_BIDE, .power = 1, .type = TYPE_NORMAL, @@ -3149,8 +3152,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Metronome"), .description = COMPOUND_STRING( - "Waggles a finger\nto use any " - "\nPokémon move at\nrandom."), + "Waggles a finger to use any\n" + "Pokémon move at random."), .effect = EFFECT_METRONOME, .power = 0, .type = TYPE_NORMAL, @@ -3180,8 +3183,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mirror Move"), .description = COMPOUND_STRING( - "Counters the foe's\nattack " - "with the\nsame move."), + "Counters the foe's attack\n" + "with the same move."), .effect = EFFECT_MIRROR_MOVE, .power = 0, .type = TYPE_FLYING, @@ -3210,8 +3213,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Self-Destruct"), .description = COMPOUND_STRING( - "Inflicts severe\ndamage but " - "makes\nthe user faint."), + "Inflicts severe damage but\n" + "makes the user faint."), .effect = EFFECT_EXPLOSION, .power = 200, .type = TYPE_NORMAL, @@ -3234,7 +3237,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Egg Bomb"), .description = COMPOUND_STRING( - "An egg is forcibly\nhurled at " + "An egg is forcibly hurled at\n" "the foe."), .effect = EFFECT_HIT, .power = 100, @@ -3257,8 +3260,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lick"), .description = COMPOUND_STRING( - "Licks with a long\ntongue to " - "injure.\nMay also paralyze."), + "Licks with a long tongue to\n" + "injure. May also paralyze."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 30 : 20, .type = TYPE_GHOST, @@ -3284,8 +3287,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Smog"), .description = COMPOUND_STRING( - "An exhaust-gas\nattack " - "that may\nalso poison."), + "An exhaust-gas attack\n" + "that may also poison."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 30 : 20, .type = TYPE_POISON, @@ -3309,8 +3312,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sludge"), .description = COMPOUND_STRING( - "Sludge is hurled\nto inflict " - "damage.\nMay also poison."), + "Sludge is hurled to inflict\n" + "damage. May also poison."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_POISON, @@ -3334,8 +3337,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bone Club"), .description = COMPOUND_STRING( - "Clubs the foe with\na bone. " - "May cause\nflinching."), + "Clubs the foe with a bone.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_GROUND, @@ -3359,8 +3362,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Blast"), .description = COMPOUND_STRING( - "Incinerates\neverything it " - "\nstrikes. May cause\na burn."), + "Incinerates everything it\n" + "strikes. May cause a burn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, .type = TYPE_FIRE, @@ -3385,8 +3388,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Waterfall"), .description = COMPOUND_STRING( - "Charges with speed\nto climb " - "\nwaterfalls. May\nflinch."), + "Charges with speed to climb\n" + "waterfalls. May flinch."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_WATER, @@ -3414,8 +3417,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Clamp"), .description = COMPOUND_STRING( - "Traps and squeezes\nthe " - "foe for "BINDING_TURNS"\nturns."), + "Traps and squeezes the\n" + "foe for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = 35, .type = TYPE_WATER, @@ -3428,6 +3431,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_CLAMP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -3441,8 +3445,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Swift"), .description = COMPOUND_STRING( - "Sprays star-shaped\nrays " - "that never\nmiss."), + "Sprays star-shaped rays\n" + "that never miss."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_NORMAL, @@ -3463,8 +3467,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Skull Bash"), .description = COMPOUND_STRING( - "Tucks in the head,\nthen " - "attacks on\nthe next turn."), + "Tucks in the head, then\n" + "attacks on the next turn."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 130 : 100, .type = TYPE_NORMAL, @@ -3494,8 +3498,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spike Cannon"), .description = COMPOUND_STRING( - "Launches sharp\nspikes that " - "strike\n2 to 5 times."), + "Launches sharp spikes that\n" + "strike 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 20, .type = TYPE_NORMAL, @@ -3515,8 +3519,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Constrict"), .description = COMPOUND_STRING( - "Constricts to\ninflict pain. " - "May\nlower Speed."), + "Constricts to inflict pain.\n" + "May lower Speed."), .effect = EFFECT_HIT, .power = 10, .type = TYPE_NORMAL, @@ -3541,8 +3545,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Amnesia"), .description = COMPOUND_STRING( - "Forgets about\nsomething " - "and\nsharply raises Sp.\nDef."), + "Forgets about something\n" + "and sharply raises Sp. Def."), .effect = EFFECT_SPECIAL_DEFENSE_UP_2, .power = 0, .type = TYPE_PSYCHIC, @@ -3568,7 +3572,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Kinesis"), .description = COMPOUND_STRING( "Distracts the foe.\n" - "May lower\naccuracy."), + "May lower accuracy."), .effect = EFFECT_ACCURACY_DOWN, .power = 0, .type = TYPE_PSYCHIC, @@ -3591,8 +3595,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Soft-Boiled"), .description = COMPOUND_STRING( - "Recovers up to\nhalf the " - "user's\nmaximum HP."), + "Recovers up to half the\n" + "user's maximum HP."), .effect = EFFECT_SOFTBOILED, .power = 0, .type = TYPE_NORMAL, @@ -3618,8 +3622,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("High Jump Kick"), .description = COMPOUND_STRING( - "A jumping knee\nkick. If it " - "\nmisses, the user\nis hurt."), + "A jumping knee kick. If it\n" + "misses, the user is hurt."), #if B_UPDATED_MOVE_DATA >= GEN_5 .power = 130, #elif B_UPDATED_MOVE_DATA == GEN_4 @@ -3648,8 +3652,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Glare"), .description = COMPOUND_STRING( - "Intimidates and\nfrightens " - "the foe\ninto paralysis."), + "Intimidates and frightens\n" + "the foe into paralysis."), #if B_UPDATED_MOVE_DATA >= GEN_6 .accuracy = 100, #elif B_UPDATED_MOVE_DATA == GEN_5 @@ -3679,8 +3683,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dream Eater"), .description = COMPOUND_STRING( - "Takes one half the\ndamage " - "inflicted\non a sleeping foe."), + "Takes one half the damage\n" + "inflicted on a sleeping foe."), .effect = EFFECT_DREAM_EATER, .power = 100, .type = TYPE_PSYCHIC, @@ -3704,11 +3708,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Poison Gas"), .description = COMPOUND_STRING( #if B_UPDATED_MOVE_DATA >= GEN_5 - "Envelops the foes\nin a toxic " + "Envelops the foes in a toxic\n" #else - "Envelops the foe\nin a toxic " + "Envelops the foe in a toxic\n" #endif - "gas that may\npoison."), + "gas that may poison."), #if B_UPDATED_MOVE_DATA >= GEN_6 .accuracy = 90, #elif B_UPDATED_MOVE_DATA >= GEN_5 @@ -3737,8 +3741,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Barrage"), .description = COMPOUND_STRING( - "Hurls round\nobjects at the " - "foe\n2 to 5 times."), + "Hurls round objects at the\n" + "foe 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 15, .type = TYPE_NORMAL, @@ -3759,8 +3763,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leech Life"), .description = COMPOUND_STRING( - "An attack that\nsteals half " - "the\ndamage inflicted."), + "An attack that steals half\n" + "the damage inflicted."), .effect = EFFECT_ABSORB, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 80 : 20, .type = TYPE_BUG, @@ -3784,8 +3788,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lovely Kiss"), .description = COMPOUND_STRING( - "Demands a kiss\nwith a scary " - "face\nthat induces\nsleep."), + "Demands a kiss with a scary\n" + "face that induces sleep."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_NORMAL, @@ -3809,8 +3813,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sky Attack"), .description = COMPOUND_STRING( - "2-turn attack.\nHigh critical " - "hit\nratio, and may\nflinch."), + "2-turn attack. High critical\n" + "hit ratio, and may flinch."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 140, .type = TYPE_FLYING, @@ -3841,8 +3845,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Transform"), .description = COMPOUND_STRING( - "Alters the user's\ncells to " - "become a\ncopy of the foe."), + "Alters the user's cells to\n" + "become a copy of the foe."), .effect = EFFECT_TRANSFORM, .power = 0, .type = TYPE_NORMAL, @@ -3872,8 +3876,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bubble"), .description = COMPOUND_STRING( - "An attack using\nbubbles. " - "May lower\nthe foe's Speed."), + "An attack using bubbles.\n" + "May lower the foe's Speed."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 40 : 20, .type = TYPE_WATER, @@ -3897,8 +3901,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dizzy Punch"), .description = COMPOUND_STRING( - "A rhythmic punch\nthat may " - "confuse\nthe foe."), + "A rhythmic punch that may\n" + "confuse the foe."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_NORMAL, @@ -3925,8 +3929,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spore"), .description = COMPOUND_STRING( - "Scatters a cloud\nof spores " - "that\nalways induce\nsleep."), + "Scatters a cloud of spores\n" + "that always induce sleep."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_GRASS, @@ -3951,8 +3955,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flash"), .description = COMPOUND_STRING( - "Looses a powerful\nblast of " - "light\nthat cuts\naccuracy."), + "Looses a powerful blast of\n" + "light that cuts accuracy."), .effect = EFFECT_ACCURACY_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -3975,8 +3979,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psywave"), .description = COMPOUND_STRING( - "Attacks with a\npsychic " - "wave of\nvarying intensity."), + "Attacks with a psychic\n" + "wave of varying intensity."), .effect = EFFECT_PSYWAVE, .power = 1, .type = TYPE_PSYCHIC, @@ -3997,8 +4001,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Splash"), .description = COMPOUND_STRING( - "It's just a\nsplash... " - "Has no\neffect whatsoever."), + "It's just a splash...\n" + "Has no effect whatsoever."), .effect = EFFECT_DO_NOTHING, .power = 0, .type = TYPE_NORMAL, @@ -4022,8 +4026,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acid Armor"), .description = COMPOUND_STRING( - "Liquifies the\nuser's body " - "to\nsharply raise\nDefense."), + "Liquifies the user's body\n" + "to sharply raise Defense."), .effect = EFFECT_DEFENSE_UP_2, .power = 0, .type = TYPE_POISON, @@ -4048,8 +4052,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Crabhammer"), .description = COMPOUND_STRING( - "Hammers with a\npincer. Has a " - "high\ncritical-hit\nratio."), + "Hammers with a pincer. Has a\n" + "high critical-hit ratio."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 100 : 90, .type = TYPE_WATER, @@ -4072,8 +4076,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Explosion"), .description = COMPOUND_STRING( - "Inflicts severe\ndamage but " - "makes\nthe user faint."), + "Inflicts severe damage but\n" + "makes the user faint."), .effect = EFFECT_EXPLOSION, .power = 250, .type = TYPE_NORMAL, @@ -4096,8 +4100,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fury Swipes"), .description = COMPOUND_STRING( - "Rakes the foe with\nsharp " - "claws, etc.,\n2 to 5 times."), + "Rakes the foe with sharp\n" + "claws, etc., 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 18, .type = TYPE_NORMAL, @@ -4118,8 +4122,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bonemerang"), .description = COMPOUND_STRING( - "Throws a bone\nboomerang " - "that\nstrikes twice."), + "Throws a bone boomerang\n" + "that strikes twice."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_GROUND, @@ -4141,8 +4145,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rest"), .description = COMPOUND_STRING( - "The user sleeps\nfor 2 turns, " - "\nrestoring HP and\nstatus."), + "The user sleeps for 2 turns,\n" + "restoring HP and status."), .effect = EFFECT_REST, .power = 0, .type = TYPE_PSYCHIC, @@ -4168,8 +4172,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Slide"), .description = COMPOUND_STRING( - "Large boulders are\nhurled. " - "May cause\nflinching."), + "Large boulders are hurled.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_ROCK, @@ -4194,8 +4198,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hyper Fang"), .description = COMPOUND_STRING( - "Attacks with sharp\nfangs. " - "May cause\nflinching."), + "Attacks with sharp fangs.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_NORMAL, @@ -4222,8 +4226,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sharpen"), .description = COMPOUND_STRING( - "Reduces the\npolygon count " - "and\nraises Attack."), + "Reduces the polygon count\n" + "and raises Attack."), .effect = EFFECT_ATTACK_UP, .power = 0, .type = TYPE_NORMAL, @@ -4248,11 +4252,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Conversion"), .description = COMPOUND_STRING( - "Changes the user's\ntype " + "Changes the user's type\n" #if B_UPDATED_CONVERSION >= GEN_6 - "into first\nknown move's type."), + "into first known move's type."), #else - "into a known\nmove's type."), + "into a known move's type."), #endif .effect = EFFECT_CONVERSION, .power = 0, @@ -4278,11 +4282,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tri Attack"), .description = COMPOUND_STRING( - "Fires three types\nof beams. " + "Fires three types of beams.\n" #if B_USE_FROSTBITE == TRUE - "May\nburn/para/frostbite."), + "May burn/para/frostbite."), #else - "May\nburn/paralyze/freeze."), + "May burn/paralyze/freeze."), #endif .effect = EFFECT_HIT, .power = 80, @@ -4308,8 +4312,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Super Fang"), .description = COMPOUND_STRING( - "Attacks with sharp\nfangs " - "and cuts\nhalf the foe's HP."), + "Attacks with sharp fangs\n" + "and cuts half the foe's HP."), .effect = EFFECT_FIXED_PERCENT_DAMAGE, .power = 1, .type = TYPE_NORMAL, @@ -4333,8 +4337,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Slash"), .description = COMPOUND_STRING( - "Slashes with\nclaws, etc. Has " - "a\nhigh critical-hit\nratio."), + "Slashes with claws, etc. Has\n" + "a high critical-hit ratio."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_NORMAL, @@ -4358,8 +4362,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Substitute"), .description = COMPOUND_STRING( - "Creates a decoy\nusing 1/4 " - "of the\nuser's maximum HP."), + "Creates a decoy using 1/4\n" + "of the user's maximum HP."), .effect = EFFECT_SUBSTITUTE, .power = 0, .type = TYPE_NORMAL, @@ -4385,8 +4389,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Struggle"), .description = COMPOUND_STRING( - "Used only if all\nPP are gone. " - "Also\nhurts the user a\nlittle."), + "Used only if all PP are gone.\n" + "Also hurts the user a little."), #if B_UPDATED_MOVE_DATA >= GEN_4 .effect = EFFECT_STRUGGLE, .accuracy = 0, @@ -4424,8 +4428,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sketch"), .description = COMPOUND_STRING( - "Copies the foe's\nlast move " - "\npermanently."), + "Copies the foe's last move\n" + "permanently."), .effect = EFFECT_SKETCH, .power = 0, .type = TYPE_NORMAL, @@ -4458,8 +4462,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Triple Kick"), .description = COMPOUND_STRING( - "Kicks the foe 3\ntimes in a " - "row\nwith rising\nintensity."), + "Kicks the foe 3 times in a\n" + "row with rising intensity."), .effect = EFFECT_TRIPLE_KICK, .power = 10, .type = TYPE_FIGHTING, @@ -4482,9 +4486,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thief"), .description = COMPOUND_STRING( - "While attacking,\nit may " - "steal the\nfoe's held item."), - .effect = EFFECT_HIT, + "While attacking, it may\n" + "steal the foe's held item."), + .effect = EFFECT_STEAL_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 40, .type = TYPE_DARK, .accuracy = 100, @@ -4493,9 +4497,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEAL_ITEM, - }), .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .meFirstBanned = TRUE, .metronomeBanned = TRUE, @@ -4513,8 +4514,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spider Web"), .description = COMPOUND_STRING( - "Ensnares the foe\nto stop it " - "from\nfleeing or\nswitching."), + "Ensnares the foe to stop it\n" + "from fleeing or switching."), .effect = EFFECT_MEAN_LOOK, .power = 0, .type = TYPE_BUG, @@ -4538,8 +4539,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mind Reader"), .description = COMPOUND_STRING( - "Senses the foe's\naction to " - "ensure\nthe next move's\nhit."), + "Senses the foe's action to\n" + "ensure the next move's hit."), .effect = EFFECT_LOCK_ON, .power = 0, .type = TYPE_NORMAL, @@ -4561,8 +4562,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Nightmare"), .description = COMPOUND_STRING( - "Inflicts 1/4\ndamage on a " - "\nsleeping foe every\nturn."), + "Inflicts 1/4 damage on a\n" + "sleeping foe every turn."), .effect = EFFECT_NIGHTMARE, .power = 0, .type = TYPE_GHOST, @@ -4585,8 +4586,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flame Wheel"), .description = COMPOUND_STRING( - "A fiery charge\nattack that " - "may\ninflict a burn."), + "A fiery charge attack that\n" + "may inflict a burn."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_FIRE, @@ -4612,8 +4613,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Snore"), .description = COMPOUND_STRING( - "A loud attack that\ncan only " - "be used\nasleep. May\nflinch."), + "A loud attack that can only\n" + "be used asleep. May flinch."), .effect = EFFECT_SNORE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 50 : 40, .type = TYPE_NORMAL, @@ -4641,8 +4642,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Curse"), .description = COMPOUND_STRING( - "A move that\nfunctions " - "\ndifferently for\nGHOSTS."), + "A move that functions\n" + "differently for GHOSTS."), .effect = EFFECT_CURSE, .power = 0, .type = B_UPDATED_MOVE_TYPES >= GEN_5 ? TYPE_GHOST : TYPE_MYSTERY, @@ -4667,8 +4668,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flail"), .description = COMPOUND_STRING( - "Inflicts more\ndamage when " - "the\nuser's HP is down."), + "Inflicts more damage when\n" + "the user's HP is down."), .effect = EFFECT_FLAIL, .power = 1, .type = TYPE_NORMAL, @@ -4690,8 +4691,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Conversion 2"), .description = COMPOUND_STRING( - "Makes the user\nresistant " - "to the\nlast attack's\ntype."), + "Makes the user resistant\n" + "to the last attack's type."), .effect = EFFECT_CONVERSION_2, .power = 0, .type = TYPE_NORMAL, @@ -4716,8 +4717,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aeroblast"), .description = COMPOUND_STRING( - "Launches a\nvacuumed blast. " - "\nHigh critical-hit\nratio."), + "Launches a vacuumed blast.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FLYING, @@ -4741,11 +4742,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Cotton Spore"), .description = COMPOUND_STRING( #if B_UPDATED_MOVE_DATA >= GEN_6 - "Spores cling to\nthe foes, " + "Spores cling to the foes,\n" #else - "Spores cling to\nthe foe, " + "Spores cling to the foe,\n" #endif - "sharply reducing\nSpeed."), + "sharply reducing Speed."), .effect = EFFECT_SPEED_DOWN_2, .power = 0, .type = TYPE_GRASS, @@ -4769,8 +4770,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Reversal"), .description = COMPOUND_STRING( - "Inflicts more\ndamage when " - "the\nuser's HP is down."), + "Inflicts more damage when\n" + "the user's HP is down."), .effect = EFFECT_FLAIL, .power = 1, .type = TYPE_FIGHTING, @@ -4792,11 +4793,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spite"), .description = COMPOUND_STRING( - "Spitefully cuts\nthe PP " + "Spitefully cuts the PP\n" #if B_PP_REDUCED_BY_SPITE >= GEN_4 - "of the\nfoe's last move by\n4."), + "of the foe's last move by 4."), #else - "of foe's\nlast move by 2-5."), + "of foe's last move by 2-5."), #endif .effect = EFFECT_SPITE, .power = 0, @@ -4821,11 +4822,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Powder Snow"), .description = COMPOUND_STRING( - "Blasts the foes\nwith a snowy " + "Blasts the foes with a snowy\n" #if B_USE_FROSTBITE == TRUE - "gust.\nMay cause\nfrostbite."), + "gust. May cause frostbite."), #else - "gust.\nMay cause\nfreezing."), + "gust. May cause freezing."), #endif .effect = EFFECT_HIT, .power = 40, @@ -4875,8 +4876,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mach Punch"), .description = COMPOUND_STRING( - "A punch is thrown\nat wicked " - "speed to\nstrike first."), + "A punch is thrown at wicked\n" + "speed to strike first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FIGHTING, @@ -4899,8 +4900,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Scary Face"), .description = COMPOUND_STRING( - "Frightens with a\nscary face " - "to\nsharply reduce\nSpeed."), + "Frightens with a scary face\n" + "to sharply reduce Speed."), .effect = EFFECT_SPEED_DOWN_2, .power = 0, .type = TYPE_NORMAL, @@ -4923,8 +4924,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Feint Attack"), .description = COMPOUND_STRING( - "Draws the foe\nclose, then " - "\nstrikes without\nfail."), + "Draws the foe close, then\n" + "strikes without fail."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_DARK, @@ -4946,8 +4947,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sweet Kiss"), .description = COMPOUND_STRING( - "Demands a kiss\nwith a cute " - "look.\nMay cause\nconfusion."), + "Demands a kiss with a cute\n" + "look. May cause confusion."), .effect = EFFECT_CONFUSE, .power = 0, .type = B_UPDATED_MOVE_TYPES >= GEN_6 ? TYPE_FAIRY : TYPE_NORMAL, @@ -4970,8 +4971,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Belly Drum"), .description = COMPOUND_STRING( - "Maximizes Attack\nwhile " - "sacrificing\nhalf of max HP."), + "Maximizes Attack while\n" + "sacrificing half of max HP."), .effect = EFFECT_BELLY_DRUM, .power = 0, .type = TYPE_NORMAL, @@ -4996,8 +4997,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sludge Bomb"), .description = COMPOUND_STRING( - "Sludge is hurled\nto inflict " - "damage.\nMay also poison."), + "Sludge is hurled to inflict\n" + "damage. May also poison."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_POISON, @@ -5023,8 +5024,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mud-Slap"), .description = COMPOUND_STRING( - "Hurls mud in the\nfoe's face " - "to\nreduce its\naccuracy."), + "Hurls mud in the foe's face\n" + "to reduce its accuracy."), .effect = EFFECT_HIT, .power = 20, .type = TYPE_GROUND, @@ -5049,8 +5050,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Octazooka"), .description = COMPOUND_STRING( - "Fires a lump of\nink to " - "damage and\ncut accuracy."), + "Fires a lump of ink to\n" + "damage and cut accuracy."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_WATER, @@ -5076,8 +5077,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spikes"), .description = COMPOUND_STRING( - "Sets spikes that\nhurt a " - "foe\nswitching in."), + "Sets spikes that hurt a \n" + "foe switching in."), .effect = EFFECT_SPIKES, .power = 0, .type = TYPE_GROUND, @@ -5104,8 +5105,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Zap Cannon"), .description = COMPOUND_STRING( - "Powerful and sure\nto cause " - "\nparalysis, but\ninaccurate."), + "Powerful and sure to cause\n" + "paralysis, but inaccurate."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 120 : 100, .type = TYPE_ELECTRIC, @@ -5131,8 +5132,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Foresight"), .description = COMPOUND_STRING( - "Negates the foe's\nefforts " - "to\nheighten\nevasiveness."), + "Negates the foe's efforts\n" + "to heighten evasiveness."), .effect = EFFECT_FORESIGHT, .power = 0, .type = TYPE_NORMAL, @@ -5156,8 +5157,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Destiny Bond"), .description = COMPOUND_STRING( - "If the user\nfaints, the foe " - "is\nalso made to\nfaint."), + "If the user faints, the foe\n" + "is also made to faint."), .effect = EFFECT_DESTINY_BOND, .power = 0, .type = TYPE_GHOST, @@ -5185,8 +5186,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Perish Song"), .description = COMPOUND_STRING( - "Any Pokémon\nhearing this " - "song\nfaints in 3 turns."), + "Any Pokémon hearing this\n" + "song faints in 3 turns."), .effect = EFFECT_PERISH_SONG, .power = 0, .type = TYPE_NORMAL, @@ -5212,8 +5213,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Icy Wind"), .description = COMPOUND_STRING( - "A chilling attack\nthat " - "lowers the\nfoe's Speed."), + "A chilling attack that\n" + "lowers the foe's Speed."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_ICE, @@ -5266,8 +5267,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bone Rush"), .description = COMPOUND_STRING( - "Strikes the foe\nwith a bone " - "in\nhand 2 to 5 times."), + "Strikes the foe with a bone\n" + "in hand 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 25, .type = TYPE_GROUND, @@ -5287,8 +5288,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lock-On"), .description = COMPOUND_STRING( - "Locks on to the\nfoe to " - "ensure the\nnext move hits."), + "Locks on to the foe to\n" + "ensure the next move hits."), .effect = EFFECT_LOCK_ON, .power = 0, .type = TYPE_NORMAL, @@ -5310,8 +5311,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Outrage"), .description = COMPOUND_STRING( - "A rampage of 2 to\n3 turns " - "that\nconfuses the user."), + "A rampage of 2 to 3 turns\n" + "that confuses the user."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 120 : 90, .type = TYPE_DRAGON, @@ -5338,8 +5339,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sandstorm"), .description = COMPOUND_STRING( - "Causes a sandstorm\nthat " - "rages for\nseveral turns."), + "Causes a sandstorm that\n" + "rages for several turns."), .effect = EFFECT_SANDSTORM, .power = 0, .type = TYPE_ROCK, @@ -5364,8 +5365,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Giga Drain"), .description = COMPOUND_STRING( - "An attack that\nsteals half " - "the\ndamage inflicted."), + "An attack that steals half\n" + "the damage inflicted."), .effect = EFFECT_ABSORB, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 75 : 60, .type = TYPE_GRASS, @@ -5389,8 +5390,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Endure"), .description = COMPOUND_STRING( - "Endures any attack\nfor " - "1 turn,\nleaving at least\n1HP."), + "Endures any attack for\n" + "1 turn, leaving at least 1HP."), .effect = EFFECT_ENDURE, .power = 0, .type = TYPE_NORMAL, @@ -5417,8 +5418,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Charm"), .description = COMPOUND_STRING( - "Charms the foe and\nsharply " - "reduces\nits Attack."), + "Charms the foe and sharply\n" + "reduces its Attack."), .effect = EFFECT_ATTACK_DOWN_2, .power = 0, .type = B_UPDATED_MOVE_TYPES >= GEN_6 ? TYPE_FAIRY : TYPE_NORMAL, @@ -5441,8 +5442,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rollout"), .description = COMPOUND_STRING( - "An attack lasting\n5 turns " - "with\nrising intensity."), + "An attack lasting 5 turns\n" + "with rising intensity."), .effect = EFFECT_ROLLOUT, .power = 30, .type = TYPE_ROCK, @@ -5487,8 +5488,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Swagger"), .description = COMPOUND_STRING( - "Confuses the foe,\nbut also " - "sharply\nraises its Attack."), + "Confuses the foe, but also\n" + "sharply raises its Attack."), .effect = EFFECT_SWAGGER, .power = 0, .type = TYPE_NORMAL, @@ -5511,8 +5512,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Milk Drink"), .description = COMPOUND_STRING( - "Recovers up to\nhalf the " - "user's\nmaximum HP."), + "Recovers up to half the\n" + "user's maximum HP."), .effect = EFFECT_SOFTBOILED, .power = 0, .type = TYPE_NORMAL, @@ -5538,8 +5539,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spark"), .description = COMPOUND_STRING( - "An electrified\ntackle that " - "may\nparalyze the foe."), + "An electrified tackle that\n" + "may paralyze the foe."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_ELECTRIC, @@ -5564,8 +5565,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fury Cutter"), .description = COMPOUND_STRING( - "An attack that\nintensifies " - "on\neach successive\nhit."), + "An attack that intensifies\n" + "on each successive hit."), #if B_UPDATED_MOVE_DATA >= GEN_6 .power = 40, #elif B_UPDATED_MOVE_DATA >= GEN_5 @@ -5594,8 +5595,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Steel Wing"), .description = COMPOUND_STRING( - "Strikes the foe\nwith hard " - "wings\nspread wide."), + "Strikes the foe with hard\n" + "wings spread wide."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_STEEL, @@ -5622,8 +5623,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mean Look"), .description = COMPOUND_STRING( - "Fixes the foe with\na mean " - "look that\nprevents escape."), + "Fixes the foe with a mean\n" + "look that prevents escape."), .effect = EFFECT_MEAN_LOOK, .power = 0, .type = TYPE_NORMAL, @@ -5647,8 +5648,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Attract"), .description = COMPOUND_STRING( - "Makes the opposite\ngender " - "less likely\nto attack."), + "Makes the opposite gender\n" + "less likely to attack."), .effect = EFFECT_ATTRACT, .power = 0, .type = TYPE_NORMAL, @@ -5672,8 +5673,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sleep Talk"), .description = COMPOUND_STRING( - "Uses an available\nmove " - "randomly\nwhile asleep."), + "Uses an available move\n" + "randomly while asleep."), .effect = EFFECT_SLEEP_TALK, .power = 0, .type = TYPE_NORMAL, @@ -5704,8 +5705,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heal Bell"), .description = COMPOUND_STRING( - "Chimes soothingly\nto heal " - "all status\nabnormalities."), + "Chimes soothingly to heal\n" + "all status abnormalities."), .effect = EFFECT_HEAL_BELL, .power = 0, .type = TYPE_NORMAL, @@ -5732,8 +5733,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Return"), .description = COMPOUND_STRING( - "An attack that\nincreases " - "in power\nwith friendship."), + "An attack that increases\n" + "in power with friendship."), .effect = EFFECT_RETURN, .power = 1, .type = TYPE_NORMAL, @@ -5755,8 +5756,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Present"), .description = COMPOUND_STRING( - "A gift in the form\nof a " - "bomb. May\nrestore HP."), + "A gift in the form of a\n" + "bomb. May restore HP."), .effect = EFFECT_PRESENT, .power = 1, .type = TYPE_NORMAL, @@ -5778,8 +5779,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Frustration"), .description = COMPOUND_STRING( - "An attack that is\nstronger " - "if the\nTrainer is\ndisliked."), + "An attack that is stronger\n" + "if the Trainer is disliked."), .effect = EFFECT_FRUSTRATION, .power = 1, .type = TYPE_NORMAL, @@ -5801,8 +5802,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Safeguard"), .description = COMPOUND_STRING( - "Protects allies\nfrom status " - "\nproblems for 5\nturns."), + "Protects allies from status\n" + "problems for 5 turns."), .effect = EFFECT_SAFEGUARD, .power = 0, .type = TYPE_NORMAL, @@ -5827,8 +5828,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pain Split"), .description = COMPOUND_STRING( - "Adds the user and\nfoe's HP, " - "then\nshares them\nequally."), + "Adds the user and foe's HP,\n" + "then shares them equally."), .effect = EFFECT_PAIN_SPLIT, .power = 0, .type = TYPE_NORMAL, @@ -5850,8 +5851,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sacred Fire"), .description = COMPOUND_STRING( - "A mystical fire\nattack that " - "may\ninflict a burn."), + "A mystical fire attack that\n" + "may inflict a burn."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIRE, @@ -5877,8 +5878,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magnitude"), .description = COMPOUND_STRING( - "A ground-shaking\nattack " - "of random\nintensity."), + "A ground-shaking attack\n" + "of random intensity."), .effect = EFFECT_MAGNITUDE, .power = 1, .type = TYPE_GROUND, @@ -5900,8 +5901,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dynamic Punch"), .description = COMPOUND_STRING( - "Powerful and sure\nto cause " - "\nconfusion, but\ninaccurate."), + "Powerful and sure to cause\n" + "confusion, but inaccurate."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIGHTING, @@ -5928,8 +5929,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Megahorn"), .description = COMPOUND_STRING( - "A brutal ramming\nattack " - "using\nout-thrust horns."), + "A brutal ramming attack\n" + "using out-thrust horns."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_BUG, @@ -5951,8 +5952,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Breath"), .description = COMPOUND_STRING( - "Strikes the foe\nwith a blast " - "of\nbreath. May\nparalyze."), + "Strikes the foe with a blast\n" + "of breath. May paralyze."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_DRAGON, @@ -5978,8 +5979,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Baton Pass"), .description = COMPOUND_STRING( - "Switches out the\nuser while " - "keeping\neffects in play."), + "Switches out the user while\n" + "keeping effects in play."), .effect = EFFECT_BATON_PASS, .power = 0, .type = TYPE_NORMAL, @@ -6003,8 +6004,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Encore"), .description = COMPOUND_STRING( - "Makes the foe\nrepeat its " - "last\nmove over 3 turns."), + "Makes the foe repeat its\n" + "last move over 3 turns."), .effect = EFFECT_ENCORE, .power = 0, .type = TYPE_NORMAL, @@ -6029,8 +6030,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pursuit"), .description = COMPOUND_STRING( - "Inflicts bad\ndamage if used " - "on\na foe switching\nout."), + "Inflicts bad damage if used\n" + "on a foe switching out."), .effect = EFFECT_PURSUIT, .power = 40, .type = TYPE_DARK, @@ -6053,11 +6054,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rapid Spin"), .description = COMPOUND_STRING( - "User spins and\nremoves some " + "User spins and removes some\n" #if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8 - "\neffects, while\nupping speed."), - #else - "\neffects."), + "effects, while upping speed."), + #else + "effects."), #endif .effect = EFFECT_RAPID_SPIN, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 50 : 20, @@ -6090,11 +6091,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Sweet Scent"), .description = COMPOUND_STRING( #if B_UPDATED_MOVE_DATA >= GEN_6 - "Allures the foes\nto harshly " - "reduce\nevasiveness."), + "Allures the foes to harshly\n" + "reduce evasiveness."), #else - "Allures the foes\nto reduce " - "\nevasiveness."), + "Allures the foes to reduce\n" + "evasiveness."), #endif .effect = B_UPDATED_MOVE_DATA >= GEN_6 ? EFFECT_EVASION_DOWN_2 : EFFECT_EVASION_DOWN, .power = 0, @@ -6118,8 +6119,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Iron Tail"), .description = COMPOUND_STRING( - "Attacks with a\nrock-hard " - "tail.\nMay lower Defense."), + "Attacks with a rock-hard\n" + "tail. May lower Defense."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_STEEL, @@ -6145,8 +6146,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Metal Claw"), .description = COMPOUND_STRING( - "A claw attack that\nmay " - "raise the\nuser's Attack."), + "A claw attack that may\n" + "raise the user's Attack."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_STEEL, @@ -6173,8 +6174,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Vital Throw"), .description = COMPOUND_STRING( - "Makes the user's\nmove last, " - "but it\nnever misses."), + "Makes the user's move last,\n" + "but it never misses."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_FIGHTING, @@ -6196,8 +6197,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Morning Sun"), .description = COMPOUND_STRING( - "Restores HP. The\namount " - "varies with\nthe weather."), + "Restores HP. The amount\n" + "varies with the weather."), .effect = EFFECT_MORNING_SUN, .power = 0, .type = TYPE_NORMAL, @@ -6223,8 +6224,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Synthesis"), .description = COMPOUND_STRING( - "Restores HP. The\namount " - "varies with\nthe weather."), + "Restores HP. The amount\n" + "varies with the weather."), .effect = EFFECT_SYNTHESIS, .power = 0, .type = TYPE_GRASS, @@ -6250,8 +6251,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Moonlight"), .description = COMPOUND_STRING( - "Restores HP. The\namount " - "varies with\nthe weather."), + "Restores HP. The amount\n" + "varies with the weather."), .effect = EFFECT_MOONLIGHT, .power = 0, .type = B_UPDATED_MOVE_TYPES >= GEN_6 ? TYPE_FAIRY : TYPE_NORMAL, @@ -6278,11 +6279,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Hidden Power"), .description = COMPOUND_STRING( #if B_HIDDEN_POWER_DMG >= GEN_6 - "The type varies " - "\nwith the user."), + "The type varies\n" + "with the user."), #else - "The type and\neffectiveness " - "vary\nwith the user."), + "The type and effectiveness\n" + "vary with the user."), #endif .power = B_HIDDEN_POWER_DMG >= GEN_6 ? 60 : 1, .effect = EFFECT_HIDDEN_POWER, @@ -6304,8 +6305,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Cross Chop"), .description = COMPOUND_STRING( - "A double-chopping\nattack. " - "High\ncritical-hit\nratio."), + "A double-chopping attack.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIGHTING, @@ -6328,8 +6329,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Twister"), .description = COMPOUND_STRING( - "Whips up a vicious\ntwister " - "to tear at\nfoes. May flinch."), + "Whips up a vicious twister\n" + "to tear at foes. May flinch."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_DRAGON, @@ -6355,8 +6356,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rain Dance"), .description = COMPOUND_STRING( - "Boosts the power\nof Water- " - "type\nmoves for 5 turns."), + "Boosts the power of Water-\n" + "type moves for 5 turns."), .effect = EFFECT_RAIN_DANCE, .power = 0, .type = TYPE_WATER, @@ -6380,8 +6381,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sunny Day"), .description = COMPOUND_STRING( - "Boosts the power\nof Fire- " - "type\nmoves for 5 turns."), + "Boosts the power of Fire-\n" + "type moves for 5 turns."), .effect = EFFECT_SUNNY_DAY, .power = 0, .type = TYPE_FIRE, @@ -6405,11 +6406,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Crunch"), .description = COMPOUND_STRING( - "Crunches with\nsharp fangs. " + "Crunches with sharp fangs.\n" #if B_UPDATED_MOVE_DATA >= GEN_4 - "May\nlower Defense."), + "May lower Defense."), #else - "May\nlower Sp. Def."), + "May lower Sp. Def."), #endif .effect = EFFECT_HIT, .power = 80, @@ -6441,8 +6442,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mirror Coat"), .description = COMPOUND_STRING( - "Counters the foe's\nspecial " - "attack at\ndouble the power."), + "Counters the foe's special\n" + "attack at double the power."), .effect = EFFECT_MIRROR_COAT, .power = 1, .type = TYPE_PSYCHIC, @@ -6467,8 +6468,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psych Up"), .description = COMPOUND_STRING( - "Copies foe's stat\nchanges " - "and gives\nto the user."), + "Copies foe's stat changes\n" + "and gives to the user."), .effect = EFFECT_PSYCH_UP, .power = 0, .type = TYPE_NORMAL, @@ -6494,8 +6495,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Extreme Speed"), .description = COMPOUND_STRING( - "An extremely fast\nand " - "powerful\nattack."), + "An extremely fast and\n" + "powerful attack."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_NORMAL, @@ -6517,7 +6518,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ancient Power"), .description = COMPOUND_STRING( - "An attack that may\nraise " + "An attack that may raise\n" "all stats."), .effect = EFFECT_HIT, .power = 60, @@ -6545,8 +6546,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shadow Ball"), .description = COMPOUND_STRING( - "Hurls a black blob\nthat may " - "lower the\nfoe's Sp. Def."), + "Hurls a black blob that may\n" + "lower the foe's Sp. Def."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GHOST, @@ -6572,8 +6573,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Future Sight"), .description = COMPOUND_STRING( - "Heightens inner\npower to " - "strike 2\nturns later."), + "Heightens inner power to\n" + "strike 2 turns later."), #if B_UPDATED_MOVE_DATA >= GEN_6 .power = 120, #elif B_UPDATED_MOVE_DATA >= GEN_5 @@ -6602,8 +6603,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Smash"), .description = COMPOUND_STRING( - "A rock-crushing\nattack " - "that may\nlower Defense."), + "A rock-crushing attack\n" + "that may lower Defense."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 40 : 20, .type = TYPE_FIGHTING, @@ -6629,8 +6630,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Whirlpool"), .description = COMPOUND_STRING( - "Traps and hurts\nthe foe in " - "a\nwhirlpool for\n"BINDING_TURNS" turns."), + "Traps and hurts the foe in\n" + "a whirlpool for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 35 : 15, .type = TYPE_WATER, @@ -6642,6 +6643,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .damagesUnderwater = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_WHIRLPOOL, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -6655,8 +6657,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Beat Up"), .description = COMPOUND_STRING( - "Summons party\nPokémon to " - "join\nin the attack."), + "Summons party Pokémon to\n" + "join in the attack."), .effect = EFFECT_BEAT_UP, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 1 : 10, .type = TYPE_DARK, @@ -6677,8 +6679,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fake Out"), .description = COMPOUND_STRING( - "Moves 1st and\nflinches. Only " - "\nworks on user's\n1st turn."), + "Moves 1st and flinches. Only\n" + "works on user's 1st turn."), .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 3 : 1, .makesContact = B_UPDATED_MOVE_DATA >= GEN_4, .effect = EFFECT_FIRST_TURN_ONLY, @@ -6705,11 +6707,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Uproar"), .description = COMPOUND_STRING( #if B_UPROAR_TURNS >= GEN_5 - "Causes an uproar\nfor 2 to 5 " + "Causes an uproar for 2 to 5\n" #else - "Causes an uproar\nfor 3 " + "Causes an uproar for 3\n" #endif - "turns and prevents\nsleep."), + "turns and prevents sleep."), .effect = EFFECT_UPROAR, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 90 : 50, .type = TYPE_NORMAL, @@ -6738,7 +6740,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stockpile"), .description = COMPOUND_STRING( - "Charges up power\nfor up to " + "Charges up power for up to\n" "3 turns."), .effect = EFFECT_STOCKPILE, .power = 0, @@ -6764,8 +6766,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spit Up"), .description = COMPOUND_STRING( - "Releases\nstockpiled power " - "\n(the more the\nbetter)."), + "Releases stockpiled power\n" + "(the more the better)."), .effect = EFFECT_SPIT_UP, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 1 : 100, .type = TYPE_NORMAL, @@ -6787,8 +6789,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Swallow"), .description = COMPOUND_STRING( - "Absorbs stockpiled\npower " - "and restores\nHP."), + "Absorbs stockpiled power\n" + "and restores HP."), .effect = EFFECT_SWALLOW, .power = 0, .type = TYPE_NORMAL, @@ -6814,8 +6816,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heat Wave"), .description = COMPOUND_STRING( - "Exhales a hot\nbreath on the " - "\nfoes. May inflict\na burn."), + "Exhales a hot breath on the\n" + "foes. May inflict a burn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 95 : 100, .type = TYPE_FIRE, @@ -6842,13 +6844,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Hail"), #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_SNOW .description = COMPOUND_STRING( - "Summons a\nsnowstorm that " - "\nlasts for five\nturns."), + "Summons a snowstorm that\n" + "lasts for five turns."), .effect = EFFECT_SNOWSCAPE, #else .description = COMPOUND_STRING( - "Summons a\nhailstorm that " - "\nstrikes every turn."), + "Summons a hailstorm that\n" + "strikes every turn."), .effect = EFFECT_HAIL, #endif .power = 0, @@ -6873,8 +6875,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Torment"), .description = COMPOUND_STRING( - "Torments the foe\nand stops " - "\nsuccessive use of\na move."), + "Torments the foe and stops\n" + "successive use of a move."), .effect = EFFECT_TORMENT, .power = 0, .type = TYPE_DARK, @@ -6897,8 +6899,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flatter"), .description = COMPOUND_STRING( - "Confuses the foe,\nbut " - "raises its Sp.\nAtk."), + "Confuses the foe, but\n" + "raises its Sp. Atk."), .effect = EFFECT_FLATTER, .power = 0, .type = TYPE_DARK, @@ -6921,8 +6923,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Will-O-Wisp"), .description = COMPOUND_STRING( - "Inflicts a burn on\nthe foe " - "with\nintense fire."), + "Inflicts a burn on the foe\n" + "with intense fire."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_FIRE, @@ -6946,8 +6948,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Memento"), .description = COMPOUND_STRING( - "The user faints\nand harshly " - "lowers\nfoes Atk and\nSp.Atk."), + "The user faints and harshly\n" + "lowers foes Atk and Sp.Atk."), .effect = EFFECT_MEMENTO, .power = 0, .type = TYPE_DARK, @@ -6969,8 +6971,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Facade"), .description = COMPOUND_STRING( - "Boosts power when\nburned, " - "paralyzed,\nor poisoned."), + "Boosts power when burned,\n" + "paralyzed, or poisoned."), .effect = EFFECT_FACADE, .power = 70, .type = TYPE_NORMAL, @@ -6992,8 +6994,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Focus Punch"), .description = COMPOUND_STRING( - "Powerful attack,\nmoves last. " - "The\nuser flinches if\nhit."), + "Powerful attack, moves last.\n" + "The user flinches if hit."), .effect = EFFECT_FOCUS_PUNCH, .power = 150, .type = TYPE_FIGHTING, @@ -7023,8 +7025,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Smelling Salts"), .description = COMPOUND_STRING( - "Powerful against\nparalyzed " - "foes,\nbut also heals\nthem."), + "Powerful against paralyzed\n" + "foes, but also heals them."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 70 : 60, .type = TYPE_NORMAL, @@ -7050,8 +7052,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Follow Me"), .description = COMPOUND_STRING( - "Draws attention to\nmake " - "foes attack\nonly the user."), + "Draws attention to make\n" + "foes attack only the user."), .effect = EFFECT_FOLLOW_ME, .power = 0, .type = TYPE_NORMAL, @@ -7078,8 +7080,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Nature Power"), .description = COMPOUND_STRING( - "The type of attack\nvaries " - "depending\non the location."), + "The type of attack varies\n" + "depending on the location."), .effect = EFFECT_NATURE_POWER, .power = 1, .type = TYPE_NORMAL, @@ -7107,8 +7109,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Charge"), .description = COMPOUND_STRING( - "Charges power to\nboost the " - "Electric\nmove used next."), + "Charges power to boost the\n" + "Electric move used next."), .effect = EFFECT_CHARGE, .power = 0, .type = TYPE_ELECTRIC, @@ -7133,8 +7135,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Taunt"), .description = COMPOUND_STRING( - "Taunts the foe\ninto only " - "using\nattack moves."), + "Taunts the foe into only\n" + "using attack moves."), .effect = EFFECT_TAUNT, .power = 0, .type = TYPE_DARK, @@ -7158,8 +7160,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Helping Hand"), .description = COMPOUND_STRING( - "Boosts the power\nof ally " - "\nrecipient's moves."), + "Boosts the power of ally\n" + "recipient's moves."), .effect = EFFECT_HELPING_HAND, .power = 0, .type = TYPE_NORMAL, @@ -7187,8 +7189,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trick"), .description = COMPOUND_STRING( - "Tricks the foe\ninto trading " - "held\nitems."), + "Tricks the foe into trading\n" + "held items."), .effect = EFFECT_TRICK, .power = 0, .type = TYPE_PSYCHIC, @@ -7213,8 +7215,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Role Play"), .description = COMPOUND_STRING( - "Mimics the target\nand " - "copies its\nAbility."), + "Mimics the target and\n" + "copies its Ability."), .effect = EFFECT_ROLE_PLAY, .power = 0, .type = TYPE_PSYCHIC, @@ -7239,8 +7241,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wish"), .description = COMPOUND_STRING( - "A wish that\nrestores HP. " - "It\ntakes time to\nwork."), + "A wish that restores HP.\n" + "It takes time to work."), .effect = EFFECT_WISH, .power = 0, .type = TYPE_NORMAL, @@ -7266,8 +7268,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Assist"), .description = COMPOUND_STRING( - "Attacks randomly\nwith one " - "of the\npartner's moves."), + "Attacks randomly with one\n" + "of the partner's moves."), .effect = EFFECT_ASSIST, .power = 0, .type = TYPE_NORMAL, @@ -7297,8 +7299,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ingrain"), .description = COMPOUND_STRING( - "Lays roots that\nrestore HP. " - "The\nuser can't switch\nout."), + "Lays roots that restore HP.\n" + "The user can't switch out."), .effect = EFFECT_INGRAIN, .power = 0, .type = TYPE_GRASS, @@ -7324,8 +7326,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Superpower"), .description = COMPOUND_STRING( - "Boosts strength\nsharply, " - "but\nlowers abilities."), + "Boosts strength sharply,\n" + "but lowers abilities."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_FIGHTING, @@ -7351,8 +7353,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magic Coat"), .description = COMPOUND_STRING( - "Reflects special\neffects " - "back to\nthe attacker."), + "Reflects special effects\n" + "back to the attacker."), .effect = EFFECT_MAGIC_COAT, .power = 0, .type = TYPE_PSYCHIC, @@ -7376,8 +7378,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Recycle"), .description = COMPOUND_STRING( - "Recycles a used\nitem for " - "one more\nuse."), + "Recycles a used item for\n" + "one more use."), .effect = EFFECT_RECYCLE, .power = 0, .type = TYPE_NORMAL, @@ -7423,8 +7425,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Brick Break"), .description = COMPOUND_STRING( - "Destroys barriers\nsuch as " - "REFLECT\nand causes damage."), + "Destroys barriers such as\n" + "REFLECT and causes damage."), .effect = EFFECT_BRICK_BREAK, .power = 75, .type = TYPE_FIGHTING, @@ -7446,8 +7448,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Yawn"), .description = COMPOUND_STRING( - "Lulls the foe into\nyawning, " - "then\nsleeping next\nturn."), + "Lulls the foe into yawning,\n" + "then sleeping next turn."), .effect = EFFECT_YAWN, .power = 0, .type = TYPE_NORMAL, @@ -7471,8 +7473,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Knock Off"), .description = COMPOUND_STRING( - "Knocks down the\nfoe's held " - "item to\nprevent its use."), + "Knocks down the foe's held\n" + "item to prevent its use."), .effect = EFFECT_KNOCK_OFF, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 65 : 20, .type = TYPE_DARK, @@ -7494,7 +7496,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Endeavor"), .description = COMPOUND_STRING( - "Cuts foe's HP to\nequal " + "Cuts foe's HP to equal\n" "user's HP."), .effect = EFFECT_ENDEAVOR, .power = 1, @@ -7518,8 +7520,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Eruption"), .description = COMPOUND_STRING( - "The higher the\nuser's HP, " - "the\nmore damage\ncaused."), + "The higher the user's HP,\n" + "the more damage caused."), .effect = EFFECT_POWER_BASED_ON_USER_HP, .power = 150, .type = TYPE_FIRE, @@ -7540,8 +7542,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Skill Swap"), .description = COMPOUND_STRING( - "The user swaps\nspecial " - "abilities\nwith the target."), + "The user swaps special\n" + "abilities with the target."), .effect = EFFECT_SKILL_SWAP, .power = 0, .type = TYPE_PSYCHIC, @@ -7564,8 +7566,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Imprison"), .description = COMPOUND_STRING( - "Prevents foes from\nusing " - "moves known\nby the user."), + "Prevents foes from using\n" + "moves known by the user."), .effect = EFFECT_IMPRISON, .power = 0, .type = TYPE_PSYCHIC, @@ -7592,8 +7594,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Refresh"), .description = COMPOUND_STRING( - "Heals poisoning,\nparalysis, " - "or a\nburn."), + "Heals poisoning, paralysis,\n" + "or a burn."), .effect = EFFECT_REFRESH, .power = 0, .type = TYPE_NORMAL, @@ -7618,8 +7620,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grudge"), .description = COMPOUND_STRING( - "If the user\nfaints, deletes " - "\nall PP of foe's\nlast move."), + "If the user faints, deletes\n" + "all PP of foe's last move."), .effect = EFFECT_GRUDGE, .power = 0, .type = TYPE_GHOST, @@ -7644,8 +7646,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Snatch"), .description = COMPOUND_STRING( - "Steals the effects\nof the " - "move the\ntarget uses next."), + "Steals the effects of the\n" + "move the target uses next."), .effect = EFFECT_SNATCH, .power = 0, .type = TYPE_DARK, @@ -7672,8 +7674,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Secret Power"), .description = COMPOUND_STRING( - "An attack with\neffects " - "that vary\nby location."), + "An attack with effects\n" + "that vary by location."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_NORMAL, @@ -7698,8 +7700,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dive"), .description = COMPOUND_STRING( - "Dives underwater\nthe first " - "turn and\nstrikes next turn."), + "Dives underwater the first\n" + "turn and strikes next turn."), .effect = EFFECT_SEMI_INVULNERABLE, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 80 : 60, .type = TYPE_WATER, @@ -7713,7 +7715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = COMPRESS_BITS(STATUS3_UNDERWATER) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = STATE_UNDERWATER }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_DIVE, @@ -7726,8 +7728,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Arm Thrust"), .description = COMPOUND_STRING( - "Straight-arm\npunches that " - "\nstrike the foe 2\nto 5 times."), + "Straight-arm punches that\n" + "strike the foe 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 15, .type = TYPE_FIGHTING, @@ -7748,8 +7750,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Camouflage"), .description = COMPOUND_STRING( - "Alters the\nPokémon's type " - "\ndepending on the\nlocation."), + "Alters the Pokémon's type\n" + "depending on the location."), .effect = EFFECT_CAMOUFLAGE, .power = 0, .type = TYPE_NORMAL, @@ -7775,9 +7777,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Tail Glow"), .description = COMPOUND_STRING( #if B_UPDATED_MOVE_DATA >= GEN_5 - "Flash light that\ndrastically " + "Flash light that drastically\n" #else - "Flashes a light\nthat sharply " + "Flashes a light that sharply\n" #endif "raises Sp. Atk."), .effect = B_UPDATED_MOVE_DATA >= GEN_5 ? EFFECT_SPECIAL_ATTACK_UP_3 : EFFECT_SPECIAL_ATTACK_UP_2, @@ -7804,8 +7806,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Luster Purge"), .description = COMPOUND_STRING( - "Attacks with a\nburst of " - "light.\nMay lower Sp. Def."), + "Attacks with a burst of\n" + "light. May lower Sp. Def."), .effect = EFFECT_HIT, .power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70, .type = TYPE_PSYCHIC, @@ -7830,8 +7832,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mist Ball"), .description = COMPOUND_STRING( - "Attacks with a\nflurry of " - "down.\nMay lower Sp. Atk."), + "Attacks with a flurry of\n" + "down. May lower Sp. Atk."), .effect = EFFECT_HIT, .power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70, .type = TYPE_PSYCHIC, @@ -7857,8 +7859,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Feather Dance"), .description = COMPOUND_STRING( - "Envelops the foe\nwith down " - "to\nsharply reduce\nAttack."), + "Envelops the foe with down\n" + "to sharply reduce Attack."), .effect = EFFECT_ATTACK_DOWN_2, .power = 0, .type = TYPE_FLYING, @@ -7882,8 +7884,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Teeter Dance"), .description = COMPOUND_STRING( - "Confuses all\nPokémon on " - "the\nscene."), + "Confuses all Pokémon on\n" + "the scene."), .effect = EFFECT_CONFUSE, .power = 0, .type = TYPE_NORMAL, @@ -7907,8 +7909,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Blaze Kick"), .description = COMPOUND_STRING( - "A kick with a high\ncritical- " - "hit\nratio. May cause a\nburn."), + "A kick with a high critical-\n" + "hit ratio. May cause a burn."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_FIRE, @@ -7935,8 +7937,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mud Sport"), .description = COMPOUND_STRING( - "Covers the user in\nmud to " - "weaken all\nElectric moves."), + "Covers the user in mud to\n" + "weaken all Electric moves."), // in theory this should mention 5 turns (gen 6+) .effect = EFFECT_MUD_SPORT, .power = 0, @@ -7962,8 +7964,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Ball"), .description = COMPOUND_STRING( - "A 5-turn attack\nthat gains " - "power\non successive\nhits."), + "A 5-turn attack that gains\n" + "power on successive hits."), .effect = EFFECT_ROLLOUT, .power = 30, .type = TYPE_ICE, @@ -7987,8 +7989,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Needle Arm"), .description = COMPOUND_STRING( - "Attacks with\nthorny arms. " - "May\ncause flinching."), + "Attacks with thorny arms.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_GRASS, @@ -8015,8 +8017,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Slack Off"), .description = COMPOUND_STRING( - "Slacks off and\nrestores " - "half the\nmaximum HP."), + "Slacks off and restores\n" + "half the maximum HP."), .effect = EFFECT_RESTORE_HP, .power = 0, .type = TYPE_NORMAL, @@ -8042,8 +8044,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hyper Voice"), .description = COMPOUND_STRING( - "A loud attack that\nuses " - "sound waves\nto injure."), + "A loud attack that uses\n" + "sound waves to injure."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_NORMAL, @@ -8066,8 +8068,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poison Fang"), .description = COMPOUND_STRING( - "A sharp-fanged\nattack. " - "May badly\npoison the foe."), + "A sharp-fanged attack.\n" + "May badly poison the foe."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_POISON, @@ -8093,8 +8095,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Crush Claw"), .description = COMPOUND_STRING( - "Tears at the foe\nwith sharp " - "claws.\nMay lower Defense."), + "Tears at the foe with sharp\n" + "claws. May lower Defense."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_NORMAL, @@ -8120,8 +8122,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Blast Burn"), .description = COMPOUND_STRING( - "Powerful, but\nleaves the " - "user\nimmobile the next\nturn."), + "Powerful, but leaves the\n" + "user immobile the next turn."), .effect = EFFECT_HIT, .power = 150, .type = TYPE_FIRE, @@ -8146,8 +8148,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hydro Cannon"), .description = COMPOUND_STRING( - "Powerful, but\nleaves the " - "user\nimmobile the next\nturn."), + "Powerful, but leaves the\n" + "user immobile the next turn."), .effect = EFFECT_HIT, .power = 150, .type = TYPE_WATER, @@ -8172,7 +8174,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Meteor Mash"), .description = COMPOUND_STRING( - "Fires a\nmeteor-like punch.\n" + "Fires a meteor-like punch.\n" "May raise Attack."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 100, @@ -8201,8 +8203,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Astonish"), .description = COMPOUND_STRING( - "An attack that may\nshock " - "the foe into\nflinching."), + "An attack that may shock\n" + "the foe into flinching."), .effect = EFFECT_HIT, .power = 30, .type = TYPE_GHOST, @@ -8229,8 +8231,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Weather Ball"), .description = COMPOUND_STRING( - "The move's type\nand power " - "change\nwith the weather."), + "The move's type and power\n" + "change with the weather."), .effect = EFFECT_WEATHER_BALL, .power = 50, .type = TYPE_NORMAL, @@ -8253,8 +8255,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aromatherapy"), .description = COMPOUND_STRING( - "Heals all status\nproblems " - "with a\nsoothing scent."), + "Heals all status problems\n" + "with a soothing scent."), .effect = EFFECT_HEAL_BELL, .power = 0, .type = TYPE_GRASS, @@ -8279,8 +8281,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fake Tears"), .description = COMPOUND_STRING( - "Feigns crying to\nsharply " - "lower the\nfoe's Sp. Def."), + "Feigns crying to sharply\n" + "lower the foe's Sp. Def."), .effect = EFFECT_SPECIAL_DEFENSE_DOWN_2, .power = 0, .type = TYPE_DARK, @@ -8303,8 +8305,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Air Cutter"), .description = COMPOUND_STRING( - "Hacks with\nrazorlike wind. " - "\nHigh critical-hit\nratio."), + "Hacks with razorlike wind.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 55, .type = TYPE_FLYING, @@ -8328,8 +8330,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Overheat"), .description = COMPOUND_STRING( - "Allows a\nfull-power attack,\n" - "but sharply lowers\nSp. Atk."), + "Allows a full-power attack,\n" + "but sharply lowers Sp. Atk."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 130 : 140, .type = TYPE_FIRE, @@ -8355,8 +8357,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Odor Sleuth"), .description = COMPOUND_STRING( - "Negate evasiveness\nand " - "Ghost type's\nimmunities."), + "Negate evasiveness and\n" + "Ghost type's immunities."), .effect = EFFECT_FORESIGHT, .power = 0, .type = TYPE_NORMAL, @@ -8380,8 +8382,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Tomb"), .description = COMPOUND_STRING( - "Stops the foe from\nmoving " - "with rocks\nand cuts Speed."), + "Stops the foe from moving\n" + "with rocks and cuts Speed."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 50, .type = TYPE_ROCK, @@ -8406,8 +8408,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Silver Wind"), .description = COMPOUND_STRING( - "A powdery attack\nthat may " - "raise\nabilities."), + "A powdery attack that may\n" + "raise abilities."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_BUG, @@ -8434,8 +8436,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Metal Sound"), .description = COMPOUND_STRING( - "Emits a horrible\nscreech " - "that\nsharply lowers Sp.\nDef."), + "Emits a horrible screech\n" + "that sharply lowers Sp. Def."), .effect = EFFECT_SPECIAL_DEFENSE_DOWN_2, .power = 0, .type = TYPE_STEEL, @@ -8460,8 +8462,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grass Whistle"), .description = COMPOUND_STRING( - "Lulls the foe into\nsleep " - "with a\npleasant melody."), + "Lulls the foe into sleep\n" + "with a pleasant melody."), .effect = EFFECT_NON_VOLATILE_STATUS, .power = 0, .type = TYPE_GRASS, @@ -8487,8 +8489,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tickle"), .description = COMPOUND_STRING( - "Makes the foe\nlaugh to " - "lower\nAttack and\nDefense."), + "Makes the foe laugh to\n" + "lower Attack and Defense."), .effect = EFFECT_TICKLE, .power = 0, .type = TYPE_NORMAL, @@ -8511,8 +8513,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Cosmic Power"), .description = COMPOUND_STRING( - "Raises Defense and\nSp. Def " - "with a\nmystic power."), + "Raises Defense and Sp. Def\n" + "with a mystic power."), .effect = EFFECT_COSMIC_POWER, .power = 0, .type = TYPE_PSYCHIC, @@ -8537,8 +8539,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Spout"), .description = COMPOUND_STRING( - "Inflicts more\ndamage if the " - "\nuser's HP is high."), + "Inflicts more damage if the\n" + "user's HP is high."), .effect = EFFECT_POWER_BASED_ON_USER_HP, .power = 150, .type = TYPE_WATER, @@ -8559,8 +8561,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Signal Beam"), .description = COMPOUND_STRING( - "A strange beam\nattack that " - "may\nconfuse the foe."), + "A strange beam attack that\n" + "may confuse the foe."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_BUG, @@ -8585,8 +8587,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shadow Punch"), .description = COMPOUND_STRING( - "An unavoidable\npunch that " - "is\nthrown from\nshadows."), + "An unavoidable punch that\n" + "is thrown from shadows."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_GHOST, @@ -8609,8 +8611,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Extrasensory"), .description = COMPOUND_STRING( - "Attacks with a\npeculiar " - "power.\nMay cause\nflinching."), + "Attacks with a peculiar\n" + "power. May cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_PSYCHIC, @@ -8636,8 +8638,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sky Uppercut"), .description = COMPOUND_STRING( - "An uppercut thrown\nas if " - "leaping into\nthe sky."), + "An uppercut thrown as if\n" + "leaping into the sky."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_FIGHTING, @@ -8661,8 +8663,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sand Tomb"), .description = COMPOUND_STRING( - "Traps and hurts\nthe foe in " - "\nquicksand for\n"BINDING_TURNS" turns."), + "Traps and hurts the foe in\n" + "quicksand for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 35 : 15, .type = TYPE_GROUND, @@ -8673,6 +8675,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_SAND_TOMB, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, @@ -8686,8 +8689,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sheer Cold"), .description = COMPOUND_STRING( - "A chilling attack\nthat " - "causes\nfainting if it\nhits."), + "A chilling attack that\n" + "causes fainting if it hits."), .effect = EFFECT_SHEER_COLD, .power = 1, .type = TYPE_ICE, @@ -8708,8 +8711,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Muddy Water"), .description = COMPOUND_STRING( - "Attacks with muddy\nwater. " - "May lower\naccuracy."), + "Attacks with muddy water.\n" + "May lower accuracy."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 95, .type = TYPE_WATER, @@ -8735,8 +8738,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bullet Seed"), .description = COMPOUND_STRING( - "Shoots 2 to 5\nseeds in a row " - "to\nstrike the foe."), + "Shoots 2 to 5 seeds in a row\n" + "to strike the foe."), .effect = EFFECT_MULTI_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 25 : 10, .type = TYPE_GRASS, @@ -8757,8 +8760,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aerial Ace"), .description = COMPOUND_STRING( - "An extremely\nspeedy and " - "\nunavoidable attack."), + "An extremely speedy and\n" + "unavoidable attack."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_FLYING, @@ -8781,8 +8784,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Icicle Spear"), .description = COMPOUND_STRING( - "Attacks the foe by\nfiring " - "2 to 5\nicicles in a row."), + "Attacks the foe by firing\n" + "2 to 5 icicles in a row."), .effect = EFFECT_MULTI_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 25 : 10, .type = TYPE_ICE, @@ -8802,8 +8805,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Iron Defense"), .description = COMPOUND_STRING( - "Hardens the body's\nsurface " - "to sharply\nraise Defense."), + "Hardens the body's surface\n" + "to sharply raise Defense."), .effect = EFFECT_DEFENSE_UP_2, .power = 0, .type = TYPE_STEEL, @@ -8828,8 +8831,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Block"), .description = COMPOUND_STRING( - "Blocks the foe's\nway and " - "prevents\nescape."), + "Blocks the foe's way and\n" + "prevents escape."), .effect = EFFECT_MEAN_LOOK, .power = 0, .type = TYPE_NORMAL, @@ -8853,8 +8856,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Howl"), .description = COMPOUND_STRING( - "Howls to raise the\nspirit " - "and boosts\nAttack."), + "Howls to raise the spirit\n" + "and boosts Attack."), .power = 0, .effect = B_UPDATED_MOVE_DATA >= GEN_8 ? EFFECT_ATTACK_UP_USER_ALLY : EFFECT_ATTACK_UP, .type = TYPE_NORMAL, @@ -8880,7 +8883,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Claw"), .description = COMPOUND_STRING( - "Slashes the foe\nwith sharp " + "Slashes the foe with sharp\n" "claws."), .effect = EFFECT_HIT, .power = 80, @@ -8903,8 +8906,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Frenzy Plant"), .description = COMPOUND_STRING( - "Powerful, but\nleaves the " - "user\nimmobile the next\nturn."), + "Powerful, but leaves the\n" + "user immobile the next turn."), .effect = EFFECT_HIT, .power = 150, .type = TYPE_GRASS, @@ -8930,8 +8933,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bulk Up"), .description = COMPOUND_STRING( - "Bulks up the body\nto boost " - "both\nAttack and\nDefense."), + "Bulks up the body to boost\n" + "both Attack and Defense."), .effect = EFFECT_BULK_UP, .power = 0, .type = TYPE_FIGHTING, @@ -8956,8 +8959,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bounce"), .description = COMPOUND_STRING( - "Bounces up, then\ndown the " - "next\nturn. May\nparalyze."), + "Bounces up, then down the\n" + "next turn. May paralyze."), .effect = EFFECT_SEMI_INVULNERABLE, .power = 85, .type = TYPE_FLYING, @@ -8971,7 +8974,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = STATE_ON_AIR }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, @@ -8988,8 +8991,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mud Shot"), .description = COMPOUND_STRING( - "Hurls mud at the\nfoe and " - "reduces\nSpeed."), + "Hurls mud at the foe and\n" + "reduces Speed."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_GROUND, @@ -9013,8 +9016,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poison Tail"), .description = COMPOUND_STRING( - "Has a high\ncritical-hit " - "\nratio. May also\npoison."), + "Has a high critical-hit\n" + "ratio. May also poison."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_POISON, @@ -9041,9 +9044,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Covet"), .description = COMPOUND_STRING( - "Cutely begs to\nobtain an " - "item\nheld by the foe."), - .effect = EFFECT_HIT, + "Cutely begs to obtain an\n" + "item held by the foe."), + .effect = EFFECT_STEAL_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 60 : 40, .type = TYPE_NORMAL, .accuracy = 100, @@ -9056,9 +9059,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEAL_ITEM, - }), .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, @@ -9072,12 +9072,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Volt Tackle"), #if B_UPDATED_MOVE_DATA >= GEN_4 .description = COMPOUND_STRING( - "A\nlife-risking\ntackle that " - "hurts\nthe user. May\nparalyze."), + "A life-risking tackle that\n" + "hurts the user. May paralyze."), #else .description = COMPOUND_STRING( - "A life-risking\ntackle that " - "\nslightly hurts the\nuser."), + "A life-risking tackle that\n" + "slightly hurts the user."), #endif .effect = EFFECT_HIT, .power = 120, @@ -9107,8 +9107,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magical Leaf"), .description = COMPOUND_STRING( - "Attacks with a\nstrange leaf " - "that\ncannot be evaded."), + "Attacks with a strange leaf\n" + "that cannot be evaded."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_GRASS, @@ -9129,8 +9129,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Sport"), .description = COMPOUND_STRING( - "The user becomes\nsoaked to " - "weaken\nall Fire moves."), + "The user becomes soaked to\n" + "weaken all Fire moves."), // in theory this should mention 5 turns (gen6+) .effect = EFFECT_WATER_SPORT, .power = 0, @@ -9156,8 +9156,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Calm Mind"), .description = COMPOUND_STRING( - "Raises Sp. Atk and\nSp. Def " - "by\nfocusing the mind."), + "Raises Sp. Atk and Sp. Def\n" + "by focusing the mind."), .effect = EFFECT_CALM_MIND, .power = 0, .type = TYPE_PSYCHIC, @@ -9182,8 +9182,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leaf Blade"), .description = COMPOUND_STRING( - "Slashes with a\nsharp leaf. " - "High\ncritical-hit\nratio."), + "Slashes with a sharp leaf.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_4 ? 90 : 70, .type = TYPE_GRASS, @@ -9207,8 +9207,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Dance"), .description = COMPOUND_STRING( - "A mystical dance\nthat ups " - "Attack\nand Speed."), + "A mystical dance that ups\n" + "Attack and Speed."), .effect = EFFECT_DRAGON_DANCE, .power = 0, .type = TYPE_DRAGON, @@ -9234,8 +9234,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Blast"), .description = COMPOUND_STRING( - "Hurls boulders at\nthe foe " - "2 to 5\ntimes in a row."), + "Hurls boulders at the foe\n" + "2 to 5 times in a row."), .effect = EFFECT_MULTI_HIT, .power = 25, .type = TYPE_ROCK, @@ -9256,8 +9256,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shock Wave"), .description = COMPOUND_STRING( - "A fast and\nunavoidable " - "\nelectric attack."), + "A fast and unavoidable\n" + "electric attack."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_ELECTRIC, @@ -9278,8 +9278,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Pulse"), .description = COMPOUND_STRING( - "Attacks with\nultrasonic " - "waves.\nMay confuse the\nfoe."), + "Attacks with ultrasonic\n" + "waves. May confuse the foe."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_WATER, @@ -9305,8 +9305,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Doom Desire"), .description = COMPOUND_STRING( - "Summons strong\nlight to " - "attack 2\nturns later."), + "Summons strong light to\n" + "attack 2 turns later."), .effect = EFFECT_FUTURE_SIGHT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 140 : 120, .type = TYPE_STEEL, @@ -9329,8 +9329,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psycho Boost"), .description = COMPOUND_STRING( - "Allows a\nfull-power attack,\n" - "but sharply lowers\nSp. Atk."), + "Allows a full-power attack,\n" + "but sharply lowers Sp. Atk."), .effect = EFFECT_HIT, .power = 140, .type = TYPE_PSYCHIC, @@ -9355,8 +9355,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Roost"), .description = COMPOUND_STRING( - "Restores the\nuser's HP by " - "half\nof its max HP."), + "Restores the user's HP by\n" + "half of its max HP."), .effect = EFFECT_ROOST, .power = 0, .type = TYPE_FLYING, @@ -9381,8 +9381,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gravity"), .description = COMPOUND_STRING( - "Gravity is\nintensified " - "\nnegating\nlevitation."), + "Gravity is intensified\n" + "negating levitation."), .effect = EFFECT_GRAVITY, .power = 0, .type = TYPE_PSYCHIC, @@ -9406,8 +9406,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Miracle Eye"), .description = COMPOUND_STRING( - "Negate evasiveness\nand " - "Dark type's\nimmunities."), + "Negate evasiveness and\n" + "Dark type's immunities."), .effect = EFFECT_MIRACLE_EYE, .power = 0, .type = TYPE_PSYCHIC, @@ -9430,8 +9430,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wake-Up Slap"), .description = COMPOUND_STRING( - "Powerful against\nsleeping " - "foes, but\nalso wakes them."), + "Powerful against sleeping\n" + "foes, but also wakes them."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 70 : 60, .type = TYPE_FIGHTING, @@ -9456,8 +9456,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hammer Arm"), .description = COMPOUND_STRING( - "A swinging fist\nattack " - "that also\nlowers Speed."), + "A swinging fist attack\n" + "that also lowers Speed."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIGHTING, @@ -9483,8 +9483,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gyro Ball"), .description = COMPOUND_STRING( - "A high-speed spin\nthat does " - "more\ndamage to faster\nfoes."), + "A high-speed spin that does\n" + "more damage to faster foes."), .effect = EFFECT_GYRO_BALL, .power = 1, .type = TYPE_STEEL, @@ -9529,8 +9529,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Brine"), .description = COMPOUND_STRING( - "Does double damage\nto foes " - "with half\nHP or less."), + "Does double damage to foes\n" + "with half HP or less."), .effect = EFFECT_BRINE, .power = 65, .type = TYPE_WATER, @@ -9550,8 +9550,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Natural Gift"), .description = COMPOUND_STRING( - "The effectiveness\nvaries " - "with the\nheld Berry."), + "The effectiveness varies\n" + "with the held Berry."), .effect = EFFECT_NATURAL_GIFT, .power = 1, .type = TYPE_NORMAL, @@ -9621,11 +9621,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tailwind"), .description = COMPOUND_STRING( - "Whips up a breeze,\ndoubling " + "Whips up a breeze, doubling\n" #if B_TAILWIND_TURNS >= GEN_5 - "ally\nSpeed for 4 turns."), + "ally Speed for 4 turns."), #else - "ally\nSpeed for 3 turns."), + "ally Speed for 3 turns."), #endif .effect = EFFECT_TAILWIND, .power = 0, @@ -9651,8 +9651,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acupressure"), .description = COMPOUND_STRING( - "The user sharply\nraises " - "one of its\nstats."), + "The user sharply raises\n" + "one of its stats."), .effect = EFFECT_ACUPRESSURE, .power = 0, .type = TYPE_NORMAL, @@ -9676,8 +9676,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Metal Burst"), .description = COMPOUND_STRING( - "Retaliates any hit\nwith " - "greater\npower."), + "Retaliates any hit with\n" + "greater power."), .effect = EFFECT_METAL_BURST, .power = 1, .type = TYPE_STEEL, @@ -9742,8 +9742,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Payback"), .description = COMPOUND_STRING( - "An attack that\ngains power " - "if the\nuser moves last."), + "An attack that gains power\n" + "if the user moves last."), .effect = EFFECT_PAYBACK, .power = 50, .type = TYPE_DARK, @@ -9764,8 +9764,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Assurance"), .description = COMPOUND_STRING( - "An attack that\ngains power " - "if the\nfoe has been hurt."), + "An attack that gains power\n" + "if the foe has been hurt."), .effect = EFFECT_ASSURANCE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 50, .type = TYPE_DARK, @@ -9786,8 +9786,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Embargo"), .description = COMPOUND_STRING( - "Prevents the foe\nfrom " - "using any\nitems."), + "Prevents the foe from\n" + "using any items."), .effect = EFFECT_EMBARGO, .power = 0, .type = TYPE_DARK, @@ -9809,8 +9809,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fling"), .description = COMPOUND_STRING( - "The effectiveness\nvaries " - "with the\nheld item."), + "The effectiveness varies\n" + "with the held item."), .effect = EFFECT_FLING, .power = 1, .type = TYPE_DARK, @@ -9831,8 +9831,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psycho Shift"), .description = COMPOUND_STRING( - "Transfers status\nproblems " - "to the\nfoe."), + "Transfers status problems\n" + "to the foe."), .effect = EFFECT_PSYCHO_SHIFT, .power = 0, .type = TYPE_PSYCHIC, @@ -9853,8 +9853,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trump Card"), .description = COMPOUND_STRING( - "The less PP the\nmove has " - "the more\ndamage it does."), + "The less PP the move has\n" + "the more damage it does."), .effect = EFFECT_TRUMP_CARD, .power = 1, .type = TYPE_NORMAL, @@ -9875,8 +9875,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heal Block"), .description = COMPOUND_STRING( - "Prevents the foes\nfrom " - "recovering HP\nfor 5 turns."), + "Prevents the foes from\n" + "recovering HP for 5 turns."), .effect = EFFECT_HEAL_BLOCK, .power = 0, .type = TYPE_PSYCHIC, @@ -9918,8 +9918,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Trick"), .description = COMPOUND_STRING( - "The user swaps its\nAttack " - "and Defense\nstats."), + "The user swaps its Attack\n" + "and Defense stats."), .effect = EFFECT_POWER_TRICK, .power = 0, .type = TYPE_PSYCHIC, @@ -9943,8 +9943,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gastro Acid"), .description = COMPOUND_STRING( - "Stomach acid\nsuppresses " - "the\nfoe's Ability."), + "Stomach acid suppresses\n" + "the foe's Ability."), .effect = EFFECT_GASTRO_ACID, .power = 0, .type = TYPE_POISON, @@ -9966,8 +9966,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lucky Chant"), .description = COMPOUND_STRING( - "Prevents the foe\nfrom " - "landing\ncritical hits."), + "Prevents the foe from\n" + "landing critical hits."), .effect = EFFECT_LUCKY_CHANT, .power = 0, .type = TYPE_NORMAL, @@ -9991,8 +9991,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Me First"), .description = COMPOUND_STRING( - "Executes the foe's\nattack " - "with\ngreater power."), + "Executes the foe's attack\n" + "with greater power."), .effect = EFFECT_ME_FIRST, .power = 0, .type = TYPE_NORMAL, @@ -10023,8 +10023,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Copycat"), .description = COMPOUND_STRING( - "The user mimics\nthe last " - "move used\nby a foe."), + "The user mimics the last\n" + "move used by a foe."), .effect = EFFECT_COPYCAT, .power = 0, .type = TYPE_NORMAL, @@ -10054,8 +10054,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Swap"), .description = COMPOUND_STRING( - "Swaps changes to\nAttack " - "and Sp. Atk\nwith the foe."), + "Swaps changes to Attack\n" + "and Sp. Atk with the foe."), .effect = EFFECT_POWER_SWAP, .power = 0, .type = TYPE_PSYCHIC, @@ -10077,8 +10077,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Guard Swap"), .description = COMPOUND_STRING( - "Swaps changes to\nDefense " - "and Sp.\nDef with the foe."), + "Swaps changes to Defense\n" + "and Sp. Def with the foe."), .effect = EFFECT_GUARD_SWAP, .power = 0, .type = TYPE_PSYCHIC, @@ -10100,8 +10100,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Punishment"), .description = COMPOUND_STRING( - "Does more damage\nthe more " - "the foe\nhas powered up."), + "Does more damage the more\n" + "the foe has powered up."), .effect = EFFECT_PUNISHMENT, .power = 60, .type = TYPE_DARK, @@ -10122,8 +10122,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Last Resort"), .description = COMPOUND_STRING( - "Can only be used\nif every " - "other\nmove has been\nused."), + "Can only be used if every\n" + "other move has been used."), .effect = EFFECT_LAST_RESORT, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 140 : 130, .type = TYPE_NORMAL, @@ -10144,8 +10144,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Worry Seed"), .description = COMPOUND_STRING( - "Plants a seed on\nthe foe " - "giving it\nInsomnia."), + "Plants a seed on the foe\n" + "giving it Insomnia."), .effect = EFFECT_WORRY_SEED, .power = 0, .type = TYPE_GRASS, @@ -10187,8 +10187,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Toxic Spikes"), .description = COMPOUND_STRING( - "Sets spikes that\npoison a " - "foe\nswitching in."), + "Sets spikes that poison a\n" + "foe switching in."), .effect = EFFECT_TOXIC_SPIKES, .power = 0, .type = TYPE_POISON, @@ -10214,8 +10214,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heart Swap"), .description = COMPOUND_STRING( - "Swaps any stat\nchanges " - "with the\nfoe."), + "Swaps any stat changes\n" + "with the foe."), .effect = EFFECT_HEART_SWAP, .power = 0, .type = TYPE_PSYCHIC, @@ -10237,8 +10237,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aqua Ring"), .description = COMPOUND_STRING( - "Forms a veil of\nwater " - "that\nrestores HP."), + "Forms a veil of water\n" + "that restores HP."), .effect = EFFECT_AQUA_RING, .power = 0, .type = TYPE_WATER, @@ -10262,8 +10262,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magnet Rise"), .description = COMPOUND_STRING( - "The user levitates\nwith " - "\nelectromagnetism."), + "The user levitates with\n" + "electromagnetism."), .effect = EFFECT_MAGNET_RISE, .power = 0, .type = TYPE_ELECTRIC, @@ -10288,8 +10288,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flare Blitz"), .description = COMPOUND_STRING( - "A charge that may\nburn the " - "foe. Also\nhurts the user."), + "A charge that may burn the\n" + "foe. Also hurts the user."), .effect = EFFECT_RECOIL, .power = 120, .type = TYPE_FIRE, @@ -10316,8 +10316,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Force Palm"), .description = COMPOUND_STRING( - "A shock wave\nattack that " - "may\nparalyze the foe."), + "A shock wave attack that\n" + "may paralyze the foe."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_FIGHTING, @@ -10342,8 +10342,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aura Sphere"), .description = COMPOUND_STRING( - "Attacks with an\naura blast " - "that\ncannot be evaded."), + "Attacks with an aura blast\n" + "that cannot be evaded."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 80 : 90, .type = TYPE_FIGHTING, @@ -10365,8 +10365,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Polish"), .description = COMPOUND_STRING( - "Polishes the body\nto " - "sharply raise\nSpeed."), + "Polishes the body to\n" + "sharply raise Speed."), .effect = EFFECT_SPEED_UP_2, .power = 0, .type = TYPE_ROCK, @@ -10390,8 +10390,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poison Jab"), .description = COMPOUND_STRING( - "A stabbing attack\nthat " - "may poison\nthe foe."), + "A stabbing attack that\n" + "may poison the foe."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_POISON, @@ -10416,8 +10416,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dark Pulse"), .description = COMPOUND_STRING( - "Attacks with a\nhorrible " - "aura. May\ncause flinching."), + "Attacks with a horrible\n" + "aura. May cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_DARK, @@ -10442,8 +10442,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Night Slash"), .description = COMPOUND_STRING( - "Hits as soon as\npossible. " - "High\ncritical-hit\nratio."), + "Hits as soon as possible.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_DARK, @@ -10466,8 +10466,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aqua Tail"), .description = COMPOUND_STRING( - "The user swings\nits tail " - "like a\nwave to attack."), + "The user swings its tail\n" + "like a wave to attack."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_WATER, @@ -10488,8 +10488,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Seed Bomb"), .description = COMPOUND_STRING( - "A barrage of hard\nseeds " - "is fired at\nthe foe."), + "A barrage of hard seeds\n" + "is fired at the foe."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GRASS, @@ -10510,8 +10510,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Air Slash"), .description = COMPOUND_STRING( - "Attacks with a\nblade of " - "air. May\ncause flinching."), + "Attacks with a blade of\n" + "air. May cause flinching."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_FLYING, @@ -10536,8 +10536,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("X-Scissor"), .description = COMPOUND_STRING( - "Slashes the foe\nwith crossed " - "\nscythes, claws,\netc."), + "Slashes the foe with crossed\n" + "scythes, claws, etc."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_BUG, @@ -10559,8 +10559,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bug Buzz"), .description = COMPOUND_STRING( - "A damaging sound\nwave that " - "may\nlower Sp. Def."), + "A damaging sound wave that\n" + "may lower Sp. Def."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_BUG, @@ -10586,8 +10586,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Pulse"), .description = COMPOUND_STRING( - "Generates a shock\nwave to " - "damage the\nfoe."), + "Generates a shock wave to\n" + "damage the foe."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 85 : 90, .type = TYPE_DRAGON, @@ -10608,8 +10608,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Rush"), .description = COMPOUND_STRING( - "Tackles the foe\nwith menace. " - "May\ncause flinching."), + "Tackles the foe with menace.\n" + "May cause flinching."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_DRAGON, @@ -10635,8 +10635,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Gem"), .description = COMPOUND_STRING( - "Attacks with rays\nof light " - "that\nsparkle like\ndiamonds."), + "Attacks with rays of light\n" + "that sparkle like diamonds."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 80 : 70, .type = TYPE_ROCK, @@ -10679,8 +10679,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Vacuum Wave"), .description = COMPOUND_STRING( - "Whirls its fists\nto send " - "a wave\nthat strikes\nfirst."), + "Whirls its fists to send\n" + "a wave that strikes first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FIGHTING, @@ -10700,8 +10700,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Focus Blast"), .description = COMPOUND_STRING( - "Attacks at full\npower. " - "May lower\nSp. Def."), + "Attacks at full power.\n" + "May lower Sp. Def."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_FIGHTING, @@ -10726,8 +10726,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Energy Ball"), .description = COMPOUND_STRING( - "Draws power from\nnature to " - "attack.\nMay lower Sp. Def."), + "Draws power from nature to\n" + "attack. May lower Sp. Def."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 90 : 80, .type = TYPE_GRASS, @@ -10752,8 +10752,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Brave Bird"), .description = COMPOUND_STRING( - "A low altitude\ncharge that " - "also\nhurts the user."), + "A low altitude charge that\n" + "also hurts the user."), .effect = EFFECT_RECOIL, .power = 120, .type = TYPE_FLYING, @@ -10775,8 +10775,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Earth Power"), .description = COMPOUND_STRING( - "Makes the ground\nerupt with " - "power.\nMay lower Sp. Def."), + "Makes the ground erupt with\n" + "power. May lower Sp. Def."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_GROUND, @@ -10801,8 +10801,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Switcheroo"), .description = COMPOUND_STRING( - "Swaps items with\nthe foe " - "faster\nthan the eye can\nsee."), + "Swaps items with the foe\n" + "faster than the eye can see."), .effect = EFFECT_TRICK, .power = 0, .type = TYPE_DARK, @@ -10850,8 +10850,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Nasty Plot"), .description = COMPOUND_STRING( - "Thinks bad\nthoughts to " - "\nsharply boost Sp.\nAtk."), + "Thinks bad thoughts to\n" + "sharply boost Sp. Atk."), .effect = EFFECT_SPECIAL_ATTACK_UP_2, .power = 0, .type = TYPE_DARK, @@ -10875,8 +10875,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bullet Punch"), .description = COMPOUND_STRING( - "Punches as fast as\na bul- " - "let. It\nalways hits first."), + "Punches as fast as a bul-\n" + "let. It always hits first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_STEEL, @@ -10918,8 +10918,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Shard"), .description = COMPOUND_STRING( - "Hurls a chunk of\nice that " - "always\nstrikes first."), + "Hurls a chunk of ice that\n" + "always strikes first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_ICE, @@ -10939,8 +10939,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shadow Claw"), .description = COMPOUND_STRING( - "Strikes with a\nshadow claw. " - "High\ncritical-hit\nratio."), + "Strikes with a shadow claw.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_GHOST, @@ -10962,8 +10962,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder Fang"), .description = COMPOUND_STRING( - "May cause\nflinching or " - "leave\nthe foe paralyzed."), + "May cause flinching or\n" + "leave the foe paralyzed."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_ELECTRIC, @@ -10993,11 +10993,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Fang"), .description = COMPOUND_STRING( - "May cause\nflinching or " + "May cause flinching or\n" #if B_USE_FROSTBITE == TRUE - "leave\nthe foe with\nfrostbite."), + "leave the foe with frostbite."), #else - "leave\nthe foe frozen."), + "leave the foe frozen."), #endif .effect = EFFECT_HIT, .power = 65, @@ -11028,8 +11028,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Fang"), .description = COMPOUND_STRING( - "May cause\nflinching or " - "leave\nthe foe with a\nburn."), + "May cause flinching or\n" + "leave the foe with a burn."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_FIRE, @@ -11059,8 +11059,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shadow Sneak"), .description = COMPOUND_STRING( - "Extends the user's\nshadow " - "to strike\nfirst."), + "Extends the user's shadow\n" + "to strike first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_GHOST, @@ -11081,8 +11081,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mud Bomb"), .description = COMPOUND_STRING( - "Throws a blob of\nmud to " - "damage and\ncut accuracy."), + "Throws a blob of mud to\n" + "damage and cut accuracy."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_GROUND, @@ -11107,8 +11107,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psycho Cut"), .description = COMPOUND_STRING( - "Tears with psychic\nblades. " - "High\ncritical-hit\nratio."), + "Tears with psychic blades.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_PSYCHIC, @@ -11130,8 +11130,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Zen Headbutt"), .description = COMPOUND_STRING( - "Hits with a strong\nhead- " - "butt. May\ncause flinching."), + "Hits with a strong head-\n" + "butt. May cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_PSYCHIC, @@ -11156,8 +11156,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mirror Shot"), .description = COMPOUND_STRING( - "Emits a flash of\nenergy to " - "damage\nand cut accuracy."), + "Emits a flash of energy to\n" + "damage and cut accuracy."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_STEEL, @@ -11181,8 +11181,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flash Cannon"), .description = COMPOUND_STRING( - "Releases a blast\nof light " - "that may\nlower Sp. Def."), + "Releases a blast of light\n" + "that may lower Sp. Def."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_STEEL, @@ -11206,8 +11206,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rock Climb"), .description = COMPOUND_STRING( - "A charging attack\nthat may " - "confuse\nthe foe."), + "A charging attack that may\n" + "confuse the foe."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_NORMAL, @@ -11232,8 +11232,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Defog"), .description = COMPOUND_STRING( - "Removes obstacles\nand " - "lowers\nevasion."), + "Removes obstacles and\n" + "lowers evasion."), .effect = EFFECT_DEFOG, .power = 0, .type = TYPE_FLYING, @@ -11256,8 +11256,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trick Room"), .description = COMPOUND_STRING( - "Slower Pokémon\nget to move " - "first\nfor 5 turns."), + "Slower Pokémon get to move\n" + "first for 5 turns."), .effect = EFFECT_TRICK_ROOM, .power = 0, .type = TYPE_PSYCHIC, @@ -11279,8 +11279,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Draco Meteor"), .description = COMPOUND_STRING( - "Casts comets onto\nthe foe. " - "Harshly\nlowers the Sp.\nAtk."), + "Casts comets onto the foe.\n" + "Harshly lowers the Sp. Atk."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 130 : 140, .type = TYPE_DRAGON, @@ -11304,8 +11304,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Discharge"), .description = COMPOUND_STRING( - "Zaps all other\n{PKMN} with " - "\nelectricity. May\nparalyze."), + "Zaps all other {PKMN} with\n" + "electricity. May paralyze."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_ELECTRIC, @@ -11352,8 +11352,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leaf Storm"), .description = COMPOUND_STRING( - "Whips up a storm\nof leaves. " - "Harshly\nlowers the Sp.\nAtk."), + "Whips up a storm of leaves.\n" + "Harshly lowers the Sp. Atk."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 130 : 140, .type = TYPE_GRASS, @@ -11377,8 +11377,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Whip"), .description = COMPOUND_STRING( - "Violently lashes\nthe foe " - "with vines\nor tentacles."), + "Violently lashes the foe\n" + "with vines or tentacles."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_GRASS, @@ -11423,8 +11423,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Cross Poison"), .description = COMPOUND_STRING( - "A slash that may\npoison a " - "foe and\ndo critical\ndamage."), + "A slash that may poison a\n" + "foe and do critical damage."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_POISON, @@ -11451,8 +11451,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gunk Shot"), .description = COMPOUND_STRING( - "Shoots filthy\ngarbage at " - "the\nfoe. May also\npoison."), + "Shoots filthy garbage at\n" + "the foe. May also poison."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_POISON, @@ -11476,8 +11476,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Iron Head"), .description = COMPOUND_STRING( - "Slams the foe with\na hard " - "head. May\ncause flinching."), + "Slams the foe with a hard\n" + "head. May cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_STEEL, @@ -11502,8 +11502,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magnet Bomb"), .description = COMPOUND_STRING( - "Launches a magnet\nthat " - "strikes\nwithout fail."), + "Launches a magnet that\n" + "strikes without fail."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_STEEL, @@ -11524,8 +11524,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stone Edge"), .description = COMPOUND_STRING( - "Stabs the foe with\nstones. " - "High\ncritical-hit\nratio."), + "Stabs the foe with stones.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_ROCK, @@ -11546,8 +11546,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Captivate"), .description = COMPOUND_STRING( - "Makes the opposite\ngender " - "sharply\nreduce its Sp.\nAtk."), + "Makes the opposite gender\n" + "sharply reduce its Sp. Atk."), .effect = EFFECT_CAPTIVATE, .power = 0, .type = TYPE_NORMAL, @@ -11569,8 +11569,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stealth Rock"), .description = COMPOUND_STRING( - "Sets floating\nstones that " - "hurt a\nfoe switching in."), + "Sets floating stones that\n" + "hurt a foe switching in."), .effect = EFFECT_STEALTH_ROCK, .power = 0, .type = TYPE_ROCK, @@ -11595,8 +11595,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grass Knot"), .description = COMPOUND_STRING( - "A snare attack\nthat does " - "more\ndamage to heavier\nfoes."), + "A snare attack that does\n" + "more damage to heavier foes."), .effect = EFFECT_LOW_KICK, .power = 1, .type = TYPE_GRASS, @@ -11618,8 +11618,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Chatter"), .description = COMPOUND_STRING( - "Attacks with a\nsound wave " - "that\ncauses confusion."), + "Attacks with a sound wave\n" + "that causes confusion."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 65 : 60, .type = TYPE_FLYING, @@ -11658,8 +11658,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Judgment"), .description = COMPOUND_STRING( - "The type varies\nwith the " - "kind of\nPlate held."), + "The type varies with the\n" + "kind of Plate held."), .effect = EFFECT_CHANGE_TYPE_ON_ITEM, .power = 100, .type = TYPE_NORMAL, @@ -11703,8 +11703,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Charge Beam"), .description = COMPOUND_STRING( - "Fires a beam of\nelectricity. " - "May\nraise Sp. Atk."), + "Fires a beam of electricity.\n" + "May raise Sp. Atk."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_ELECTRIC, @@ -11729,8 +11729,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wood Hammer"), .description = COMPOUND_STRING( - "Slams the body\ninto a foe. " - "The\nuser gets hurt\ntoo."), + "Slams the body into a foe.\n" + "The user gets hurt too."), .effect = EFFECT_RECOIL, .power = 120, .type = TYPE_GRASS, @@ -11752,8 +11752,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aqua Jet"), .description = COMPOUND_STRING( - "Strikes first by\ndashing " - "at the foe\nat a high speed."), + "Strikes first by dashing\n" + "at the foe at a high speed."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_WATER, @@ -11774,8 +11774,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Attack Order"), .description = COMPOUND_STRING( - "Underlings pummel\nthe foe. " - "High\ncritical-hit\nratio."), + "Underlings pummel the foe.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_BUG, @@ -11796,8 +11796,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Defend Order"), .description = COMPOUND_STRING( - "Raises Defense and\nSp. Def " - "with a\nliving shield."), + "Raises Defense and Sp. Def\n" + "with a living shield."), .effect = EFFECT_COSMIC_POWER, .power = 0, .type = TYPE_BUG, @@ -11821,8 +11821,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heal Order"), .description = COMPOUND_STRING( - "The user's\nunderlings show " - "up\nto heal half its\nmax HP."), + "The user's underlings show\n" + "up to heal half its max HP."), .effect = EFFECT_RESTORE_HP, .power = 0, .type = TYPE_BUG, @@ -11847,8 +11847,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Head Smash"), .description = COMPOUND_STRING( - "A life-risking\nheadbutt that " - "\nseriously hurts\nthe user."), + "A life-risking headbutt that\n" + "seriously hurts the user."), .effect = EFFECT_RECOIL, .power = 150, .type = TYPE_ROCK, @@ -11870,8 +11870,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Hit"), .description = COMPOUND_STRING( - "Slams the foe with\na tail " - "etc.\nStrikes twice."), + "Slams the foe with a tail\n" + "etc. Strikes twice."), .effect = EFFECT_HIT, .power = 35, .type = TYPE_NORMAL, @@ -11893,8 +11893,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Roar of Time"), .description = COMPOUND_STRING( - "Powerful, but\nleaves the " - "user\nimmobile the next\nturn."), + "Powerful, but leaves the\n" + "user immobile the next turn."), .effect = EFFECT_HIT, .power = 150, .type = TYPE_DRAGON, @@ -11918,8 +11918,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spacial Rend"), .description = COMPOUND_STRING( - "Tears the foe, and\nspace. " - "High\ncritical-hit\nratio."), + "Tears the foe, and space.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_DRAGON, @@ -11984,8 +11984,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magma Storm"), .description = COMPOUND_STRING( - "Traps the foe in a\nvortex " - "of fire for\n"BINDING_TURNS" turns."), + "Traps the foe in a vortex\n" + "of fire for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 100 : 120, .type = TYPE_FIRE, @@ -11996,6 +11996,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_MAGMA_STORM, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -12008,8 +12009,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dark Void"), .description = COMPOUND_STRING( - "Drags the foes\ninto total " - "\ndarkness, inducing\nSleep."), + "Drags the foes into total\n" + "darkness, inducing Sleep."), .effect = EFFECT_DARK_VOID, .power = 0, .type = TYPE_DARK, @@ -12033,8 +12034,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Seed Flare"), .description = COMPOUND_STRING( - "Generates a shock\nwave that " - "sharply\nreduces Sp. Def."), + "Generates a shock wave that\n" + "sharply reduces Sp. Def."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_GRASS, @@ -12058,8 +12059,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ominous Wind"), .description = COMPOUND_STRING( - "A repulsive attack\nthat may " - "raise all\nstats."), + "A repulsive attack that may\n" + "raise all stats."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_GHOST, @@ -12099,7 +12100,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), @@ -12114,8 +12115,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hone Claws"), .description = COMPOUND_STRING( - "Sharpens its claws\nto raise " - "Attack\nand Accuracy."), + "Sharpens its claws to raise\n" + "Attack and Accuracy."), .effect = EFFECT_ATTACK_ACCURACY_UP, .power = 0, .type = TYPE_DARK, @@ -12139,8 +12140,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wide Guard"), .description = COMPOUND_STRING( - "Evades\nwide-ranging\nattacks " - "for one\nturn."), + "Evades wide-ranging attacks\n" + "for one turn."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_ROCK, @@ -12166,8 +12167,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Guard Split"), .description = COMPOUND_STRING( - "Averages changes\nto Defense " - "and Sp.\nDef with the foe."), + "Averages changes to Defense\n" + "and Sp. Def with the foe."), .effect = EFFECT_GUARD_SPLIT, .power = 0, .type = TYPE_PSYCHIC, @@ -12189,8 +12190,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Split"), .description = COMPOUND_STRING( - "Averages changes\nto Attack " - "and Sp.\nAtk with the foe."), + "Averages changes to Attack\n" + "and Sp. Atk with the foe."), .effect = EFFECT_POWER_SPLIT, .power = 0, .type = TYPE_PSYCHIC, @@ -12212,8 +12213,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wonder Room"), .description = COMPOUND_STRING( - "Defense and Sp.\nDef stats " - "are\nswapped for 5\nturns."), + "Defense and Sp. Def stats\n" + "are swapped for 5 turns."), .effect = EFFECT_WONDER_ROOM, .power = 0, .type = TYPE_PSYCHIC, @@ -12254,8 +12255,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Venoshock"), .description = COMPOUND_STRING( - "Does double damage\nif the " - "foe is\npoisoned."), + "Does double damage if the\n" + "foe is poisoned."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = 65, .type = TYPE_POISON, @@ -12276,8 +12277,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Autotomize"), .description = COMPOUND_STRING( - "Sheds additional\nweight to " - "sharply\nboost Speed."), + "Sheds additional weight to\n" + "sharply boost Speed."), .effect = EFFECT_AUTOTOMIZE, .power = 0, .type = TYPE_STEEL, @@ -12301,8 +12302,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rage Powder"), .description = COMPOUND_STRING( - "Scatters powder to\nmake " - "foes attack\nonly the user."), + "Scatters powder to make\n" + "foes attack only the user."), .effect = EFFECT_FOLLOW_ME, .power = 0, .type = TYPE_BUG, @@ -12329,8 +12330,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Telekinesis"), .description = COMPOUND_STRING( - "Makes the foe\nfloat. It is " - "\neasier to hit for\n3 turns."), + "Makes the foe float. It is\n" + "easier to hit for 3 turns."), .effect = EFFECT_TELEKINESIS, .power = 0, .type = TYPE_PSYCHIC, @@ -12353,8 +12354,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magic Room"), .description = COMPOUND_STRING( - "Hold items lose\ntheir " - "effects for\n5 turns."), + "Hold items lose their\n" + "effects for 5 turns."), .effect = EFFECT_MAGIC_ROOM, .power = 0, .type = TYPE_PSYCHIC, @@ -12376,8 +12377,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Smack Down"), .description = COMPOUND_STRING( - "Throws a rock to\nknock the " - "foe down\nto the ground."), + "Throws a rock to knock the\n" + "foe down to the ground."), .effect = EFFECT_SMACK_DOWN, .power = 50, .type = TYPE_ROCK, @@ -12420,8 +12421,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flame Burst"), .description = COMPOUND_STRING( - "A bursting flame\nthat does " - "damage\nto all foes."), + "A bursting flame that does\n" + "damage to all foes."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_FIRE, @@ -12445,8 +12446,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sludge Wave"), .description = COMPOUND_STRING( - "Swamps all others\nwith a wave " - "of\nsludge. May also\npoison."), + "Swamps all others with a wave\n" + "of sludge. May also poison."), .effect = EFFECT_HIT, .power = 95, .type = TYPE_POISON, @@ -12470,8 +12471,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Quiver Dance"), .description = COMPOUND_STRING( - "Dances to raise\nSp. Atk " - "Sp. Def\nand Speed."), + "Dances to raise Sp. Atk\n" + "Sp. Def and Speed."), .effect = EFFECT_QUIVER_DANCE, .power = 0, .type = TYPE_BUG, @@ -12518,8 +12519,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Synchronoise"), .description = COMPOUND_STRING( - "An odd shock wave\nthat only " - "damages\nsame-type {PKMN}."), + "An odd shock wave that only\n" + "damages same-type {PKMN}."), .effect = EFFECT_SYNCHRONOISE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 120 : 70, .type = TYPE_PSYCHIC, @@ -12539,8 +12540,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electro Ball"), .description = COMPOUND_STRING( - "Hurls an orb that\ndoes more " - "damage\nto slower foes."), + "Hurls an orb that does more\n" + "damage to slower foes."), .effect = EFFECT_ELECTRO_BALL, .power = 1, .type = TYPE_ELECTRIC, @@ -12561,8 +12562,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Soak"), .description = COMPOUND_STRING( - "Sprays water at\nthe foe, " - "changing\nit to Water type."), + "Sprays water at the foe,\n" + "changing it to Water type."), .effect = EFFECT_SOAK, .power = 0, .type = TYPE_WATER, @@ -12585,8 +12586,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flame Charge"), .description = COMPOUND_STRING( - "Attacks in a cloak\nof " - "flames. Raises\nSpeed."), + "Attacks in a cloak of\n" + "flames. Raises Speed."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_FIRE, @@ -12612,8 +12613,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Coil"), .description = COMPOUND_STRING( - "Coils up to raise\nAttack, " - "Defense\nand Accuracy."), + "Coils up to raise Attack,\n" + "Defense and Accuracy."), .effect = EFFECT_COIL, .power = 0, .type = TYPE_POISON, @@ -12637,8 +12638,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Low Sweep"), .description = COMPOUND_STRING( - "Attacks the foe's\nlegs " - "lowering its\nSpeed."), + "Attacks the foe's legs\n" + "lowering its Speed."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 65 : 60, .type = TYPE_FIGHTING, @@ -12663,8 +12664,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acid Spray"), .description = COMPOUND_STRING( - "Sprays a\nhide-melting acid.\n" - "Sharply reduces\nSp. Def."), + "Sprays a hide-melting acid.\n" + "Sharply reduces Sp. Def."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_POISON, @@ -12689,8 +12690,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Foul Play"), .description = COMPOUND_STRING( - "The higher the\nfoe's Attack " - "the\nmore damage\ncaused."), + "The higher the foe's Attack\n" + "the more damage caused."), .effect = EFFECT_FOUL_PLAY, .power = 95, .type = TYPE_DARK, @@ -12711,8 +12712,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Simple Beam"), .description = COMPOUND_STRING( - "A beam that\nchanges the " - "foe's\nAbility to Simple."), + "A beam that changes the\n" + "foe's Ability to Simple."), .effect = EFFECT_SIMPLE_BEAM, .power = 0, .type = TYPE_NORMAL, @@ -12734,8 +12735,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Entrainment"), .description = COMPOUND_STRING( - "Makes the foe\nmimic the " - "user,\ngaining its\nAbility."), + "Makes the foe mimic the\n" + "user, gaining its Ability."), .effect = EFFECT_ENTRAINMENT, .power = 0, .type = TYPE_NORMAL, @@ -12757,8 +12758,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("After You"), .description = COMPOUND_STRING( - "Helps out the\ntarget, letting " - "it\nmove next."), + "Helps out the target, letting\n" + "it move next."), .effect = EFFECT_AFTER_YOU, .power = 0, .type = TYPE_NORMAL, @@ -12783,8 +12784,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Round"), .description = COMPOUND_STRING( - "A song that\ninflicts damage. " - "\nOthers can join in\ntoo."), + "A song that inflicts damage.\n" + "Others can join in too."), .effect = EFFECT_ROUND, .power = 60, .type = TYPE_NORMAL, @@ -12809,8 +12810,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Echoed Voice"), .description = COMPOUND_STRING( - "Does more damage\nevery turn " - "it is\nused."), + "Does more damage every turn\n" + "it is used."), .effect = EFFECT_ECHOED_VOICE, .power = 40, .type = TYPE_NORMAL, @@ -12853,8 +12854,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Clear Smog"), .description = COMPOUND_STRING( - "Attacks with white\nhaze that " - "\neliminates all\nstat changes."), + "Attacks with white haze that\n" + "eliminates all stat changes."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_POISON, @@ -12877,8 +12878,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stored Power"), .description = COMPOUND_STRING( - "The higher the\nuser's stats " - "the\nmore damage\ncaused."), + "The higher the user's stats\n" + "the more damage caused."), .effect = EFFECT_STORED_POWER, .power = 20, .type = TYPE_PSYCHIC, @@ -12898,8 +12899,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Quick Guard"), .description = COMPOUND_STRING( - "Evades priority\nattacks " - "for one\nturn."), + "Evades priority attacks\n" + "for one turn."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_FIGHTING, @@ -12925,8 +12926,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ally Switch"), .description = COMPOUND_STRING( - "The user switches\nplaces " - "with its\npartner."), + "The user switches places\n" + "with its partner."), .effect = EFFECT_ALLY_SWITCH, .power = 0, .type = TYPE_PSYCHIC, @@ -12949,8 +12950,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Scald"), .description = COMPOUND_STRING( - "Shoots boiling\nwater at the " - "foe.\nMay inflict a\nburn."), + "Shoots boiling water at the\n" + "foe. May inflict a burn."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_WATER, @@ -12975,8 +12976,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shell Smash"), .description = COMPOUND_STRING( - "Sharply raises\nAtk/Sp.Atk/ " - "Speed,\nbut drops\nDef/Sp.Def."), + "Sharply raises Atk/Sp.Atk/\n" + "Speed, but drops Def/Sp.Def."), .effect = EFFECT_SHELL_SMASH, .power = 0, .type = TYPE_NORMAL, @@ -13000,8 +13001,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heal Pulse"), .description = COMPOUND_STRING( - "Recovers up to\nhalf the " - "target's\nmaximum HP."), + "Recovers up to half the\n" + "target's maximum HP."), .effect = EFFECT_HEAL_PULSE, .power = 0, .type = TYPE_PSYCHIC, @@ -13026,8 +13027,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hex"), .description = COMPOUND_STRING( - "Does double damage\nif the " - "foe has a\nstatus problem."), + "Does double damage if the\n" + "foe has a status problem."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 65 : 50, .type = TYPE_GHOST, @@ -13049,8 +13050,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sky Drop"), .description = COMPOUND_STRING( - "Takes the foe into\nthe sky " - "then drops\nit the next turn."), + "Takes the foe into the sky\n" + "then drops it the next turn."), .effect = EFFECT_SKY_DROP, .power = 60, .type = TYPE_FLYING, @@ -13064,7 +13065,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = STATE_ON_AIR }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -13076,8 +13077,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shift Gear"), .description = COMPOUND_STRING( - "Rotates its gears\nto raise " - "Attack\nand Speed."), + "Rotates its gears to raise\n" + "Attack and Speed."), .effect = EFFECT_SHIFT_GEAR, .power = 0, .type = TYPE_STEEL, @@ -13123,8 +13124,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Incinerate"), .description = COMPOUND_STRING( - "Burns up Berries\nand Gems " - "\npreventing their\nuse."), + "Burns up Berries and Gems\n" + "preventing their use."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 30, .type = TYPE_FIRE, @@ -13147,8 +13148,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Quash"), .description = COMPOUND_STRING( - "Suppresses the\nfoe, making " - "it\nmove last."), + "Suppresses the foe, making\n" + "it move last."), .effect = EFFECT_QUASH, .power = 0, .type = TYPE_DARK, @@ -13170,8 +13171,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acrobatics"), .description = COMPOUND_STRING( - "Does double damage\nif the " - "user has no\nitem."), + "Does double damage if the\n" + "user has no item."), .effect = EFFECT_ACROBATICS, .power = 55, .type = TYPE_FLYING, @@ -13192,8 +13193,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Reflect Type"), .description = COMPOUND_STRING( - "The user reflects\nthe foe's " - "type,\ncopying it."), + "The user reflects the foe's\n" + "type, copying it."), .effect = EFFECT_REFLECT_TYPE, .power = 0, .type = TYPE_NORMAL, @@ -13216,8 +13217,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Retaliate"), .description = COMPOUND_STRING( - "An attack that\ndoes more " - "damage\nif an ally\nfainted."), + "An attack that does more\n" + "damage if an ally fainted."), .effect = EFFECT_RETALIATE, .power = 70, .type = TYPE_NORMAL, @@ -13238,8 +13239,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Final Gambit"), .description = COMPOUND_STRING( - "The user faints to\ndamage " - "the foe\nequal to its HP."), + "The user faints to damage\n" + "the foe equal to its HP."), .effect = EFFECT_FINAL_GAMBIT, .power = 1, .type = TYPE_FIGHTING, @@ -13261,8 +13262,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bestow"), .description = COMPOUND_STRING( - "The user gives its\nheld " - "item to the\nfoe."), + "The user gives its held\n" + "item to the foe."), .effect = EFFECT_BESTOW, .power = 0, .type = TYPE_NORMAL, @@ -13288,8 +13289,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Inferno"), .description = COMPOUND_STRING( - "Powerful and sure\nto inflict " - "a burn,\nbut inaccurate."), + "Powerful and sure to inflict\n" + "a burn, but inaccurate."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIRE, @@ -13313,8 +13314,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Pledge"), .description = COMPOUND_STRING( - "Attacks with a\ncolumn of " - "water.\nMay make a\nrainbow."), + "Attacks with a column of\n" + "water. May make a rainbow."), .effect = EFFECT_PLEDGE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 80 : 50, .type = TYPE_WATER, @@ -13335,8 +13336,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Pledge"), .description = COMPOUND_STRING( - "Attacks with a\ncolumn of " - "fire.\nMay burn the\ngrass."), + "Attacks with a column of\n" + "fire. May burn the grass."), .effect = EFFECT_PLEDGE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 80 : 50, .type = TYPE_FIRE, @@ -13357,8 +13358,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grass Pledge"), .description = COMPOUND_STRING( - "Attacks with a\ncolumn of " - "grass.\nMay create a\nswamp."), + "Attacks with a column of\n" + "grass. May create a swamp."), .effect = EFFECT_PLEDGE, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 80 : 50, .type = TYPE_GRASS, @@ -13398,8 +13399,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Struggle Bug"), .description = COMPOUND_STRING( - "Resisting, the\nuser attacks " - "the\nfoes. Lowers Sp.\nAtk."), + "Resisting, the user attacks\n" + "the foes. Lowers Sp. Atk."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 50 : 30, .type = TYPE_BUG, @@ -13423,8 +13424,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bulldoze"), .description = COMPOUND_STRING( - "Stomps down on the\nground. " - "Hits all\nand lowers Speed."), + "Stomps down on the ground.\n" + "Hits all and lowers Speed."), .effect = EFFECT_EARTHQUAKE, .power = 60, .type = TYPE_GROUND, @@ -13491,8 +13492,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Work Up"), .description = COMPOUND_STRING( - "The user is\nroused. " - "Ups Attack\nand Sp. Atk."), + "The user is roused.\n" + "Ups Attack and Sp. Atk."), .effect = EFFECT_ATTACK_SPATK_UP, .power = 0, .type = TYPE_NORMAL, @@ -13516,8 +13517,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electroweb"), .description = COMPOUND_STRING( - "Snares the foes\nwith an " - "electric\nnet. Lowers Speed."), + "Snares the foes with an\n" + "electric net. Lowers Speed."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_ELECTRIC, @@ -13541,8 +13542,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wild Charge"), .description = COMPOUND_STRING( - "An electrical\ntackle that " - "also\nhurts the user."), + "An electrical tackle that\n" + "also hurts the user."), .effect = EFFECT_RECOIL, .power = 90, .type = TYPE_ELECTRIC, @@ -13564,8 +13565,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Drill Run"), .description = COMPOUND_STRING( - "Spins its body\nlike a drill. " - "High\ncritical-hit\nratio."), + "Spins its body like a drill.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GROUND, @@ -13587,8 +13588,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dual Chop"), .description = COMPOUND_STRING( - "Attacks with\nbrutal hits " - "that\nstrike twice."), + "Attacks with brutal hits\n" + "that strike twice."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_DRAGON, @@ -13610,8 +13611,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Heart Stamp"), .description = COMPOUND_STRING( - "A sudden blow\nafter a cute " - "act.\nMay cause\nflinching."), + "A sudden blow after a cute\n" + "act. May cause flinching."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_PSYCHIC, @@ -13680,8 +13681,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Razor Shell"), .description = COMPOUND_STRING( - "Tears at the foe\nwith sharp " - "shells.\nMay lower Defense."), + "Tears at the foe with sharp\n" + "shells. May lower Defense."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_WATER, @@ -13728,8 +13729,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leaf Tornado"), .description = COMPOUND_STRING( - "Circles the foe\nwith leaves " - "to\ndamage and cut\naccuracy."), + "Circles the foe with leaves\n" + "to damage and cut accuracy."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_GRASS, @@ -13753,8 +13754,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Steamroller"), .description = COMPOUND_STRING( - "Crushes the foe\nwith its " - "body. May\ncause flinching."), + "Crushes the foe with its\n" + "body. May cause flinching."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_BUG, @@ -13780,8 +13781,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Cotton Guard"), .description = COMPOUND_STRING( - "Wraps its body in\ncotton. " - "\nDrastically raises\nDefense."), + "Wraps its body in cotton.\n" + "Drastically raises Defense."), .effect = EFFECT_DEFENSE_UP_3, .power = 0, .type = TYPE_GRASS, @@ -13805,8 +13806,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Night Daze"), .description = COMPOUND_STRING( - "Looses a\npitch-black shock " - "\nwave. May lower\naccuracy."), + "Looses a pitch-black shock\n" + "wave. May lower accuracy."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_DARK, @@ -13849,8 +13850,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tail Slap"), .description = COMPOUND_STRING( - "Strikes the foe\nwith its " - "tail 2 to\n5 times."), + "Strikes the foe with its\n" + "tail 2 to 5 times."), .effect = EFFECT_MULTI_HIT, .power = 25, .type = TYPE_NORMAL, @@ -13871,8 +13872,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hurricane"), .description = COMPOUND_STRING( - "Traps the foe in a\nfierce " - "wind. May\ncause confusion."), + "Traps the foe in a fierce\n" + "wind. May cause confusion."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 110 : 120, .type = TYPE_FLYING, @@ -13900,8 +13901,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Head Charge"), .description = COMPOUND_STRING( - "A charge using\nguard hair. " - "It\nhurts the user a\nlittle."), + "A charge using guard hair.\n" + "It hurts the user a little."), .effect = EFFECT_RECOIL, .power = 120, .type = TYPE_NORMAL, @@ -13923,8 +13924,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gear Grind"), .description = COMPOUND_STRING( - "Throws two steel\ngears " - "that strike\ntwice."), + "Throws two steel gears\n" + "that strike twice."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_STEEL, @@ -13971,8 +13972,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Techno Blast"), .description = COMPOUND_STRING( - "The type varies\nwith the " - "kind of\nDrive held."), + "The type varies with the\n" + "kind of Drive held."), .effect = EFFECT_CHANGE_TYPE_ON_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 120 : 85, .type = TYPE_NORMAL, @@ -13994,8 +13995,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Relic Song"), .description = COMPOUND_STRING( - "Attacks with an\nancient " - "song. May\ninduce sleep."), + "Attacks with an ancient\n" + "song. May induce sleep."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_NORMAL, @@ -14023,8 +14024,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Secret Sword"), .description = COMPOUND_STRING( - "Cuts with a long\nhorn that " - "does\nphysical damage."), + "Cuts with a long horn that\n" + "does physical damage."), .effect = EFFECT_PSYSHOCK, .power = 85, .type = TYPE_FIGHTING, @@ -14046,8 +14047,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Glaciate"), .description = COMPOUND_STRING( - "Blows very cold\nair at the " - "foes.\nIt lowers their\nSpeed."), + "Blows very cold air at the\n" + "foes. It lowers their Speed."), .effect = EFFECT_HIT, .power = 65, .type = TYPE_ICE, @@ -14071,8 +14072,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bolt Strike"), .description = COMPOUND_STRING( - "Strikes with a\ngreat amount " - "of\nlightning. May\nparalyze."), + "Strikes with a great amount\n" + "of lightning. May paralyze."), .effect = EFFECT_HIT, .power = 130, .type = TYPE_ELECTRIC, @@ -14097,8 +14098,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Blue Flare"), .description = COMPOUND_STRING( - "Engulfs the foe in\na blue " - "flame. May\ninflict a burn."), + "Engulfs the foe in a blue\n" + "flame. May inflict a burn."), .effect = EFFECT_HIT, .power = 130, .type = TYPE_FIRE, @@ -14122,8 +14123,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fiery Dance"), .description = COMPOUND_STRING( - "Dances cloaked in\nflames. " - "May raise\nSp. Atk."), + "Dances cloaked in flames.\n" + "May raise Sp. Atk."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FIRE, @@ -14149,8 +14150,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Freeze Shock"), .description = COMPOUND_STRING( - "A powerful 2-turn\nmove that " - "may\nparalyze the foe."), + "A powerful 2-turn move that\n" + "may paralyze the foe."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 140, .type = TYPE_ICE, @@ -14178,8 +14179,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Burn"), .description = COMPOUND_STRING( - "A powerful 2-turn\nmove that " - "may\ninflict a burn."), + "A powerful 2-turn move that\n" + "may inflict a burn."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 140, .type = TYPE_ICE, @@ -14207,8 +14208,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Snarl"), .description = COMPOUND_STRING( - "Yells and rants at\nthe foe " - "lowering\nits Sp. Atk."), + "Yells and rants at the foe\n" + "lowering its Sp. Atk."), .effect = EFFECT_HIT, .power = 55, .type = TYPE_DARK, @@ -14235,8 +14236,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Icicle Crash"), .description = COMPOUND_STRING( - "Drops large\nicicles on the " - "\nfoe. May cause\nflinching."), + "Drops large icicles on the\n" + "foe. May cause flinching."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_ICE, @@ -14260,8 +14261,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("V-create"), .description = COMPOUND_STRING( - "Very powerful, but\nlowers " - "Defense,\nSp. Def and Speed."), + "Very powerful, but lowers\n" + "Defense, Sp. Def and Speed."), .effect = EFFECT_HIT, .power = 180, .type = TYPE_FIRE, @@ -14288,8 +14289,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fusion Flare"), .description = COMPOUND_STRING( - "Summons a\nfireball. Works " - "\nwell with a\nthunderbolt."), + "Summons a fireball. Works\n" + "well with a thunderbolt."), .effect = EFFECT_FUSION_COMBO, .power = 100, .type = TYPE_FIRE, @@ -14310,8 +14311,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fusion Bolt"), .description = COMPOUND_STRING( - "Summons a\nthunderbolt. " - "Works\nwell with a\nfireball."), + "Summons a thunderbolt.\n" + "Works well with a fireball."), .effect = EFFECT_FUSION_COMBO, .power = 100, .type = TYPE_ELECTRIC, @@ -14331,8 +14332,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flying Press"), .description = COMPOUND_STRING( - "This attack does\nFighting " - "and\nFlying-type\ndamage."), + "This attack does Fighting\n" + "and Flying-type damage."), .effect = EFFECT_TWO_TYPED_MOVE, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 100 : 80, .type = TYPE_FIGHTING, @@ -14358,8 +14359,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mat Block"), .description = COMPOUND_STRING( - "Evades damaging\nmoves. " - "Only works\non 1st turn."), + "Evades damaging moves.\n" + "Only works on 1st turn."), .effect = EFFECT_MAT_BLOCK, .power = 0, .type = TYPE_FIGHTING, @@ -14388,8 +14389,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Belch"), .description = COMPOUND_STRING( - "Lets out a loud\nbelch. " - "Must eat a\nBerry to use it."), + "Lets out a loud belch.\n" + "Must eat a Berry to use it."), .effect = EFFECT_BELCH, .power = 120, .type = TYPE_POISON, @@ -14417,8 +14418,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rototiller"), .description = COMPOUND_STRING( - "Ups the Attack and\nSp. Atk " - "of\nGrass-type\nPokémon."), + "Ups the Attack and Sp. Atk\n" + "of Grass-type Pokémon."), .effect = EFFECT_ROTOTILLER, .power = 0, .type = TYPE_GROUND, @@ -14442,8 +14443,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sticky Web"), .description = COMPOUND_STRING( - "Weaves a sticky\nnet that " - "slows\nfoes switching in."), + "Weaves a sticky net that\n" + "slows foes switching in."), .effect = EFFECT_STICKY_WEB, .power = 0, .type = TYPE_BUG, @@ -14468,8 +14469,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fell Stinger"), .description = COMPOUND_STRING( - "If it knocks out a\nfoe " - "the Attack\nstat is raised."), + "If it knocks out a foe\n" + "the Attack stat is raised."), .effect = EFFECT_FELL_STINGER, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 50 : 30, .type = TYPE_BUG, @@ -14504,7 +14505,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), @@ -14519,8 +14520,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trick-or-Treat"), .description = COMPOUND_STRING( - "Goes\ntrick-or-treating,\n" - "adding Ghost type\nto foe."), + "Goes trick-or-treating,\n" + "adding Ghost type to foe."), .effect = EFFECT_THIRD_TYPE, .power = 0, .type = TYPE_GHOST, @@ -14543,8 +14544,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Noble Roar"), .description = COMPOUND_STRING( - "Intimidates the\nfoe, to cut " - "Attack\nand Sp. Atk."), + "Intimidates the foe, to cut\n" + "Attack and Sp. Atk."), .effect = EFFECT_NOBLE_ROAR, .power = 0, .type = TYPE_NORMAL, @@ -14568,8 +14569,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ion Deluge"), .description = COMPOUND_STRING( - "Electrifies\nNormal-type " - "moves\nwith charged\natoms."), + "Electrifies Normal-type\n" + "moves with charged atoms."), .effect = EFFECT_ION_DELUGE, .power = 0, .type = TYPE_ELECTRIC, @@ -14592,8 +14593,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Parabolic Charge"), .description = COMPOUND_STRING( - "Damages adjacent\nPokémon " - "and heals\nup by half of it."), + "Damages adjacent Pokémon\n" + "and heals up by half of it."), .effect = EFFECT_ABSORB, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 65 : 50, .type = TYPE_ELECTRIC, @@ -14615,8 +14616,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Forest's Curse"), .description = COMPOUND_STRING( - "Puts a curse on\nthe foe, " - "adding\nthe Grass type."), + "Puts a curse on the foe,\n" + "adding the Grass type."), .effect = EFFECT_THIRD_TYPE, .power = 0, .type = TYPE_GRASS, @@ -14639,8 +14640,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Petal Blizzard"), .description = COMPOUND_STRING( - "Stirs up a violent\nstorm " - "of petals to\nattack all."), + "Stirs up a violent storm\n" + "of petals to attack all."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_GRASS, @@ -14661,11 +14662,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Freeze-Dry"), .description = COMPOUND_STRING( - "Super effective on\nWater- " + "Super effective on Water-\n" #if B_USE_FROSTBITE == TRUE - "types. May\ncause frostbite."), + "types. May cause frostbite."), #else - "types. May\ncause freezing."), + "types. May cause freezing."), #endif .effect = EFFECT_SUPER_EFFECTIVE_ON_ARG, .power = 70, @@ -14691,8 +14692,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Disarming Voice"), .description = COMPOUND_STRING( - "Lets out a\ncharming cry " - "that\ncannot be evaded."), + "Lets out a charming cry\n" + "that cannot be evaded."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FAIRY, @@ -14714,8 +14715,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Parting Shot"), .description = COMPOUND_STRING( - "Lowers the foe's\nAttack and " - "Sp.\nAtk, then switches\nout."), + "Lowers the foe's Attack and\n" + "Sp. Atk, then switches out."), .effect = EFFECT_PARTING_SHOT, .power = 0, .type = TYPE_DARK, @@ -14739,8 +14740,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Topsy-Turvy"), .description = COMPOUND_STRING( - "Swaps all stat\nchanges that " - "\naffect the target."), + "Swaps all stat changes that\n" + "affect the target."), .effect = EFFECT_TOPSY_TURVY, .power = 0, .type = TYPE_DARK, @@ -14784,8 +14785,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Crafty Shield"), .description = COMPOUND_STRING( - "Evades status\nmoves for " - "one\nturn."), + "Evades status moves for\n" + "one turn."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_FAIRY, @@ -14810,8 +14811,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flower Shield"), .description = COMPOUND_STRING( - "Raises the Defense\nof " - "Grass-type\nPokémon."), + "Raises the Defense of\n" + "Grass-type Pokémon."), .effect = EFFECT_FLOWER_SHIELD, .power = 0, .type = TYPE_FAIRY, @@ -14834,8 +14835,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grassy Terrain"), .description = COMPOUND_STRING( - "The ground turns\nto grass " - "for 5\nturns. Restores\nHP."), + "The ground turns to grass\n" + "for 5 turns. Restores HP."), .effect = EFFECT_GRASSY_TERRAIN, .power = 0, .type = TYPE_GRASS, @@ -14859,8 +14860,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Misty Terrain"), .description = COMPOUND_STRING( - "Covers the ground\nwith mist " - "for 5\nturns. Blocks\nstatus."), + "Covers the ground with mist\n" + "for 5 turns. Blocks status."), .effect = EFFECT_MISTY_TERRAIN, .power = 0, .type = TYPE_FAIRY, @@ -14884,8 +14885,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electrify"), .description = COMPOUND_STRING( - "Electrifies the\nfoe, making " - "its\nnext move\nElectric-type."), + "Electrifies the foe, making\n" + "its next move Electric-type."), .effect = EFFECT_ELECTRIFY, .power = 0, .type = TYPE_ELECTRIC, @@ -14906,8 +14907,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Play Rough"), .description = COMPOUND_STRING( - "Plays rough with\nthe foe. " - "May lower\nAttack."), + "Plays rough with the foe.\n" + "May lower Attack."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_FAIRY, @@ -14932,8 +14933,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fairy Wind"), .description = COMPOUND_STRING( - "Stirs up a fairy\nwind to " - "strike the\nfoe."), + "Stirs up a fairy wind to\n" + "strike the foe."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FAIRY, @@ -14954,8 +14955,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Moonblast"), .description = COMPOUND_STRING( - "Attacks with the\npower of " - "the moon.\nMay lower Sp. Atk."), + "Attacks with the power of\n" + "the moon. May lower Sp. Atk."), .effect = EFFECT_HIT, .power = 95, .type = TYPE_FAIRY, @@ -14979,8 +14980,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Boomburst"), .description = COMPOUND_STRING( - "Attacks everything\nwith a " - "destructive\nsound wave."), + "Attacks everything with a\n" + "destructive sound wave."), .effect = EFFECT_HIT, .power = 140, .type = TYPE_NORMAL, @@ -15002,8 +15003,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fairy Lock"), .description = COMPOUND_STRING( - "Locks down the\nbattlefield " - "\npreventing escape\nnext turn."), + "Locks down the battlefield\n" + "preventing escape next turn."), .effect = EFFECT_FAIRY_LOCK, .power = 0, .type = TYPE_FAIRY, @@ -15026,8 +15027,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("King's Shield"), .description = COMPOUND_STRING( - "Evades damage, and\nsharply " - "reduces\nAttack if struck."), + "Evades damage, and sharply\n" + "reduces Attack if struck."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_STEEL, @@ -15055,8 +15056,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Play Nice"), .description = COMPOUND_STRING( - "Befriend the foe,\nlowering " - "its\nAttack without\nfail."), + "Befriend the foe, lowering\n" + "its Attack without fail."), .effect = EFFECT_ATTACK_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -15080,8 +15081,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Confide"), .description = COMPOUND_STRING( - "Shares a secret\nwith the " - "foe,\nlowering Sp. Atk."), + "Shares a secret with the\n" + "foe, lowering Sp. Atk."), .effect = EFFECT_SPECIAL_ATTACK_DOWN, .power = 0, .type = TYPE_NORMAL, @@ -15106,8 +15107,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Diamond Storm"), .description = COMPOUND_STRING( - "Whips up a storm\nof " - "diamonds. May\nup Defense."), + "Whips up a storm of\n" + "diamonds. May up Defense."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_ROCK, @@ -15133,8 +15134,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Steam Eruption"), .description = COMPOUND_STRING( - "Immerses the foe\nin heated " - "steam.\nMay inflict a\nburn."), + "Immerses the foe in heated\n" + "steam. May inflict a burn."), .effect = EFFECT_HIT, .power = 110, .type = TYPE_WATER, @@ -15185,8 +15186,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Water Shuriken"), .description = COMPOUND_STRING( - "Throws 2 to 5\nstars that " - "are\nsure to strike\nfirst."), + "Throws 2 to 5 stars that\n" + "are sure to strike first."), .effect = EFFECT_MULTI_HIT, .power = 15, .type = TYPE_WATER, @@ -15206,8 +15207,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mystical Fire"), .description = COMPOUND_STRING( - "Breathes a\nspecial, hot " - "fire.\nLowers Sp. Atk."), + "Breathes a special, hot\n" + "fire. Lowers Sp. Atk."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_7 ? 75 : 65, .type = TYPE_FIRE, @@ -15231,8 +15232,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spiky Shield"), .description = COMPOUND_STRING( - "Evades attack, and\ndamages " - "the foe if\nstruck."), + "Evades attack, and damages\n" + "the foe if struck."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_GRASS, @@ -15259,8 +15260,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aromatic Mist"), .description = COMPOUND_STRING( - "Raises the Sp. Def\nof a " - "partner\nPokémon."), + "Raises the Sp. Def of a\n" + "partner Pokémon."), .effect = EFFECT_AROMATIC_MIST, .power = 0, .type = TYPE_FAIRY, @@ -15284,8 +15285,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Eerie Impulse"), .description = COMPOUND_STRING( - "Exposes the foe to\na pulse " - "that\nsharply cuts Sp.\nAtk."), + "Exposes the foe to a pulse\n" + "that sharply cuts Sp. Atk."), .effect = EFFECT_SPECIAL_ATTACK_DOWN_2, .power = 0, .type = TYPE_ELECTRIC, @@ -15307,8 +15308,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Venom Drench"), .description = COMPOUND_STRING( - "Lowers the Attack,\nSp. Atk " - "and Speed\nof poisoned foes."), + "Lowers the Attack, Sp. Atk\n" + "and Speed of poisoned foes."), .effect = EFFECT_VENOM_DRENCH, .power = 0, .type = TYPE_POISON, @@ -15330,8 +15331,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Powder"), .description = COMPOUND_STRING( - "Damages the foe if\nit uses " - "a\nFire-type move."), + "Damages the foe if it uses\n" + "a Fire-type move."), .effect = EFFECT_POWDER, .power = 0, .type = TYPE_BUG, @@ -15354,8 +15355,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Geomancy"), .description = COMPOUND_STRING( - "Raises Sp. Atk,\nSp. Def and " - "Speed\non the 2nd turn."), + "Raises Sp. Atk, Sp. Def and\n" + "Speed on the 2nd turn."), .effect = EFFECT_GEOMANCY, .power = 0, .type = TYPE_FAIRY, @@ -15380,8 +15381,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magnetic Flux"), .description = COMPOUND_STRING( - "Boosts the\ndefenses of " - "those\nwith Plus or\nMinus."), + "Boosts the defenses of\n" + "those with Plus or Minus."), .effect = EFFECT_MAGNETIC_FLUX, .power = 0, .type = TYPE_ELECTRIC, @@ -15406,8 +15407,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Happy Hour"), .description = COMPOUND_STRING( - "Doubles the amount\nof " - "Prize Money\nreceived."), + "Doubles the amount of\n" + "Prize Money received."), .effect = EFFECT_HAPPY_HOUR, .power = 0, .type = TYPE_NORMAL, @@ -15430,8 +15431,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electric Terrain"), .description = COMPOUND_STRING( - "Electrifies the\nground for " - "5\nturns. Prevents\nsleep."), + "Electrifies the ground for\n" + "5 turns. Prevents sleep."), .effect = EFFECT_ELECTRIC_TERRAIN, .power = 0, .type = TYPE_ELECTRIC, @@ -15455,8 +15456,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dazzling Gleam"), .description = COMPOUND_STRING( - "Damages foes by\nemitting " - "a bright\nflash."), + "Damages foes by emitting\n" + "a bright flash."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FAIRY, @@ -15476,8 +15477,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Celebrate"), .description = COMPOUND_STRING( - "Congratulates you\non your " - "special\nday."), + "Congratulates you on your\n" + "special day."), .effect = EFFECT_CELEBRATE, .power = 0, .type = TYPE_NORMAL, @@ -15506,8 +15507,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hold Hands"), .description = COMPOUND_STRING( - "The user and ally\nhold hands " - "making\nthem happy."), + "The user and ally hold hands\n" + "making them happy."), .effect = EFFECT_HOLD_HANDS, .power = 0, .type = TYPE_NORMAL, @@ -15536,8 +15537,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Baby-Doll Eyes"), .description = COMPOUND_STRING( - "Lowers the foe's\nAttack " - "before it\ncan move."), + "Lowers the foe's Attack\n" + "before it can move."), .effect = EFFECT_ATTACK_DOWN, .power = 0, .type = TYPE_FAIRY, @@ -15559,8 +15560,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Nuzzle"), .description = COMPOUND_STRING( - "Rubs its cheeks\nagainst " - "the foe,\nparalyzing it."), + "Rubs its cheeks against\n" + "the foe, paralyzing it."), .effect = EFFECT_HIT, .power = 20, .type = TYPE_ELECTRIC, @@ -15605,8 +15606,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Infestation"), .description = COMPOUND_STRING( - "The foe is\ninfested and " - "\nattacked for\n"BINDING_TURNS" turns."), + "The foe is infested and\n" + "attacked for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = 20, .type = TYPE_BUG, @@ -15618,6 +15619,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_INFESTATION, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, @@ -15630,8 +15632,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power-Up Punch"), .description = COMPOUND_STRING( - "A hard punch that\nraises " - "the user's\nAttack."), + "A hard punch that raises\n" + "the user's Attack."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FIGHTING, @@ -15679,8 +15681,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thousand Arrows"), .description = COMPOUND_STRING( - "Can hit Flying\nfoes, then " - "knocks\nthem to the\nground."), + "Can hit Flying foes, then\n" + "knocks them to the ground."), .effect = EFFECT_SMACK_DOWN, .power = 90, .type = TYPE_GROUND, @@ -15704,8 +15706,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thousand Waves"), .description = COMPOUND_STRING( - "Those hit by the\nwave can " - "no longer\nescape."), + "Those hit by the wave can\n" + "no longer escape."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_GROUND, @@ -15730,8 +15732,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Land's Wrath"), .description = COMPOUND_STRING( - "Gathers the energy\nof the " - "land to\nattack every foe."), + "Gathers the energy of the\n" + "land to attack every foe."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_GROUND, @@ -15752,8 +15754,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Light Of Ruin"), .description = COMPOUND_STRING( - "Fires a great beam\nof light " - "that also\nhurts the user."), + "Fires a great beam of light\n" + "that also hurts the user."), .effect = EFFECT_RECOIL, .power = 140, .type = TYPE_FAIRY, @@ -15771,8 +15773,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Origin Pulse"), .description = COMPOUND_STRING( - "Beams of glowing\nblue light " - "blast\nboth foes."), + "Beams of glowing blue light\n" + "blast both foes."), .effect = EFFECT_HIT, .power = 110, .type = TYPE_WATER, @@ -15794,8 +15796,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Precipice Blades"), .description = COMPOUND_STRING( - "Fearsome blades of\nstone " - "attack both\nfoes."), + "Fearsome blades of stone\n" + "attack both foes."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_GROUND, @@ -15869,8 +15871,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shore Up"), .description = COMPOUND_STRING( - "Restores the\nuser's HP. " - "More HP\nin a sandstorm."), + "Restores the user's HP.\n" + "More HP in a sandstorm."), .effect = EFFECT_SHORE_UP, .power = 0, .type = TYPE_GROUND, @@ -15895,8 +15897,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("First Impression"), .description = COMPOUND_STRING( - "Hits hard and\nfirst. " - "Only works\nfirst turn."), + "Hits hard and first.\n" + "Only works first turn."), .effect = EFFECT_FIRST_TURN_ONLY, .power = 90, .type = TYPE_BUG, @@ -15918,8 +15920,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Baneful Bunker"), .description = COMPOUND_STRING( - "Protects user and\npoisons " - "foes on\ncontact."), + "Protects user and poisons\n" + "foes on contact."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_POISON, @@ -15946,8 +15948,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spirit Shackle"), .description = COMPOUND_STRING( - "After being hit,\nfoes can " - "no longer\nescape."), + "After being hit, foes can\n" + "no longer escape."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GHOST, @@ -15971,8 +15973,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Darkest Lariat"), .description = COMPOUND_STRING( - "Swings the arms to\nstrike " - "It ignores\nstat changes."), + "Swings the arms to strike\n" + "It ignores stat changes."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_DARK, @@ -15994,8 +15996,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sparkling Aria"), .description = COMPOUND_STRING( - "Sings with\nbubbles. Cures " - "\nburns on contact."), + "Sings with bubbles. Cures\n" + "burns on contact."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_WATER, @@ -16009,7 +16011,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .soundMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -16022,8 +16024,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Hammer"), .description = COMPOUND_STRING( - "Swings the fist to\nstrike. " - "Lowers the\nuser's Speed."), + "Swings the fist to strike.\n" + "Lowers the user's Speed."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_ICE, @@ -16049,8 +16051,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Floral Healing"), .description = COMPOUND_STRING( - "Restores an ally's\nHP. " - "Heals more on\ngrass."), + "Restores an ally's HP.\n" + "Heals more on grass."), .effect = EFFECT_HEAL_PULSE, .power = 0, .type = TYPE_FAIRY, @@ -16075,8 +16077,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("High Horsepower"), .description = COMPOUND_STRING( - "Slams hard into\nthe foe with " - "its\nentire body."), + "Slams hard into the foe with\n" + "its entire body."), .effect = EFFECT_HIT, .power = 95, .type = TYPE_GROUND, @@ -16097,8 +16099,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Strength Sap"), .description = COMPOUND_STRING( - "Saps the foe's\nAttack to " - "heal HP,\nthen drops Attack."), + "Saps the foe's Attack to\n" + "heal HP, then drops Attack."), .effect = EFFECT_STRENGTH_SAP, .power = 0, .type = TYPE_GRASS, @@ -16121,8 +16123,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Solar Blade"), .description = COMPOUND_STRING( - "Charges first\nturn, then " - "chops\nwith a blade of\nlight."), + "Charges first turn, then\n" + "chops with a blade of light."), .effect = EFFECT_SOLAR_BEAM, .power = 125, .type = TYPE_GRASS, @@ -16147,8 +16149,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Leafage"), .description = COMPOUND_STRING( - "Attacks with a\nflurry of " - "small\nleaves."), + "Attacks with a flurry of\n" + "small leaves."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_GRASS, @@ -16168,8 +16170,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spotlight"), .description = COMPOUND_STRING( - "Makes the foe\nattack the " - "\nspotlighted\nPokémon."), + "Makes the foe attack the\n" + "spotlighted Pokémon."), .effect = EFFECT_FOLLOW_ME, .power = 0, .type = TYPE_NORMAL, @@ -16195,8 +16197,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Toxic Thread"), .description = COMPOUND_STRING( - "Attacks with a\nthread that " - "\npoisons and drops\nSpeed."), + "Attacks with a thread that\n" + "poisons and drops Speed."), .effect = EFFECT_TOXIC_THREAD, .power = 0, .type = TYPE_POISON, @@ -16218,8 +16220,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Laser Focus"), .description = COMPOUND_STRING( - "Guarantees the\nnext move " - "will be\na critical hit."), + "Guarantees the next move\n" + "will be a critical hit."), .effect = EFFECT_LASER_FOCUS, .power = 0, .type = TYPE_NORMAL, @@ -16243,8 +16245,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gear Up"), .description = COMPOUND_STRING( - "Boosts the attacks\nof " - "those with Plus\nor Minus."), + "Boosts the attacks of\n" + "those with Plus or Minus."), .effect = EFFECT_GEAR_UP, .power = 0, .type = TYPE_STEEL, @@ -16269,8 +16271,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Throat Chop"), .description = COMPOUND_STRING( - "Chops the throat\nto disable " - "sound\nmoves for 2 turns."), + "Chops the throat to disable\n" + "sound moves for 2 turns."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_DARK, @@ -16295,8 +16297,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pollen Puff"), .description = COMPOUND_STRING( - "Explodes on foes,\nbut " - "restores\nally's HP."), + "Explodes on foes, but\n" + "restores ally's HP."), .effect = EFFECT_HIT_ENEMY_HEAL_ALLY, .power = 90, .type = TYPE_BUG, @@ -16317,8 +16319,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Anchor Shot"), .description = COMPOUND_STRING( - "Strangles the foe\nwith a " - "chain. The\nfoe can't escape."), + "Strangles the foe with a\n" + "chain. The foe can't escape."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_STEEL, @@ -16343,8 +16345,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psychic Terrain"), .description = COMPOUND_STRING( - "The ground turns\nweird for " - "5 turns.\nBlocks priority."), + "The ground turns weird for\n" + "5 turns. Blocks priority."), .effect = EFFECT_PSYCHIC_TERRAIN, .power = 0, .type = TYPE_PSYCHIC, @@ -16367,8 +16369,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lunge"), .description = COMPOUND_STRING( - "Lunges at the foe\nto lower " - "its\nAttack stat."), + "Lunges at the foe to lower\n" + "its Attack stat."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_BUG, @@ -16393,8 +16395,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fire Lash"), .description = COMPOUND_STRING( - "Whips the foe with\nfire " - "lowering its\nDefense."), + "Whips the foe with fire\n" + "lowering its Defense."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FIRE, @@ -16419,8 +16421,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Trip"), .description = COMPOUND_STRING( - "It hits harder the\nmore " - "stat boosts\nthe user has."), + "It hits harder the more\n" + "stat boosts the user has."), .effect = EFFECT_STORED_POWER, .power = 20, .type = TYPE_DARK, @@ -16441,8 +16443,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Burn Up"), .description = COMPOUND_STRING( - "Burns out the user\nfully " - "removing the\nFire type."), + "Burns out the user fully\n" + "removing the Fire type."), .effect = EFFECT_FAIL_IF_NOT_ARG_TYPE, .power = 130, .type = TYPE_FIRE, @@ -16468,7 +16470,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Speed Swap"), .description = COMPOUND_STRING( - "Swaps user's Speed\nwith " + "Swaps user's Speed with\n" "the target's."), .effect = EFFECT_SPEED_SWAP, .power = 0, @@ -16491,8 +16493,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Smart Strike"), .description = COMPOUND_STRING( - "Hits with an\naccurate " - "horn that\nnever misses."), + "Hits with an accurate\n" + "horn that never misses."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_STEEL, @@ -16513,8 +16515,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Purify"), .description = COMPOUND_STRING( - "Cures the foe's\nstatus " - "to restore\nHP."), + "Cures the foe's status\n" + "to restore HP."), .effect = EFFECT_PURIFY, .power = 0, .type = TYPE_POISON, @@ -16538,8 +16540,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Revelation Dance"), .description = COMPOUND_STRING( - "Dances with\nmystical power. " - "\nMatches user's\nfirst type."), + "Dances with mystical power.\n" + "Matches user's first type."), .effect = EFFECT_REVELATION_DANCE, .power = 90, .type = TYPE_NORMAL, @@ -16560,8 +16562,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Core Enforcer"), .description = COMPOUND_STRING( - "Hits with a ray\nthat " - "nullifies the\nfoe's Ability."), + "Hits with a ray that\n" + "nullifies the foe's Ability."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_DRAGON, @@ -16585,8 +16587,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trop Kick"), .description = COMPOUND_STRING( - "An intense kick\nfrom the " - "tropics.\nLowers Attack."), + "An intense kick from the\n" + "tropics. Lowers Attack."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_GRASS, @@ -16611,8 +16613,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Instruct"), .description = COMPOUND_STRING( - "Orders the target\nto use " - "its last\nmove again."), + "Orders the target to use\n" + "its last move again."), .effect = EFFECT_INSTRUCT, .power = 0, .type = TYPE_PSYCHIC, @@ -16637,8 +16639,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Beak Blast"), .description = COMPOUND_STRING( - "Heats beak to\nattack last. " - "Burns\nfoe on contact."), + "Heats beak to attack last.\n" + "Burns foe on contact."), .effect = EFFECT_BEAK_BLAST, .power = 100, .type = TYPE_FLYING, @@ -16666,8 +16668,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Clanging Scales"), .description = COMPOUND_STRING( - "Makes a big noise\nwith " - "its scales.\nDrops Defense."), + "Makes a big noise with\n" + "its scales. Drops Defense."), .effect = EFFECT_HIT, .power = 110, .type = TYPE_DRAGON, @@ -16693,8 +16695,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Hammer"), .description = COMPOUND_STRING( - "Swings its whole\nbody " - "like a hammer\nto damage."), + "Swings its whole body\n" + "like a hammer to damage."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_DRAGON, @@ -16715,8 +16717,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Brutal Swing"), .description = COMPOUND_STRING( - "Violently swings\naround " - "to hurt\neveryone nearby."), + "Violently swings around\n" + "to hurt everyone nearby."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_DARK, @@ -16738,16 +16740,16 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Aurora Veil"), #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_SNOW .description = COMPOUND_STRING( - "\nWeakens all\nattacks, but " - "only\nusable with snow."), + "Weakens all attacks, but\n" + "only usable with snow."), #elif B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_BOTH .description = COMPOUND_STRING( - "\nWeakens all\nattacks if " - "used in\nhail or snow."), + "Weakens all attacks if\n" + "used in hail or snow."), #else .description = COMPOUND_STRING( - "Weakens all\nattacks, but " - "only\nusable with hail."), + "Weakens all attacks, but\n" + "only usable with hail."), #endif .effect = EFFECT_AURORA_VEIL, .power = 0, @@ -16772,8 +16774,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shell Trap"), .description = COMPOUND_STRING( - "Sets a shell trap\nthat " - "damages on\ncontact."), + "Sets a shell trap that\n" + "damages on contact."), .effect = EFFECT_SHELL_TRAP, .power = 150, .type = TYPE_FIRE, @@ -16800,8 +16802,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fleur Cannon"), .description = COMPOUND_STRING( - "A strong ray that\nharshly " - "lowers Sp.\nAttack."), + "A strong ray that harshly\n" + "lowers Sp. Attack."), .effect = EFFECT_HIT, .power = 130, .type = TYPE_FAIRY, @@ -16826,8 +16828,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psychic Fangs"), .description = COMPOUND_STRING( - "Chomps with\npsychic fangs. " - "\nDestroys any\nbarriers."), + "Chomps with psychic fangs.\n" + "Destroys any barriers."), .effect = EFFECT_BRICK_BREAK, .power = 85, .type = TYPE_PSYCHIC, @@ -16849,8 +16851,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stomping Tantrum"), .description = COMPOUND_STRING( - "Stomps around\nangrily. " - "Stronger\nafter a failure."), + "Stomps around angrily.\n" + "Stronger after a failure."), .effect = EFFECT_STOMPING_TANTRUM, .power = 75, .type = TYPE_GROUND, @@ -16872,8 +16874,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shadow Bone"), .description = COMPOUND_STRING( - "Strikes with a\nhaunted " - "bone.\nMight drop\nDefense."), + "Strikes with a haunted\n" + "bone. Might drop Defense."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_GHOST, @@ -16897,8 +16899,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Accelerock"), .description = COMPOUND_STRING( - "Hits with a\nhigh-speed " - "rock\nthat always goes\nfirst."), + "Hits with a high-speed\n" + "rock that always goes first."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_ROCK, @@ -16919,8 +16921,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Liquidation"), .description = COMPOUND_STRING( - "Slams the foe with\nwater. " - "Can lower\nDefense."), + "Slams the foe with water.\n" + "Can lower Defense."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_WATER, @@ -16945,8 +16947,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Prismatic Laser"), .description = COMPOUND_STRING( - "A high power laser\nthat " - "forces\nrecharge next\nturn."), + "A high power laser that\n" + "forces recharge next turn."), .effect = EFFECT_HIT, .power = 160, .type = TYPE_PSYCHIC, @@ -16970,8 +16972,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spectral Thief"), .description = COMPOUND_STRING( - "Steals the\ntarget's stat " - "\nboosts, then\nattacks."), + "Steals the target's stat\n" + "boosts, then attacks."), .effect = EFFECT_SPECTRAL_THIEF, .power = 90, .type = TYPE_GHOST, @@ -16994,8 +16996,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sunsteel Strike"), .description = COMPOUND_STRING( - "A sun-fueled\nstrike that " - "\nignores abilities."), + "A sun-fueled strike that\n" + "ignores abilities."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_STEEL, @@ -17018,8 +17020,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Moongeist Beam"), .description = COMPOUND_STRING( - "A moon-powered\nbeam that " - "ignores\nabilities."), + "A moon-powered beam that\n" + "ignores abilities."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_GHOST, @@ -17041,8 +17043,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tearful Look"), .description = COMPOUND_STRING( - "The user tears up,\ndropping " - "Attack\nand Sp. Attack."), + "The user tears up, dropping\n" + "Attack and Sp. Attack."), .effect = EFFECT_NOBLE_ROAR, .power = 0, .type = TYPE_NORMAL, @@ -17065,8 +17067,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Zing Zap"), .description = COMPOUND_STRING( - "An electrified\nimpact that " - "can\ncause flinching."), + "An electrified impact that\n" + "can cause flinching."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_ELECTRIC, @@ -17091,8 +17093,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Nature's Madness"), .description = COMPOUND_STRING( - "Halves the foe's\nHP with " - "the power\nof nature."), + "Halves the foe's HP with\n" + "the power of nature."), .effect = EFFECT_FIXED_PERCENT_DAMAGE, .power = 1, .type = TYPE_FAIRY, @@ -17113,8 +17115,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Multi-Attack"), .description = COMPOUND_STRING( - "An attack that\nchanges " - "with\nMemories."), + "An attack that changes\n" + "with Memories."), .effect = EFFECT_CHANGE_TYPE_ON_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 120 : 90, .type = TYPE_NORMAL, @@ -17136,8 +17138,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mind Blown"), .description = COMPOUND_STRING( - "It explodes the\nuser's head " - "to\ndamage everything\naround."), + "It explodes the user's head\n" + "to damage everything around."), .effect = EFFECT_MAX_HP_50_RECOIL, .power = 150, .type = TYPE_FIRE, @@ -17159,8 +17161,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Plasma Fists"), .description = COMPOUND_STRING( - "Hits with\nelectrical fists. " - "\nNormal moves turn\nElectric."), + "Hits with electrical fists.\n" + "Normal moves turn Electric."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_ELECTRIC, @@ -17178,8 +17180,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestComboMoves = {0}, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ION_DELUGE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_PlasmaFists, }, @@ -17188,8 +17188,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Photon Geyser"), .description = COMPOUND_STRING( - "User's highest\nattack stat " - "\ndetermines its\ncategory."), + "User's highest attack stat\n" + "determines its category."), .effect = EFFECT_PHOTON_GEYSER, .power = 100, .type = TYPE_PSYCHIC, @@ -17211,8 +17211,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Zippy Zap"), .description = COMPOUND_STRING( - "Electric bursts\nalways go " - "first\nand land a\ncritical hit."), + "Electric bursts always go\n" + "first and land a critical hit."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 80 : 50, .type = TYPE_ELECTRIC, @@ -17228,8 +17228,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = #if B_UPDATED_MOVE_DATA >= GEN_8 .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_EVS_PLUS_1, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, + .self = TRUE, }), #endif .battleAnimScript = gBattleAnimMove_ZippyZap, @@ -17239,8 +17238,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Splishy Splash"), .description = COMPOUND_STRING( - "A huge electrified\nwave that " - "may\nparalyze the foes."), + "A huge electrified wave that\n" + "may paralyze the foes."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_WATER, @@ -17262,8 +17261,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Floaty Fall"), .description = COMPOUND_STRING( - "Floats in air and\ndives at " - "angle.\nMay cause\nflinching."), + "Floats in air and dives at\n" + "angle. May cause flinching."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_FLYING, @@ -17279,7 +17278,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_FloatyFall, }, @@ -17288,8 +17287,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pika Papow"), .description = COMPOUND_STRING( - "Pikachu's love\nincreases its " - "\npower. It never\nmisses."), + "Pikachu's love increases its\n" + "power. It never misses."), .effect = EFFECT_RETURN, .power = 1, .type = TYPE_ELECTRIC, @@ -17307,11 +17306,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bouncy Bubble"), .description = COMPOUND_STRING( - "An attack that\nabsorbs " + "An attack that absorbs\n" #if B_UPDATED_MOVE_DATA >= GEN_8 - "all the\ndamage inflicted."), + "all the damage inflicted."), #else - "half the\ndamage inflicted."), + "half the damage inflicted."), #endif .effect = EFFECT_ABSORB, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 60 : 90, @@ -17332,8 +17331,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Buzzy Buzz"), .description = COMPOUND_STRING( - "Shoots a jolt of\nelectricity " - "that\nalways paralyzes."), + "Shoots a jolt of electricity\n" + "that always paralyzes."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 60 : 90, .type = TYPE_ELECTRIC, @@ -17346,8 +17345,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_BuzzyBuzz, }, @@ -17356,8 +17353,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sizzly Slide"), .description = COMPOUND_STRING( - "User cloaked in\nfire charges. " - "\nLeaves the foe\nwith a burn."), + "User cloaked in fire charges.\n" + "Leaves the foe with a burn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 60 : 90, .type = TYPE_FIRE, @@ -17372,8 +17369,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SizzlySlide, }, @@ -17382,8 +17377,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Glitzy Glow"), .description = COMPOUND_STRING( - "Telekinetic force\nthat sets " - "wall,\nlowering Sp. Atk\ndamage."), + "Telekinetic force that sets\n" + "wall, lowering Sp. Atk damage."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 80 : 90, .type = TYPE_PSYCHIC, @@ -17396,8 +17391,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LIGHT_SCREEN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_GlitzyGlow, }, @@ -17406,8 +17399,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Baddy Bad"), .description = COMPOUND_STRING( - "Acting badly,\nattacks. Sets " - "\nwall, lowering\nAttack damage."), + "Acting badly, attacks. Sets\n" + "wall, lowering Attack damage."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 80 : 90, .type = TYPE_DARK, @@ -17420,8 +17413,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REFLECT, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_BaddyBad, }, @@ -17430,8 +17421,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sappy Seed"), .description = COMPOUND_STRING( - "Giant stalk\nscatters seeds " - "\nthat drain HP\nevery turn."), + "Giant stalk scatters seeds\n" + "that drain HP every turn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 90, .type = TYPE_GRASS, @@ -17445,8 +17436,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LEECH_SEED, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SappySeed, }, @@ -17455,8 +17444,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Freezy Frost"), .description = COMPOUND_STRING( - "Crystal from cold\nhaze hits. " - "\nEliminates all\nstat changes."), + "Crystal from cold haze hits.\n" + "Eliminates all stat changes."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 100 : 90, .type = TYPE_ICE, @@ -17469,8 +17458,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HAZE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_FreezyFrost, }, @@ -17479,8 +17466,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sparkly Swirl"), .description = COMPOUND_STRING( - "Wrap foe with\nwhirlwind of " - "\nscent. Heals\nparty's status."), + "Wrap foe with whirlwind of\n" + "scent. Heals party's status."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 120 : 90, .type = TYPE_FAIRY, @@ -17493,8 +17480,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AROMATHERAPY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SparklySwirl, }, @@ -17503,8 +17488,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Veevee Volley"), .description = COMPOUND_STRING( - "Eevee's love\nincreases its " - "\npower. It never\nmisses."), + "Eevee's love increases its\n" + "power. It never misses."), .effect = EFFECT_RETURN, .power = 1, .type = TYPE_NORMAL, @@ -17523,8 +17508,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Iron Bash"), .description = COMPOUND_STRING( - "The user spins and\nhits with " - "its\narms. May cause\nflinch."), + "The user spins and hits with\n" + "its arms. May cause flinch."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_STEEL, @@ -17553,8 +17538,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dynamax Cannon"), .description = COMPOUND_STRING( - "Unleashes core\nenergy. " - "2x against\nDynamaxed foes."), + "Unleashes core energy.\n" + "2x against Dynamaxed foes."), .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_DRAGON, @@ -17583,8 +17568,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Snipe Shot"), .description = COMPOUND_STRING( - "The user ignores\neffects " - "that draw\nin moves."), + "The user ignores effects\n" + "that draw in moves."), .effect = EFFECT_SNIPE_SHOT, .power = 80, .type = TYPE_WATER, @@ -17605,8 +17590,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Jaw Lock"), .description = COMPOUND_STRING( - "Prevents the user\nand " - "the target\nfrom escaping."), + "Prevents the user and\n" + "the target from escaping."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_DARK, @@ -17631,8 +17616,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stuff Cheeks"), .description = COMPOUND_STRING( - "Consumes the\nuser's Berry, " - "then\nsharply raises\nDef."), + "Consumes the user's Berry,\n" + "then sharply raises Def."), .effect = EFFECT_STUFF_CHEEKS, .power = 0, .type = TYPE_NORMAL, @@ -17655,8 +17640,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("No Retreat"), .description = COMPOUND_STRING( - "Raises all of the\nuser's " - "stats but\nprevents escape."), + "Raises all of the user's\n" + "stats but prevents escape."), .effect = EFFECT_NO_RETREAT, .power = 0, .type = TYPE_FIGHTING, @@ -17679,8 +17664,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tar Shot"), .description = COMPOUND_STRING( - "Lowers the foe's\nSpeed and " - "makes it\nweak to Fire."), + "Lowers the foe's Speed and\n" + "makes it weak to Fire."), .effect = EFFECT_TAR_SHOT, .power = 0, .type = TYPE_ROCK, @@ -17701,8 +17686,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Magic Powder"), .description = COMPOUND_STRING( - "Magic powder\nchanges the " - "target\ninto a Psychic\ntype."), + "Magic powder changes the\n" + "target into a Psychic type."), .effect = EFFECT_SOAK, .power = 0, .type = TYPE_PSYCHIC, @@ -17725,8 +17710,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Darts"), .description = COMPOUND_STRING( - "The user attacks\ntwice. Two " - "targets\nare hit once each."), + "The user attacks twice. Two\n" + "targets are hit once each."), .effect = EFFECT_DRAGON_DARTS, .power = 50, .type = TYPE_DRAGON, @@ -17748,8 +17733,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Teatime"), .description = COMPOUND_STRING( - "All Pokémon have\nteatime " - "and eat\ntheir Berries."), + "All Pokémon have teatime\n" + "and eat their Berries."), .effect = EFFECT_TEATIME, .power = 0, .type = TYPE_NORMAL, @@ -17772,8 +17757,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Octolock"), .description = COMPOUND_STRING( - "Traps the foe to\nlower Def " - "and Sp.\nDef each turn."), + "Traps the foe to lower Def\n" + "and Sp. Def each turn."), .effect = EFFECT_OCTOLOCK, .power = 0, .type = TYPE_FIGHTING, @@ -17793,8 +17778,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bolt Beak"), .description = COMPOUND_STRING( - "Double power if\nthe user " - "moves\nbefore the target."), + "Double power if the user\n" + "moves before the target."), .effect = EFFECT_BOLT_BEAK, .power = 85, .type = TYPE_ELECTRIC, @@ -17815,8 +17800,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fishious Rend"), .description = COMPOUND_STRING( - "Double power if\nthe user " - "moves\nbefore the target."), + "Double power if the user\n" + "moves before the target."), .effect = EFFECT_BOLT_BEAK, .power = 85, .type = TYPE_WATER, @@ -17838,8 +17823,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Court Change"), .description = COMPOUND_STRING( - "The user swaps\neffects on " - "either\nside of the field."), + "The user swaps effects on\n" + "either side of the field."), .effect = EFFECT_COURT_CHANGE, .power = 0, .type = TYPE_NORMAL, @@ -17860,8 +17845,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Clangorous Soul"), .description = COMPOUND_STRING( - "The user uses some\nof its " - "HP to raise\nall its stats."), + "The user uses some of its\n" + "HP to raise all its stats."), .effect = EFFECT_CLANGOROUS_SOUL, .power = 0, .type = TYPE_DRAGON, @@ -17887,8 +17872,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Body Press"), .description = COMPOUND_STRING( - "Does more damage\nthe " - "higher the\nuser's Def."), + "Does more damage the\n" + "higher the user's Def."), .effect = EFFECT_BODY_PRESS, .power = 80, .type = TYPE_FIGHTING, @@ -17911,8 +17896,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Decorate"), .description = COMPOUND_STRING( - "The user sharply\nraises " - "the\ntarget's Atk and\nSp.Atk."), + "The user sharply raises\n" + "the target's Atk and Sp.Atk."), .effect = EFFECT_DECORATE, .power = 0, .type = TYPE_FAIRY, @@ -17935,8 +17920,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Drum Beating"), .description = COMPOUND_STRING( - "Plays a drum to\nattack. " - "The foe's\nSpeed is lowered."), + "Plays a drum to attack.\n" + "The foe's Speed is lowered."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GRASS, @@ -17961,8 +17946,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Snap Trap"), .description = COMPOUND_STRING( - "Snares the target\nin a snap " - "trap for\nfour to five\nturns."), + "Snares the target in a snap\n" + "trap for four to five turns."), .effect = EFFECT_HIT, .power = 35, .type = TYPE_GRASS, @@ -17976,6 +17961,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_SNAP_TRAP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -17988,8 +17974,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pyro Ball"), .description = COMPOUND_STRING( - "Launches a fiery\nball at the " - "\ntarget. It may\ncause a burn."), + "Launches a fiery ball at the\n" + "target. It may cause a burn."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_FIRE, @@ -18016,8 +18002,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Behemoth Blade"), .description = COMPOUND_STRING( - "Strikes as a\nsword. Deals 2x " - "\ndamage to\nDynamaxed foes."), + "Strikes as a sword. Deals 2x\n" + "damage to Dynamaxed foes."), .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_STEEL, @@ -18043,8 +18029,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Behemoth Bash"), .description = COMPOUND_STRING( - "Attacks as a\nshield. Deals 2x " - "\ndamage to\nDynamaxed foes."), + "Attacks as a shield. Deals 2x\n" + "damage to Dynamaxed foes."), .effect = EFFECT_DYNAMAX_DOUBLE_DMG, .power = 100, .type = TYPE_STEEL, @@ -18069,8 +18055,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aura Wheel"), .description = COMPOUND_STRING( - "Raises Speed to\nattack. The " - "Type\nis based on its\nform."), + "Raises Speed to attack. The\n" + "Type is based on its form."), .effect = EFFECT_AURA_WHEEL, .power = 110, .type = TYPE_ELECTRIC, @@ -18096,8 +18082,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Breaking Swipe"), .description = COMPOUND_STRING( - "Swings its tail to\nattack. " - "Lowers the\nAtk of those hit."), + "Swings its tail to attack.\n" + "Lowers the Atk of those hit."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_DRAGON, @@ -18123,8 +18109,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Branch Poke"), .description = COMPOUND_STRING( - "The user pokes the\ntarget " - "with a\npointed branch."), + "The user pokes the target\n" + "with a pointed branch."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_GRASS, @@ -18146,8 +18132,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Overdrive"), .description = COMPOUND_STRING( - "The user twangs\nits guitar, " - "\ncausing strong\nvibrations."), + "The user twangs its guitar,\n" + "causing strong vibrations."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_ELECTRIC, @@ -18170,8 +18156,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Apple Acid"), .description = COMPOUND_STRING( - "Attacks with tart\napple acid " - "to\nlower the foe's\nSp. Def."), + "Attacks with tart apple acid\n" + "to lower the foe's Sp. Def."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_GRASS, @@ -18196,8 +18182,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grav Apple"), .description = COMPOUND_STRING( - "Drops an apple\nfrom above. " - "Lowers\nthe foe's Defense."), + "Drops an apple from above.\n" + "Lowers the foe's Defense."), .effect = EFFECT_GRAV_APPLE, .power = 80, .type = TYPE_GRASS, @@ -18222,8 +18208,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spirit Break"), .description = COMPOUND_STRING( - "Attacks with\nspirit-breaking " - "\nforce. Lowers Sp.\nAtk."), + "Attacks with spirit-breaking\n" + "force. Lowers Sp. Atk."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_FAIRY, @@ -18249,8 +18235,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Strange Steam"), .description = COMPOUND_STRING( - "Emits a strange\nsteam to " - "\npotentially\nconfuse the foe."), + "Emits a strange steam to\n" + "potentially confuse the foe."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_FAIRY, @@ -18275,14 +18261,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Life Dew"), .description = COMPOUND_STRING( - "Scatters water to\nrestore " - "the HP of\nitself and allies."), - .effect = EFFECT_JUNGLE_HEALING, + "Scatters water to restore\n" + "the HP of itself and allies."), + .effect = EFFECT_LIFE_DEW, .power = 0, .type = TYPE_WATER, .accuracy = 0, .pp = 10, - .target = MOVE_TARGET_ALL_BATTLERS, + .target = MOVE_TARGET_USER, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .snatchAffected = TRUE, @@ -18302,8 +18288,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Obstruct"), .description = COMPOUND_STRING( - "Protects itself,\nharshly " - "lowering\nDef on contact."), + "Protects itself, harshly\n" + "lowering Def on contact."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_DARK, @@ -18328,8 +18314,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("False Surrender"), .description = COMPOUND_STRING( - "Bows to stab the\nfoe " - "with hair. It\nnever misses."), + "Bows to stab the foe\n" + "with hair. It never misses."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_DARK, @@ -18351,8 +18337,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Meteor Assault"), .description = COMPOUND_STRING( - "Attacks with a\nthick leek. " - "The\nuser must then\nrest."), + "Attacks with a thick leek.\n" + "The user must then rest."), .effect = EFFECT_HIT, .power = 150, .type = TYPE_FIGHTING, @@ -18378,8 +18364,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Eternabeam"), .description = COMPOUND_STRING( - "Eternatus'\nstrongest move. " - "\nThe user rests\nnext turn."), + "Eternatus' strongest move.\n" + "The user rests next turn."), .effect = EFFECT_HIT, .power = 160, .type = TYPE_DRAGON, @@ -18404,8 +18390,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Steel Beam"), .description = COMPOUND_STRING( - "Fires a beam of\nsteel from " - "its\nbody. It hurts the\nuser."), + "Fires a beam of steel from\n" + "its body. It hurts the user."), .effect = EFFECT_MAX_HP_50_RECOIL, .power = 140, .type = TYPE_STEEL, @@ -18426,8 +18412,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Expanding Force"), .description = COMPOUND_STRING( - "Power goes up and\ndamages " - "all foes\non Psychic\nTerrain."), + "Power goes up and damages\n" + "all foes on Psychic Terrain."), .effect = EFFECT_EXPANDING_FORCE, .power = 80, .type = TYPE_PSYCHIC, @@ -18447,9 +18433,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Steel Roller"), .description = COMPOUND_STRING( - "Destroys terrain.\nFails if " - "ground\nisn't terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + "Destroys terrain. Fails if\n" + "ground isn't terrain."), + .effect = EFFECT_STEEL_ROLLER, .power = 130, .type = TYPE_STEEL, .accuracy = 100, @@ -18458,7 +18444,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_FAIL }, // Remove a field terrain if there is one and hit, otherwise fail. .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -18471,8 +18456,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Scale Shot"), .description = COMPOUND_STRING( - "Shoots scales 2 to\n5 times. " - "Ups\nSpeed, lowers\ndefense."), + "Shoots scales 2 to 5 times.\n" + "Ups Speed, lowers defense."), .effect = EFFECT_MULTI_HIT, .power = 25, .type = TYPE_DRAGON, @@ -18493,8 +18478,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Meteor Beam"), .description = COMPOUND_STRING( - "A 2-turn move that\nraises " - "Sp. Attack\nbefore attacking."), + "A 2-turn move that raises\n" + "Sp. Attack before attacking."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 120, .type = TYPE_ROCK, @@ -18521,8 +18506,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shell Side Arm"), .description = COMPOUND_STRING( - "Deals better of\nphysical and " - "\nspecial damage.\nMay poison."), + "Deals better of physical and\n" + "special damage. May poison."), .effect = EFFECT_SHELL_SIDE_ARM, .power = 90, .type = TYPE_POISON, @@ -18546,8 +18531,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Misty Explosion"), .description = COMPOUND_STRING( - "Hit everything and\nfaint. " - "Powers up\non Misty Terrain."), + "Hit everything and faint.\n" + "Powers up on Misty Terrain."), .effect = EFFECT_MISTY_EXPLOSION, .power = 100, .type = TYPE_FAIRY, @@ -18568,8 +18553,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Grassy Glide"), .description = COMPOUND_STRING( - "Gliding on ground,\nhits. Goes " - "first\non Grassy Terrain."), + "Gliding on ground, hits. Goes\n" + "first on Grassy Terrain."), .effect = EFFECT_GRASSY_GLIDE, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 55 : 70, .type = TYPE_GRASS, @@ -18591,8 +18576,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rising Voltage"), .description = COMPOUND_STRING( - "This move's power\ndoubles " - "when on\nElectric Terrain."), + "This move's power doubles\n" + "when on Electric Terrain."), .effect = EFFECT_RISING_VOLTAGE, .power = 70, .type = TYPE_ELECTRIC, @@ -18612,8 +18597,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Terrain Pulse"), .description = COMPOUND_STRING( - "Type and power\nchanges " - "depending\non the terrain."), + "Type and power changes\n" + "depending on the terrain."), .effect = EFFECT_TERRAIN_PULSE, .power = 50, .type = TYPE_NORMAL, @@ -18634,8 +18619,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Skitter Smack"), .description = COMPOUND_STRING( - "User skitters\nbehind foe to " - "\nattack. Lowers\nfoe's Sp. Atk."), + "User skitters behind foe to\n" + "attack. Lowers foe's Sp. Atk."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_BUG, @@ -18660,8 +18645,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Burning Jealousy"), .description = COMPOUND_STRING( - "Foes that have\nstats upped " - "during\nthe turn get\nburned."), + "Foes that have stats upped\n" + "during the turn get burned."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_FIRE, @@ -18686,8 +18671,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lash Out"), .description = COMPOUND_STRING( - "If stats lowered\nduring this " - "turn,\npower is doubled."), + "If stats lowered during this\n" + "turn, power is doubled."), .effect = EFFECT_LASH_OUT, .power = 75, .type = TYPE_DARK, @@ -18708,8 +18693,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Poltergeist"), .description = COMPOUND_STRING( - "Control foe's item\nto attack. " - "Fails\nif foe has no\nitem."), + "Control foe's item to attack.\n" + "Fails if foe has no item."), .effect = EFFECT_POLTERGEIST, .power = 110, .type = TYPE_GHOST, @@ -18729,8 +18714,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Corrosive Gas"), .description = COMPOUND_STRING( - "Highly acidic gas\nmelts items " - "held\nby surrounding\nPokémon."), + "Highly acidic gas melts items\n" + "held by surrounding Pokémon."), .effect = EFFECT_CORROSIVE_GAS, .power = 0, .type = TYPE_POISON, @@ -18751,8 +18736,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Coaching"), .description = COMPOUND_STRING( - "Properly coaches\nallies to " - "up their\nAttack and\nDefense."), + "Properly coaches allies to\n" + "up their Attack and Defense."), .effect = EFFECT_COACHING, .power = 0, .type = TYPE_FIGHTING, @@ -18775,8 +18760,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flip Turn"), .description = COMPOUND_STRING( - "Attacks and rushes\nback to " - "switch\nwith a party\nPokémon."), + "Attacks and rushes back to\n" + "switch with a party Pokémon."), .effect = EFFECT_HIT_ESCAPE, .power = 60, .type = TYPE_WATER, @@ -18797,8 +18782,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Triple Axel"), .description = COMPOUND_STRING( - "A 3-kick attack\nthat gets " - "more\npowerful with each\nhit."), + "A 3-kick attack that gets\n" + "more powerful with each hit."), .effect = EFFECT_TRIPLE_KICK, .power = 20, .type = TYPE_ICE, @@ -18820,8 +18805,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dual Wingbeat"), .description = COMPOUND_STRING( - "User slams the\ntarget with " - "wings\nand hits twice in\na row."), + "User slams the target with\n" + "wings and hits twice in a row."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_FLYING, @@ -18843,8 +18828,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Scorching Sands"), .description = COMPOUND_STRING( - "Throws scorching\nsand at " - "the\ntarget. May leave\na burn."), + "Throws scorching sand at\n" + "the target. May leave a burn."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_GROUND, @@ -18869,8 +18854,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Jungle Healing"), .description = COMPOUND_STRING( - "Heals HP and\nstatus of " - "itself\nand allies in\nbattle."), + "Heals HP and status of\n" + "itself and allies in battle."), .effect = EFFECT_JUNGLE_HEALING, .power = 0, .type = TYPE_GRASS, @@ -18895,8 +18880,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wicked Blow"), .description = COMPOUND_STRING( - "Mastering the Dark\nstyle, " - "strikes\nwith a critical\nhit."), + "Mastering the Dark style,\n" + "strikes with a critical hit."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 75 : 80, .type = TYPE_DARK, @@ -18920,8 +18905,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Surging Strikes"), .description = COMPOUND_STRING( - "Mastering the\nWater style, " - "\nstrikes with 3\ncritical hits."), + "Mastering the Water style,\n" + "strikes with 3 critical hits."), .effect = EFFECT_HIT, .power = 25, .type = TYPE_WATER, @@ -18946,8 +18931,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunder Cage"), .description = COMPOUND_STRING( - "Traps the foe in a\ncage of " - "\nelectricity for\n"BINDING_TURNS" turns."), + "Traps the foe in a cage of\n" + "electricity for "BINDING_TURNS" turns."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_ELECTRIC, @@ -18959,6 +18944,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_THUNDER_CAGE, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_COOL, @@ -18971,8 +18957,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Energy"), .description = COMPOUND_STRING( - "The higher the\nuser's HP " - "the more\ndamage caused."), + "The higher the user's HP\n" + "the more damage caused."), .effect = EFFECT_POWER_BASED_ON_USER_HP, .power = 150, .type = TYPE_DRAGON, @@ -18993,11 +18979,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Freezing Glare"), .description = COMPOUND_STRING( - "Shoots psychic\npower from " + "Shoots psychic power from\n" #if B_USE_FROSTBITE == TRUE - "the\neyes. May\nfrostbite."), + "the eyes. May frostbite."), #else - "the\neyes. May freeze\nthe foe."), + "the eyes. May freeze the foe."), #endif .power = 90, .effect = EFFECT_HIT, @@ -19023,8 +19009,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fiery Wrath"), .description = COMPOUND_STRING( - "An attack fueled\nby your " - "wrath. May\ncause flinching."), + "An attack fueled by your\n" + "wrath. May cause flinching."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_DARK, @@ -19049,8 +19035,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Thunderous Kick"), .description = COMPOUND_STRING( - "Uses a\nlightning-like\nkick " - "to hit.\nLowers foe's\nDefense."), + "Uses a lightning-like kick\n" + "to hit. Lowers foe's Defense."), .effect = EFFECT_HIT, .power = 90, .type = TYPE_FIGHTING, @@ -19076,8 +19062,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Glacial Lance"), .description = COMPOUND_STRING( - "Hurls a\nblizzard-cloaked " - "\nicicle lance at\nfoes."), + "Hurls a blizzard-cloaked\n" + "icicle lance at foes."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 120 : 130, .type = TYPE_ICE, @@ -19098,8 +19084,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Astral Barrage"), .description = COMPOUND_STRING( - "Sends a frightful\namount " - "of small\nghosts at foes."), + "Sends a frightful amount\n" + "of small ghosts at foes."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_GHOST, @@ -19120,8 +19106,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Eerie Spell"), .description = COMPOUND_STRING( - "Attacks with\npsychic power. " - "\nFoe's last move\nhas 3 PP cut."), + "Attacks with psychic power.\n" + "Foe's last move has 3 PP cut."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_PSYCHIC, @@ -19147,8 +19133,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dire Claw"), .description = COMPOUND_STRING( - "High critical hit\nchance. May " - "\nparalyze, poison\nor drowse."), + "High critical hit chance. May\n" + "paralyze, poison or drowse."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 80 : 60, .type = TYPE_POISON, @@ -19169,8 +19155,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psyshield Bash"), .description = COMPOUND_STRING( - "Hits a foe with\npsychic " - "energy.\nMay raise Defense."), + "Hits a foe with psychic\n" + "energy. May raise Defense."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_PSYCHIC, @@ -19192,8 +19178,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Power Shift"), .description = COMPOUND_STRING( - "The user swaps its\nAttack " - "and Defense\nstats."), + "The user swaps its Attack\n" + "and Defense stats."), .effect = EFFECT_POWER_TRICK, .power = 0, .type = TYPE_NORMAL, @@ -19213,9 +19199,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stone Axe"), .description = COMPOUND_STRING( - "High critical hit\nratio. Sets " - "\nSplinters that\nhurt the foe."), - .effect = EFFECT_HIT, + "High critical hit ratio. Sets\n" + "Splinters that hurt the foe."), + .effect = EFFECT_STONE_AXE, .power = 65, .type = TYPE_ROCK, .accuracy = 90, @@ -19226,8 +19212,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEALTH_ROCK, - .chance = 100, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_StoneAxe, }, @@ -19236,8 +19221,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Springtide Storm"), .description = COMPOUND_STRING( - "Wraps a foe in\nfierce winds. " - "\nVaries with the\nuser's form."), + "Wraps a foe in fierce winds.\n" + "Varies with the user's form."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 100 : 95, .type = TYPE_FAIRY, @@ -19259,8 +19244,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mystical Power"), .description = COMPOUND_STRING( - "A mysterious power\nstrikes, " - "raising\nthe user's Sp.\nAtk."), + "A mysterious power strikes,\n" + "raising the user's Sp. Atk."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_PSYCHIC, @@ -19281,8 +19266,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Raging Fury"), .description = COMPOUND_STRING( - "A rampage of 2 to\n3 turns " - "that\nconfuses the user."), + "A rampage of 2 to 3 turns\n" + "that confuses the user."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 120 : 90, .type = TYPE_FIRE, @@ -19303,8 +19288,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wave Crash"), .description = COMPOUND_STRING( - "A slam shrouded in\nwater. " - "It also\nhurts the user."), + "A slam shrouded in water.\n" + "It also hurts the user."), .effect = EFFECT_RECOIL, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 120 : 75, .type = TYPE_WATER, @@ -19323,8 +19308,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Chloroblast"), .description = COMPOUND_STRING( - "A user-hurting\nblast of " - "amassed\nchlorophyll."), + "A user-hurting blast of\n" + "amassed chlorophyll."), .effect = EFFECT_CHLOROBLAST, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 150 : 120, .type = TYPE_GRASS, @@ -19340,8 +19325,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mountain Gale"), .description = COMPOUND_STRING( - "Giant chunks of\nice damage " - "the\nfoe. It may\nflinch."), + "Giant chunks of ice damage\n" + "the foe. It may flinch."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_ICE, @@ -19361,8 +19346,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Victory Dance"), .description = COMPOUND_STRING( - "Dances to raise\nAttack, " - "Defense\nand Speed."), + "Dances to raise Attack,\n" + "Defense and Speed."), .effect = EFFECT_VICTORY_DANCE, .power = 0, .type = TYPE_FIGHTING, @@ -19382,8 +19367,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Headlong Rush"), .description = COMPOUND_STRING( - "Hits with a\nfull-body tackle. " - "\nLowers the users's\ndefenses."), + "Hits with a full-body tackle.\n" + "Lowers the users's defenses."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 120 : 100, .type = TYPE_GROUND, @@ -19405,8 +19390,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Barb Barrage"), .description = COMPOUND_STRING( - "Can poison on\nimpact. Powers " - "up\nagainst poisoned\nfoes."), + "Can poison on impact. Powers\n" + "up against poisoned foes."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = 60, .type = TYPE_POISON, @@ -19427,8 +19412,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Esper Wing"), .description = COMPOUND_STRING( - "High critical hit\nratio. " - "Ups the\nuser's Speed."), + "High critical hit ratio.\n" + "Ups the user's Speed."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 80 : 75, .type = TYPE_PSYCHIC, @@ -19450,8 +19435,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bitter Malice"), .description = COMPOUND_STRING( - "A spine-chilling\nresentment. " - "Lowers\nthe foe's Attack."), + "A spine-chilling resentment.\n" + "Lowers the foe's Attack."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 75 : 60, .type = TYPE_GHOST, @@ -19471,8 +19456,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shelter"), .description = COMPOUND_STRING( - "The user hardens\ntheir skin, " - "\nsharply raising\nits Defense."), + "The user hardens their skin,\n" + "sharply raising its Defense."), .effect = EFFECT_DEFENSE_UP_2, .power = 0, .type = TYPE_STEEL, @@ -19491,8 +19476,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Triple Arrows"), .description = COMPOUND_STRING( - "High critical hit\nratio. " - "May lower\nDefense or flinch."), + "High critical hit ratio.\n" + "May lower Defense or flinch."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 90 : 50, .type = TYPE_FIGHTING, @@ -19517,8 +19502,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Infernal Parade"), .description = COMPOUND_STRING( - "Hurts a foe harder\nif it has " - "an\nailment. May leave\na burn."), + "Hurts a foe harder if it has\n" + "an ailment. May leave a burn."), .effect = EFFECT_DOUBLE_POWER_ON_ARG_STATUS, .power = 60, .type = TYPE_GHOST, @@ -19539,9 +19524,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ceaseless Edge"), .description = COMPOUND_STRING( - "High critical hit\nratio. Sets " - "\nSplinters that\nhurt the foe."), - .effect = EFFECT_HIT, + "High critical hit ratio. Sets\n" + "Splinters that hurt the foe."), + .effect = EFFECT_CEASELESS_EDGE, .power = 65, .type = TYPE_DARK, .accuracy = 90, @@ -19552,8 +19537,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_SPIKES, - .chance = 100, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_CeaselessEdge, }, @@ -19562,8 +19546,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bleakwind Storm"), .description = COMPOUND_STRING( - "Hits with brutal,\ncold winds. " - "May\nlower the foe's\nSpeed."), + "Hits with brutal, cold winds.\n" + "May lower the foe's Speed."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 100 : 95, .type = TYPE_FLYING, @@ -19585,8 +19569,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Wildbolt Storm"), .description = COMPOUND_STRING( - "Hits with a brutal\ntempest. " - "May\ninflict paralysis."), + "Hits with a brutal tempest.\n" + "May inflict paralysis."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 100 : 95, .type = TYPE_ELECTRIC, @@ -19608,8 +19592,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Sandsear Storm"), .description = COMPOUND_STRING( - "Hits with brutally\nhot sand. " - "May\ninflict a burn."), + "Hits with brutally hot sand.\n" + "May inflict a burn."), .effect = EFFECT_HIT, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 100 : 95, .type = TYPE_GROUND, @@ -19631,8 +19615,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lunar Blessing"), .description = COMPOUND_STRING( - "The user heals and\ncures " - "itself and\nits ally."), + "The user heals and cures\n" + "itself and its ally."), .effect = EFFECT_JUNGLE_HEALING, .power = 0, .type = TYPE_PSYCHIC, @@ -19652,8 +19636,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Take Heart"), .description = COMPOUND_STRING( - "The user lifts its\nspirits to " - "heal\nand strengthen\nitself."), + "The user lifts its spirits to\n" + "heal and strengthen itself."), .effect = EFFECT_TAKE_HEART, .power = 0, .type = TYPE_PSYCHIC, @@ -19672,8 +19656,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tera Blast"), .description = COMPOUND_STRING( - "If the user's\nTerastallized, " - "it\nhits with its Tera\ntype."), + "If the user's Terastallized,\n" + "it hits with its Tera type."), .effect = EFFECT_TERA_BLAST, .power = 80, .type = TYPE_NORMAL, @@ -19694,8 +19678,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Silk Trap"), .description = COMPOUND_STRING( - "Protects itself,\nlowering " - "Speed on\ncontact."), + "Protects itself, lowering\n" + "Speed on contact."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_BUG, @@ -19715,8 +19699,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Axe Kick"), .description = COMPOUND_STRING( - "May miss and hurt\nthe kicker. " - "May\ncause confusion."), + "May miss and hurt the kicker.\n" + "May cause confusion."), .effect = EFFECT_RECOIL_IF_MISS, .power = 120, .type = TYPE_FIGHTING, @@ -19737,8 +19721,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Last Respects"), .description = COMPOUND_STRING( - "This move deals\nmore damage " - "for\neach defeated\nally."), + "This move deals more damage\n" + "for each defeated ally."), .effect = EFFECT_LAST_RESPECTS, .power = 50, .type = TYPE_GHOST, @@ -19755,8 +19739,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Lumina Crash"), .description = COMPOUND_STRING( - "A mind-affecting\nlight " - "harshly\nlowers Sp. Def."), + "A mind-affecting light\n" + "harshly lowers Sp. Def."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_PSYCHIC, @@ -19776,8 +19760,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Order Up"), .description = COMPOUND_STRING( - "Boosts a user's\nstats " - "depending on\nTatsugiri."), + "Boosts a user's stats\n" + "depending on Tatsugiri."), .effect = EFFECT_ORDER_UP, .power = 80, .type = TYPE_DRAGON, @@ -19800,8 +19784,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Jet Punch"), .description = COMPOUND_STRING( - "A punch is thrown\nat blinding " - "speed\nto strike first."), + "A punch is thrown at blinding\n" + "speed to strike first."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_WATER, @@ -19820,8 +19804,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spicy Extract"), .description = COMPOUND_STRING( - "Sharply ups\ntarget's Attack, " - "\nharshly lowers its\nDefense."), + "Sharply ups target's Attack,\n" + "harshly lowers its Defense."), .effect = EFFECT_SPICY_EXTRACT, .power = 0, .type = TYPE_GRASS, @@ -19839,8 +19823,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Spin Out"), .description = COMPOUND_STRING( - "Furiously strains\nits legs. " - "Harshly\nlowers user's\nSpeed."), + "Furiously strains its legs.\n" + "Harshly lowers user's Speed."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_STEEL, @@ -19862,8 +19846,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Population Bomb"), .description = COMPOUND_STRING( - "The user's fellows\nhit one " - "to ten\ntimes in a row."), + "The user's fellows hit one\n" + "to ten times in a row."), .effect = EFFECT_POPULATION_BOMB, .power = 20, .type = TYPE_NORMAL, @@ -19883,9 +19867,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ice Spinner"), .description = COMPOUND_STRING( - "Ice-covered feet\nhit a foe " - "and\ndestroy the\nterrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + "Ice-covered feet hit a foe\n" + "and destroy the terrain."), + .effect = EFFECT_ICE_SPINNER, .power = 80, .type = TYPE_ICE, .accuracy = 100, @@ -19894,7 +19878,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .battleAnimScript = gBattleAnimMove_IceSpinner, }, @@ -19903,8 +19886,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Glaive Rush"), .description = COMPOUND_STRING( - "Foe attacks next\nturn can't " - "miss\nand do double\ndamage."), + "Foe attacks next turn can't\n" + "miss and do double damage."), .effect = EFFECT_GLAIVE_RUSH, .power = 120, .type = TYPE_DRAGON, @@ -19921,8 +19904,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Revival Blessing"), .description = COMPOUND_STRING( - "Revives a fainted\nparty {PKMN} " - "and\nrestores half of\nits HP."), + "Revives a fainted party {PKMN}\n" + "and restores half of its HP."), .effect = EFFECT_REVIVAL_BLESSING, .power = 0, .type = TYPE_NORMAL, @@ -19943,8 +19926,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Salt Cure"), .description = COMPOUND_STRING( - "Hurts foe every\nturn. Double " - "\ndamage to Steel\nand Water."), + "Hurts foe every turn. Double\n" + "damage to Steel and Water."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_ROCK, @@ -19965,8 +19948,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Triple Dive"), .description = COMPOUND_STRING( - "Hits target with\nsplashes " - "of water\n3 times in a row."), + "Hits target with splashes\n" + "of water 3 times in a row."), .effect = EFFECT_HIT, .power = 30, .type = TYPE_WATER, @@ -19984,8 +19967,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Mortal Spin"), .description = COMPOUND_STRING( - "Erases trap moves\nand Leech " - "Seed.\nPoisons adjacent\nfoes."), + "Erases trap moves and Leech\n" + "Seed. Poisons adjacent foes."), .effect = EFFECT_RAPID_SPIN, .power = 30, .type = TYPE_POISON, @@ -20007,8 +19990,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Doodle"), .description = COMPOUND_STRING( - "Changes user's and\nally's " - "Ability\ninto the target's."), + "Changes user's and ally's\n" + "Ability into the target's."), .effect = EFFECT_DOODLE, .power = 0, .type = TYPE_NORMAL, @@ -20027,8 +20010,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fillet Away"), .description = COMPOUND_STRING( - "Sharply boosts\noffenses and " - "Speed\nby using its own\nHP."), + "Sharply boosts offenses and\n" + "Speed by using its own HP."), .effect = EFFECT_FILLET_AWAY, .power = 0, .type = TYPE_NORMAL, @@ -20049,8 +20032,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Kowtow Cleave"), .description = COMPOUND_STRING( - "User slashes the\nfoe after " - "\nkowtowing. It\nnever misses."), + "User slashes the foe after\n" + "kowtowing. It never misses."), .effect = EFFECT_HIT, .power = 85, .type = TYPE_DARK, @@ -20068,8 +20051,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Flower Trick"), .description = COMPOUND_STRING( - "Rigged bouquet.\nAlways gets " - "a\ncritical hit,\nnever missing."), + "Rigged bouquet. Always gets\n" + "a critical hit, never missing."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_GRASS, @@ -20086,8 +20069,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Torch Song"), .description = COMPOUND_STRING( - "Flames scorch the\ntarget. " - "Boosts the\nuser's Sp. Atk."), + "Flames scorch the target.\n" + "Boosts the user's Sp. Atk."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FIRE, @@ -20110,8 +20093,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aqua Step"), .description = COMPOUND_STRING( - "Hits with light,\nfluid dance " - "steps.\nUps the user's\nSpeed."), + "Hits with light, fluid dance\n" + "steps. Ups the user's Speed."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_WATER, @@ -20134,8 +20117,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Raging Bull"), .description = COMPOUND_STRING( - "Tackle that breaks\nbarriers. " - "User's\nform determines\ntype."), + "Tackle that breaks barriers.\n" + "User's form determines type."), .effect = EFFECT_RAGING_BULL, .power = 90, .type = TYPE_NORMAL, @@ -20153,8 +20136,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Make It Rain"), .description = COMPOUND_STRING( - "Lowers the user's\nSp. Atk. " - "Money is\nrecovered after."), + "Lowers the user's Sp. Atk.\n" + "Money is recovered after."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_STEEL, @@ -20178,8 +20161,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ruination"), .description = COMPOUND_STRING( - "Summons a ruinous\ndisaster " - "and cuts\nhalf the foe's HP."), + "Summons a ruinous disaster\n" + "and cuts half the foe's HP."), .effect = EFFECT_FIXED_PERCENT_DAMAGE, .power = 1, .type = TYPE_DARK, @@ -20196,8 +20179,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Collision Course"), .description = COMPOUND_STRING( - "Prehistoric\nexplosion that's " - "\nstronger if super\neffective."), + "Prehistoric explosion that's\n" + "stronger if super effective."), .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_FIGHTING, @@ -20215,8 +20198,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electro Drift"), .description = COMPOUND_STRING( - "Futuristic\nelectricity. It's " - "\nstronger if super\neffective."), + "Futuristic electricity. It's\n" + "stronger if super effective."), .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_ELECTRIC, @@ -20234,8 +20217,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shed Tail"), .description = COMPOUND_STRING( - "Creates a\nSubstitute for " - "\nitself before\nswitching out."), + "Creates a Substitute for\n" + "itself before switching out."), .effect = EFFECT_SHED_TAIL, .power = 0, .type = TYPE_NORMAL, @@ -20256,12 +20239,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Chilly Reception"), #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_HAIL .description = COMPOUND_STRING( - "Bad\njoke summons\nhailstorm. " - "The\nuser also switches\nout."), + "Bad joke summons hailstorm.\n" + "The user also switches out."), #else .description = COMPOUND_STRING( - "Bad joke summons\nsnowstorm. " - "The\nuser also switches\nout."), + "Bad joke summons snowstorm.\n" + "The user also switches out."), #endif .effect = EFFECT_CHILLY_RECEPTION, .power = 0, @@ -20282,8 +20265,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tidy Up"), .description = COMPOUND_STRING( - "User tidies up\nhazards and " - "raises\nits Attack and\nSpeed."), + "User tidies up hazards and\n" + "raises its Attack and Speed."), .effect = EFFECT_TIDY_UP, .power = 0, .type = TYPE_NORMAL, @@ -20303,13 +20286,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .name = COMPOUND_STRING("Snowscape"), #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_HAIL .description = COMPOUND_STRING( - "Summons a\nhailstorm that " - "\nstrikes every turn."), + "Summons a hailstorm that\n" + "strikes every turn."), .effect = EFFECT_HAIL, #else .description = COMPOUND_STRING( - "Summons a\nsnowstorm that " - "\nlasts for five\nturns."), + "Summons a snowstorm that\n" + "lasts for five turns."), .effect = EFFECT_SNOWSCAPE, #endif .power = 0, @@ -20330,8 +20313,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pounce"), .description = COMPOUND_STRING( - "The user pounces\non the foe, " - "\nlowering its Speed."), + "The user pounces on the foe,\n" + "lowering its Speed."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_BUG, @@ -20353,8 +20336,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Trailblaze"), .description = COMPOUND_STRING( - "The user attacks\nsuddenly, " - "raising\nits Speed."), + "The user attacks suddenly,\n" + "raising its Speed."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_GRASS, @@ -20377,8 +20360,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Chilling Water"), .description = COMPOUND_STRING( - "A shower with\nice-cold water " - "\nlowers the\ntarget's Attack."), + "A shower with ice-cold water\n" + "lowers the target's Attack."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_WATER, @@ -20399,8 +20382,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hyper Drill"), .description = COMPOUND_STRING( - "A spinning pointed\npart " - "bypasses a\nfoe's Protect."), + "A spinning pointed part\n" + "bypasses a foe's Protect."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_NORMAL, @@ -20419,8 +20402,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Twin Beam"), .description = COMPOUND_STRING( - "Mystical eye-beams\nthat hit " - "the\ntarget twice in a\nrow."), + "Mystical eye-beams that hit\n" + "the target twice in a row."), .effect = EFFECT_HIT, .power = 40, .type = TYPE_PSYCHIC, @@ -20438,8 +20421,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rage Fist"), .description = COMPOUND_STRING( - "The more the user\nhas been " - "hit, the\nstronger the move."), + "The more the user has been\n" + "hit, the stronger the move."), .effect = EFFECT_RAGE_FIST, .power = 50, .type = TYPE_GHOST, @@ -20458,8 +20441,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Armor Cannon"), .description = COMPOUND_STRING( - "A strong attack\nbut lowers " - "the\ndefensive stats."), + "A strong attack but lowers\n" + "the defensive stats."), .effect = EFFECT_HIT, .power = 120, .type = TYPE_FIRE, @@ -20480,8 +20463,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bitter Blade"), .description = COMPOUND_STRING( - "An attack that\nabsorbs " - "half the\ndamage inflicted."), + "An attack that absorbs\n" + "half the damage inflicted."), .effect = EFFECT_ABSORB, .power = 90, .type = TYPE_FIRE, @@ -20501,8 +20484,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Double Shock"), .description = COMPOUND_STRING( - "Discharges all\nelectricity, " - "\nlosing the\nElectric type."), + "Discharges all electricity,\n" + "losing the Electric type."), .effect = EFFECT_FAIL_IF_NOT_ARG_TYPE, .power = 120, .type = TYPE_ELECTRIC, @@ -20525,8 +20508,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gigaton Hammer"), .description = COMPOUND_STRING( - "Swings a huge\nhammer. Can't " - "be\nused twice in a\nrow."), + "Swings a huge hammer. Can't\n" + "be used twice in a row."), .effect = EFFECT_HIT, .power = 160, .type = TYPE_STEEL, @@ -20543,8 +20526,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Comeuppance"), .description = COMPOUND_STRING( - "Retaliates\nstrongly against " - "\nwho last hurt the\nuser."), + "Retaliates strongly against\n" + "who last hurt the user."), .effect = EFFECT_METAL_BURST, .power = 1, .type = TYPE_DARK, @@ -20563,8 +20546,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Aqua Cutter"), .description = COMPOUND_STRING( - "Pressurized water\ncut with a " - "high\ncritical-hit\nratio."), + "Pressurized water cut with a\n" + "high critical-hit ratio."), .effect = EFFECT_HIT, .power = 70, .type = TYPE_WATER, @@ -20727,8 +20710,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psyblade"), .description = COMPOUND_STRING( - "This move's power\nincreases " - "when on\nElectric Terrain."), + "This move's power increases\n" + "when on Electric Terrain."), .effect = EFFECT_PSYBLADE, .power = 80, .type = TYPE_PSYCHIC, @@ -20746,8 +20729,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hydro Steam"), .description = COMPOUND_STRING( - "This move's power\nincreases " - "under\nharsh sunlight."), + "This move's power increases\n" + "under harsh sunlight."), .effect = EFFECT_HYDRO_STEAM, .power = 80, .type = TYPE_WATER, @@ -20764,8 +20747,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Blood Moon"), .description = COMPOUND_STRING( - "Unleashes the\nblood moon. " - "Can't\nbe used twice in a\nrow."), + "Unleashes the blood moon.\n" + "Can't be used twice in a row."), .effect = EFFECT_HIT, .power = 140, .type = TYPE_NORMAL, @@ -20782,8 +20765,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Matcha Gotcha"), .description = COMPOUND_STRING( - "Absorbs half the\ndamage " - "inflicted.\nMay cause a burn."), + "Absorbs half the damage\n" + "inflicted. May cause a burn."), .effect = EFFECT_ABSORB, .power = 80, .type = TYPE_GRASS, @@ -20807,8 +20790,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Syrup Bomb"), .description = COMPOUND_STRING( - "Lowers the foe's\nspeed " - "each turn\nfor 3 turns."), + "Lowers the foe's speed\n" + "each turn for 3 turns."), .effect = EFFECT_HIT, .power = 60, .type = TYPE_GRASS, @@ -20830,8 +20813,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Ivy Cudgel"), .description = COMPOUND_STRING( - "Type changes with\nheld mask. " - "High\ncritical-hit\nratio."), + "Type changes with held mask.\n" + "High critical-hit ratio."), .effect = EFFECT_IVY_CUDGEL, .power = 100, .type = TYPE_GRASS, @@ -20849,8 +20832,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Electro Shot"), .description = COMPOUND_STRING( - "Gathers\nelectricity, then " - "\nfires a\nhigh-voltage shot."), + "Gathers electricity, then\n" + "fires a high-voltage shot."), .effect = EFFECT_TWO_TURNS_ATTACK, .power = 130, .type = TYPE_ELECTRIC, @@ -20864,7 +20847,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1, .self = TRUE, .onChargeTurnOnly = TRUE, - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_ElectroShot, }, @@ -20873,8 +20856,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tera Starstorm"), .description = COMPOUND_STRING( - "In Terapagos's\nStellar " - "Form, it\nhits all foes."), + "In Terapagos's Stellar\n" + "Form, it hits all foes."), .effect = EFFECT_TERA_STARSTORM, .power = 120, .type = TYPE_NORMAL, @@ -20894,8 +20877,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Fickle Beam"), .description = COMPOUND_STRING( - "Shoots a beam of\nlight. " - "Sometimes\ntwice as strong."), + "Shoots a beam of light.\n" + "Sometimes twice as strong."), .effect = EFFECT_FICKLE_BEAM, .power = 80, .type = TYPE_DRAGON, @@ -20911,8 +20894,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Burning Bulwark"), .description = COMPOUND_STRING( - "Evades attack, and\nburns " - "the foe if\nstruck."), + "Evades attack, and burns\n" + "the foe if struck."), .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_FIRE, @@ -20968,8 +20951,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tachyon Cutter"), .description = COMPOUND_STRING( - "Launches particle\nblades at " - "the\ntarget. Strikes\ntwice."), + "Launches particle blades at\n" + "the target. Strikes twice."), .effect = EFFECT_HIT, .power = 50, .type = TYPE_STEEL, @@ -21003,8 +20986,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Dragon Cheer"), .description = COMPOUND_STRING( - "Increases allies'\ncritical hit " - "\nratio, especially\nif Dragons."), + "Increases allies' critical hit\n" + "ratio, especially if Dragons."), .effect = EFFECT_DRAGON_CHEER, .power = 0, .type = TYPE_DRAGON, @@ -21021,8 +21004,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Alluring Voice"), .description = COMPOUND_STRING( - "Confuses foe if\nits stats " - "were\nboosted this turn."), + "Confuses foe if its stats\n" + "were boosted this turn."), .effect = EFFECT_HIT, .power = 80, .type = TYPE_FAIRY, @@ -21045,8 +21028,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Temper Flare"), .description = COMPOUND_STRING( - "A desperation\nattack. Power " - "\ndoubles if last\nmove failed."), + "A desperation attack. Power\n" + "doubles if last move failed."), .effect = EFFECT_STOMPING_TANTRUM, .power = 75, .type = TYPE_FIRE, @@ -21063,8 +21046,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Supercell Slam"), .description = COMPOUND_STRING( - "An electrified\nslam. If it " - "\nmisses, the user\nis hurt."), + "An electrified slam. If it\n" + "misses, the user is hurt."), .effect = EFFECT_RECOIL_IF_MISS, .power = 100, .type = TYPE_ELECTRIC, @@ -21082,8 +21065,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Psychic Noise"), .description = COMPOUND_STRING( - "Sound waves that\ndamage and " - "prevent\nhealing for 2\nturns."), + "Sound waves that damage and\n" + "prevent healing for 2 turns."), .effect = EFFECT_HIT, .power = 75, .type = TYPE_PSYCHIC, @@ -21106,8 +21089,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .effect = EFFECT_UPPER_HAND, .name = COMPOUND_STRING("Upper Hand"), .description = COMPOUND_STRING( - "Makes the target\nflinch if " - "readying\na priority move."), + "Makes the target flinch if\n" + "readying a priority move."), .power = 65, .type = TYPE_FIGHTING, .accuracy = 100, @@ -21127,8 +21110,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Malignant Chain"), .description = COMPOUND_STRING( - "A corrosive chain\nattack " - "that may\nbadly poison."), + "A corrosive chain attack\n" + "that may badly poison."), .effect = EFFECT_HIT, .power = 100, .type = TYPE_POISON, @@ -21140,7 +21123,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_TOXIC, .chance = 50, - .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_MalignantChain, }, @@ -21150,8 +21132,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Breakneck Blitz"), .description = COMPOUND_STRING( - "Builds momentum\nand crashes " - "into\nthe foe. Power\nvaries."), + "Builds momentum and crashes\n" + "into the foe. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_NORMAL, @@ -21166,8 +21148,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("All-Out Pummeling"), .description = COMPOUND_STRING( - "Rams an energy orb\ninto " - "the target.\nPower varies."), + "Rams an energy orb into\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_FIGHTING, @@ -21182,8 +21164,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Supersonic Skystrike"), .description = COMPOUND_STRING( - "Soars up and\nplummets toward " - "\nthe target. Power\nvaries."), + "Soars up and plummets toward\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_FLYING, @@ -21198,8 +21180,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Acid Downpour"), .description = COMPOUND_STRING( - "Sinks the target\nin a poison " - "swamp.\nPower varies."), + "Sinks the target in a poison\n" + "swamp. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_POISON, @@ -21214,8 +21196,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Tectonic Rage"), .description = COMPOUND_STRING( - "Burrows deep and\nslams into " - "the\ntarget. Power\nvaries."), + "Burrows deep and slams into\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_GROUND, @@ -21231,8 +21213,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Continental Crush"), .description = COMPOUND_STRING( - "Drops a huge rock\nmountain " - "on the\nfoe. Power varies."), + "Drops a huge rock mountain\n" + "on the foe. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_ROCK, @@ -21247,8 +21229,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Savage Spin-Out"), .description = COMPOUND_STRING( - "Spits threads of\nsilk to " - "bind the\nfoe. Power varies."), + "Spits threads of silk to\n" + "bind the foe. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_BUG, @@ -21263,8 +21245,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Never-Ending Nightmare"), .description = COMPOUND_STRING( - "Deep-seated\ngrudges trap " - "the\ntarget. Power\nvaries."), + "Deep-seated grudges trap\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_GHOST, @@ -21279,8 +21261,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Corkscrew Crash"), .description = COMPOUND_STRING( - "Spins very fast\nand rams " - "the\ntarget. Power\nvaries."), + "Spins very fast and rams\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_STEEL, @@ -21295,8 +21277,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Inferno Overdrive"), .description = COMPOUND_STRING( - "Breathes intense\nfire at " - "the\ntarget. Power\nvaries."), + "Breathes intense fire at\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_FIRE, @@ -21311,8 +21293,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Hydro Vortex"), .description = COMPOUND_STRING( - "A huge whirlpool\nswallows " - "the\ntarget. Power\nvaries."), + "A huge whirlpool swallows\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_WATER, @@ -21327,8 +21309,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Bloom Doom"), .description = COMPOUND_STRING( - "Uses plant energy\nto attack " - "the\ntarget. Power\nvaries."), + "Uses plant energy to attack\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_GRASS, @@ -21343,8 +21325,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Gigavolt Havoc"), .description = COMPOUND_STRING( - "Hits the foe with\npowerful " - "\nelectricity. Power\nvaries."), + "Hits the foe with powerful\n" + "electricity. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_ELECTRIC, @@ -21359,8 +21341,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Shattered Psyche"), .description = COMPOUND_STRING( - "Controls the\ntarget to " - "hurt it.\nPower varies."), + "Controls the target to\n" + "hurt it. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_PSYCHIC, @@ -21375,8 +21357,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Subzero Slammer"), .description = COMPOUND_STRING( - "Drops the temp and\nfreezes " - "the\ntarget. Power\nvaries."), + "Drops the temp and freezes\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_ICE, @@ -21391,8 +21373,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Devastating Drake"), .description = COMPOUND_STRING( - "Develops aura and\nattacks " - "the\ntarget. Power\nvaries."), + "Develops aura and attacks\n" + "the target. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_DRAGON, @@ -21407,8 +21389,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Black Hole Eclipse"), .description = COMPOUND_STRING( - "Sucks the target\ninto dark " - "energy.\nPower varies."), + "Sucks the target into dark\n" + "energy. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_DARK, @@ -21423,8 +21405,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Twinkle Tackle"), .description = COMPOUND_STRING( - "Toys with the\ntarget in a " - "\ncharming space.\nPower varies."), + "Toys with the target in a\n" + "charming space. Power varies."), .effect = EFFECT_HIT, .power = 1, .type = TYPE_FAIRY, @@ -21439,8 +21421,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Catastropika"), .description = COMPOUND_STRING( - "Pikachu uses the\nmax amount " - "of\nelectricity and\npounces."), + "Pikachu uses the max amount\n" + "of electricity and pounces."), .effect = EFFECT_HIT, .power = 210, .type = TYPE_ELECTRIC, @@ -21455,8 +21437,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("10,000,000 Volt Thunderbolt"), .description = COMPOUND_STRING( - "Cap Pikachu\nunleashes jolt. " - "\nHigh critical-hit\nratio."), + "Cap Pikachu unleashes jolt.\n" + "High critical-hit ratio."), .effect = EFFECT_HIT, .power = 195, .type = TYPE_ELECTRIC, @@ -21472,8 +21454,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Stoked Sparksurfer"), .description = COMPOUND_STRING( - "Alolan Raichu\nattacks with " - "full\nforce. Causes\nparalysis."), + "Alolan Raichu attacks with\n" + "full force. Causes paralysis."), .effect = EFFECT_HIT, .power = 175, .type = TYPE_ELECTRIC, @@ -21492,8 +21474,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Extreme Evoboost"), .description = COMPOUND_STRING( - "Eevee gets energy\nfrom " - "its friends.\nBoosts stats."), + "Eevee gets energy from\n" + "its friends. Boosts stats."), .effect = EFFECT_EXTREME_EVOBOOST, .power = 0, .type = TYPE_NORMAL, @@ -21508,8 +21490,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Pulverizing Pancake"), .description = COMPOUND_STRING( - "Snorlax\nenergetically\nmoves " - "and attacks\nwith full force."), + "Snorlax energetically moves\n" + "and attacks with full force."), .effect = EFFECT_HIT, .power = 210, .type = TYPE_NORMAL, @@ -21524,9 +21506,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Genesis Supernova"), .description = COMPOUND_STRING( - "Mew attacks with\nfull force. " - "\nPsychically\ncharges terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + "Mew attacks with full force.\n" + "Psychically charges terrain."), + .effect = EFFECT_HIT_SET_TERRAIN, .power = 185, .type = TYPE_PSYCHIC, .accuracy = 0, @@ -21534,15 +21516,15 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = { .moveProperty = ARG_SET_PSYCHIC_TERRAIN }, // Set Psychic Terrain. If there's a different field terrain active, overwrite it. + .argument = { .moveProperty = STATUS_FIELD_PSYCHIC_TERRAIN }, .battleAnimScript = gBattleAnimMove_GenesisSupernova, }, [MOVE_SINISTER_ARROW_RAID] = { .name = COMPOUND_STRING("Sinister Arrow Raid"), .description = COMPOUND_STRING( - "Decidueye shoots\ncountless " - "arrows\nwith full force."), + "Decidueye shoots countless\n" + "arrows with full force."), .effect = EFFECT_HIT, .power = 180, .type = TYPE_GHOST, @@ -21557,8 +21539,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Malicious Moonsault"), .description = COMPOUND_STRING( - "Incineroar crashes\ninto " - "the target\nwith full force."), + "Incineroar crashes into\n" + "the target with full force."), .effect = EFFECT_HIT, .power = 180, .type = TYPE_DARK, @@ -21573,8 +21555,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Oceanic Operetta"), .description = COMPOUND_STRING( - "Primarina summons\na massive " - "amount\nof water at the\nfoe."), + "Primarina summons a massive\n" + "amount of water at the foe."), .effect = EFFECT_HIT, .power = 195, .type = TYPE_WATER, @@ -21589,9 +21571,9 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Splintered Stormshards"), .description = COMPOUND_STRING( - "Lycanroc attacks\nwith full " - "force.\nRemoves all\nterrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + "Lycanroc attacks with full\n" + "force. Removes all terrain."), + .effect = EFFECT_ICE_SPINNER, .power = 190, .type = TYPE_ROCK, .accuracy = 0, @@ -21599,15 +21581,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .battleAnimScript = gBattleAnimMove_SplinteredStormshards, }, [MOVE_LETS_SNUGGLE_FOREVER] = { .name = COMPOUND_STRING("Let's Snuggle Forever"), .description = COMPOUND_STRING( - "Mimikyu punches\nthe target " - "with\nfull force."), + "Mimikyu punches the target\n" + "with full force."), .effect = EFFECT_HIT, .power = 190, .type = TYPE_FAIRY, @@ -21622,8 +21603,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Clangorous Soulblaze"), .description = COMPOUND_STRING( - "Kommo-o attacks\nwith full " - "force.\nBoosts all stats."), + "Kommo-o attacks with full\n" + "force. Boosts all stats."), .effect = EFFECT_HIT, .power = 185, .type = TYPE_DRAGON, @@ -21645,8 +21626,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Guardian of Alola"), .description = COMPOUND_STRING( - "The Land Spirit\nPokémon " - "greatly\nreduces the foe's\nHP."), + "The Land Spirit Pokémon\n" + "greatly reduces the foe's HP."), .effect = EFFECT_FIXED_PERCENT_DAMAGE, .power = 1, .type = TYPE_FAIRY, @@ -21662,8 +21643,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Searing Sunraze Smash"), .description = COMPOUND_STRING( - "Solgaleo attacks\nwith full " - "force.\nIgnores abilities."), + "Solgaleo attacks with full\n" + "force. Ignores abilities."), .effect = EFFECT_HIT, .power = 200, .type = TYPE_STEEL, @@ -21679,8 +21660,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Menacing Moonraze Maelstrom"), .description = COMPOUND_STRING( - "Lunala attacks\nwith full " - "force.\nIgnores abilities."), + "Lunala attacks with full\n" + "force. Ignores abilities."), .effect = EFFECT_HIT, .power = 200, .type = TYPE_GHOST, @@ -21696,8 +21677,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Light That Burns the Sky"), .description = COMPOUND_STRING( - "Uses Necrozma's\nhighest " - "attack.\nIgnores abilities."), + "Uses Necrozma's highest\n" + "attack. Ignores abilities."), .effect = EFFECT_PHOTON_GEYSER, .power = 200, .type = TYPE_PSYCHIC, @@ -21713,8 +21694,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Soul-Stealing 7-Star Strike"), .description = COMPOUND_STRING( - "Marshadow punches\nand " - "kicks with\nfull force."), + "Marshadow punches and\n" + "kicks with full force."), .effect = EFFECT_HIT, .power = 195, .type = TYPE_GHOST, @@ -21746,8 +21727,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Flare"), .description = COMPOUND_STRING( - "Fire Dynamax\nattack. " - "\nIntensifies sun\nfor 5 turns."), + "Fire Dynamax attack.\n" + "Intensifies sun for 5 turns."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_FIRE, @@ -21759,8 +21740,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxFlare, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SUN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21768,8 +21747,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Flutterby"), .description = COMPOUND_STRING( - "Bug Dynamax\nattack. " - "Lowers\nfoe's Sp. Atk\nstat."), + "Bug Dynamax attack.\n" + "Lowers foe's Sp. Atk stat."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_BUG, @@ -21781,8 +21760,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxFlutterby, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SP_ATK_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21790,8 +21767,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Lightning"), .description = COMPOUND_STRING( - "Electric Dynamax\nattack. " - "Turns the\nterrain electric."), + "Electric Dynamax attack.\n" + "Turns the terrain electric."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_ELECTRIC, @@ -21803,8 +21780,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxLightning, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ELECTRIC_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21812,8 +21787,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Strike"), .description = COMPOUND_STRING( - "Normal Dynamax\nattack. " - "Lowers\nfoe's Speed stat."), + "Normal Dynamax attack.\n" + "Lowers foe's Speed stat."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_NORMAL, @@ -21825,8 +21800,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxStrike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SPEED_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21834,8 +21807,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Knuckle"), .description = COMPOUND_STRING( - "Fighting Dynamax\nattack. " - "Boosts\nally Attack stats."), + "Fighting Dynamax attack.\n" + "Boosts ally Attack stats."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_FIGHTING, @@ -21847,8 +21820,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxKnuckle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_ATTACK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21856,8 +21827,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Phantasm"), .description = COMPOUND_STRING( - "Ghost Dynamax\nattack. " - "Lowers\nfoe's Defense\nstat."), + "Ghost Dynamax attack.\n" + "Lowers foe's Defense stat."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_GHOST, @@ -21869,8 +21840,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxPhantasm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_DEFENSE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21878,8 +21847,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Hailstorm"), .description = COMPOUND_STRING( - "Ice Dynamax\nattack. " - "Summons\nhail for 5 turns."), + "Ice Dynamax attack.\n" + "Summons hail for 5 turns."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_ICE, @@ -21891,8 +21860,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxHailstorm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HAIL, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21900,8 +21867,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Ooze"), .description = COMPOUND_STRING( - "Poison Dynamax\nattack. " - "Boosts\nally Sp. Atk\nstats."), + "Poison Dynamax attack.\n" + "Boosts ally Sp. Atk stats."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_POISON, @@ -21913,8 +21880,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxOoze, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_ATK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21922,8 +21887,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Geyser"), .description = COMPOUND_STRING( - "Water Dynamax\nattack. " - "Summons\nrain for 5 turns."), + "Water Dynamax attack.\n" + "Summons rain for 5 turns."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_WATER, @@ -21935,8 +21900,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxGeyser, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21944,8 +21907,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Airstream"), .description = COMPOUND_STRING( - "Flying Dynamax\nattack. " - "Boosts\nally Speed stats."), + "Flying Dynamax attack.\n" + "Boosts ally Speed stats."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_FLYING, @@ -21957,8 +21920,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxAirstream, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SPEED, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21966,8 +21927,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Starfall"), .description = COMPOUND_STRING( - "Fairy Dynamax\nattack. " - "Turns the\nterrain misty."), + "Fairy Dynamax attack.\n" + "Turns the terrain misty."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_FAIRY, @@ -21979,8 +21940,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxStarfall, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_MISTY_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21988,8 +21947,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Wyrmwind"), .description = COMPOUND_STRING( - "Dragon Dynamax\nattack. " - "Lowers\nfoe's Attack stat."), + "Dragon Dynamax attack.\n" + "Lowers foe's Attack stat."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_DRAGON, @@ -22001,8 +21960,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxWyrmwind, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_ATTACK_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22010,8 +21967,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Mindstorm"), .description = COMPOUND_STRING( - "Psychic Dynamax\nattack. " - "Turns the\nterrain psychic."), + "Psychic Dynamax attack.\n" + "Turns the terrain psychic."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_PSYCHIC, @@ -22023,8 +21980,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxMindstorm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PSYCHIC_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22032,8 +21987,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Rockfall"), .description = COMPOUND_STRING( - "Rock Dynamax\nattack. " - "Summons a\nsandstorm."), + "Rock Dynamax attack.\n" + "Summons a sandstorm."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_ROCK, @@ -22045,8 +22000,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxRockfall, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SANDSTORM, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22054,8 +22007,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Quake"), .description = COMPOUND_STRING( - "Ground Dynamax\nattack. " - "Boosts\nally Sp. Def\nstats."), + "Ground Dynamax attack.\n" + "Boosts ally Sp. Def stats."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_GROUND, @@ -22068,8 +22021,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxQuake, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_DEF, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22077,8 +22028,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Darkness"), .description = COMPOUND_STRING( - "Dark Dynamax\nattack. " - "Lowers\nfoe's Sp. Def\nstat."), + "Dark Dynamax attack.\n" + "Lowers foe's Sp. Def stat."), .effect = EFFECT_MAX_MOVE, .power = 1, .type = TYPE_DARK, @@ -22090,8 +22041,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxDarkness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SP_DEF_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22099,8 +22048,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Overgrowth"), .description = COMPOUND_STRING( - "Grass Dynamax\nattack. " - "Turns the\nterrain grassy."), + "Grass Dynamax attack.\n" + "Turns the terrain grassy."), .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GRASS, @@ -22112,8 +22061,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxOvergrowth, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_GRASSY_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22121,8 +22068,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Max Steelspike"), .description = COMPOUND_STRING( - "Steel Dynamax\nattack. " - "Boosts\nally Defense\nstats."), + "Steel Dynamax attack.\n" + "Boosts ally Defense stats."), .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_STEEL, @@ -22134,8 +22081,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxSteelspike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_DEFENSE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22143,8 +22088,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Vine Lash"), .description = COMPOUND_STRING( - "G-max Venusaur\nattack. " - "Damages\nfor 4 turns."), //ANIM TODO + "G-max Venusaur attack.\n" + "Damages for 4 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GRASS, @@ -22156,8 +22101,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVineLash, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_VINE_LASH, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22165,8 +22108,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Wildfire"), .description = COMPOUND_STRING( - "G-max Charizard\nattack. " - "Damages\nfor 4 turns."), //ANIM TODO + "G-max Charizard attack.\n" + "Damages for 4 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FIRE, @@ -22178,8 +22121,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxWildfire, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WILDFIRE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22187,8 +22128,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Cannonade"), .description = COMPOUND_STRING( - "G-max Blastoise\nattack. " - "Damages\nfor 4 turns."), //ANIM TODO + "G-max Blastoise attack.\n" + "Damages for 4 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_WATER, @@ -22200,8 +22141,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCannonade, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CANNONADE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22209,8 +22148,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Befuddle"), .description = COMPOUND_STRING( - "G-max Butterfree\nattack. " - "Poison,\nparalysis, or\nsleep."), //ANIM TODO + "G-max Butterfree attack.\n" + "Poison, paralysis, or sleep."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_BUG, @@ -22222,8 +22161,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxBefuddle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_EFFECT_SPORE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22231,8 +22168,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Volt Crash"), .description = COMPOUND_STRING( - "G-max Pikachu\nattack. " - "Paralyzes\nopponents."), //ANIM TODO + "G-max Pikachu attack.\n" + "Paralyzes opponents."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_ELECTRIC, @@ -22244,8 +22181,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVoltCrash, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYZE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22253,8 +22188,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Gold Rush"), .description = COMPOUND_STRING( - "G-max Meowth\nattack. " - "Confuses\nand earns money."), //ANIM TODO + "G-max Meowth attack.\n" + "Confuses and earns money."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_NORMAL, @@ -22266,8 +22201,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxGoldRush, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22275,8 +22208,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Chi Strike"), .description = COMPOUND_STRING( - "G-max Machamp\nattack. " - "Boosts\ncritical-hit\nratio."), //ANIM TODO + "G-max Machamp attack.\n" + "Boosts critical-hit ratio."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FIGHTING, @@ -22288,8 +22221,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxChiStrike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CRIT_PLUS_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22297,8 +22228,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Terror"), .description = COMPOUND_STRING( - "G-max Gengar\nattack. " - "Prevents\nfoes from\nescaping."), //ANIM TODO + "G-max Gengar attack.\n" + "Prevents foes from escaping."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GHOST, @@ -22310,8 +22241,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxTerror, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PREVENT_ESCAPE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22319,8 +22248,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Foam Burst"), .description = COMPOUND_STRING( - "G-max Kingler\nattack. " - "Harshly\nlowers foe's\nSpeed."), //ANIM TODO + "G-max Kingler attack.\n" + "Harshly lowers foe's Speed."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_WATER, @@ -22332,8 +22261,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFoamBurst, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SPEED_2_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22341,8 +22268,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Resonance"), .description = COMPOUND_STRING( - "G-max Lapras\nattack. " - "Reduces\ndamage for 5\nturns."), //ANIM TODO + "G-max Lapras attack.\n" + "Reduces damage for 5 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_ICE, @@ -22354,8 +22281,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxResonance, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AURORA_VEIL, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22363,8 +22288,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Cuddle"), .description = COMPOUND_STRING( - "G-max Eevee\nattack. " - "Infatuates\nopponents."), //ANIM TODO + "G-max Eevee attack.\n" + "Infatuates opponents."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_NORMAL, @@ -22376,8 +22301,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCuddle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_INFATUATE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22385,8 +22308,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Replenish"), .description = COMPOUND_STRING( - "G-max Snorlax\nattack. " - "Restores\neaten Berries."), //ANIM TODO + "G-max Snorlax attack.\n" + "Restores eaten Berries."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_NORMAL, @@ -22398,8 +22321,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxReplenish, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RECYCLE_BERRIES, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22407,8 +22328,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Malodor"), .description = COMPOUND_STRING( - "G-max Garbodor\nattack. " - "Poisons\nopponents."), //ANIM TODO + "G-max Garbodor attack.\n" + "Poisons opponents."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_POISON, @@ -22420,8 +22341,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxMalodor, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22429,8 +22348,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Meltdown"), .description = COMPOUND_STRING( - "G-max Melmetal\nattack. " - "Prevents\nrepeat move use."), //ANIM TODO + "G-max Melmetal attack.\n" + "Prevents repeat move use."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_STEEL, @@ -22442,8 +22361,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxMeltdown, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_TORMENT_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22451,8 +22368,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Drum Solo"), .description = COMPOUND_STRING( - "G-max Rillaboom\nattack. " - "Ignores\ntarget's\nabilities."), //ANIM TODO + "G-max Rillaboom attack.\n" + "Ignores target's abilities."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GRASS, @@ -22465,8 +22382,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxDrumSolo, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22474,8 +22389,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Fireball"), .description = COMPOUND_STRING( - "G-max Cinderace\nattack. " - "Ignores\ntarget's\nabilities."), //ANIM TODO + "G-max Cinderace attack.\n" + "Ignores target's abilities."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FIRE, @@ -22488,8 +22403,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFireball, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22497,8 +22410,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Hydrosnipe"), .description = COMPOUND_STRING( - "G-max Inteleon\nattack. " - "Ignores\ntarget's\nabilities."), //ANIM TODO + "G-max Inteleon attack.\n" + "Ignores target's abilities."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_WATER, @@ -22511,8 +22424,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxHydrosnipe, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22520,8 +22431,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Wind Rage"), .description = COMPOUND_STRING( - "G-max Corviknight\nattack. " - "Removes\nopponent screens."), //ANIM TODO + "G-max Corviknight attack.\n" + "Removes opponent screens."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FLYING, @@ -22533,8 +22444,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxWindRage, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_DEFOG, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22542,8 +22451,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Gravitas"), .description = COMPOUND_STRING( - "G-max Orbeetle\nattack. " - "Changes\ngravity for 5\nturns."), //ANIM TODO + "G-max Orbeetle attack.\n" + "Changes gravity for 5 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_PSYCHIC, @@ -22555,8 +22464,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxGravitas, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_GRAVITY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22564,8 +22471,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Stonesurge"), .description = COMPOUND_STRING( - "G-max Drednaw\nattack. " - "Scatters\nsharp rocks."), //ANIM TODO + "G-max Drednaw attack.\n" + "Scatters sharp rocks."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_WATER, @@ -22577,8 +22484,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxStonesurge, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_STEALTH_ROCK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22586,8 +22491,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Volcalith"), .description = COMPOUND_STRING( - "G-max Coalossal\nattack. " - "Damages\nfor 4 turns."), //ANIM TODO + "G-max Coalossal attack.\n" + "Damages for 4 turns."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_ROCK, @@ -22599,8 +22504,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVolcalith, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_VOLCALITH, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22608,8 +22511,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Tartness"), .description = COMPOUND_STRING( - "G-max Flapple\nattack. " - "Lowers\nfoe's evasiveness."), //ANIM TODO + "G-max Flapple attack.\n" + "Lowers foe's evasiveness."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GRASS, @@ -22621,8 +22524,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxTartness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_EVASIVENESS_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22630,8 +22531,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Sweetness"), .description = COMPOUND_STRING( - "G-max Appletun\nattack. " - "Heals ally\nstatus conditions."), //ANIM TODO + "G-max Appletun attack.\n" + "Heals ally status conditions."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GRASS, @@ -22643,8 +22544,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSweetness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AROMATHERAPY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22652,8 +22551,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Sandblast"), .description = COMPOUND_STRING( - "G-max Sandaconda\nattack. " - "Traps foes\nin a sandstorm."), //ANIM TODO + "G-max Sandaconda attack.\n" + "Traps foes in a sandstorm."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_GROUND, @@ -22665,8 +22564,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSandblast, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SANDBLAST_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22674,8 +22571,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Stun Shock"), .description = COMPOUND_STRING( - "G-max Toxtricity\nattack. " - "Poisons or\nparalyzes foes."), //ANIM TODO + "G-max Toxtricity attack.\n" + "Poisons or paralyzes foes."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_ELECTRIC, @@ -22687,8 +22584,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxStunShock, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON_PARALYZE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22696,8 +22591,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Centiferno"), .description = COMPOUND_STRING( - "G-max Toxtricity\nattack. " - "Traps foes\nin flames."), //ANIM TODO + "G-max Toxtricity attack.\n" + "Traps foes in flames."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FIRE, @@ -22709,8 +22604,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCentiferno, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIRE_SPIN_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22718,8 +22611,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Smite"), .description = COMPOUND_STRING( - "G-max Hatterene\nattack. " - "Confuses\nopponents."), //ANIM TODO + "G-max Hatterene attack.\n" + "Confuses opponents."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FAIRY, @@ -22731,8 +22624,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSmite, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CONFUSE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22741,8 +22632,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Snooze"), .description = COMPOUND_STRING( - "G-max Grimmsnarl\nattack. " - "Lulls foes\ninto sleep."), //ANIM TODO + "G-max Grimmsnarl attack.\n" + "Lulls foes into sleep."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_DARK, @@ -22754,8 +22645,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSnooze, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_YAWN_FOE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22763,8 +22652,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Finale"), .description = COMPOUND_STRING( - "G-max Alcremie\nattack. " - "Heals ally\nHP."), //ANIM TODO + "G-max Alcremie attack.\n" + "Heals ally HP."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_FAIRY, @@ -22776,8 +22665,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFinale, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HEAL_TEAM, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22785,8 +22672,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Steelsurge"), .description = COMPOUND_STRING( - "G-max Copperajah\nattack. " - "Scatters\nsharp spikes."), //ANIM TODO + "G-max Copperajah attack.\n" + "Scatters sharp spikes."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_STEEL, @@ -22798,8 +22685,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSteelsurge, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_STEELSURGE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22807,8 +22692,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("G-Max Depletion"), .description = COMPOUND_STRING( - "G-max Duraludon\nattack. " - "Reduces\ntarget's PP."), //ANIM TODO + "G-max Duraludon attack.\n" + "Reduces target's PP."), //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, .type = TYPE_DRAGON, @@ -22820,8 +22705,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxDepletion, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SPITE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, diff --git a/src/data/trainers.h b/src/data/trainers.h index c1f5a0ffa..c946ac11f 100644 --- a/src/data/trainers.h +++ b/src/data/trainers.h @@ -1,9 +1,7 @@ // // DO NOT MODIFY THIS FILE! It is auto-generated from src/data/trainers.party // -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'src/data/trainers.h' to remove #line markers. +// If you want to modify this file see expansion PR #7154 // #line 1 "src/data/trainers.party" @@ -22,6 +20,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 7 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 0, .party = (const struct TrainerMon[]) { @@ -43,6 +43,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 16 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AQUA_LEADER_ARCHIE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -75,6 +77,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 29 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AQUA_GRUNT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -107,6 +111,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 42 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AQUA_GRUNT_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -139,6 +145,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 55 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_AROMA_LADY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -171,6 +179,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 68 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_RUIN_MANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -203,6 +213,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 81 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_INTERVIEWER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -235,6 +247,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 94 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_TUBER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -267,6 +281,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 107 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_TUBER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -299,6 +315,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 120 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_COOLTRAINER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -331,6 +349,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 133 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_COOLTRAINER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -363,6 +383,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 146 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HEX_MANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -395,6 +417,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 159 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_LADY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -427,6 +451,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 172 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BEAUTY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -459,6 +485,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 185 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RICH_BOY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -491,6 +519,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 198 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_POKEMANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -523,6 +553,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 211 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -555,6 +587,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 224 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BLACK_BELT, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -587,6 +621,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 237 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GUITARIST, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -619,6 +655,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 250 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_KINDLER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -651,6 +689,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 263 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -683,6 +723,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 276 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_MANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -715,6 +757,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 289 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_PSYCHIC_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -747,6 +791,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 302 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_PSYCHIC_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -779,6 +825,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 315 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_GENTLEMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -811,6 +859,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 328 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_SIDNEY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -843,6 +893,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 341 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_PHOEBE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -875,6 +927,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 354 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_ROXANNE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -907,6 +961,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 367 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_BRAWLY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -939,6 +995,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 380 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -971,6 +1029,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 393 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCHOOL_KID_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1003,6 +1063,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 406 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCHOOL_KID_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1035,6 +1097,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 419 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SR_AND_JR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1067,6 +1131,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 432 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEFAN_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1099,6 +1165,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 445 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEFAN_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1131,6 +1199,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 458 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_EXPERT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1163,6 +1233,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 471 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_EXPERT_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1195,6 +1267,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 484 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1227,6 +1301,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 497 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_STEVEN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1259,6 +1335,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 510 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_FISHERMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1291,6 +1369,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 523 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1323,6 +1403,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 536 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1355,6 +1437,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 549 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1387,6 +1471,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 562 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1419,6 +1505,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 575 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1451,6 +1539,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 588 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1483,6 +1573,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 601 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_DRAGON_TAMER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1515,6 +1607,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 614 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BIRD_KEEPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1547,6 +1641,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 627 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_NINJA_BOY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1579,6 +1675,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 640 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BATTLE_GIRL, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1611,6 +1709,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 653 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PARASOL_LADY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1643,6 +1743,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 666 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_SWIMMER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1675,6 +1777,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 679 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1707,6 +1811,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 692 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_TWINS, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1739,6 +1845,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 705 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_SAILOR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1771,6 +1879,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 718 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1803,6 +1913,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 731 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1835,6 +1947,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 744 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_COLLECTOR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1867,6 +1981,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 757 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_WALLY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1899,6 +2015,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 770 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BRENDAN_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1931,6 +2049,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 783 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BRENDAN_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1963,6 +2083,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 796 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BRENDAN_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -1995,6 +2117,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 809 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_MAY_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2027,6 +2151,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 822 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_MAY_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2059,6 +2185,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 835 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_MAY_1, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2091,6 +2219,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 848 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_POKEMON_BREEDER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2123,6 +2253,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 861 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_POKEMON_BREEDER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2155,6 +2287,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 874 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_POKEMON_RANGER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2187,6 +2321,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 887 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_POKEMON_RANGER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2219,6 +2355,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 900 .aiFlags = AI_FLAG_BASIC_TRAINER, +#line 0 + .trainerBackPic = TRAINER_PIC_MAGMA_LEADER_MAXIE, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -2273,6 +2411,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 921 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_MAGMA_GRUNT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2305,6 +2445,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 934 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_MAGMA_GRUNT_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2337,6 +2479,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 947 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_LASS, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2369,6 +2513,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 960 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2401,6 +2547,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 973 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_HIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2433,6 +2581,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 986 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -2476,6 +2626,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 1003 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_OLD_COUPLE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2508,6 +2660,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 1016 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_SIS_AND_BRO, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2540,6 +2694,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1029 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AQUA_ADMIN_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2572,6 +2728,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1042 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AQUA_ADMIN_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2604,6 +2762,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1055 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_MAGMA_ADMIN_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -2658,6 +2818,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1076 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_MAGMA_ADMIN_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2690,6 +2852,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1089 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_WATTSON, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2722,6 +2886,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1102 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_FLANNERY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2754,6 +2920,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1115 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_NORMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2786,6 +2954,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1128 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_WINONA, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2818,6 +2988,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1141 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_WALLACE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2850,6 +3022,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1154 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_GLACIA, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2882,6 +3056,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1167 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_DRAKE, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2914,6 +3090,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1180 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -2957,6 +3135,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1197 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -2989,6 +3169,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1210 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3043,6 +3225,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1231 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3086,6 +3270,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1248 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3129,6 +3315,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1265 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -3161,6 +3349,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1278 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3204,6 +3394,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1295 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -3236,6 +3428,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1308 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -3268,6 +3462,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1321 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3311,6 +3507,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1338 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3365,6 +3563,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1359 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3408,6 +3608,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1376 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3451,6 +3653,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1393 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3494,6 +3698,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1410 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3548,6 +3754,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1431 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -3580,6 +3788,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1444 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3634,6 +3844,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1465 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -3699,6 +3911,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1490 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3742,6 +3956,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1507 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -3785,6 +4001,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1524 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3839,6 +4057,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1545 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -3904,6 +4124,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1570 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -3958,6 +4180,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1591 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -3990,6 +4214,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1604 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4044,6 +4270,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1625 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4087,6 +4315,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4141,6 +4371,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1663 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4184,6 +4416,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1680 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4227,6 +4461,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1697 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -4259,6 +4495,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1710 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4313,6 +4551,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1731 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4356,6 +4596,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1748 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -4388,6 +4630,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1761 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4431,6 +4675,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1778 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4485,6 +4731,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1799 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4528,6 +4776,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1816 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4582,6 +4832,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1837 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4625,6 +4877,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1854 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4668,6 +4922,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1871 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4711,6 +4967,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1888 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4765,6 +5023,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1909 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -4841,6 +5101,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1938 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4884,6 +5146,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1955 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4927,6 +5191,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1972 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -4970,6 +5236,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 1989 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5013,6 +5281,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2006 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5056,6 +5326,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2023 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5088,6 +5360,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2036 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -5142,6 +5416,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2057 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5185,6 +5461,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2074 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -5239,6 +5517,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2095 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5271,6 +5551,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2108 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SAILOR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5314,6 +5596,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2125 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5368,6 +5652,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2147 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5411,6 +5697,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2164 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5443,6 +5731,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2177 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5475,6 +5765,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2190 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5518,6 +5810,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2207 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5550,6 +5844,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2220 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5593,6 +5889,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2237 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -5658,6 +5956,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2262 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5690,6 +5990,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2275 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5733,6 +6035,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2292 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -5787,6 +6091,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2313 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5830,6 +6136,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2330 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -5895,6 +6203,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2355 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -5927,6 +6237,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2368 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -5970,6 +6282,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2385 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6013,6 +6327,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2402 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6067,6 +6383,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2423 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6110,6 +6428,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2440 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6153,6 +6473,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2457 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -6229,6 +6551,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2486 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6272,6 +6596,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2503 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6315,6 +6641,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2520 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6369,6 +6697,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2541 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6412,6 +6742,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2558 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -6444,6 +6776,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2571 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6498,6 +6832,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2592 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6541,6 +6877,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2609 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6584,6 +6922,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2626 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6638,6 +6978,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2647 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -6731,6 +7073,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2688 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6785,6 +7129,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2709 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -6824,6 +7170,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2726 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -6878,6 +7226,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2747 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -6943,6 +7293,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2772 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -6986,6 +7338,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2789 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7040,6 +7394,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2810 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -7105,6 +7461,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2835 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -7137,6 +7495,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2848 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7180,6 +7540,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2865 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7234,6 +7596,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2886 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7277,6 +7641,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2903 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -7342,6 +7708,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2928 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -7374,6 +7742,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2941 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7431,6 +7801,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2966 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7485,6 +7857,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 2987 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7542,6 +7916,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3012 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7585,6 +7961,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3029 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7660,6 +8038,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3062 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -7699,6 +8079,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3079 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7742,6 +8124,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3096 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -7807,6 +8191,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3121 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7861,6 +8247,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3142 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -7918,6 +8306,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3167 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -7993,6 +8383,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3200 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8050,6 +8442,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3225 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -8161,6 +8555,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3274 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -8236,6 +8632,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3307 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8293,6 +8691,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3332 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -8325,6 +8725,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3345 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -8357,6 +8759,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3358 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -8432,6 +8836,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3391 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -8464,6 +8870,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3404 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8521,6 +8929,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3429 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8578,6 +8988,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3454 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -8689,6 +9101,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3503 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -8782,6 +9196,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3544 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -8857,6 +9273,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3577 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8914,6 +9332,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3602 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -8957,6 +9377,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3619 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -8989,6 +9411,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3632 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9043,6 +9467,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3653 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9097,6 +9523,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3674 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -9129,6 +9557,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3687 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9172,6 +9602,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3704 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9215,6 +9647,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3721 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9258,6 +9692,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3738 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -9290,6 +9726,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3751 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BURGLAR, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9333,6 +9771,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3768 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ENGINEER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9376,6 +9816,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3785 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ENGINEER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -9408,6 +9850,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3798 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ENGINEER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9462,6 +9906,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3819 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9516,6 +9962,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3840 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9570,6 +10018,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3861 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -9624,6 +10074,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3882 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9667,6 +10119,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3899 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -9699,6 +10153,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3912 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -9764,6 +10220,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3937 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -9829,6 +10287,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3962 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -9872,6 +10332,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 3979 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -9959,6 +10421,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4012 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10002,6 +10466,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4029 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10045,6 +10511,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4046 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10088,6 +10556,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4063 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10131,6 +10601,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4080 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -10185,6 +10657,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4101 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10228,6 +10702,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4118 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -10293,6 +10769,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4143 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -10347,6 +10825,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4164 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10390,6 +10870,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4181 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -10466,6 +10948,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4210 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10509,6 +10993,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4227 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -10541,6 +11027,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4240 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -10606,6 +11094,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4265 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10649,6 +11139,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4282 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -10681,6 +11173,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4295 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10724,6 +11218,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4312 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -10778,6 +11274,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4333 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -10832,6 +11330,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4354 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10875,6 +11375,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4371 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10918,6 +11420,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4388 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -10961,6 +11465,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4405 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11004,6 +11510,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4422 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -11036,6 +11544,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4435 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -11101,6 +11611,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4460 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11144,6 +11656,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4477 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -11198,6 +11712,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4498 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11241,6 +11757,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4515 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11284,6 +11802,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4532 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11327,6 +11847,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4549 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11370,6 +11892,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4566 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -11424,6 +11948,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4587 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -11456,6 +11982,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4600 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11499,6 +12027,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4617 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -11564,6 +12094,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11607,6 +12139,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4659 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -11639,6 +12173,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4672 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -11693,6 +12229,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4693 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11736,6 +12274,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4710 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -11768,6 +12308,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4723 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -11822,6 +12364,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4744 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11865,6 +12409,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4761 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11908,6 +12454,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4778 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11951,6 +12499,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4795 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -12005,6 +12555,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4816 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -12081,6 +12633,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4845 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12124,6 +12678,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4862 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -12178,6 +12734,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4883 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -12232,6 +12790,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4904 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -12297,6 +12857,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4929 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12340,6 +12902,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4946 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -12394,6 +12958,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4967 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -12426,6 +12992,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 4980 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -12480,6 +13048,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5001 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12523,6 +13093,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5018 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12566,6 +13138,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5035 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -12631,6 +13205,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5060 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -12696,6 +13272,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5085 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12739,6 +13317,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5102 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -12778,6 +13358,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5119 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -12871,6 +13453,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5160 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -12903,6 +13487,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5173 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12946,6 +13532,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5190 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -12989,6 +13577,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5207 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -13043,6 +13633,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5228 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -13075,6 +13667,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5241 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13118,6 +13712,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5258 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13161,6 +13757,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5275 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -13226,6 +13824,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5300 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13269,6 +13869,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5317 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -13345,6 +13947,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5346 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -13410,6 +14014,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5371 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -13442,6 +14048,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5384 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13485,6 +14093,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5401 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -13550,6 +14160,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5426 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -13604,6 +14216,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5447 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13647,6 +14261,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5464 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -13679,6 +14295,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5477 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -13744,6 +14362,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5502 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -13798,6 +14418,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5523 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -13863,6 +14485,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5548 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -13906,6 +14530,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5565 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -13960,6 +14586,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5586 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -14025,6 +14653,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5611 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14068,6 +14698,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5628 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -14122,6 +14754,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5649 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14169,6 +14803,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5666 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -14229,6 +14865,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5687 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14276,6 +14914,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5704 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -14310,6 +14950,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5717 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -14370,6 +15012,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5738 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14417,6 +15061,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5755 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -14451,6 +15097,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5768 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -14511,6 +15159,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5789 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -14571,6 +15221,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5810 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -14608,6 +15260,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5825 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -14645,6 +15299,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5840 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -14682,6 +15338,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5855 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14735,6 +15393,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5876 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14788,6 +15448,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5897 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -14841,6 +15503,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5918 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -14930,6 +15594,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5955 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -15019,6 +15685,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 5992 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_EARLY, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -15108,6 +15776,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6029 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15151,6 +15821,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6046 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -15244,6 +15916,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6087 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -15298,6 +15972,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6108 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15355,6 +16031,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6133 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -15387,6 +16065,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6146 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -15480,6 +16160,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6187 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -15591,6 +16273,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6236 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15634,6 +16318,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6253 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15677,6 +16363,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6270 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -15752,6 +16440,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6303 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15795,6 +16485,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6320 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -15849,6 +16541,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6341 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -15892,6 +16586,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6358 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_GIOVANNI, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -15946,6 +16642,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6379 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_GIOVANNI, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -16013,6 +16711,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6405 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_GIOVANNI, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -16124,6 +16824,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6454 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16167,6 +16869,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6471 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -16221,6 +16925,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6492 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16264,6 +16970,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6509 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16307,6 +17015,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6526 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16350,6 +17060,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6543 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16393,6 +17105,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6560 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16436,6 +17150,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6577 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16479,6 +17195,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6594 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16522,6 +17240,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6611 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -16595,6 +17315,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -16660,6 +17382,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6667 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16717,6 +17441,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6692 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -16827,6 +17553,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6740 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -16881,6 +17609,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6761 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -16924,6 +17654,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6778 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -16978,6 +17710,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6799 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -17032,6 +17766,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6820 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17075,6 +17811,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6837 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -17129,6 +17867,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6858 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17172,6 +17912,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6875 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -17237,6 +17979,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6900 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17280,6 +18024,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6917 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17323,6 +18069,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6934 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -17399,6 +18147,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6963 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -17453,6 +18203,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 6984 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17496,6 +18248,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7001 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -17550,6 +18304,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7022 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -17582,6 +18338,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7035 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -17614,6 +18372,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7048 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17657,6 +18417,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7065 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -17711,6 +18473,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7086 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -17804,6 +18568,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7127 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17847,6 +18613,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7144 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -17890,6 +18658,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7161 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -17955,6 +18725,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7186 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -18009,6 +18781,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7207 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -18063,6 +18837,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7228 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -18117,6 +18893,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7249 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -18149,6 +18927,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7262 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18225,6 +19005,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7291 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -18281,6 +19063,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7313 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18394,6 +19178,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7363 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18507,6 +19293,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7413 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18620,6 +19408,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7463 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18733,6 +19523,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7513 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18846,6 +19638,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7563 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -18959,6 +19753,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7613 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19072,6 +19868,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7663 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19185,6 +19983,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7713 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19298,6 +20098,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7763 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19411,6 +20213,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7813 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19524,6 +20328,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7863 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19637,6 +20443,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7913 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19750,6 +20558,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 7963 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19863,6 +20673,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8013 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -19976,6 +20788,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8063 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20089,6 +20903,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8113 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20202,6 +21018,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8163 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20317,6 +21135,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 8214 .mugshotColor = MUGSHOT_COLOR_PURPLE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_LORELEI, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20434,6 +21254,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 8265 .mugshotColor = MUGSHOT_COLOR_GREEN, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_BRUNO, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20551,6 +21373,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 8316 .mugshotColor = MUGSHOT_COLOR_PINK, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_AGATHA, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20668,6 +21492,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 8367 .mugshotColor = MUGSHOT_COLOR_BLUE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_LANCE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -20781,6 +21607,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8416 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_BROCK, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -20837,6 +21665,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8439 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_MISTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -20896,6 +21726,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8465 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_LT_SURGE, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -20973,6 +21805,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8499 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_ERIKA, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -21050,6 +21884,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8533 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_KOGA, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21145,6 +21981,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8575 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_BLAINE, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21240,6 +22078,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8617 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_LEADER_SABRINA, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21333,6 +22173,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8658 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -21376,6 +22218,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8675 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -21419,6 +22263,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8692 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -21451,6 +22297,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8705 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -21483,6 +22331,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8718 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -21526,6 +22376,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8735 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21591,6 +22443,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8760 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21656,6 +22510,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8785 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -21721,6 +22577,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8810 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -21797,6 +22655,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8839 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -21873,6 +22733,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8868 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -21949,6 +22811,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8897 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -22025,6 +22889,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8926 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -22101,6 +22967,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8955 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -22177,6 +23045,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 8984 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22306,6 +23176,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9041 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22435,6 +23307,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9098 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_RIVAL_LATE, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22568,6 +23442,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 9157 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22703,6 +23579,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 9216 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22838,6 +23716,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 9275 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -22969,6 +23849,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9332 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23001,6 +23883,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9345 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23033,6 +23917,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9358 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23065,6 +23951,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9371 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23097,6 +23985,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9384 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -23140,6 +24030,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9401 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23172,6 +24064,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9414 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23204,6 +24098,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9427 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23236,6 +24132,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9440 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23268,6 +24166,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9453 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23300,6 +24200,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9466 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -23354,6 +24256,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9487 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23386,6 +24290,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9500 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23418,6 +24324,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9513 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23450,6 +24358,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9526 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23482,6 +24392,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9539 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23514,6 +24426,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9552 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23546,6 +24460,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9565 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23578,6 +24494,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9578 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -23632,6 +24550,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9599 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23664,6 +24584,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9612 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23696,6 +24618,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9625 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -23739,6 +24663,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -23771,6 +24697,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9655 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CHANNELER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -23825,6 +24753,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9676 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -23868,6 +24798,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9693 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -23922,6 +24854,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9714 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -23998,6 +24932,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9743 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24041,6 +24977,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9760 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -24106,6 +25044,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9785 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -24181,6 +25121,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9818 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24224,6 +25166,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9835 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24267,6 +25211,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9852 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -24321,6 +25267,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9873 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -24375,6 +25323,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9894 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -24440,6 +25390,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9919 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24483,6 +25435,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9936 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24526,6 +25480,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9953 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -24580,6 +25536,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9974 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -24634,6 +25592,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 9995 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24677,6 +25637,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10012 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -24709,6 +25671,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10025 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -24741,6 +25705,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10038 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24784,6 +25750,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10055 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24827,6 +25795,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10072 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOL_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24884,6 +25854,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10097 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24927,6 +25899,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10114 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -24970,6 +25944,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10131 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25017,6 +25993,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10148 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25060,6 +26038,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10165 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SIS_AND_BRO, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25103,6 +26083,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10182 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SIS_AND_BRO, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25146,6 +26128,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10199 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25178,6 +26162,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10212 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25210,6 +26196,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10225 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25242,6 +26230,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10238 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25274,6 +26264,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10251 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25306,6 +26298,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10264 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25338,6 +26332,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10277 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25381,6 +26377,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10294 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25424,6 +26422,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10311 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25467,6 +26467,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10328 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25510,6 +26512,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10345 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25553,6 +26557,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10362 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -25607,6 +26613,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10383 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -25661,6 +26669,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10404 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -25715,6 +26725,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10425 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25758,6 +26770,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10442 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25801,6 +26815,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10459 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25844,6 +26860,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10476 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25887,6 +26905,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10493 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25930,6 +26950,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10510 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PROFESSOR_OAK, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25962,6 +26984,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10523 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_BRENDAN_2, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25994,6 +27018,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10536 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RS_MAY_2, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26026,6 +27052,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10549 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26058,6 +27086,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10562 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LEAF, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26090,6 +27120,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10575 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26133,6 +27165,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10592 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26208,6 +27242,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10625 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26255,6 +27291,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TUBER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26309,6 +27347,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10663 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_BREEDER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26365,6 +27405,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10685 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26424,6 +27466,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10711 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26481,6 +27525,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10736 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AROMA_LADY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26524,6 +27570,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10753 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26580,6 +27628,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10775 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LADY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26627,6 +27677,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10792 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PAINTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26666,6 +27718,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10809 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26723,6 +27777,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10834 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26762,6 +27818,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10851 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26794,6 +27852,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10864 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -26826,6 +27886,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10877 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26869,6 +27931,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10894 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26923,6 +27987,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 10915 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26966,6 +28032,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10932 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27020,6 +28088,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10953 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27095,6 +28165,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 10986 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27138,6 +28210,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11003 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27181,6 +28255,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11020 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -27246,6 +28322,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11045 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27300,6 +28378,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11066 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27354,6 +28434,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11087 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27408,6 +28490,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11108 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27453,6 +28537,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11126 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27530,6 +28616,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11160 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27605,6 +28693,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11193 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SCIENTIST, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -27716,6 +28806,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11242 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27770,6 +28862,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11263 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27813,6 +28907,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11280 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27867,6 +28963,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11301 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -27899,6 +28997,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11314 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -27953,6 +29053,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11335 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -28029,6 +29131,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11364 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28076,6 +29180,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11381 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28123,6 +29229,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11398 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28170,6 +29278,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11415 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28224,6 +29334,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11436 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -28289,6 +29401,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 11461 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28336,6 +29450,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11478 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AROMA_LADY, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28390,6 +29506,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11499 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TUBER_F, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -28455,6 +29573,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 11524 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28498,6 +29618,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11541 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -28530,6 +29652,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11554 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PAINTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -28569,6 +29693,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11571 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PAINTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -28610,6 +29736,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11589 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LADY, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28670,6 +29798,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11610 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28713,6 +29843,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11627 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28767,6 +29899,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11648 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28821,6 +29955,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11669 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28878,6 +30014,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11694 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKET_GRUNT_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -28932,6 +30070,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11715 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -28975,6 +30115,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11732 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29018,6 +30160,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11749 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29061,6 +30205,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11766 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29104,6 +30250,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11783 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29147,6 +30295,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11800 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -29179,6 +30329,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 11813 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SIS_AND_BRO, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29222,6 +30374,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11830 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AROMA_LADY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29265,6 +30419,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11847 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -29297,6 +30453,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11860 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29340,6 +30498,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 11877 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29383,6 +30543,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11894 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29426,6 +30588,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11911 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -29458,6 +30622,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11924 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29501,6 +30667,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11941 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -29533,6 +30701,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11954 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29576,6 +30746,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11971 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -29615,6 +30787,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 11988 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -29690,6 +30864,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12021 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_AROMA_LADY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29733,6 +30909,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 12038 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29776,6 +30954,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12055 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -29869,6 +31049,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12096 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -29929,6 +31111,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12117 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -29976,6 +31160,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12134 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30030,6 +31216,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12155 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -30075,6 +31263,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12173 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -30134,6 +31324,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12199 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30211,6 +31403,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12233 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30267,6 +31461,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12255 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -30308,6 +31504,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12273 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -30421,6 +31619,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12323 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -30534,6 +31734,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 12373 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOL_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -30591,6 +31793,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12398 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -30623,6 +31827,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12411 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30698,6 +31904,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12444 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PAINTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -30737,6 +31945,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12461 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GENTLEMAN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -30782,6 +31992,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12479 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LADY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -30843,6 +32055,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12504 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30897,6 +32111,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12525 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -30951,6 +32167,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12546 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_BREEDER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -30983,6 +32201,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12559 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_BREEDER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31037,6 +32257,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12580 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -31069,6 +32291,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12593 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -31134,6 +32358,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12618 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31177,6 +32403,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12635 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31231,6 +32459,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12656 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31274,6 +32504,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12673 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -31339,6 +32571,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12698 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -31371,6 +32605,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12711 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31414,6 +32650,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12728 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31468,6 +32706,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12749 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31522,6 +32762,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12770 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31565,6 +32807,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12787 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31608,6 +32852,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12804 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31651,6 +32897,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12821 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -31683,6 +32931,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12834 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -31715,6 +32965,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12847 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -31747,6 +32999,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12860 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31790,6 +33044,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12877 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31833,6 +33089,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12894 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31876,6 +33134,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12911 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31930,6 +33190,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12932 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -31984,6 +33246,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12953 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -32038,6 +33302,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12974 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -32092,6 +33358,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 12995 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -32146,6 +33414,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13016 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ENGINEER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -32200,6 +33470,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13037 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32243,6 +33515,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13054 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32286,6 +33560,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13071 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32329,6 +33605,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13088 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CAMPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32372,6 +33650,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13105 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -32404,6 +33684,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13118 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -32436,6 +33718,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13131 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -32468,6 +33752,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13144 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32511,6 +33797,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13161 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32554,6 +33842,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13178 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32597,6 +33887,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13195 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32640,6 +33932,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13212 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32683,6 +33977,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13229 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -32759,6 +34055,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13258 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_LASS, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -32835,6 +34133,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13287 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SUPER_NERD, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -32889,6 +34189,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13308 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_GAMER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32932,6 +34234,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13325 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -32975,6 +34279,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13342 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -33040,6 +34346,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13367 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_ROCKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33083,6 +34391,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13384 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33126,6 +34436,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13401 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -33191,6 +34503,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13426 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -33256,6 +34570,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13451 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -33332,6 +34648,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13480 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -33408,6 +34726,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13509 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -33484,6 +34804,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13538 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -33549,6 +34871,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13563 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33592,6 +34916,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13580 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33635,6 +34961,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13597 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -33689,6 +35017,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13618 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -33743,6 +35073,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13639 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BEAUTY, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33786,6 +35118,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13656 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -33840,6 +35174,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13677 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -33894,6 +35230,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13698 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33937,6 +35275,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13715 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -33980,6 +35320,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13732 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34023,6 +35365,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 13749 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34070,6 +35414,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 13766 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34117,6 +35463,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 13783 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34164,6 +35512,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13800 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -34218,6 +35568,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13821 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34261,6 +35613,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13838 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34304,6 +35658,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13855 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34347,6 +35703,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13872 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34390,6 +35748,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13889 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -34455,6 +35815,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13914 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -34520,6 +35882,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13939 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34563,6 +35927,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13956 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -34628,6 +35994,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13981 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34671,6 +36039,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 13998 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PICNICKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34714,6 +36084,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14015 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_FISHERMAN, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -34801,6 +36173,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14048 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -34833,6 +36207,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14061 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SIS_AND_BRO, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34876,6 +36252,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14078 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SIS_AND_BRO, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34919,6 +36297,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14095 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -34951,6 +36331,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14108 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -34998,6 +36380,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14125 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35045,6 +36429,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14142 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35092,6 +36478,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14159 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35139,6 +36527,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14176 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35186,6 +36576,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14193 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35233,6 +36625,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14210 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35280,6 +36674,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14227 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BLACK_BELT, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35327,6 +36723,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14244 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35374,6 +36772,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14261 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_KIN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35421,6 +36821,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14278 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TUBER_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -35475,6 +36877,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14299 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TWINS, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35518,6 +36922,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14316 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PAINTER, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -35557,6 +36963,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14333 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNGSTER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35600,6 +37008,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14350 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_BREEDER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -35654,6 +37064,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14371 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35697,6 +37109,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14388 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_YOUNG_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35740,6 +37154,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14405 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35783,6 +37199,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14422 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35826,6 +37244,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14439 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BIRD_KEEPER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -35869,6 +37289,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14456 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -35901,6 +37323,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14469 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -35976,6 +37400,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14502 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -36008,6 +37434,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14515 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_HIKER, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36051,6 +37479,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14532 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_RUIN_MANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36094,6 +37524,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14549 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMANIAC, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36137,6 +37569,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14566 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_M, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -36176,6 +37610,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14583 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_PSYCHIC_F, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -36251,6 +37687,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14616 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_JUGGLER, .partySize = 4, .party = (const struct TrainerMon[]) { @@ -36318,6 +37756,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14642 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36377,6 +37817,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14668 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36434,6 +37876,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14693 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CRUSH_GIRL, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -36494,6 +37938,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14714 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_TAMER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -36550,6 +37996,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14736 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_M, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -36627,6 +38075,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14770 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_POKEMON_RANGER_F, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -36668,6 +38118,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14788 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_M, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -36781,6 +38233,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14838 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOLTRAINER_F, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -36894,6 +38348,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 14888 .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, +#line 0 + .trainerBackPic = TRAINER_PIC_COOL_COUPLE, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -36951,6 +38407,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14913 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -37005,6 +38463,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14934 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -37059,6 +38519,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14955 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_BUG_CATCHER, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -37113,6 +38575,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14976 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -37156,6 +38620,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 14993 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_M, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -37199,6 +38665,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 15010 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_SWIMMER_F, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -37246,6 +38714,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15029 .mugshotColor = MUGSHOT_COLOR_PURPLE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_LORELEI, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -37363,6 +38833,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15080 .mugshotColor = MUGSHOT_COLOR_GREEN, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_BRUNO, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -37480,6 +38952,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15131 .mugshotColor = MUGSHOT_COLOR_PINK, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_AGATHA, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -37597,6 +39071,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15182 .mugshotColor = MUGSHOT_COLOR_BLUE, +#line 0 + .trainerBackPic = TRAINER_PIC_ELITE_FOUR_LANCE, .partySize = 5, .party = (const struct TrainerMon[]) { @@ -37714,6 +39190,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15233 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -37849,6 +39327,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15292 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -37984,6 +39464,8 @@ .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY, #line 15351 .mugshotColor = MUGSHOT_COLOR_YELLOW, +#line 0 + .trainerBackPic = TRAINER_PIC_CHAMPION_RIVAL, .partySize = 6, .party = (const struct TrainerMon[]) { @@ -38115,6 +39597,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 15408 .aiFlags = AI_FLAG_CHECK_BAD_MOVE, +#line 0 + .trainerBackPic = TRAINER_PIC_CUE_BALL, .partySize = 2, .party = (const struct TrainerMon[]) { diff --git a/src/debug.c b/src/debug.c index d9d5eb0c1..8d9cec562 100644 --- a/src/debug.c +++ b/src/debug.c @@ -17,13 +17,16 @@ #include "data.h" #include "daycare.h" #include "debug.h" +// #include "decoration.h" +// #include "decoration_inventory.h" #include "event_data.h" #include "event_object_movement.h" #include "event_scripts.h" #include "field_fadetransition.h" #include "field_message_box.h" -#include "field_screen_effect.h" +// #include "field_screen_effect.h" #include "field_weather.h" +#include "follower_npc.h" #include "international_string_util.h" #include "item.h" #include "item_icon.h" @@ -59,6 +62,8 @@ #include "constants/battle_ai.h" // #include "constants/battle_frontier.h" #include "constants/coins.h" +// #include "constants/decorations.h" +// #include "constants/event_objects.h" // #include "constants/expansion.h" #include "constants/flags.h" #include "constants/items.h" @@ -72,106 +77,15 @@ #include "fake_rtc.h" #include "save.h" -// ******************************* -enum DebugMenu +enum FollowerNPCCreateDebugMenu { - DEBUG_MENU_ITEM_UTILITIES, - DEBUG_MENU_ITEM_PCBAG, - DEBUG_MENU_ITEM_PARTY, - DEBUG_MENU_ITEM_GIVE, - DEBUG_MENU_ITEM_PLAYER, - DEBUG_MENU_ITEM_SCRIPTS, - DEBUG_MENU_ITEM_FLAGVAR, - //DEBUG_MENU_ITEM_BATTLE, - DEBUG_MENU_ITEM_SOUND, - DEBUG_MENU_ITEM_ROMINFO, - DEBUG_MENU_ITEM_CANCEL, -}; - -enum UtilDebugMenu -{ - DEBUG_UTIL_MENU_ITEM_FLY, - DEBUG_UTIL_MENU_ITEM_WARP, - DEBUG_UTIL_MENU_ITEM_WEATHER, - DEBUG_UTIL_MENU_ITEM_FONT_TEST, - DEBUG_UTIL_MENU_ITEM_TIME_MENU, - DEBUG_UTIL_MENU_ITEM_WATCHCREDITS, - DEBUG_UTIL_MENU_ITEM_CHEAT, - DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS, - DEBUG_UTIL_MENU_ITEM_EWRAM_COUNTERS, - DEBUG_UTIL_MENU_ITEM_STEVEN_MULTI // Please keep this at the bottom <3 -}; - -enum TimeMenuDebugMenu -{ - DEBUG_TIME_MENU_ITEM_PRINTTIME, - DEBUG_TIME_MENU_ITEM_PRINTTIMEOFDAY, - DEBUG_TIME_MENU_ITEM_TIMESOFDAY, - DEBUG_TIME_MENU_ITEM_WEEKDAYS, - DEBUG_TIME_MENU_ITEM_CHECKWALLCLOCK, - DEBUG_TIME_MENU_ITEM_SETWALLCLOCK, -}; - -enum TimeMenuTimeOfDay -{ - DEBUG_TIME_MENU_ITEM_MORNING, - DEBUG_TIME_MENU_ITEM_DAY, - DEBUG_TIME_MENU_ITEM_EVENING, - DEBUG_TIME_MENU_ITEM_NIGHT, -}; - -enum TimeMenuWeekdays -{ - DEBUG_TIME_MENU_ITEM_SUNDAY, - DEBUG_TIME_MENU_ITEM_MONDAY, - DEBUG_TIME_MENU_ITEM_TUESDAY, - DEBUG_TIME_MENU_ITEM_WEDNESDAY, - DEBUG_TIME_MENU_ITEM_THURSDAY, - DEBUG_TIME_MENU_ITEM_FRIDAY, - DEBUG_TIME_MENU_ITEM_SATURDAY, -}; - -enum GivePCBagDebugMenu -{ - DEBUG_PCBAG_MENU_ITEM_ACCESS_PC, - DEBUG_PCBAG_MENU_ITEM_FILL, - DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG, - DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES, -}; - -enum GivePCBagFillDebugMenu -{ - DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST, - DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW, - DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS, - DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS, - DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS, - DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM, - DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES, - DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS, -}; - -enum PartyDebugMenu -{ - DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER, - DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG, - DEBUG_PARTY_MENU_ITEM_HEAL_PARTY, - DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1, - DEBUG_PARTY_MENU_ITEM_CHECK_EVS, - DEBUG_PARTY_MENU_ITEM_CHECK_IVS, - DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY, -}; - -enum ScriptDebugMenu -{ - DEBUG_UTIL_MENU_ITEM_SCRIPT_1, - DEBUG_UTIL_MENU_ITEM_SCRIPT_2, - DEBUG_UTIL_MENU_ITEM_SCRIPT_3, - DEBUG_UTIL_MENU_ITEM_SCRIPT_4, - DEBUG_UTIL_MENU_ITEM_SCRIPT_5, - DEBUG_UTIL_MENU_ITEM_SCRIPT_6, - DEBUG_UTIL_MENU_ITEM_SCRIPT_7, - DEBUG_UTIL_MENU_ITEM_SCRIPT_8, + DEBUG_FNPC_BRENDAN, + DEBUG_FNPC_MAY, + DEBUG_FNPC_STEVEN, + DEBUG_FNPC_WALLY, + DEBUG_FNPC_RED, + DEBUG_FNPC_LEAF, + DEBUG_FNPC_COUNT, }; enum FlagsVarsDebugMenu @@ -192,11 +106,11 @@ enum FlagsVarsDebugMenu DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE, - DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE, }; -enum BattleType +enum DebugBattleType { DEBUG_BATTLE_0_MENU_ITEM_WILD, DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE, @@ -205,7 +119,7 @@ enum BattleType DEBUG_BATTLE_0_MENU_ITEM_MULTI, }; -enum BattleAIFlags +enum DebugBattleAIFlags { DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01, @@ -228,63 +142,23 @@ enum BattleAIFlags DEBUG_BATTLE_1_MENU_ITEM_CONTINUE, }; -enum BattleTerrain +enum DebugBattleEnvironment { - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9, -}; - -enum GiveDebugMenu -{ - DEBUG_GIVE_MENU_ITEM_ITEM_X, - DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE, - DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX, - DEBUG_GIVE_MENU_ITEM_MAX_MONEY, - DEBUG_GIVE_MENU_ITEM_MAX_COINS, - DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS, - DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG, -}; - -enum SoundDebugMenu -{ - DEBUG_SOUND_MENU_ITEM_SE, - DEBUG_SOUND_MENU_ITEM_MUS, -}; - -enum BerryFunctionsMenu -{ - DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL, - DEBUG_BERRY_FUNCTIONS_MENU_READY, - DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE, - DEBUG_BERRY_FUNCTIONS_MENU_WEEDS, - DEBUG_BERRY_FUNCTIONS_MENU_PESTS, -}; - -enum PlayerDebugMenu -{ - DEBUG_PLAYER_MENU_ITEM_PLAYER_NAME, - DEBUG_PLAYER_MENU_ITEM_PLAYER_GENDER, - DEBUG_PLAYER_MENU_ITEM_PLAYER_ID, -}; - -enum ROMInfoDebugMenu -{ - DEBUG_ROM_INFO_MENU_ITEM_SAVEBLOCK, - DEBUG_ROM_INFO_MENU_ITEM_ROM_SPACE, - DEBUG_ROM_INFO_MENU_ITEM_EXPANSION_VER, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_0, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_1, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_2, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_3, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_4, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_5, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_6, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_7, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_8, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_9, }; // ******************************* // Constants -#define DEBUG_MENU_FONT FONT_SHORT +#define DEBUG_MENU_FONT FONT_NORMAL #define DEBUG_MENU_WIDTH_MAIN 17 #define DEBUG_MENU_HEIGHT_MAIN 9 @@ -310,9 +184,22 @@ enum ROMInfoDebugMenu #define DEBUG_NUMBER_ICON_X 210 #define DEBUG_NUMBER_ICON_Y 50 -#define DEBUG_MAX_MENU_ITEMS 50 +#define DEBUG_MAX_MENU_ITEMS 20 +#define DEBUG_MAX_SUB_MENU_LEVELS 4 // ******************************* +struct DebugMenuOption; + +typedef void (*DebugFunc)(u8 taskId); +typedef void (*DebugSubmenuFunc)(u8 taskId, const struct DebugMenuOption *items); + +struct DebugMenuOption +{ + const u8 *text; + const void *action; + const void *actionParams; +}; + struct DebugMonData { u16 species; @@ -330,68 +217,35 @@ struct DebugMonData struct DebugMenuListData { - struct ListMenuItem listItems[20 + 1]; + const struct DebugMenuOption *subMenuItems[DEBUG_MAX_SUB_MENU_LEVELS]; + struct ListMenuItem listItems[DEBUG_MAX_MENU_ITEMS + 1]; u8 itemNames[DEBUG_MAX_MENU_ITEMS + 1][26]; u8 listId; }; -struct DebugBattleData -{ - u8 submenu; - u8 battleType; - u8 battleTerrain; - bool8 aiFlags[AI_FLAG_COUNT]; -}; - // EWRAM static EWRAM_DATA struct DebugMonData *sDebugMonData = NULL; static EWRAM_DATA struct DebugMenuListData *sDebugMenuListData = NULL; -static EWRAM_DATA struct DebugBattleData *sDebugBattleData = NULL; EWRAM_DATA bool8 gIsDebugBattle = FALSE; EWRAM_DATA u64 gDebugAIFlags = 0; // ******************************* // Define functions -static void Debug_ReShowMainMenu(void); -static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate); +static void Debug_ShowMenu(DebugFunc HandleInput, const struct DebugMenuOption *items); +static u8 Debug_GenerateListMenuNames(void); static void Debug_DestroyMenu(u8 taskId); -static void Debug_DestroyMenu_Full(u8 taskId); static void DebugAction_Cancel(u8 taskId); static void DebugAction_DestroyExtraWindow(u8 taskId); -static void Debug_InitDebugBattleData(void); static void Debug_RefreshListMenu(u8 taskId); -static void Debug_RedrawListMenu(u8 taskId); -static void DebugAction_Util_Script_1(u8 taskId); -static void DebugAction_Util_Script_2(u8 taskId); -static void DebugAction_Util_Script_3(u8 taskId); -static void DebugAction_Util_Script_4(u8 taskId); -static void DebugAction_Util_Script_5(u8 taskId); -static void DebugAction_Util_Script_6(u8 taskId); -static void DebugAction_Util_Script_7(u8 taskId); -static void DebugAction_Util_Script_8(u8 taskId); +static void DebugAction_OpenSubMenu(u8 taskId, const struct DebugMenuOption *items); +static void DebugAction_OpenSubMenuFlagsVars(u8 taskId, const struct DebugMenuOption *items); +static void DebugAction_OpenSubMenuFakeRTC(u8 taskId, const struct DebugMenuOption *items); +static void DebugAction_OpenSubMenuCreateFollowerNPC(u8 taskId, const struct DebugMenuOption *items); +static void DebugAction_ExecuteScript(u8 taskId, const u8 *script); +static void DebugAction_ToggleFlag(u8 taskId); -static void DebugAction_OpenUtilitiesMenu(u8 taskId); -static void DebugAction_OpenPCBagMenu(u8 taskId); -static void DebugAction_OpenPartyMenu(u8 taskId); -static void DebugAction_OpenScriptsMenu(u8 taskId); -static void DebugAction_OpenFlagsVarsMenu(u8 taskId); -static void DebugAction_OpenGiveMenu(u8 taskId); -static void DebugAction_OpenSoundMenu(u8 taskId); -static void DebugAction_OpenPlayerMenu(u8 taskId); -static void DebugAction_OpenROMInfoMenu(u8 taskId); - -static void DebugTask_HandleMenuInput_Main(u8 taskId); -static void DebugTask_HandleMenuInput_Utilities(u8 taskId); -static void DebugTask_HandleMenuInput_PCBag(u8 taskId); -static void DebugTask_HandleMenuInput_PCBag_Fill(u8 taskId); -static void DebugTask_HandleMenuInput_Party(u8 taskId); -static void DebugTask_HandleMenuInput_Scripts(u8 taskId); -static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId); -static void DebugTask_HandleMenuInput_Battle(u8 taskId); -static void DebugTask_HandleMenuInput_Give(u8 taskId); -static void DebugTask_HandleMenuInput_Sound(u8 taskId); -static void DebugTask_HandleMenuInput_BerryFunctions(u8 taskId); +static void DebugTask_HandleMenuInput_General(u8 taskId); static void DebugAction_Util_Fly(u8 taskId); static void DebugAction_Util_Warp_Warp(u8 taskId); @@ -400,25 +254,15 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId); static void DebugAction_Util_Warp_SelectWarp(u8 taskId); static void DebugAction_Util_Weather(u8 taskId); static void DebugAction_Util_Weather_SelectId(u8 taskId); -static void DebugAction_Util_FontTest(u8 taskId); -static void DebugAction_TimeMenu_CheckWallClock(u8 taskId); -static void DebugAction_TimeMenu_SetWallClock(u8 taskId); static void DebugAction_Util_WatchCredits(u8 taskId); static void DebugAction_Util_CheatStart(u8 taskId); -static void DebugAction_Util_BerryFunctions(u8 taskId); -static void DebugAction_Util_CheckEWRAMCounters(u8 taskId); -static void DebugAction_Util_Steven_Multi(u8 taskId); -static void DebugAction_Util_OpenTimeMenu(u8 taskId); - -static void DebugAction_TimeMenu_PrintTime(u8 taskId); -static void DebugAction_TimeMenu_PrintTimeOfDay(u8 taskId); -static void DebugAction_TimeMenu_TimesOfDay(u8 taskId); -static void DebugAction_TimeMenu_Weekdays(u8 taskId); static void DebugAction_TimeMenu_ChangeTimeOfDay(u8 taskId); static void DebugAction_TimeMenu_ChangeWeekdays(u8 taskId); -static void DebugAction_OpenPCBagFillMenu(u8 taskId); +static void DebugAction_CreateFollowerNPC(u8 taskId); +static void DebugAction_DestroyFollowerNPC(u8 taskId); + static void DebugAction_PCBag_Fill_PCBoxes_Fast(u8 taskId); static void DebugAction_PCBag_Fill_PCBoxes_Slow(u8 taskId); static void DebugAction_PCBag_Fill_PCItemStorage(u8 taskId); @@ -427,17 +271,13 @@ static void DebugAction_PCBag_Fill_PocketPokeBalls(u8 taskId); static void DebugAction_PCBag_Fill_PocketTMHM(u8 taskId); static void DebugAction_PCBag_Fill_PocketBerries(u8 taskId); static void DebugAction_PCBag_Fill_PocketKeyItems(u8 taskId); -static void DebugAction_PCBag_AccessPC(u8 taskId); static void DebugAction_PCBag_ClearBag(u8 taskId); static void DebugAction_PCBag_ClearBoxes(u8 taskId); -static void DebugAction_Party_MoveReminder(u8 taskId); -static void DebugAction_Party_HatchAnEgg(u8 taskId); static void DebugAction_Party_HealParty(u8 taskId); -static void DebugAction_Party_InflictStatus1(u8 taskId); -static void DebugAction_Party_CheckEVs(u8 taskId); -static void DebugAction_Party_CheckIVs(u8 taskId); static void DebugAction_Party_ClearParty(u8 taskId); +static void DebugAction_Party_SetParty(u8 taskId); +static void DebugAction_Party_BattleSingle(u8 taskId); static void DebugAction_FlagsVars_Flags(u8 taskId); static void DebugAction_FlagsVars_FlagsSelect(u8 taskId); @@ -461,8 +301,6 @@ static void DebugAction_FlagsVars_BagUseOnOff(u8 taskId); static void DebugAction_FlagsVars_CatchingOnOff(u8 taskId); static void DebugAction_FlagsVars_RunningShoes(u8 taskId); -static void Debug_InitializeBattle(u8 taskId); - static void DebugAction_Give_Item(u8 taskId); static void DebugAction_Give_Item_SelectId(u8 taskId); static void DebugAction_Give_Item_SelectQuantity(u8 taskId); @@ -480,6 +318,8 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId); static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId); static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId); static void DebugAction_Give_Pokemon_Move(u8 taskId); +static void DebugAction_Give_Decoration(u8 taskId); +static void DebugAction_Give_Decoration_SelectId(u8 taskId); static void DebugAction_Give_MaxMoney(u8 taskId); static void DebugAction_Give_MaxCoins(u8 taskId); static void DebugAction_Give_MaxBattlePoints(u8 taskId); @@ -500,17 +340,15 @@ static void DebugAction_Player_Name(u8 taskId); static void DebugAction_Player_Gender(u8 taskId); static void DebugAction_Player_Id(u8 taskId); -static void DebugAction_ROMInfo_CheckSaveBlock(u8 taskId); -static void DebugAction_ROMInfo_CheckROMSpace(u8 taskId); -static void DebugAction_ROMInfo_ExpansionVersion(u8 taskId); - extern const u8 Debug_FlagsNotSetOverworldConfigMessage[]; extern const u8 Debug_FlagsNotSetBattleConfigMessage[]; +extern const u8 Debug_VarsNotSetBattleConfigMessage[]; extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; extern const u8 Debug_EventScript_FontTest[]; extern const u8 Debug_EventScript_CheckEVs[]; extern const u8 Debug_EventScript_CheckIVs[]; extern const u8 Debug_EventScript_InflictStatus1[]; +extern const u8 Debug_EventScript_SetHiddenNature[]; extern const u8 Debug_EventScript_Script_1[]; extern const u8 Debug_EventScript_Script_2[]; extern const u8 Debug_EventScript_Script_3[]; @@ -533,6 +371,8 @@ extern const u8 Debug_CheckROMSpace[]; extern const u8 Debug_BoxFilledMessage[]; extern const u8 Debug_ShowExpansionVersion[]; extern const u8 Debug_EventScript_EWRAMCounters[]; +extern const u8 Debug_Follower_NPC_Event_Script[]; +extern const u8 Debug_Follower_NPC_Not_Enabled[]; extern const u8 Debug_EventScript_Steven_Multi[]; extern const u8 Debug_EventScript_PrintTimeOfDay[]; extern const u8 Debug_EventScript_TellTheTime[]; @@ -547,13 +387,14 @@ extern const u8 TwoIsland_House_EventScript_ChooseMonToTutor[]; // Text // General +static const u8 sDebugText_Arrow[] = _("{CLEAR_TO 110}{RIGHT_ARROW}"); static const u8 sDebugText_True[] = _("TRUE"); static const u8 sDebugText_False[] = _("FALSE"); static const u8 sDebugText_Colored_True[] = _("{COLOR GREEN}TRUE"); static const u8 sDebugText_Colored_False[] = _("{COLOR RED}FALSE"); static const u8 sDebugText_Dashes[] = _("---"); static const u8 sDebugText_Empty[] = _(""); -static const u8 sDebugText_Continue[] = _("Continue…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Continue[] = _("Continue…"); // Util Menu static const u8 sDebugText_Util_WarpToMap_SelectMapGroup[] = _("Group: {STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n\n{STR_VAR_3}{CLEAR_TO 90}"); static const u8 sDebugText_Util_WarpToMap_SelectMap[] = _("Map: {STR_VAR_1}{CLEAR_TO 90}\nMapSec:{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}{CLEAR_TO 90}"); @@ -580,21 +421,23 @@ static const u8 *const gTimeOfDayStringsTable[TIMES_OF_DAY_COUNT] = { COMPOUND_STRING("Night"), }; +// Follower NPC + +static const u8 *const gFollowerNPCStringsTable[DEBUG_FNPC_COUNT] = { + COMPOUND_STRING("Brendan"), + COMPOUND_STRING("May"), + COMPOUND_STRING("Steven"), + COMPOUND_STRING("Wally"), + COMPOUND_STRING("Red"), + COMPOUND_STRING("Leaf"), +}; + // Flags/Vars Menu -static const u8 sDebugText_FlagsVars_Flag[] = _("Flag: {STR_VAR_1}{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}"); static const u8 sDebugText_FlagsVars_VariableHex[] = _("{STR_VAR_1}{CLEAR_TO 90}\n0x{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_FlagsVars_Variable[] = _("Var: {STR_VAR_1}{CLEAR_TO 90}\nVal: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_2}"); static const u8 sDebugText_FlagsVars_VariableValueSet[] = _("Var: {STR_VAR_1}{CLEAR_TO 90}\nVal: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_2}"); // Give Menu -static const u8 sDebugText_ItemQuantity[] = _("Quantity:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}"); -static const u8 sDebugText_ItemID[] = _("Item ID: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}"); -static const u8 sDebugText_PokemonID[] = _("Species: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}{CLEAR_TO 90}"); -static const u8 sDebugText_PokemonLevel[] = _("Level:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_PokemonShiny[] = _("Shiny:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}"); -static const u8 sDebugText_PokemonAbility[] = _("Ability Num: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); -static const u8 sDebugText_PokemonTeraType[] = _("Tera Type: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); -static const u8 sDebugText_PokemonDynamaxLevel[] = _("Dmax Lvl:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); -static const u8 sDebugText_PokemonGmaxFactor[] = _("Gmax Factor:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}"); static const u8 sDebugText_IVs[] = _("IV {STR_VAR_1}:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_EVs[] = _("EV {STR_VAR_1}:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); // Sound Menu @@ -628,378 +471,212 @@ static const s32 sPowersOfTen[] = }; // ******************************* -// List Menu Items -static const struct ListMenuItem sDebugMenu_Items_Main[] = +// Menu Actions. Make sure that submenus are defined before the menus that call them. +static const struct DebugMenuOption sDebugMenu_Actions_TimeMenu_TimesOfDay[] = { - [DEBUG_MENU_ITEM_UTILITIES] = {COMPOUND_STRING("Utilities…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_UTILITIES}, - [DEBUG_MENU_ITEM_PCBAG] = {COMPOUND_STRING("PC/Bag…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_PCBAG}, - [DEBUG_MENU_ITEM_PARTY] = {COMPOUND_STRING("Party…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_PARTY}, - [DEBUG_MENU_ITEM_GIVE] = {COMPOUND_STRING("Give X…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_GIVE}, - [DEBUG_MENU_ITEM_PLAYER] = {COMPOUND_STRING("Player…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_PLAYER}, - [DEBUG_MENU_ITEM_SCRIPTS] = {COMPOUND_STRING("Scripts…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_SCRIPTS}, - [DEBUG_MENU_ITEM_FLAGVAR] = {COMPOUND_STRING("Flags & Vars…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_FLAGVAR}, - //[DEBUG_MENU_ITEM_BATTLE] = {COMPOUND_STRING("Battle Test{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_BATTLE}, - [DEBUG_MENU_ITEM_SOUND] = {COMPOUND_STRING("Sound…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_SOUND}, - [DEBUG_MENU_ITEM_ROMINFO] = {COMPOUND_STRING("ROM Info…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_MENU_ITEM_ROMINFO}, - [DEBUG_MENU_ITEM_CANCEL] = {COMPOUND_STRING("Cancel"), DEBUG_MENU_ITEM_CANCEL}, + [TIME_MORNING] = { gTimeOfDayStringsTable[TIME_MORNING], DebugAction_TimeMenu_ChangeTimeOfDay }, + [TIME_DAY] = { gTimeOfDayStringsTable[TIME_DAY], DebugAction_TimeMenu_ChangeTimeOfDay }, + [TIME_EVENING] = { gTimeOfDayStringsTable[TIME_EVENING], DebugAction_TimeMenu_ChangeTimeOfDay }, + [TIME_NIGHT] = { gTimeOfDayStringsTable[TIME_NIGHT], DebugAction_TimeMenu_ChangeTimeOfDay }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Utilities[] = +static const struct DebugMenuOption sDebugMenu_Actions_TimeMenu_Weekdays[] = { - [DEBUG_UTIL_MENU_ITEM_FLY] = {COMPOUND_STRING("Fly to map…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_FLY}, - [DEBUG_UTIL_MENU_ITEM_WARP] = {COMPOUND_STRING("Warp to map warp…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_WARP}, - [DEBUG_UTIL_MENU_ITEM_WEATHER] = {COMPOUND_STRING("Set weather…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_WEATHER}, - [DEBUG_UTIL_MENU_ITEM_FONT_TEST] = {COMPOUND_STRING("Font Test…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_FONT_TEST}, - [DEBUG_UTIL_MENU_ITEM_TIME_MENU] = {COMPOUND_STRING("Time Functions…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_TIME_MENU}, - [DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = {COMPOUND_STRING("Watch credits…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_WATCHCREDITS}, - [DEBUG_UTIL_MENU_ITEM_CHEAT] = {COMPOUND_STRING("Cheat start"), DEBUG_UTIL_MENU_ITEM_CHEAT}, - [DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS] = {COMPOUND_STRING("Berry Functions…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS}, - [DEBUG_UTIL_MENU_ITEM_EWRAM_COUNTERS] = {COMPOUND_STRING("EWRAM Counters…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_UTIL_MENU_ITEM_EWRAM_COUNTERS}, - [DEBUG_UTIL_MENU_ITEM_STEVEN_MULTI] = {COMPOUND_STRING("Steven Multi"), DEBUG_UTIL_MENU_ITEM_STEVEN_MULTI}, + [WEEKDAY_SUN] = { gDayNameStringsTable[WEEKDAY_SUN], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_MON] = { gDayNameStringsTable[WEEKDAY_MON], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_TUE] = { gDayNameStringsTable[WEEKDAY_TUE], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_WED] = { gDayNameStringsTable[WEEKDAY_WED], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_THU] = { gDayNameStringsTable[WEEKDAY_THU], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_FRI] = { gDayNameStringsTable[WEEKDAY_FRI], DebugAction_TimeMenu_ChangeWeekdays }, + [WEEKDAY_SAT] = { gDayNameStringsTable[WEEKDAY_SAT], DebugAction_TimeMenu_ChangeWeekdays }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_TimeMenu[] = +static const struct DebugMenuOption sDebugMenu_Actions_FollowerNPCMenu_Create[] = { - [DEBUG_TIME_MENU_ITEM_PRINTTIME] = {COMPOUND_STRING("Print current time…"), DEBUG_TIME_MENU_ITEM_PRINTTIME}, - [DEBUG_TIME_MENU_ITEM_PRINTTIMEOFDAY] = {COMPOUND_STRING("{FONT_NARROW}Print current time of day…"), DEBUG_TIME_MENU_ITEM_PRINTTIMEOFDAY}, - [DEBUG_TIME_MENU_ITEM_TIMESOFDAY] = {COMPOUND_STRING("{FONT_NARROW}Change current time of day…"), DEBUG_TIME_MENU_ITEM_TIMESOFDAY}, - [DEBUG_TIME_MENU_ITEM_WEEKDAYS] = {COMPOUND_STRING("Change current weekday…"), DEBUG_TIME_MENU_ITEM_WEEKDAYS}, - [DEBUG_TIME_MENU_ITEM_CHECKWALLCLOCK] = {COMPOUND_STRING("Check wall clock…"), DEBUG_TIME_MENU_ITEM_CHECKWALLCLOCK}, - [DEBUG_TIME_MENU_ITEM_SETWALLCLOCK] = {COMPOUND_STRING("Set wall clock…"), DEBUG_TIME_MENU_ITEM_SETWALLCLOCK}, + [DEBUG_FNPC_BRENDAN] = { gFollowerNPCStringsTable[DEBUG_FNPC_BRENDAN], DebugAction_CreateFollowerNPC }, + [DEBUG_FNPC_MAY] = { gFollowerNPCStringsTable[DEBUG_FNPC_MAY], DebugAction_CreateFollowerNPC }, + [DEBUG_FNPC_STEVEN] = { gFollowerNPCStringsTable[DEBUG_FNPC_STEVEN], DebugAction_CreateFollowerNPC }, + [DEBUG_FNPC_WALLY] = { gFollowerNPCStringsTable[DEBUG_FNPC_WALLY], DebugAction_CreateFollowerNPC }, + [DEBUG_FNPC_RED] = { gFollowerNPCStringsTable[DEBUG_FNPC_RED], DebugAction_CreateFollowerNPC }, + [DEBUG_FNPC_LEAF] = { gFollowerNPCStringsTable[DEBUG_FNPC_LEAF], DebugAction_CreateFollowerNPC }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_TimeMenu_TimesOfDay[] = +static const struct DebugMenuOption sDebugMenu_Actions_TimeMenu[] = { - [DEBUG_TIME_MENU_ITEM_MORNING] = {gTimeOfDayStringsTable[TIME_MORNING], DEBUG_TIME_MENU_ITEM_MORNING}, - [DEBUG_TIME_MENU_ITEM_DAY] = {gTimeOfDayStringsTable[TIME_DAY], DEBUG_TIME_MENU_ITEM_DAY}, - [DEBUG_TIME_MENU_ITEM_EVENING] = {gTimeOfDayStringsTable[TIME_EVENING], DEBUG_TIME_MENU_ITEM_EVENING}, - [DEBUG_TIME_MENU_ITEM_NIGHT] = {gTimeOfDayStringsTable[TIME_NIGHT], DEBUG_TIME_MENU_ITEM_NIGHT}, + { COMPOUND_STRING("Get time…"), DebugAction_ExecuteScript, Debug_EventScript_TellTheTime }, + { COMPOUND_STRING("Get time of day…"), DebugAction_ExecuteScript, Debug_EventScript_PrintTimeOfDay }, + { COMPOUND_STRING("Set time of day…"), DebugAction_OpenSubMenuFakeRTC, sDebugMenu_Actions_TimeMenu_TimesOfDay }, + { COMPOUND_STRING("Set weekday…"), DebugAction_OpenSubMenuFakeRTC, sDebugMenu_Actions_TimeMenu_Weekdays }, + // { COMPOUND_STRING("Check wall clock…"), DebugAction_ExecuteScript, PlayersHouse_2F_EventScript_CheckWallClock }, + // { COMPOUND_STRING("Set wall clock…"), DebugAction_ExecuteScript, PlayersHouse_2F_EventScript_SetWallClock }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_TimeMenu_Weekdays[] = +static const struct DebugMenuOption sDebugMenu_Actions_BerryFunctions[] = { - [DEBUG_TIME_MENU_ITEM_SUNDAY] = {gDayNameStringsTable[WEEKDAY_SUN], DEBUG_TIME_MENU_ITEM_SUNDAY}, - [DEBUG_TIME_MENU_ITEM_MONDAY] = {gDayNameStringsTable[WEEKDAY_MON], DEBUG_TIME_MENU_ITEM_MONDAY}, - [DEBUG_TIME_MENU_ITEM_TUESDAY] = {gDayNameStringsTable[WEEKDAY_TUE], DEBUG_TIME_MENU_ITEM_TUESDAY}, - [DEBUG_TIME_MENU_ITEM_WEDNESDAY] = {gDayNameStringsTable[WEEKDAY_WED], DEBUG_TIME_MENU_ITEM_WEDNESDAY}, - [DEBUG_TIME_MENU_ITEM_THURSDAY] = {gDayNameStringsTable[WEEKDAY_THU], DEBUG_TIME_MENU_ITEM_THURSDAY}, - [DEBUG_TIME_MENU_ITEM_FRIDAY] = {gDayNameStringsTable[WEEKDAY_FRI], DEBUG_TIME_MENU_ITEM_FRIDAY}, - [DEBUG_TIME_MENU_ITEM_SATURDAY] = {gDayNameStringsTable[WEEKDAY_SAT], DEBUG_TIME_MENU_ITEM_SATURDAY}, + { COMPOUND_STRING("Clear map trees"), DebugAction_BerryFunctions_ClearAll }, + { COMPOUND_STRING("Ready map trees"), DebugAction_BerryFunctions_Ready }, + { COMPOUND_STRING("Grow map trees"), DebugAction_BerryFunctions_NextStage }, + { COMPOUND_STRING("Give map trees pests"), DebugAction_BerryFunctions_Pests }, + { COMPOUND_STRING("Give map trees weeds"), DebugAction_BerryFunctions_Weeds }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_PCBag[] = +static const struct DebugMenuOption sDebugMenu_Actions_FollowerNPCMenu[] = { - [DEBUG_PCBAG_MENU_ITEM_ACCESS_PC] = {COMPOUND_STRING("Access PC"), DEBUG_PCBAG_MENU_ITEM_ACCESS_PC}, - [DEBUG_PCBAG_MENU_ITEM_FILL] = {COMPOUND_STRING("Fill…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_PCBAG_MENU_ITEM_FILL}, - [DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG] = {COMPOUND_STRING("Clear Bag"), DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG}, - [DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES] = {COMPOUND_STRING("Clear Storage Boxes"), DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES}, + { COMPOUND_STRING("Create Follower"), DebugAction_OpenSubMenuCreateFollowerNPC, sDebugMenu_Actions_FollowerNPCMenu_Create }, + { COMPOUND_STRING("Destroy Follower"), DebugAction_DestroyFollowerNPC }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_PCBag_Fill[] = +static const struct DebugMenuOption sDebugMenu_Actions_Utilities[] = { - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST] = {COMPOUND_STRING("Fill PC Boxes Fast"), DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST}, - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW] = {COMPOUND_STRING("Fill PC Boxes Slow (LAG!)"), DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW}, - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS] = {COMPOUND_STRING("Fill PC Items") , DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS}, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS] = {COMPOUND_STRING("Fill Pocket Items"), DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS}, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS] = {COMPOUND_STRING("Fill Pocket Poké Balls"), DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS}, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM] = {COMPOUND_STRING("Fill Pocket TMHM"), DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM}, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES] = {COMPOUND_STRING("Fill Pocket Berries"), DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES}, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS] = {COMPOUND_STRING("Fill Pocket Key Items"), DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS}, + { COMPOUND_STRING("Fly to map…"), DebugAction_Util_Fly }, + { COMPOUND_STRING("Warp to map warp…"), DebugAction_Util_Warp_Warp }, + { COMPOUND_STRING("Set weather…"), DebugAction_Util_Weather }, + { COMPOUND_STRING("Font Test…"), DebugAction_ExecuteScript, Debug_EventScript_FontTest }, + { COMPOUND_STRING("Time Functions…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_TimeMenu, }, + { COMPOUND_STRING("Watch credits…"), DebugAction_Util_WatchCredits }, + { COMPOUND_STRING("Cheat start"), DebugAction_Util_CheatStart }, + { COMPOUND_STRING("Berry Functions…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_BerryFunctions }, + { COMPOUND_STRING("EWRAM Counters…"), DebugAction_ExecuteScript, Debug_EventScript_EWRAMCounters }, + { COMPOUND_STRING("Follower NPC…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_FollowerNPCMenu }, + { COMPOUND_STRING("Steven Multi"), DebugAction_ExecuteScript, Debug_EventScript_Steven_Multi }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Party[] = +static const struct DebugMenuOption sDebugMenu_Actions_PCBag_Fill[] = { - [DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = {COMPOUND_STRING("Move Reminder"), DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER}, - [DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = {COMPOUND_STRING("Hatch an Egg"), DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG}, - [DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = {COMPOUND_STRING("Heal party"), DEBUG_PARTY_MENU_ITEM_HEAL_PARTY}, - [DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = {COMPOUND_STRING("Inflict Status1"), DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1}, - [DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = {COMPOUND_STRING("Check EVs"), DEBUG_PARTY_MENU_ITEM_CHECK_EVS}, - [DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = {COMPOUND_STRING("Check IVs"), DEBUG_PARTY_MENU_ITEM_CHECK_IVS}, - [DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = {COMPOUND_STRING("Clear Party"), DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY}, + { COMPOUND_STRING("Fill PC Boxes Fast"), DebugAction_PCBag_Fill_PCBoxes_Fast }, + { COMPOUND_STRING("Fill PC Boxes Slow (LAG!)"), DebugAction_PCBag_Fill_PCBoxes_Slow }, + { COMPOUND_STRING("Fill PC Items") , DebugAction_PCBag_Fill_PCItemStorage }, + { COMPOUND_STRING("Fill Pocket Items"), DebugAction_PCBag_Fill_PocketItems }, + { COMPOUND_STRING("Fill Pocket Poké Balls"), DebugAction_PCBag_Fill_PocketPokeBalls }, + { COMPOUND_STRING("Fill Pocket TMHM"), DebugAction_PCBag_Fill_PocketTMHM }, + { COMPOUND_STRING("Fill Pocket Berries"), DebugAction_PCBag_Fill_PocketBerries }, + { COMPOUND_STRING("Fill Pocket Key Items"), DebugAction_PCBag_Fill_PocketKeyItems }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Scripts[] = +static const struct DebugMenuOption sDebugMenu_Actions_PCBag[] = { - [DEBUG_UTIL_MENU_ITEM_SCRIPT_1] = {COMPOUND_STRING("Script 1"), DEBUG_UTIL_MENU_ITEM_SCRIPT_1}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_2] = {COMPOUND_STRING("Script 2"), DEBUG_UTIL_MENU_ITEM_SCRIPT_2}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_3] = {COMPOUND_STRING("Script 3"), DEBUG_UTIL_MENU_ITEM_SCRIPT_3}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_4] = {COMPOUND_STRING("Script 4"), DEBUG_UTIL_MENU_ITEM_SCRIPT_4}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_5] = {COMPOUND_STRING("Script 5"), DEBUG_UTIL_MENU_ITEM_SCRIPT_5}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_6] = {COMPOUND_STRING("Script 6"), DEBUG_UTIL_MENU_ITEM_SCRIPT_6}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_7] = {COMPOUND_STRING("Script 7"), DEBUG_UTIL_MENU_ITEM_SCRIPT_7}, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_8] = {COMPOUND_STRING("Script 8"), DEBUG_UTIL_MENU_ITEM_SCRIPT_8}, + { COMPOUND_STRING("Access PC"), DebugAction_ExecuteScript, EventScript_PC }, + { COMPOUND_STRING("Fill…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_PCBag_Fill }, + { COMPOUND_STRING("Clear Bag"), DebugAction_PCBag_ClearBag }, + { COMPOUND_STRING("Clear Storage Boxes"), DebugAction_PCBag_ClearBoxes }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_FlagsVars[] = +static const struct DebugMenuOption sDebugMenu_Actions_Party[] = { - [DEBUG_FLAGVAR_MENU_ITEM_FLAGS] = {COMPOUND_STRING("Set Flag XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_FLAGVAR_MENU_ITEM_FLAGS}, - [DEBUG_FLAGVAR_MENU_ITEM_VARS] = {COMPOUND_STRING("Set Var XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_FLAGVAR_MENU_ITEM_VARS}, - [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = {COMPOUND_STRING("Pokédex Flags All"), DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL}, - [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = {COMPOUND_STRING("Pokédex Flags Reset"), DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = {COMPOUND_STRING("Toggle {STR_VAR_1}Pokédex"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = {COMPOUND_STRING("Toggle {STR_VAR_1}National Dex"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = {COMPOUND_STRING("Toggle {STR_VAR_1}PokéNav"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = {COMPOUND_STRING("Toggle {STR_VAR_1}Match Call"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = {COMPOUND_STRING("Toggle {STR_VAR_1}Running Shoes"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = {COMPOUND_STRING("Toggle {STR_VAR_1}Fly Flags"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = {COMPOUND_STRING("Toggle {STR_VAR_1}All badges"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = {COMPOUND_STRING("Toggle {STR_VAR_1}Game clear"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = {COMPOUND_STRING("Toggle {STR_VAR_1}Frontier Pass"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = {COMPOUND_STRING("Toggle {STR_VAR_1}Collision OFF"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = {COMPOUND_STRING("Toggle {STR_VAR_1}Encounter OFF"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = {COMPOUND_STRING("Toggle {STR_VAR_1}Trainer See OFF"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = {COMPOUND_STRING("Toggle {STR_VAR_1}Bag Use OFF"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE}, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = {COMPOUND_STRING("Toggle {STR_VAR_1}Catching OFF"), DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING}, + { COMPOUND_STRING("Move Reminder"), DebugAction_ExecuteScript, TwoIsland_House_EventScript_ChooseMonToTutor }, + { COMPOUND_STRING("Hatch an Egg"), DebugAction_ExecuteScript, Debug_HatchAnEgg }, + { COMPOUND_STRING("Heal party"), DebugAction_Party_HealParty }, + { COMPOUND_STRING("Inflict Status1"), DebugAction_ExecuteScript, Debug_EventScript_InflictStatus1 }, + { COMPOUND_STRING("Set Hidden Nature"), DebugAction_ExecuteScript, Debug_EventScript_SetHiddenNature }, + { COMPOUND_STRING("Check EVs"), DebugAction_ExecuteScript, Debug_EventScript_CheckEVs }, + { COMPOUND_STRING("Check IVs"), DebugAction_ExecuteScript, Debug_EventScript_CheckIVs }, + { COMPOUND_STRING("Clear Party"), DebugAction_Party_ClearParty }, + { COMPOUND_STRING("Set Party"), DebugAction_Party_SetParty }, + { COMPOUND_STRING("Start Debug Battle"), DebugAction_Party_BattleSingle }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Battle_0[] = +static const struct DebugMenuOption sDebugMenu_Actions_Give[] = { - [DEBUG_BATTLE_0_MENU_ITEM_WILD] = {COMPOUND_STRING("Wild…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_0_MENU_ITEM_WILD}, - [DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE] = {COMPOUND_STRING("Wild Double…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE}, - [DEBUG_BATTLE_0_MENU_ITEM_SINGLE] = {COMPOUND_STRING("Single…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_0_MENU_ITEM_SINGLE}, - [DEBUG_BATTLE_0_MENU_ITEM_DOUBLE] = {COMPOUND_STRING("Double…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_0_MENU_ITEM_DOUBLE}, - [DEBUG_BATTLE_0_MENU_ITEM_MULTI] = {COMPOUND_STRING("Multi…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_0_MENU_ITEM_MULTI}, + { COMPOUND_STRING("Give item XYZ…"), DebugAction_Give_Item }, + { COMPOUND_STRING("Pokémon (Basic)"), DebugAction_Give_PokemonSimple }, + { COMPOUND_STRING("Pokémon (Complex)"), DebugAction_Give_PokemonComplex }, + { COMPOUND_STRING("Give Decoration…"), DebugAction_Give_Decoration }, + { COMPOUND_STRING("Max Money"), DebugAction_Give_MaxMoney }, + { COMPOUND_STRING("Max Coins"), DebugAction_Give_MaxCoins }, + { COMPOUND_STRING("Max Battle Points"), DebugAction_Give_MaxBattlePoints }, + { COMPOUND_STRING("Daycare Egg"), DebugAction_Give_DayCareEgg }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Battle_1[] = +static const struct DebugMenuOption sDebugMenu_Actions_Player[] = { - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00] = {COMPOUND_STRING("{STR_VAR_1}Check bad move"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01] = {COMPOUND_STRING("{STR_VAR_1}Try to faint"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_02] = {COMPOUND_STRING("{STR_VAR_1}Check viability"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_02}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_03] = {COMPOUND_STRING("{STR_VAR_1}Setup first turn"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_03}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_04] = {COMPOUND_STRING("{STR_VAR_1}Risky"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_04}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_05] = {COMPOUND_STRING("{STR_VAR_1}Prefer strongest move"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_05}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_06] = {COMPOUND_STRING("{STR_VAR_1}Prefer Baton Pass"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_06}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_07] = {COMPOUND_STRING("{STR_VAR_1}Double battle"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_07}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_08] = {COMPOUND_STRING("{STR_VAR_1}HP aware"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_08}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_09] = {COMPOUND_STRING("{STR_VAR_1}Negate Unaware"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_09}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_10] = {COMPOUND_STRING("{STR_VAR_1}Will suicide"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_10}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_11] = {COMPOUND_STRING("{STR_VAR_1}Help partner"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_11}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_12] = {COMPOUND_STRING("{STR_VAR_1}Prefer status moves"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_12}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_13] = {COMPOUND_STRING("{STR_VAR_1}Stall"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_13}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_14] = {COMPOUND_STRING("{STR_VAR_1}Screener"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_14}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_15] = {COMPOUND_STRING("{STR_VAR_1}Smart switching"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_15}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_16] = {COMPOUND_STRING("{STR_VAR_1}Ace pokemon"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_16}, - [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_17] = {COMPOUND_STRING("{STR_VAR_1}Omniscient"), DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_17}, - [DEBUG_BATTLE_1_MENU_ITEM_CONTINUE] = {sDebugText_Continue, DEBUG_BATTLE_1_MENU_ITEM_CONTINUE}, + { COMPOUND_STRING("Player name"), DebugAction_Player_Name }, + { COMPOUND_STRING("Toggle gender"), DebugAction_Player_Gender }, + { COMPOUND_STRING("New Trainer ID"), DebugAction_Player_Id }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Battle_2[] = +static const struct DebugMenuOption sDebugMenu_Actions_Scripts[] = { - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0] = {COMPOUND_STRING("Grass…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1] = {COMPOUND_STRING("Long grass…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2] = {COMPOUND_STRING("Sand…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3] = {COMPOUND_STRING("Underwater…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4] = {COMPOUND_STRING("Water…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5] = {COMPOUND_STRING("Pond…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6] = {COMPOUND_STRING("Mountain…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7] = {COMPOUND_STRING("Cave…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8] = {COMPOUND_STRING("Building…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8}, - [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9] = {COMPOUND_STRING("Plain…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9}, + { COMPOUND_STRING("Script 1"), DebugAction_ExecuteScript, Debug_EventScript_Script_1 }, + { COMPOUND_STRING("Script 2"), DebugAction_ExecuteScript, Debug_EventScript_Script_2 }, + { COMPOUND_STRING("Script 3"), DebugAction_ExecuteScript, Debug_EventScript_Script_3 }, + { COMPOUND_STRING("Script 4"), DebugAction_ExecuteScript, Debug_EventScript_Script_4 }, + { COMPOUND_STRING("Script 5"), DebugAction_ExecuteScript, Debug_EventScript_Script_5 }, + { COMPOUND_STRING("Script 6"), DebugAction_ExecuteScript, Debug_EventScript_Script_6 }, + { COMPOUND_STRING("Script 7"), DebugAction_ExecuteScript, Debug_EventScript_Script_7 }, + { COMPOUND_STRING("Script 8"), DebugAction_ExecuteScript, Debug_EventScript_Script_8 }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Give[] = +static const struct DebugMenuOption sDebugMenu_Actions_Sound[] = { - [DEBUG_GIVE_MENU_ITEM_ITEM_X] = {COMPOUND_STRING("Give item XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_GIVE_MENU_ITEM_ITEM_X}, - [DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE] = {COMPOUND_STRING("Pokémon (Basic){CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE}, - [DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX] = {COMPOUND_STRING("Pokémon (Complex){CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX}, - [DEBUG_GIVE_MENU_ITEM_MAX_MONEY] = {COMPOUND_STRING("Max Money"), DEBUG_GIVE_MENU_ITEM_MAX_MONEY}, - [DEBUG_GIVE_MENU_ITEM_MAX_COINS] = {COMPOUND_STRING("Max Coins"), DEBUG_GIVE_MENU_ITEM_MAX_COINS}, - [DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS] = {COMPOUND_STRING("Max Battle Points"), DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS}, - [DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG] = {COMPOUND_STRING("Daycare Egg"), DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG}, + { COMPOUND_STRING("SFX…"), DebugAction_Sound_SE }, + { COMPOUND_STRING("Music…"), DebugAction_Sound_MUS }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Sound[] = +static const struct DebugMenuOption sDebugMenu_Actions_ROMInfo2[] = { - [DEBUG_SOUND_MENU_ITEM_SE] = {COMPOUND_STRING("SFX…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_SOUND_MENU_ITEM_SE}, - [DEBUG_SOUND_MENU_ITEM_MUS] = {COMPOUND_STRING("Music…{CLEAR_TO 110}{RIGHT_ARROW}"), DEBUG_SOUND_MENU_ITEM_MUS}, + { COMPOUND_STRING("Save Block space"), DebugAction_ExecuteScript, Debug_CheckSaveBlock }, + { COMPOUND_STRING("ROM space"), DebugAction_ExecuteScript, Debug_CheckROMSpace }, + { COMPOUND_STRING("Expansion Version"), DebugAction_ExecuteScript, Debug_ShowExpansionVersion }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_BerryFunctions[] = +static const struct DebugMenuOption sDebugMenu_Actions_Flags[] = { - [DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL] = {COMPOUND_STRING("Clear map trees"), DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL}, - [DEBUG_BERRY_FUNCTIONS_MENU_READY] = {COMPOUND_STRING("Ready map trees"), DEBUG_BERRY_FUNCTIONS_MENU_READY}, - [DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE] = {COMPOUND_STRING("Grow map trees"), DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE}, - [DEBUG_BERRY_FUNCTIONS_MENU_PESTS] = {COMPOUND_STRING("Give map trees pests"), DEBUG_BERRY_FUNCTIONS_MENU_PESTS}, - [DEBUG_BERRY_FUNCTIONS_MENU_WEEDS] = {COMPOUND_STRING("Give map trees weeds"), DEBUG_BERRY_FUNCTIONS_MENU_WEEDS}, + [DEBUG_FLAGVAR_MENU_ITEM_FLAGS] = { COMPOUND_STRING("Set Flag XYZ…"), DebugAction_FlagsVars_Flags }, + [DEBUG_FLAGVAR_MENU_ITEM_VARS] = { COMPOUND_STRING("Set Var XYZ…"), DebugAction_FlagsVars_Vars }, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = { COMPOUND_STRING("Pokédex Flags All"), DebugAction_FlagsVars_PokedexFlags_All }, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = { COMPOUND_STRING("Pokédex Flags Reset"), DebugAction_FlagsVars_PokedexFlags_Reset }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}Pokédex"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}National Dex"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchNatDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = { COMPOUND_STRING("Toggle {STR_VAR_1}PokéNav"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchPokeNav }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}Match Call"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchMatchCall }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = { COMPOUND_STRING("Toggle {STR_VAR_1}Running Shoes"), DebugAction_ToggleFlag, DebugAction_FlagsVars_RunningShoes }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Fly Flags"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFlyFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}All badges"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleBadgeFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = { COMPOUND_STRING("Toggle {STR_VAR_1}Game clear"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleGameClear }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Frontier Pass"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFrontierPass }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = { COMPOUND_STRING("Toggle {STR_VAR_1}Collision OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CollisionOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = { COMPOUND_STRING("Toggle {STR_VAR_1}Encounter OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_EncounterOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Trainer See OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_TrainerSeeOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = { COMPOUND_STRING("Toggle {STR_VAR_1}Catching OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CatchingOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Bag Use OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_BagUseOnOff }, + { NULL } }; -static const struct ListMenuItem sDebugMenu_Items_Player[] = +static const u8 *sDebugMenu_Actions_BagUse_Options[] = { - [DEBUG_PLAYER_MENU_ITEM_PLAYER_NAME] = {COMPOUND_STRING("Player name"), DEBUG_PLAYER_MENU_ITEM_PLAYER_NAME}, - [DEBUG_PLAYER_MENU_ITEM_PLAYER_GENDER] = {COMPOUND_STRING("Toggle gender"), DEBUG_PLAYER_MENU_ITEM_PLAYER_GENDER}, - [DEBUG_PLAYER_MENU_ITEM_PLAYER_ID] = {COMPOUND_STRING("New Trainer ID"), DEBUG_PLAYER_MENU_ITEM_PLAYER_ID}, + COMPOUND_STRING("No Bag: {STR_VAR_1}Inactive"), + COMPOUND_STRING("No Bag: {STR_VAR_1}VS Trainers"), + COMPOUND_STRING("No Bag: {STR_VAR_1}Active"), }; -static const struct ListMenuItem sDebugMenu_Items_ROMInfo[] = +static const struct DebugMenuOption sDebugMenu_Actions_Main[] = { - [DEBUG_ROM_INFO_MENU_ITEM_SAVEBLOCK] = {COMPOUND_STRING("Save Block space"), DEBUG_ROM_INFO_MENU_ITEM_SAVEBLOCK}, - [DEBUG_ROM_INFO_MENU_ITEM_ROM_SPACE] = {COMPOUND_STRING("ROM space"), DEBUG_ROM_INFO_MENU_ITEM_ROM_SPACE}, - [DEBUG_ROM_INFO_MENU_ITEM_EXPANSION_VER] = {COMPOUND_STRING("Expansion Version"), DEBUG_ROM_INFO_MENU_ITEM_EXPANSION_VER}, -}; - -// ******************************* -// Menu Actions -static void (*const sDebugMenu_Actions_Main[])(u8) = -{ - [DEBUG_MENU_ITEM_UTILITIES] = DebugAction_OpenUtilitiesMenu, - [DEBUG_MENU_ITEM_PCBAG] = DebugAction_OpenPCBagMenu, - [DEBUG_MENU_ITEM_PARTY] = DebugAction_OpenPartyMenu, - [DEBUG_MENU_ITEM_GIVE] = DebugAction_OpenGiveMenu, - [DEBUG_MENU_ITEM_PLAYER] = DebugAction_OpenPlayerMenu, - [DEBUG_MENU_ITEM_SCRIPTS] = DebugAction_OpenScriptsMenu, - [DEBUG_MENU_ITEM_FLAGVAR] = DebugAction_OpenFlagsVarsMenu, - //[DEBUG_MENU_ITEM_BATTLE] = DebugAction_OpenBattleMenu, - [DEBUG_MENU_ITEM_SOUND] = DebugAction_OpenSoundMenu, - [DEBUG_MENU_ITEM_ROMINFO] = DebugAction_OpenROMInfoMenu, - [DEBUG_MENU_ITEM_CANCEL] = DebugAction_Cancel -}; - -static void (*const sDebugMenu_Actions_Utilities[])(u8) = -{ - [DEBUG_UTIL_MENU_ITEM_FLY] = DebugAction_Util_Fly, - [DEBUG_UTIL_MENU_ITEM_WARP] = DebugAction_Util_Warp_Warp, - [DEBUG_UTIL_MENU_ITEM_WEATHER] = DebugAction_Util_Weather, - [DEBUG_UTIL_MENU_ITEM_FONT_TEST] = DebugAction_Util_FontTest, - [DEBUG_UTIL_MENU_ITEM_TIME_MENU] = DebugAction_Util_OpenTimeMenu, - [DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = DebugAction_Util_WatchCredits, - [DEBUG_UTIL_MENU_ITEM_CHEAT] = DebugAction_Util_CheatStart, - [DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS] = DebugAction_Util_BerryFunctions, - [DEBUG_UTIL_MENU_ITEM_EWRAM_COUNTERS] = DebugAction_Util_CheckEWRAMCounters, - [DEBUG_UTIL_MENU_ITEM_STEVEN_MULTI] = DebugAction_Util_Steven_Multi, -}; - -static void (*const sDebugMenu_Actions_PCBag[])(u8) = -{ - [DEBUG_PCBAG_MENU_ITEM_ACCESS_PC] = DebugAction_PCBag_AccessPC, - [DEBUG_PCBAG_MENU_ITEM_FILL] = DebugAction_OpenPCBagFillMenu, - [DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG] = DebugAction_PCBag_ClearBag, - [DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES] = DebugAction_PCBag_ClearBoxes, -}; - -static void (*const sDebugMenu_Actions_PCBag_Fill[])(u8) = -{ - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST] = DebugAction_PCBag_Fill_PCBoxes_Fast, - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW] = DebugAction_PCBag_Fill_PCBoxes_Slow, - [DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS] = DebugAction_PCBag_Fill_PCItemStorage, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS] = DebugAction_PCBag_Fill_PocketItems, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS] = DebugAction_PCBag_Fill_PocketPokeBalls, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM] = DebugAction_PCBag_Fill_PocketTMHM, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES] = DebugAction_PCBag_Fill_PocketBerries, - [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS] = DebugAction_PCBag_Fill_PocketKeyItems, -}; - -static void (*const sDebugMenu_Actions_Party[])(u8) = -{ - [DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = DebugAction_Party_MoveReminder, - [DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = DebugAction_Party_HatchAnEgg, - [DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = DebugAction_Party_HealParty, - [DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = DebugAction_Party_InflictStatus1, - [DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = DebugAction_Party_CheckEVs, - [DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = DebugAction_Party_CheckIVs, - [DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = DebugAction_Party_ClearParty, -}; - -static void (*const sDebugMenu_Actions_Scripts[])(u8) = -{ - [DEBUG_UTIL_MENU_ITEM_SCRIPT_1] = DebugAction_Util_Script_1, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_2] = DebugAction_Util_Script_2, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_3] = DebugAction_Util_Script_3, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_4] = DebugAction_Util_Script_4, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_5] = DebugAction_Util_Script_5, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_6] = DebugAction_Util_Script_6, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_7] = DebugAction_Util_Script_7, - [DEBUG_UTIL_MENU_ITEM_SCRIPT_8] = DebugAction_Util_Script_8, -}; - -static void (*const sDebugMenu_Actions_Flags[])(u8) = -{ - [DEBUG_FLAGVAR_MENU_ITEM_FLAGS] = DebugAction_FlagsVars_Flags, - [DEBUG_FLAGVAR_MENU_ITEM_VARS] = DebugAction_FlagsVars_Vars, - [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = DebugAction_FlagsVars_PokedexFlags_All, - [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = DebugAction_FlagsVars_PokedexFlags_Reset, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = DebugAction_FlagsVars_SwitchDex, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = DebugAction_FlagsVars_SwitchNatDex, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = DebugAction_FlagsVars_SwitchPokeNav, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = DebugAction_FlagsVars_SwitchMatchCall, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = DebugAction_FlagsVars_RunningShoes, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = DebugAction_FlagsVars_ToggleFlyFlags, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = DebugAction_FlagsVars_ToggleBadgeFlags, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = DebugAction_FlagsVars_ToggleGameClear, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = DebugAction_FlagsVars_ToggleFrontierPass, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = DebugAction_FlagsVars_CollisionOnOff, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = DebugAction_FlagsVars_EncounterOnOff, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = DebugAction_FlagsVars_TrainerSeeOnOff, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = DebugAction_FlagsVars_BagUseOnOff, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = DebugAction_FlagsVars_CatchingOnOff, -}; -static void (*const sDebugMenu_Actions_Give[])(u8) = -{ - [DEBUG_GIVE_MENU_ITEM_ITEM_X] = DebugAction_Give_Item, - [DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE] = DebugAction_Give_PokemonSimple, - [DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX] = DebugAction_Give_PokemonComplex, - [DEBUG_GIVE_MENU_ITEM_MAX_MONEY] = DebugAction_Give_MaxMoney, - [DEBUG_GIVE_MENU_ITEM_MAX_COINS] = DebugAction_Give_MaxCoins, - [DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS] = DebugAction_Give_MaxBattlePoints, - [DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG] = DebugAction_Give_DayCareEgg, -}; - -static void (*const sDebugMenu_Actions_Sound[])(u8) = -{ - [DEBUG_SOUND_MENU_ITEM_SE] = DebugAction_Sound_SE, - [DEBUG_SOUND_MENU_ITEM_MUS] = DebugAction_Sound_MUS, -}; - -static void (*const sDebugMenu_Actions_BerryFunctions[])(u8) = -{ - [DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL] = DebugAction_BerryFunctions_ClearAll, - [DEBUG_BERRY_FUNCTIONS_MENU_READY] = DebugAction_BerryFunctions_Ready, - [DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE] = DebugAction_BerryFunctions_NextStage, - [DEBUG_BERRY_FUNCTIONS_MENU_PESTS] = DebugAction_BerryFunctions_Pests, - [DEBUG_BERRY_FUNCTIONS_MENU_WEEDS] = DebugAction_BerryFunctions_Weeds, -}; - -static void (*const sDebugMenu_Actions_TimeMenu[])(u8) = -{ - [DEBUG_TIME_MENU_ITEM_PRINTTIME] = DebugAction_TimeMenu_PrintTime, - [DEBUG_TIME_MENU_ITEM_PRINTTIMEOFDAY] = DebugAction_TimeMenu_PrintTimeOfDay, - [DEBUG_TIME_MENU_ITEM_TIMESOFDAY] = DebugAction_TimeMenu_TimesOfDay, - [DEBUG_TIME_MENU_ITEM_WEEKDAYS] = DebugAction_TimeMenu_Weekdays, - [DEBUG_TIME_MENU_ITEM_CHECKWALLCLOCK] = DebugAction_TimeMenu_CheckWallClock, - [DEBUG_TIME_MENU_ITEM_SETWALLCLOCK] = DebugAction_TimeMenu_SetWallClock, -}; - -static void (*const sDebugMenu_Actions_TimeMenu_TimesOfDay[])(u8) = -{ - [DEBUG_TIME_MENU_ITEM_MORNING] = DebugAction_TimeMenu_ChangeTimeOfDay, - [DEBUG_TIME_MENU_ITEM_DAY] = DebugAction_TimeMenu_ChangeTimeOfDay, - [DEBUG_TIME_MENU_ITEM_EVENING] = DebugAction_TimeMenu_ChangeTimeOfDay, - [DEBUG_TIME_MENU_ITEM_NIGHT] = DebugAction_TimeMenu_ChangeTimeOfDay, -}; - -static void (*const sDebugMenu_Actions_TimeMenu_Weekdays[])(u8) = -{ - [DEBUG_TIME_MENU_ITEM_SUNDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_MONDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_TUESDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_WEDNESDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_THURSDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_FRIDAY] = DebugAction_TimeMenu_ChangeWeekdays, - [DEBUG_TIME_MENU_ITEM_SATURDAY] = DebugAction_TimeMenu_ChangeWeekdays, -}; - -static void (*const sDebugMenu_Actions_Player[])(u8) = -{ - [DEBUG_PLAYER_MENU_ITEM_PLAYER_NAME] = DebugAction_Player_Name, - [DEBUG_PLAYER_MENU_ITEM_PLAYER_GENDER] = DebugAction_Player_Gender, - [DEBUG_PLAYER_MENU_ITEM_PLAYER_ID] = DebugAction_Player_Id, -}; - -static void (*const sDebugMenu_Actions_ROMInfo[])(u8) = -{ - [DEBUG_ROM_INFO_MENU_ITEM_SAVEBLOCK] = DebugAction_ROMInfo_CheckSaveBlock, - [DEBUG_ROM_INFO_MENU_ITEM_ROM_SPACE] = DebugAction_ROMInfo_CheckROMSpace, - [DEBUG_ROM_INFO_MENU_ITEM_EXPANSION_VER] = DebugAction_ROMInfo_ExpansionVersion, + { COMPOUND_STRING("Utilities…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Utilities, }, + { COMPOUND_STRING("PC/Bag…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_PCBag, }, + { COMPOUND_STRING("Party…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Party, }, + { COMPOUND_STRING("Give X…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Give, }, + { COMPOUND_STRING("Player…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Player, }, + { COMPOUND_STRING("Scripts…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Scripts, }, + { COMPOUND_STRING("Flags & Vars…"), DebugAction_OpenSubMenuFlagsVars, sDebugMenu_Actions_Flags, }, + { COMPOUND_STRING("Sound…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_Sound, }, + { COMPOUND_STRING("ROM Info…"), DebugAction_OpenSubMenu, sDebugMenu_Actions_ROMInfo2, }, + { COMPOUND_STRING("Cancel"), DebugAction_Cancel, }, + { NULL } }; // ******************************* @@ -1048,182 +725,117 @@ static const struct WindowTemplate sDebugMenuWindowTemplateSound = .baseBlock = 1, }; -static const struct WindowTemplate sDebugMenuWindowTemplateFlagsVars = -{ - .bg = 0, - .tilemapLeft = 30 - DEBUG_MENU_WIDTH_FLAGVAR - 1, - .tilemapTop = 1, - .width = DEBUG_MENU_WIDTH_FLAGVAR, - .height = DEBUG_MENU_HEIGHT_FLAGVAR, - .paletteNum = 15, - .baseBlock = 1 + DEBUG_MENU_WIDTH_MAIN * DEBUG_MENU_HEIGHT_MAIN * 2, -}; - -// ******************************* -// List Menu Templates -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Main = -{ - .items = sDebugMenu_Items_Main, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Main), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Utilities = -{ - .items = sDebugMenu_Items_Utilities, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Utilities), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_PCBag = -{ - .items = sDebugMenu_Items_PCBag, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_PCBag), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_PCBag_Fill = -{ - .items = sDebugMenu_Items_PCBag_Fill, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_PCBag_Fill), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Party = -{ - .items = sDebugMenu_Items_Party, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Party), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Scripts = -{ - .items = sDebugMenu_Items_Scripts, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Scripts), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_FlagsVars = -{ - .items = sDebugMenu_Items_FlagsVars, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_FlagsVars), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_0 = -{ - .items = sDebugMenu_Items_Battle_0, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_0), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_1 = -{ - .items = sDebugMenu_Items_Battle_1, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_1), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_2 = -{ - .items = sDebugMenu_Items_Battle_2, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_2), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Give = -{ - .items = sDebugMenu_Items_Give, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Give), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Sound = -{ - .items = sDebugMenu_Items_Sound, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Sound), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_BerryFunctions = -{ - .items = sDebugMenu_Items_BerryFunctions, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_BerryFunctions), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_TimeMenu = -{ - .items = sDebugMenu_Items_TimeMenu, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_TimeMenu), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_TimeMenu_TimesOfDay = -{ - .items = sDebugMenu_Items_TimeMenu_TimesOfDay, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_TimeMenu_TimesOfDay), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_TimeMenu_Weekdays = -{ - .items = sDebugMenu_Items_TimeMenu_Weekdays, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_TimeMenu_Weekdays), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_Player = -{ - .items = sDebugMenu_Items_Player, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_Player), -}; - -static const struct ListMenuTemplate sDebugMenu_ListTemplate_ROMInfo = -{ - .items = sDebugMenu_Items_ROMInfo, - .moveCursorFunc = ListMenuDefaultCursorMoveFunc, - .totalItems = ARRAY_COUNT(sDebugMenu_Items_ROMInfo), -}; +static bool32 Debug_SaveCallbackMenu(struct DebugMenuOption *callbackItems); // ******************************* // Functions universal void Debug_ShowMainMenu(void) { - sDebugBattleData = AllocZeroed(sizeof(*sDebugBattleData)); sDebugMenuListData = AllocZeroed(sizeof(*sDebugMenuListData)); - Debug_InitDebugBattleData(); - - Debug_ShowMenu(DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); + sDebugMenuListData->listId = 0; + Debug_ShowMenu(DebugTask_HandleMenuInput_General, sDebugMenu_Actions_Main); } -static void Debug_ReShowMainMenu(void) +#define tMenuTaskId data[0] +#define tWindowId data[1] +#define tSubWindowId data[2] +#define tInput data[3] +#define tDigit data[4] + +static bool32 Debug_SaveCallbackMenu(struct DebugMenuOption *callbackItems) { - Debug_ShowMenu(DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); + bool32 success = FALSE; + for (u32 i = 0; i < DEBUG_MAX_SUB_MENU_LEVELS; i++) + { + if (sDebugMenuListData->subMenuItems[i] == NULL) + { + sDebugMenuListData->subMenuItems[i] = callbackItems; + success = TRUE; + break; + } + } + return success; } -#define tMenuTaskId data[0] -#define tWindowId data[1] -#define tSubWindowId data[2] -#define tInput data[3] -#define tDigit data[4] - -static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate) +static u32 Debug_RemoveCallbackMenu(void) { - struct ListMenuTemplate menuTemplate; + u32 freeCallbackLevel = 0; + for (u32 i = DEBUG_MAX_SUB_MENU_LEVELS; i > 0; i--) + { + if (sDebugMenuListData->subMenuItems[i - 1] != NULL) + { + sDebugMenuListData->subMenuItems[i - 1] = NULL; + freeCallbackLevel = i - 1; + break; + } + } + return freeCallbackLevel; +} + +static const struct DebugMenuOption *Debug_GetCurrentCallbackMenu(void) +{ + const struct DebugMenuOption *callbackItems = NULL; + for (u32 i = DEBUG_MAX_SUB_MENU_LEVELS; i > 0; i--) + { + if (sDebugMenuListData->subMenuItems[i - 1] != NULL) + { + callbackItems = sDebugMenuListData->subMenuItems[i - 1]; + break; + } + } + return callbackItems; +} + +static bool32 IsSubMenuAction(const void *action) +{ + return action == DebugAction_OpenSubMenu + || action == DebugAction_OpenSubMenuFlagsVars + || action == DebugAction_OpenSubMenuFakeRTC + || action == DebugAction_OpenSubMenuCreateFollowerNPC; +} + +static void Debug_ShowMenu(DebugFunc HandleInput, const struct DebugMenuOption *items) +{ + struct ListMenuTemplate menuTemplate = {0}; u8 windowId; u8 menuTaskId; u8 inputTaskId; + if (items != NULL) + Debug_SaveCallbackMenu((struct DebugMenuOption *)items); + else + items = Debug_GetCurrentCallbackMenu(); + // create window HideMapNamePopUpWindow(); LoadMessageBoxAndBorderGfx(); windowId = AddWindow(&sDebugMenuWindowTemplateMain); DrawStdWindowFrame(windowId, FALSE); + u32 totalItems = 0; + + if (sDebugMenuListData->listId == 1) + { + totalItems = Debug_GenerateListMenuNames(); + } + else + { + for (u32 i = 0; items[i].text != NULL; i++) + { + sDebugMenuListData->listItems[i].id = i; + StringExpandPlaceholders(gStringVar4, items[i].text); + if (IsSubMenuAction(items[i].action)) + StringAppend(gStringVar4, sDebugText_Arrow); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); + sDebugMenuListData->listItems[i].name = &sDebugMenuListData->itemNames[i][0]; + totalItems++; + } + } + // create list menu - menuTemplate = LMtemplate; + menuTemplate.items = sDebugMenuListData->listItems; + menuTemplate.moveCursorFunc = ListMenuDefaultCursorMoveFunc; + menuTemplate.totalItems = totalItems; menuTemplate.maxShowed = DEBUG_MENU_HEIGHT_MAIN; menuTemplate.windowId = windowId; menuTemplate.header_X = 0; @@ -1272,7 +884,6 @@ static void Debug_DestroyMenu_Full(u8 taskId) DestroyTask(taskId); UnfreezeObjectEvents(); Free(sDebugMenuListData); - Free(sDebugBattleData); } static void Debug_DestroyMenu_Full_Script(u8 taskId, const u8 *script) @@ -1329,29 +940,28 @@ static void DebugAction_DestroyExtraWindow(u8 taskId) UnfreezeObjectEvents(); } - static const u16 sLocationFlags[] = { FLAG_WORLD_MAP_PALLET_TOWN, FLAG_WORLD_MAP_VIRIDIAN_CITY, FLAG_WORLD_MAP_PEWTER_CITY, - FLAG_WORLD_MAP_ROUTE4_POKEMON_CENTER_1F, FLAG_WORLD_MAP_CERULEAN_CITY, - FLAG_WORLD_MAP_VERMILION_CITY, - FLAG_WORLD_MAP_ROUTE10_POKEMON_CENTER_1F, FLAG_WORLD_MAP_LAVENDER_TOWN, + FLAG_WORLD_MAP_VERMILION_CITY, FLAG_WORLD_MAP_CELADON_CITY, FLAG_WORLD_MAP_FUCHSIA_CITY, - FLAG_WORLD_MAP_SAFFRON_CITY, FLAG_WORLD_MAP_CINNABAR_ISLAND, FLAG_WORLD_MAP_INDIGO_PLATEAU_EXTERIOR, + FLAG_WORLD_MAP_SAFFRON_CITY, FLAG_WORLD_MAP_ONE_ISLAND, FLAG_WORLD_MAP_TWO_ISLAND, FLAG_WORLD_MAP_THREE_ISLAND, FLAG_WORLD_MAP_FOUR_ISLAND, FLAG_WORLD_MAP_FIVE_ISLAND, - FLAG_WORLD_MAP_SIX_ISLAND, FLAG_WORLD_MAP_SEVEN_ISLAND, + FLAG_WORLD_MAP_SIX_ISLAND, + FLAG_WORLD_MAP_ROUTE4_POKEMON_CENTER_1F, + FLAG_WORLD_MAP_ROUTE10_POKEMON_CENTER_1F, }; static u8 Debug_CheckToggleFlags(u8 id) @@ -1418,16 +1028,14 @@ static u8 Debug_CheckToggleFlags(u8 id) result = FlagGet(OW_FLAG_NO_TRAINER_SEE); break; #endif - #if B_FLAG_NO_BAG_USE != 0 - case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE: - result = FlagGet(B_FLAG_NO_BAG_USE); - break; - #endif #if B_FLAG_NO_CATCHING != 0 case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING: result = FlagGet(B_FLAG_NO_CATCHING); break; #endif + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE: + result = VarGet(B_VAR_NO_BAG_USE); + break; default: result = 0xFF; break; @@ -1436,107 +1044,56 @@ static u8 Debug_CheckToggleFlags(u8 id) return result; } -static void Debug_InitDebugBattleData(void) -{ - u32 i; - sDebugBattleData->submenu = 0; - sDebugBattleData->battleType = 0xFF; - sDebugBattleData->battleTerrain = 0xFF; - - for (i = 0; i < AI_FLAG_COUNT; i++) - sDebugBattleData->aiFlags[i] = FALSE; -} - -static void Debug_GenerateListMenuNames(u32 totalItems) +static u8 Debug_GenerateListMenuNames(void) { const u8 sColor_Red[] = _("{COLOR RED}"); const u8 sColor_Green[] = _("{COLOR GREEN}"); u32 i, flagResult = 0; u8 const *name = NULL; + u8 totalItems = 0; + if (sDebugMenuListData->listId == 1) + // Failsafe to prevent memory corruption + totalItems = min(ARRAY_COUNT(sDebugMenu_Actions_Flags) - 1, DEBUG_MAX_MENU_ITEMS); + // Copy item names for all entries but the last (which is Cancel) for (i = 0; i < totalItems; i++) { - if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu > 1) + if (sDebugMenuListData->listId == 1) { - u16 species; - if (i == 6) - { - name = sDebugText_Continue; - StringCopy(&sDebugMenuListData->itemNames[i][0], name); - } - else if (GetMonData(&gEnemyParty[i], MON_DATA_SANITY_HAS_SPECIES)) - { - species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES); - StringCopy(gStringVar1, GetSpeciesName(species)); - StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar1); - } + flagResult = Debug_CheckToggleFlags(i); + if (i == DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE) + name = sDebugMenu_Actions_BagUse_Options[flagResult]; else - { - StringCopy(&sDebugMenuListData->itemNames[i][0], sDebugText_Dashes); - } + name = sDebugMenu_Actions_Flags[i].text; + } + + if (flagResult == 0xFF) + { + StringCopy(&sDebugMenuListData->itemNames[i][0], name); + } + else if (flagResult) + { + StringCopy(gStringVar1, sColor_Green); + StringExpandPlaceholders(gStringVar4, name); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); } else { - if (sDebugMenuListData->listId == 0) - { - flagResult = Debug_CheckToggleFlags(i); - name = sDebugMenu_Items_FlagsVars[i].name; - } - else if (sDebugMenuListData->listId == 1) - { - flagResult = sDebugBattleData->aiFlags[i]; - if (i == totalItems - 1) - flagResult = 0xFF; - name = sDebugMenu_Items_Battle_1[i].name; - } - - if (flagResult == 0xFF) - { - StringCopy(&sDebugMenuListData->itemNames[i][0], name); - } - else if (flagResult) - { - StringCopy(gStringVar1, sColor_Green); - StringExpandPlaceholders(gStringVar4, name); - StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); - } - else - { - StringCopy(gStringVar1, sColor_Red); - StringExpandPlaceholders(gStringVar4, name); - StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); - } + StringCopy(gStringVar1, sColor_Red); + StringExpandPlaceholders(gStringVar4, name); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); } sDebugMenuListData->listItems[i].name = &sDebugMenuListData->itemNames[i][0]; sDebugMenuListData->listItems[i].id = i; } + return totalItems; } static void Debug_RefreshListMenu(u8 taskId) { - u8 totalItems = 0; - - if (sDebugMenuListData->listId == 0) - { - gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_FlagsVars; - totalItems = gMultiuseListMenuTemplate.totalItems; - } - else if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu <= 1) - { - gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_Battle_1; - totalItems = gMultiuseListMenuTemplate.totalItems; - } - else if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu > 1) - { - gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_Battle_2; - totalItems = 7; - } - - // Failsafe to prevent memory corruption - totalItems = min(totalItems, DEBUG_MAX_MENU_ITEMS); - Debug_GenerateListMenuNames(totalItems); + u8 totalItems = Debug_GenerateListMenuNames(); // Set list menu data gMultiuseListMenuTemplate.items = sDebugMenuListData->listItems; @@ -1557,373 +1114,69 @@ static void Debug_RefreshListMenu(u8 taskId) gMultiuseListMenuTemplate.cursorKind = 0; } -static void Debug_RedrawListMenu(u8 taskId) +static void DebugTask_HandleMenuInput_General(u8 taskId) { - u8 listTaskId = gTasks[taskId].tMenuTaskId; - u16 scrollOffset, selectedRow; - ListMenuGetScrollAndRow(listTaskId, &scrollOffset, &selectedRow); - - DestroyListMenuTask(gTasks[taskId].tMenuTaskId, &scrollOffset, &selectedRow); - Debug_RefreshListMenu(taskId); - gTasks[taskId].tMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, scrollOffset, selectedRow); -} - - -// ******************************* -// Handle Inputs -static void DebugTask_HandleMenuInput_Main(u8 taskId) -{ - void (*func)(u8); + const struct DebugMenuOption *options = Debug_GetCurrentCallbackMenu(); u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + struct DebugMenuOption option = options[input]; if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); - if ((func = sDebugMenu_Actions_Main[input]) != NULL) - func(taskId); - } - else if (JOY_NEW(B_BUTTON)) - { - PlaySE(SE_SELECT); - Debug_DestroyMenu_Full(taskId); - ScriptContext_Enable(); - } -} - -static void DebugTask_HandleMenuInput_General(u8 taskId, const void (*const actions[])(u8), void (*callbackInput)(u8), struct ListMenuTemplate callbackMenuTemplate) -{ - void (*func)(u8); - u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); - - if (JOY_NEW(A_BUTTON)) - { - PlaySE(SE_SELECT); - if ((func = actions[input]) != NULL) - func(taskId); - } - else if (JOY_NEW(B_BUTTON)) - { - PlaySE(SE_SELECT); - Debug_DestroyMenu(taskId); - Debug_ShowMenu(callbackInput, callbackMenuTemplate); - } -} - -static void DebugTask_HandleMenuInput_Utilities(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Utilities, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_PCBag(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_PCBag, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_PCBag_Fill(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_PCBag_Fill, DebugTask_HandleMenuInput_PCBag, sDebugMenu_ListTemplate_PCBag); -} - -static void DebugTask_HandleMenuInput_Party(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Party, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_Scripts(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Scripts, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_TimeMenu(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_TimeMenu, DebugTask_HandleMenuInput_Utilities, sDebugMenu_ListTemplate_Utilities); -} - -static void DebugTask_HandleMenuInput_TimeMenu_TimesOfDay(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_TimeMenu_TimesOfDay, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_TimeMenu_Weekdays(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_TimeMenu_Weekdays, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId) -{ - void (*func)(u8); - u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); - - if (JOY_NEW(A_BUTTON)) - { - PlaySE(SE_SELECT); - if ((func = sDebugMenu_Actions_Flags[input]) != NULL) + if (option.action != NULL) { - if (input == DEBUG_FLAGVAR_MENU_ITEM_FLAGS || input == DEBUG_FLAGVAR_MENU_ITEM_VARS) + if (IsSubMenuAction(option.action)) { - Debug_RedrawListMenu(taskId); - func(taskId); + ((DebugSubmenuFunc)option.action)(taskId, option.actionParams); + } + else if (option.action == DebugAction_ExecuteScript) + { + Debug_DestroyMenu_Full_Script(taskId, (const u8 *)option.actionParams); + } + else if (option.action == DebugAction_ToggleFlag) + { + ((DebugFunc)option.actionParams)(taskId); + DebugAction_ToggleFlag(taskId); } else { - func(taskId); - Debug_GenerateListMenuNames(gMultiuseListMenuTemplate.totalItems); - RedrawListMenu(gTasks[taskId].tMenuTaskId); - } - - // Remove TRUE/FALSE window for functions that haven't been assigned flags - if (gTasks[taskId].tInput == 0xFF) - { - ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, TRUE); - RemoveWindow(gTasks[taskId].tSubWindowId); - Free(sDebugMenuListData); + ((DebugFunc)option.action)(taskId); } } } else if (JOY_NEW(B_BUTTON)) { PlaySE(SE_SELECT); - Debug_DestroyMenu(taskId); - Debug_ReShowMainMenu(); - } -} - -static void DebugTask_HandleBattleMenuReDraw(u8 taskId) -{ - Debug_RefreshListMenu(taskId); - switch (sDebugBattleData->submenu) - { - case 0: - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_0); - break; - case 1: - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); - break; - case 2: - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); - break; - case 3: - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); - break; - } -} - -static void DebugTask_HandleMenuInput_Battle(u8 taskId) -{ - u16 idx; - u8 listTaskId = gTasks[taskId].tMenuTaskId; - ListMenu_ProcessInput(listTaskId); - - ListMenuGetCurrentItemArrayId(listTaskId, &idx); - - if (JOY_NEW(A_BUTTON)) - { - PlaySE(SE_SELECT); - - switch (sDebugBattleData->submenu) + if (Debug_GetCurrentCallbackMenu() != NULL && Debug_RemoveCallbackMenu() != 0) { - case 0: // Battle type - sDebugBattleData->battleType = idx; - sDebugBattleData->submenu++; Debug_DestroyMenu(taskId); - - if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD // Skip AI Flag selection if wild battle - || sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE) - { - sDebugBattleData->submenu++; - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); - } - else - { - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); - } - break; - case 1: // AI Flags - if (idx == sDebugMenu_ListTemplate_Battle_1.totalItems - 1) - { - sDebugBattleData->submenu++; - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); - } - else - { - sDebugBattleData->aiFlags[idx] = !sDebugBattleData->aiFlags[idx]; - Debug_RedrawListMenu(taskId); - } - - break; - case 2: // Terrain - sDebugBattleData->submenu++; - sDebugBattleData->battleTerrain = idx; - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); - break; - case 3: // Enemy pokemon - if (idx == 6) - Debug_InitializeBattle(taskId); - break; + if (sDebugMenuListData->listId != 0) + sDebugMenuListData->listId = 0; + Debug_ShowMenu(DebugTask_HandleMenuInput_General, NULL); } - } - else if (JOY_NEW(B_BUTTON)) - { - switch (sDebugBattleData->submenu) + else { - case 0: // Return to Main menu - PlaySE(SE_SELECT); - Debug_DestroyMenu(taskId); - Debug_ReShowMainMenu(); - break; - case 2: // Skip AI Flag selection if wild battle - if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD - || sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE) - { - sDebugBattleData->submenu = 0; - } - else - sDebugBattleData->submenu--; - DebugTask_HandleBattleMenuReDraw(taskId); - break; - default: - sDebugBattleData->submenu--; - DebugTask_HandleBattleMenuReDraw(taskId); - break; + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); } } } -static void Debug_InitializeBattle(u8 taskId) -{ - u32 i; - gBattleTypeFlags = 0; - - // Set main battle flags - switch (sDebugBattleData->battleType) - { - case DEBUG_BATTLE_0_MENU_ITEM_WILD: - break; - case DEBUG_BATTLE_0_MENU_ITEM_SINGLE: - gBattleTypeFlags = (BATTLE_TYPE_TRAINER); - break; - case DEBUG_BATTLE_0_MENU_ITEM_DOUBLE: - gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER); - break; - case DEBUG_BATTLE_0_MENU_ITEM_MULTI: - gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER); - break; - } - - // Set terrain - gBattleEnvironment = sDebugBattleData->battleTerrain; - - // Populate enemy party - for (i = 0; i < PARTY_SIZE; i++) - { - ZeroMonData(&gEnemyParty[i]); - if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_HAS_SPECIES)) - gEnemyParty[i] = gPlayerParty[i]; - } - - // Set AI flags - for (i = 0; i < ARRAY_COUNT(sDebugBattleData->aiFlags); i++) - { - if (sDebugBattleData->aiFlags[i]) - gDebugAIFlags |= (1 << i); - } - - gIsDebugBattle = TRUE; - BattleSetup_StartTrainerBattle_Debug(); - - - Debug_DestroyMenu_Full(taskId); -} - -static void DebugTask_HandleMenuInput_Give(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Give, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_Sound(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Sound, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_BerryFunctions(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_BerryFunctions, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_Player(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_Player, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -static void DebugTask_HandleMenuInput_ROMInfo(u8 taskId) -{ - DebugTask_HandleMenuInput_General(taskId, sDebugMenu_Actions_ROMInfo, DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); -} - -// ******************************* -// Open sub-menus -static void DebugAction_OpenUtilitiesMenu(u8 taskId) +static void DebugAction_OpenSubMenuFlagsVars(u8 taskId, const struct DebugMenuOption *items) { Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Utilities, sDebugMenu_ListTemplate_Utilities); + sDebugMenuListData->listId = 1; + Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); } -static void DebugAction_OpenPCBagMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_PCBag, sDebugMenu_ListTemplate_PCBag); -} - -static void DebugAction_OpenPartyMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Party, sDebugMenu_ListTemplate_Party); -} - -static void DebugAction_OpenScriptsMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Scripts, sDebugMenu_ListTemplate_Scripts); -} - -static void DebugAction_OpenFlagsVarsMenu(u8 taskId) +static void DebugAction_OpenSubMenu(u8 taskId, const struct DebugMenuOption *items) { Debug_DestroyMenu(taskId); sDebugMenuListData->listId = 0; - Debug_ShowMenu(DebugTask_HandleMenuInput_FlagsVars, gMultiuseListMenuTemplate); + Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); } -static void DebugAction_OpenGiveMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Give, sDebugMenu_ListTemplate_Give); -} - -static void DebugAction_OpenSoundMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Sound, sDebugMenu_ListTemplate_Sound); -} - -static void DebugAction_Util_BerryFunctions(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_BerryFunctions, sDebugMenu_ListTemplate_BerryFunctions); -} - -static void DebugAction_Util_OpenTimeMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_TimeMenu, sDebugMenu_ListTemplate_TimeMenu); -} - -static void DebugAction_TimeMenu_TimesOfDay(u8 taskId) +static void DebugAction_OpenSubMenuFakeRTC(u8 taskId, const struct DebugMenuOption *items) { if (!OW_USE_FAKE_RTC) { @@ -1931,34 +1184,33 @@ static void DebugAction_TimeMenu_TimesOfDay(u8 taskId) } else { - Debug_DestroyMenu_Full(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_TimeMenu_TimesOfDay, sDebugMenu_ListTemplate_TimeMenu_TimesOfDay); + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); } } -static void DebugAction_TimeMenu_Weekdays(u8 taskId) +static void DebugAction_ExecuteScript(u8 taskId, const u8 *script) { - if (!OW_USE_FAKE_RTC) - { - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_FakeRTCNotEnabled); - } - else - { - Debug_DestroyMenu_Full(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_TimeMenu_Weekdays, sDebugMenu_ListTemplate_TimeMenu_Weekdays); - } + Debug_DestroyMenu_Full_Script(taskId, script); } -static void DebugAction_OpenPlayerMenu(u8 taskId) +static void DebugAction_ToggleFlag(u8 taskId) { - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_Player, sDebugMenu_ListTemplate_Player); + Debug_GenerateListMenuNames(); + RedrawListMenu(gTasks[taskId].tMenuTaskId); } -static void DebugAction_OpenROMInfoMenu(u8 taskId) +static void DebugAction_OpenSubMenuCreateFollowerNPC(u8 taskId, const struct DebugMenuOption *items) { - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_ROMInfo, sDebugMenu_ListTemplate_ROMInfo); + // if (FNPC_ENABLE_NPC_FOLLOWERS) + // { + // Debug_DestroyMenu(taskId); + // Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); + // } + // else + // { + // Debug_DestroyMenu_Full_Script(taskId, Debug_Follower_NPC_Not_Enabled); + // } } // ******************************* @@ -2162,11 +1414,6 @@ void CheckPokemonStorageSize(struct ScriptContext *ctx) ConvertIntToDecimalStringN(gStringVar3, maxPkmnStorageSize - currPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); } -static void DebugAction_ROMInfo_CheckSaveBlock(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_CheckSaveBlock); -} - enum RoundMode { ROUND_CEILING, @@ -2215,41 +1462,6 @@ void CheckROMSize(struct ScriptContext *ctx) ConvertQ22_10ToDecimalString(gStringVar2, currROMFreeKB, 2, ROUND_FLOOR); } -static void DebugAction_ROMInfo_CheckROMSpace(u8 taskId) -{ - Debug_DestroyMenu_Full(taskId); - LockPlayerFieldControls(); - ScriptContext_SetupScript(Debug_CheckROMSpace); -} - -static const u8 sWeatherNames[WEATHER_COUNT][24] = { - [WEATHER_NONE] = _("NONE"), - [WEATHER_SUNNY_CLOUDS] = _("SUNNY CLOUDS"), - [WEATHER_SUNNY] = _("SUNNY"), - [WEATHER_RAIN] = _("RAIN"), - [WEATHER_SNOW] = _("SNOW"), - [WEATHER_RAIN_THUNDERSTORM] = _("RAIN THUNDERSTORM"), - [WEATHER_FOG_HORIZONTAL] = _("FOG HORIZONTAL"), - [WEATHER_VOLCANIC_ASH] = _("VOLCANIC ASH"), - [WEATHER_SANDSTORM] = _("SANDSTORM"), - [WEATHER_FOG_DIAGONAL] = _("FOG DIAGONAL"), - [WEATHER_UNDERWATER] = _("UNDERWATER"), - [WEATHER_SHADE] = _("SHADE"), - [WEATHER_DROUGHT] = _("DROUGHT"), - [WEATHER_DOWNPOUR] = _("DOWNPOUR"), - [WEATHER_UNDERWATER_BUBBLES] = _("UNDERWATER BUBBLES"), - [WEATHER_ABNORMAL] = _("ABNORMAL(NOT WORKING)"), - [WEATHER_ROUTE119_CYCLE] = _("ROUTE119 CYCLE"), - [WEATHER_ROUTE123_CYCLE] = _("ROUTE123 CYCLE"), - [WEATHER_FOG] = _("FOG"), -}; - -const u8 *GetWeatherName(u32 weatherId) -{ - return sWeatherNames[weatherId]; -} - -static const u8 sDebugText_WeatherNotDefined[] = _("NOT DEFINED!!!"); static void DebugAction_Util_Weather(u8 taskId) { u8 windowId; @@ -2267,7 +1479,7 @@ static void DebugAction_Util_Weather(u8 taskId) //Display initial ID StringCopy(gStringVar2, gText_DigitIndicator[0]); ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, 2); - StringCopyPadded(gStringVar1, sWeatherNames[0], CHAR_SPACE, 30); + StringCopyPadded(gStringVar1, GetWeatherName(0), CHAR_SPACE, 30); StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); @@ -2287,10 +1499,7 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId) StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); - if (gTasks[taskId].tInput <= 15 || gTasks[taskId].tInput >= 20) - StringCopyPadded(gStringVar1, sWeatherNames[gTasks[taskId].tInput], CHAR_SPACE, 30); - else - StringCopyPadded(gStringVar1, sDebugText_WeatherNotDefined, CHAR_SPACE, 30); + StringCopyPadded(gStringVar1, GetWeatherName(gTasks[taskId].tInput), CHAR_SPACE, 30); StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); @@ -2311,21 +1520,6 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId) } } -static void DebugAction_Util_FontTest(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_FontTest); -} - -static void DebugAction_TimeMenu_CheckWallClock(u8 taskId) -{ - // Debug_DestroyMenu_Full_Script(taskId, PlayersHouse_2F_EventScript_CheckWallClock); -} - -static void DebugAction_TimeMenu_SetWallClock(u8 taskId) -{ - // Debug_DestroyMenu_Full_Script(taskId, PlayersHouse_2F_EventScript_SetWallClock); -} - static void DebugAction_Util_WatchCredits(u8 taskId) { Debug_DestroyMenu_Full(taskId); @@ -2364,18 +1558,6 @@ static void DebugAction_Util_CheatStart(u8 taskId) Debug_DestroyMenu_Full_Script(taskId, Debug_CheatStart); } -static void DebugAction_ROMInfo_ExpansionVersion(u8 taskId) -{ - Debug_DestroyMenu_Full(taskId); - LockPlayerFieldControls(); - ScriptContext_SetupScript(Debug_ShowExpansionVersion); -} - -static void DebugAction_Util_Steven_Multi(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Steven_Multi); -} - void BufferExpansionVersion(struct ScriptContext *ctx) { static const u8 sText_Released[] = _("\nRelease Build"); @@ -2393,12 +1575,6 @@ void BufferExpansionVersion(struct ScriptContext *ctx) string = StringCopy(string, sText_Unreleased); } -static void DebugAction_TimeMenu_PrintTime(u8 taskId) -{ - LockPlayerFieldControls(); - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_TellTheTime); -} - void DebugMenu_CalculateTime(struct ScriptContext *ctx) { if (OW_USE_FAKE_RTC) @@ -2418,75 +1594,22 @@ void DebugMenu_CalculateTime(struct ScriptContext *ctx) } } -static void DebugAction_TimeMenu_PrintTimeOfDay(u8 taskId) -{ - LockPlayerFieldControls(); - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_PrintTimeOfDay); -} - void DebugMenu_CalculateTimeOfDay(struct ScriptContext *ctx) { - switch (GetTimeOfDay()) + enum TimeOfDay timeOfDay = GetTimeOfDay(); + switch (timeOfDay) { case TIME_MORNING: - StringExpandPlaceholders(gStringVar1, gTimeOfDayStringsTable[TIME_MORNING]); - break; case TIME_DAY: - StringExpandPlaceholders(gStringVar1, gTimeOfDayStringsTable[TIME_DAY]); - break; case TIME_EVENING: - StringExpandPlaceholders(gStringVar1, gTimeOfDayStringsTable[TIME_EVENING]); - break; case TIME_NIGHT: - StringExpandPlaceholders(gStringVar1, gTimeOfDayStringsTable[TIME_NIGHT]); + StringExpandPlaceholders(gStringVar1, gTimeOfDayStringsTable[timeOfDay]); break; - default: + case TIMES_OF_DAY_COUNT: break; } } -// ******************************* -// Actions Scripts -static void DebugAction_Util_Script_1(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_1); -} - -static void DebugAction_Util_Script_2(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_2); -} - -static void DebugAction_Util_Script_3(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_3); -} - -static void DebugAction_Util_Script_4(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_4); -} - -static void DebugAction_Util_Script_5(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_5); -} - -static void DebugAction_Util_Script_6(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_6); -} - -static void DebugAction_Util_Script_7(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_7); -} - -static void DebugAction_Util_Script_8(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_8); -} - // ******************************* // Actions Flags and Vars static void Debug_Display_FlagInfo(u32 flag, u32 digit, u8 windowId) @@ -2499,7 +1622,7 @@ static void Debug_Display_FlagInfo(u32 flag, u32 digit, u8 windowId) else StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); StringCopy(gStringVar3, gText_DigitIndicator[digit]); - StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Flag: {STR_VAR_1}{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -2530,6 +1653,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) { if (JOY_NEW(A_BUTTON)) { + PlaySE(SE_SELECT); FlagToggle(gTasks[taskId].tInput); } else if (JOY_NEW(B_BUTTON)) @@ -2539,7 +1663,6 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) return; } - PlaySE(SE_SELECT); Debug_HandleInput_Numeric(taskId, 1, FLAGS_COUNT - 1, DEBUG_NUMBER_DIGITS_FLAGS); if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) @@ -2894,14 +2017,11 @@ static void DebugAction_FlagsVars_TrainerSeeOnOff(u8 taskId) static void DebugAction_FlagsVars_BagUseOnOff(u8 taskId) { -#if B_FLAG_NO_BAG_USE == 0 - Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetBattleConfigMessage); +#if B_VAR_NO_BAG_USE < VARS_START || B_VAR_NO_BAG_USE > VARS_END + Debug_DestroyMenu_Full_Script(taskId, Debug_VarsNotSetBattleConfigMessage); #else - if (FlagGet(B_FLAG_NO_BAG_USE)) - PlaySE(SE_PC_OFF); - else - PlaySE(SE_PC_LOGIN); - FlagToggle(B_FLAG_NO_BAG_USE); + PlaySE(SE_SELECT); + VarSet(B_VAR_NO_BAG_USE, (VarGet(B_VAR_NO_BAG_USE) + 1) % 3); #endif } @@ -2931,7 +2051,7 @@ static void Debug_Display_ItemInfo(u32 itemId, u32 digit, u8 windowId) WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, itemId, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); - StringExpandPlaceholders(gStringVar4, sDebugText_ItemID); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Item ID: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -2975,7 +2095,7 @@ static void Debug_Display_ItemQuantity(u32 quantity, u32 digit, u8 windowId) StringCopy(gStringVar2, gText_DigitIndicator[digit]); ConvertIntToDecimalStringN(gStringVar1, quantity, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); - StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Quantity:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -3070,7 +2190,7 @@ static void Debug_Display_SpeciesInfo(u32 species, u32 digit, u8 windowId) WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, species, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Species: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}{CLEAR_TO 90}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -3149,7 +2269,7 @@ static void Debug_Display_Level(u32 level, u32 digit, u8 windowId) StringCopy(gStringVar2, gText_DigitIndicator[digit]); ConvertIntToDecimalStringN(gStringVar1, level, STR_CONV_MODE_LEADING_ZEROS, 3); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Level:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -3274,14 +2394,14 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId) } } -static void Debug_Display_Ability(u32 abilityId, u32 digit, u8 windowId)//(u32 natureId, u32 digit, u8 windowId) +static void Debug_Display_Ability(enum Ability abilityId, u32 digit, u8 windowId)//(u32 natureId, u32 digit, u8 windowId) { StringCopy(gStringVar2, gText_DigitIndicator[digit]); ConvertIntToDecimalStringN(gStringVar3, abilityId, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); u8 *end = StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Ability Num: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}")); AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } @@ -3313,7 +2433,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; - u32 abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); + enum Ability abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); Debug_Display_Ability(abilityId, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectAbility; @@ -3326,6 +2446,16 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) } } +static void Debug_Display_TeraType(u32 typeId, u32 digit, u8 windowId) +{ + StringCopy(gStringVar2, gText_DigitIndicator[digit]); + ConvertIntToDecimalStringN(gStringVar3, typeId, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar1, gTypesInfo[typeId].name); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Tera Type: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}")); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); +} + static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) { u8 abilityCount = NUM_ABILITY_SLOTS - 1; //-1 for proper iteration @@ -3352,7 +2482,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) { i++; } - u32 abilityId = GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i); + enum Ability abilityId = GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i); Debug_Display_Ability(abilityId, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); } @@ -3362,12 +2492,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; - StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); - StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); - StringCopy(gStringVar1, gTypesInfo[0].name); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonTeraType); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + Debug_Display_TeraType(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectTeraType; } @@ -3379,6 +2504,15 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) } } +static void Debug_Display_DynamaxLevel(u32 level, u32 digit, u8 windowId) +{ + StringCopy(gStringVar2, gText_DigitIndicator[digit]); + ConvertIntToDecimalStringN(gStringVar1, level, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Dmax Lvl:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}")); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); +} + static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId) { if (JOY_NEW(DPAD_ANY)) @@ -3398,12 +2532,7 @@ static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId) gTasks[taskId].tInput = 0; } - StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); - StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); - StringCopy(gStringVar1, gTypesInfo[gTasks[taskId].tInput].name); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonTeraType); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + Debug_Display_TeraType(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); } if (JOY_NEW(A_BUTTON)) @@ -3412,11 +2541,7 @@ static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId) gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; - StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); - StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonDynamaxLevel); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + Debug_Display_DynamaxLevel(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectDynamaxLevel; } @@ -3428,18 +2553,18 @@ static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId) } } +static void Debug_Display_GigantamaxFactor(u32 input, u8 windowId) +{ + Debug_Display_TrueFalse(input, windowId, COMPOUND_STRING("Gmax Factor:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}")); +} + static void DebugAction_Give_Pokemon_SelectDynamaxLevel(u8 taskId) { if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); Debug_HandleInput_Numeric(taskId, 0, MAX_DYNAMAX_LEVEL, 2); - - StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); - StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); - StringExpandPlaceholders(gStringVar4, sDebugText_PokemonDynamaxLevel); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + Debug_Display_DynamaxLevel(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); } if (JOY_NEW(A_BUTTON)) @@ -3447,7 +2572,7 @@ static void DebugAction_Give_Pokemon_SelectDynamaxLevel(u8 taskId) sDebugMonData->dynamaxLevel = gTasks[taskId].tInput; gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; - Debug_Display_TrueFalse(gTasks[taskId].tInput, gTasks[taskId].tSubWindowId, sDebugText_PokemonGmaxFactor); + Debug_Display_GigantamaxFactor(gTasks[taskId].tInput, gTasks[taskId].tSubWindowId); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectGigantamaxFactor; } else if (JOY_NEW(B_BUTTON)) @@ -3476,7 +2601,7 @@ static void DebugAction_Give_Pokemon_SelectGigantamaxFactor(u8 taskId) { PlaySE(SE_SELECT); gTasks[taskId].tInput ^= JOY_NEW(DPAD_UP | DPAD_DOWN) > 0; - Debug_Display_TrueFalse(gTasks[taskId].tInput, gTasks[taskId].tSubWindowId, sDebugText_PokemonGmaxFactor); + Debug_Display_GigantamaxFactor(gTasks[taskId].tInput, gTasks[taskId].tSubWindowId); } if (JOY_NEW(A_BUTTON)) @@ -3672,7 +2797,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://github.com/ghoulslash/pokeemerald/tree/custom-givemon { - u16 nationalDexNum; + enum NationalDexOrder nationalDexNum; int sentToPc; struct Pokemon mon; u8 i; @@ -3800,6 +2925,82 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu #undef tSpriteId #undef tIterator +//Decoration +#define tSpriteId data[6] + +static void UNUSED Debug_Display_DecorationInfo(u32 itemId, u32 digit, u8 windowId) +{ + // StringCopy(gStringVar2, gText_DigitIndicator[digit]); + // u8* end = StringCopy(gStringVar1, gDecorations[itemId].name); + // WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); + // StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + // ConvertIntToDecimalStringN(gStringVar3, itemId, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + // StringExpandPlaceholders(gStringVar4, COMPOUND_STRING("Decor ID: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}")); + // AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); +} + +static void DebugAction_Give_Decoration(u8 taskId) +{ + // u8 windowId; + + // ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + // RemoveWindow(gTasks[taskId].tWindowId); + + // HideMapNamePopUpWindow(); + // LoadMessageBoxAndBorderGfx(); + // windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + // DrawStdWindowFrame(windowId, FALSE); + + // CopyWindowToVram(windowId, COPYWIN_FULL); + + // // Display initial decoration + // Debug_Display_DecorationInfo(1, 0, windowId); + + // gTasks[taskId].func = DebugAction_Give_Decoration_SelectId; + // gTasks[taskId].tSubWindowId = windowId; + // gTasks[taskId].tInput = 1; + // gTasks[taskId].tDigit = 0; + // gTasks[taskId].tSpriteId = AddDecorationIconObject(gTasks[taskId].tInput, DEBUG_NUMBER_ICON_X+8, DEBUG_NUMBER_ICON_Y+10, 0, ITEM_TAG, ITEM_TAG); +} + +static void UNUSED DestroyDecorationIcon(u8 taskId) +{ + // FreeSpriteTilesByTag(ITEM_TAG); + // FreeSpritePaletteByTag(ITEM_TAG); + // FreeSpriteOamMatrix(&gSprites[gTasks[taskId].tSpriteId]); + // DestroySprite(&gSprites[gTasks[taskId].tSpriteId]); +} + +static void UNUSED DebugAction_Give_Decoration_SelectId(u8 taskId) +{ + // if (JOY_NEW(DPAD_ANY)) + // { + // PlaySE(SE_SELECT); + // Debug_HandleInput_Numeric(taskId, 1, NUM_DECORATIONS, DEBUG_NUMBER_DIGITS_ITEMS); + // Debug_Display_DecorationInfo(gTasks[taskId].tInput, gTasks[taskId].tDigit, gTasks[taskId].tSubWindowId); + // DestroyDecorationIcon(taskId); + // gTasks[taskId].tSpriteId = AddDecorationIconObject(gTasks[taskId].tInput, DEBUG_NUMBER_ICON_X+8, DEBUG_NUMBER_ICON_Y+10, 0, ITEM_TAG, ITEM_TAG); + // } + + // if (JOY_NEW(A_BUTTON)) + // { + // DestroyItemIcon(taskId); + + // PlaySE(MUS_LEVEL_UP); + // DecorationAdd(gTasks[taskId].tInput); + // DebugAction_DestroyExtraWindow(taskId); + // } + // else if (JOY_NEW(B_BUTTON)) + // { + // DestroyDecorationIcon(taskId); + + // PlaySE(SE_SELECT); + // DebugAction_DestroyExtraWindow(taskId); + // } +} + +#undef tSpriteId + static void DebugAction_Give_MaxMoney(u8 taskId) { SetMoney(&gSaveBlock1Ptr->money, MAX_MONEY); @@ -3838,16 +3039,16 @@ static void DebugAction_TimeMenu_ChangeTimeOfDay(u8 taskId) DebugAction_DestroyExtraWindow(taskId); switch (input) { - case DEBUG_TIME_MENU_ITEM_MORNING: + case TIME_MORNING: FakeRtc_ForwardTimeTo(MORNING_HOUR_BEGIN, 0, 0); break; - case DEBUG_TIME_MENU_ITEM_DAY: + case TIME_DAY: FakeRtc_ForwardTimeTo(DAY_HOUR_BEGIN, 0, 0); break; - case DEBUG_TIME_MENU_ITEM_EVENING: + case TIME_EVENING: FakeRtc_ForwardTimeTo(EVENING_HOUR_BEGIN, 0, 0); break; - case DEBUG_TIME_MENU_ITEM_NIGHT: + case TIME_NIGHT: FakeRtc_ForwardTimeTo(NIGHT_HOUR_BEGIN, 0, 0); break; } @@ -3862,37 +3063,8 @@ static void DebugAction_TimeMenu_ChangeWeekdays(u8 taskId) u32 daysToAdd = 0; DebugAction_DestroyExtraWindow(taskId); - switch(input) - { - case DEBUG_TIME_MENU_ITEM_SUNDAY: - daysToAdd = ((WEEKDAY_SUN - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_MONDAY: - daysToAdd = ((WEEKDAY_MON - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_TUESDAY: - daysToAdd = ((WEEKDAY_TUE - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_WEDNESDAY: - daysToAdd = ((WEEKDAY_WED - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_THURSDAY: - daysToAdd = ((WEEKDAY_THU - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_FRIDAY: - daysToAdd = ((WEEKDAY_FRI - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - case DEBUG_TIME_MENU_ITEM_SATURDAY: - daysToAdd = ((WEEKDAY_SAT - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; - FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); - break; - } + daysToAdd = ((input - rtc->dayOfWeek) + WEEKDAY_COUNT) % WEEKDAY_COUNT; + FakeRtc_AdvanceTimeBy(daysToAdd, 0, 0, 0); Debug_DestroyMenu_Full(taskId); SetMainCallback2(CB2_LoadMap); } @@ -3900,12 +3072,6 @@ static void DebugAction_TimeMenu_ChangeWeekdays(u8 taskId) // ******************************* // Actions PCBag -static void DebugAction_OpenPCBagFillMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - Debug_ShowMenu(DebugTask_HandleMenuInput_PCBag_Fill, sDebugMenu_ListTemplate_PCBag_Fill); -} - static void DebugAction_PCBag_Fill_PCBoxes_Fast(u8 taskId) //Credit: Sierraffinity { int boxId, boxPosition; @@ -4005,10 +3171,11 @@ static void DebugAction_PCBag_Fill_PocketPokeBalls(u8 taskId) static void DebugAction_PCBag_Fill_PocketTMHM(u8 taskId) { - u16 itemId; + u16 index, itemId; - for (itemId = ITEM_TM01; itemId <= ITEM_HM08; itemId++) + for (index = 0; index < NUM_ALL_MACHINES; index++) { + itemId = GetTMHMItemId(index + 1); if (CheckBagHasSpace(itemId, 1) && ItemIdToBattleMoveId(itemId) != MOVE_NONE) AddBagItem(itemId, 1); } @@ -4036,11 +3203,6 @@ static void DebugAction_PCBag_Fill_PocketKeyItems(u8 taskId) } } -static void DebugAction_PCBag_AccessPC(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, EventScript_PC); -} - static void DebugAction_PCBag_ClearBag(u8 taskId) { PlaySE(MUS_LEVEL_UP); @@ -4056,8 +3218,8 @@ static void DebugAction_PCBag_ClearBoxes(u8 taskId) // ******************************* // Actions Sound -static const u8 *const sBGMNames[]; -static const u8 *const sSENames[]; +static const u8 *const sBGMNames[END_MUS - START_MUS + 1]; +static const u8 *const sSENames[END_SE + 1]; #define tCurrentSong data[5] @@ -4095,10 +3257,14 @@ static void DebugAction_Sound_SE_SelectId(u8 taskId) { if (JOY_NEW(DPAD_ANY)) { + const u8 *seName; Debug_HandleInput_Numeric(taskId, 1, END_SE, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopyPadded(gStringVar1, sSENames[gTasks[taskId].tInput - 1], CHAR_SPACE, 35); + seName = sSENames[gTasks[taskId].tInput - 1]; + if (seName == NULL) + seName = sDebugText_Dashes; + StringCopyPadded(gStringVar1, seName, CHAR_SPACE, 35); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); @@ -4156,10 +3322,14 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId) { if (JOY_NEW(DPAD_ANY)) { + const u8 *bgmName; Debug_HandleInput_Numeric(taskId, START_MUS, END_MUS, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopyPadded(gStringVar1, sBGMNames[gTasks[taskId].tInput - START_MUS], CHAR_SPACE, 35); + bgmName = sBGMNames[gTasks[taskId].tInput - START_MUS]; + if (bgmName == NULL) + bgmName = sDebugText_Dashes; + StringCopyPadded(gStringVar1, bgmName, CHAR_SPACE, 35); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); @@ -4183,6 +3353,44 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId) } } +// static const u32 gDebugFollowerNPCGraphics[] = +// { +// OBJ_EVENT_GFX_RIVAL_BRENDAN_NORMAL, +// OBJ_EVENT_GFX_RIVAL_MAY_NORMAL, +// OBJ_EVENT_GFX_STEVEN, +// OBJ_EVENT_GFX_WALLY, +// OBJ_EVENT_GFX_RED, +// OBJ_EVENT_GFX_LEAF, +// }; + +static void DebugAction_CreateFollowerNPC(u8 taskId) +{ + // u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + // u32 gfx = gDebugFollowerNPCGraphics[input]; + + // Debug_DestroyMenu_Full(taskId); + // LockPlayerFieldControls(); + // DestroyFollowerNPC(); + // SetFollowerNPCData(FNPC_DATA_BATTLE_PARTNER, PARTNER_STEVEN); + // CreateFollowerNPC(gfx, FNPC_ALL, Debug_Follower_NPC_Event_Script); + // UnlockPlayerFieldControls(); +} + +static void DebugAction_DestroyFollowerNPC(u8 taskId) +{ + // if (FNPC_ENABLE_NPC_FOLLOWERS) + // { + // Debug_DestroyMenu_Full(taskId); + // LockPlayerFieldControls(); + // DestroyFollowerNPC(); + // UnlockPlayerFieldControls(); + // } + // else + // { + // Debug_DestroyMenu_Full_Script(taskId, Debug_Follower_NPC_Not_Enabled); + // } +} + #undef tCurrentSong #undef tMenuTaskId @@ -4547,7 +3755,7 @@ SOUND_LIST_BGM #undef X #define X(songId) [songId - START_MUS] = sBGMName_##songId, -static const u8 *const sBGMNames[] = +static const u8 *const sBGMNames[END_MUS - START_MUS + 1] = { SOUND_LIST_BGM }; @@ -4559,7 +3767,7 @@ SOUND_LIST_SE #undef X #define X(songId) [songId - 1] = sSEName_##songId, -static const u8 *const sSENames[] = +static const u8 *const sSENames[END_SE + 1] = { SOUND_LIST_SE }; @@ -4673,16 +3881,6 @@ static void DebugAction_BerryFunctions_Weeds(u8 taskId) // ******************************* // Actions Party/Boxes -static void DebugAction_Party_MoveReminder(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, TwoIsland_House_EventScript_ChooseMonToTutor); -} - -static void DebugAction_Party_HatchAnEgg(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_HatchAnEgg); -} - static void DebugAction_Party_HealParty(u8 taskId) { PlaySE(SE_USE_ITEM); @@ -4691,21 +3889,6 @@ static void DebugAction_Party_HealParty(u8 taskId) Debug_DestroyMenu_Full(taskId); } -static void DebugAction_Party_InflictStatus1(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_InflictStatus1); -} - -static void DebugAction_Party_CheckEVs(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_CheckEVs); -} - -static void DebugAction_Party_CheckIVs(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_CheckIVs); -} - static void DebugAction_Party_ClearParty(u8 taskId) { ZeroPlayerPartyMons(); @@ -4713,13 +3896,49 @@ static void DebugAction_Party_ClearParty(u8 taskId) Debug_DestroyMenu_Full(taskId); } +enum DebugTrainerIds +{ + DEBUG_TRAINER_PLAYER, + DEBUG_TRAINER_AI, + DEBUG_TRAINERS_COUNT +}; + +const struct Trainer sDebugTrainers[DIFFICULTY_COUNT][DEBUG_TRAINERS_COUNT] = +{ +#include "data/debug_trainers.h" +}; + +const struct Trainer* GetDebugAiTrainer(void) +{ + return &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI]; +} + +static void DebugAction_Party_SetParty(u8 taskId) +{ + ZeroPlayerPartyMons(); + CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER); + ScriptContext_Enable(); + Debug_DestroyMenu_Full(taskId); +} + +static void DebugAction_Party_BattleSingle(u8 taskId) +{ + ZeroPlayerPartyMons(); + ZeroEnemyPartyMons(); + CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER); + CreateNPCTrainerPartyFromTrainer(gEnemyParty, GetDebugAiTrainer(), FALSE, BATTLE_TYPE_TRAINER); + + gBattleTypeFlags = BATTLE_TYPE_TRAINER; + gDebugAIFlags = sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI].aiFlags; + gIsDebugBattle = TRUE; + gBattleEnvironment = BattleSetup_GetEnvironmentId(); + CalculateEnemyPartyCount(); + BattleSetup_StartTrainerBattle_Debug(); + Debug_DestroyMenu_Full(taskId); +} + void CheckEWRAMCounters(struct ScriptContext *ctx) { ConvertIntToDecimalStringN(gStringVar1, gFollowerSteps, STR_CONV_MODE_LEFT_ALIGN, 5); ConvertIntToDecimalStringN(gStringVar2, gChainFishingDexNavStreak, STR_CONV_MODE_LEFT_ALIGN, 5); } - -static void DebugAction_Util_CheckEWRAMCounters(u8 taskId) -{ - Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_EWRAMCounters); -} diff --git a/src/field_specials.c b/src/field_specials.c index 48598afce..b2dcf7bcc 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -2143,6 +2143,13 @@ void RunMassageCooldownStepCounter(void) VarSet(VAR_MASSAGE_COOLDOWN_STEP_COUNTER, count + 1); } +void SetHiddenNature(void) +{ + u32 hiddenNature = gSpecialVar_Result; + SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_HIDDEN_NATURE, &hiddenNature); + CalculateMonStats(&gPlayerParty[gSpecialVar_0x8004]); +} + void DaisyMassageServices(void) { AdjustFriendship(&gPlayerParty[gSpecialVar_0x8004], FRIENDSHIP_EVENT_MASSAGE); diff --git a/src/field_weather.c b/src/field_weather.c index f815b6fb5..bf6e4c55a 100644 --- a/src/field_weather.c +++ b/src/field_weather.c @@ -1139,3 +1139,33 @@ bool32 IsWeatherAlphaBlend(void) || gWeatherPtr->currWeather == WEATHER_UNDERWATER_BUBBLES || gWeatherPtr->currWeather == WEATHER_UNDERWATER); } + +static const u8 sWeatherNames[WEATHER_COUNT][24] = { + [WEATHER_NONE] = _("NONE"), + [WEATHER_SUNNY_CLOUDS] = _("SUNNY CLOUDS"), + [WEATHER_SUNNY] = _("SUNNY"), + [WEATHER_RAIN] = _("RAIN"), + [WEATHER_SNOW] = _("SNOW"), + [WEATHER_RAIN_THUNDERSTORM] = _("RAIN THUNDERSTORM"), + [WEATHER_FOG_HORIZONTAL] = _("FOG HORIZONTAL"), + [WEATHER_VOLCANIC_ASH] = _("VOLCANIC ASH"), + [WEATHER_SANDSTORM] = _("SANDSTORM"), + [WEATHER_FOG_DIAGONAL] = _("FOG DIAGONAL"), + [WEATHER_UNDERWATER] = _("UNDERWATER"), + [WEATHER_SHADE] = _("SHADE"), + [WEATHER_DROUGHT] = _("DROUGHT"), + [WEATHER_DOWNPOUR] = _("DOWNPOUR"), + [WEATHER_UNDERWATER_BUBBLES] = _("UNDERWATER BUBBLES"), + [WEATHER_ABNORMAL] = _("ABNORMAL(NOT WORKING)"), + [WEATHER_ROUTE119_CYCLE] = _("ROUTE119 CYCLE"), + [WEATHER_ROUTE123_CYCLE] = _("ROUTE123 CYCLE"), + [WEATHER_FOG] = _("FOG"), +}; + +static const u8 sDebugText_WeatherNotDefined[] = _("NOT DEFINED!!!"); +const u8 *GetWeatherName(u32 weatherId) +{ + if (sWeatherNames[weatherId][0] != 0) + return sWeatherNames[weatherId]; + return sDebugText_WeatherNotDefined; +} diff --git a/src/item.c b/src/item.c index 5bd2ca00c..b8e72c8e5 100644 --- a/src/item.c +++ b/src/item.c @@ -17,6 +17,13 @@ #include "constants/items.h" #include "constants/maps.h" +#define DUMMY_PC_BAG_POCKET \ +{ \ + .id = POCKET_DUMMY, \ + .capacity = PC_ITEMS_COUNT, \ + .itemSlots = gSaveBlock1Ptr->pcItems, \ +} + EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {}; static const u8 *ItemId_GetPluralName(u16); @@ -28,6 +35,27 @@ static bool32 DoesItemHavePluralName(u16); #include "data/pokemon/item_effects.h" #include "data/items.h" +#define UNPACK_TM_ITEM_ID(_tm) [CAT(ENUM_TM_HM_, _tm) + 1] = { CAT(ITEM_TM_, _tm), CAT(MOVE_, _tm) }, +#define UNPACK_HM_ITEM_ID(_hm) [CAT(ENUM_TM_HM_, _hm) + 1] = { CAT(ITEM_HM_, _hm), CAT(MOVE_, _hm) }, + +const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = +{ + [0] = { ITEM_NONE, MOVE_NONE }, // Failsafe + FOREACH_TM(UNPACK_TM_ITEM_ID) + FOREACH_HM(UNPACK_HM_ITEM_ID) + /* + * Expands to the following: + * + * [1] = { ITEM_TM_FOCUS_PUNCH, MOVE_FOCUS_PUNCH }, + * [2] = { ITEM_TM_DRAGON_CLAW, MOVE_DRAGON_CLAW }, + * [3] = { ITEM_TM_WATER_PULSE, MOVE_WATER_PULSE }, + * etc etc + */ +}; + +#undef UNPACK_TM_ITEM_ID +#undef UNPACK_HM_ITEM_ID + static inline u16 GetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos) { return pocket->itemSlots[pocketPos].itemId; @@ -726,9 +754,11 @@ ItemUseFunc GetItemFieldFunc(u16 itemId) return gItemsInfo[SanitizeItemId(itemId)].fieldUseFunc; } -bool8 GetItemBattleUsage(u16 itemId) +// Returns an item's battle effect script ID. +u8 GetItemBattleUsage(u16 itemId) { - u16 item = SanitizeItemId(itemId); + u16 item = SanitizeItemId(itemId); + // Handle E-Reader berries. if (item == ITEM_ENIGMA_BERRY_E_READER) { switch (GetItemEffectType(gSpecialVar_ItemId)) @@ -740,7 +770,7 @@ bool8 GetItemBattleUsage(u16 itemId) case ITEM_EFFECT_CURE_POISON: case ITEM_EFFECT_CURE_SLEEP: case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: case ITEM_EFFECT_CURE_PARALYSIS: case ITEM_EFFECT_CURE_ALL_STATUS: case ITEM_EFFECT_CURE_CONFUSION: @@ -800,17 +830,18 @@ u32 GetItemStatus1Mask(u16 itemId) return 0; } -u32 GetItemStatus2Mask(u16 itemId) +bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile _volatile) { const u8 *effect = GetItemEffect(itemId); - if (effect[3] & ITEM3_STATUS_ALL) - return STATUS2_INFATUATION | STATUS2_CONFUSION; - else if (effect[0] & ITEM0_INFATUATION) - return STATUS2_INFATUATION; - else if (effect[3] & ITEM3_CONFUSION) - return STATUS2_CONFUSION; - else - return 0; + switch (_volatile) + { + case VOLATILE_CONFUSION: + return (effect[3] & ITEM3_STATUS_ALL) || (effect[3] & ITEM3_CONFUSION); + case VOLATILE_INFATUATION: + return (effect[3] & ITEM3_STATUS_ALL) || (effect[0] & ITEM0_INFATUATION); + default: + return FALSE; + } } u32 GetItemSellPrice(u32 itemId) @@ -818,6 +849,13 @@ u32 GetItemSellPrice(u32 itemId) return GetItemPrice(itemId) / ITEM_SELL_FACTOR; } +bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect) +{ + return holdEffect == HOLD_EFFECT_CHOICE_BAND + || holdEffect == HOLD_EFFECT_CHOICE_SCARF + || holdEffect == HOLD_EFFECT_CHOICE_SPECS; +} + bool8 IsItemTM(u16 itemId) { itemId = SanitizeItemId(itemId); diff --git a/src/item_icon.c b/src/item_icon.c index dc5880bd6..9c07a9e18 100644 --- a/src/item_icon.c +++ b/src/item_icon.c @@ -1,4 +1,5 @@ #include "global.h" +#include "battle_main.h" #include "gflib.h" #include "decompress.h" #include "graphics.h" @@ -7,7 +8,6 @@ #include "move.h" #include "constants/item.h" #include "constants/items.h" -#include "battle_main.h" EWRAM_DATA u8 *gItemIconDecompressionBuffer = NULL; EWRAM_DATA u8 *gItemIcon4x4Buffer = NULL; diff --git a/src/item_use.c b/src/item_use.c index 345728480..30d7222b5 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -89,11 +89,12 @@ static void (*const sExitCallbackByItemType[])(void) = { [ITEM_USE_PARTY_MENU_MOVES - 1] = CB2_ShowPartyMenuForItemUse }; +#define tEnigmaBerryType data[4] static void SetUpItemUseCallback(u8 taskId) { u8 itemType; if (gSpecialVar_ItemId == ITEM_ENIGMA_BERRY_E_READER) - itemType = gTasks[taskId].data[4] - 1; + itemType = gTasks[taskId].tEnigmaBerryType - 1; else itemType = GetItemType(gSpecialVar_ItemId) - 1; if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRIES) @@ -976,9 +977,9 @@ static u32 GetBallThrowableState(void) return BALL_THROW_UNABLE_TWO_MONS; else if (IsPlayerPartyAndPokemonStorageFull() == TRUE) return BALL_THROW_UNABLE_NO_ROOM; - else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE)) + else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && IsSemiInvulnerable(GetCatchingBattler(), CHECK_ALL)) return BALL_THROW_UNABLE_SEMI_INVULNERABLE; - else if (FlagGet(B_FLAG_NO_CATCHING)) + else if (FlagGet(B_FLAG_NO_CATCHING) || !IsAllowedToUseBag()) return BALL_THROW_UNABLE_DISABLED_FLAG; return BALL_THROW_ABLE; @@ -992,6 +993,29 @@ bool32 CanThrowBall(void) static const u8 sText_CantThrowPokeBall_TwoMons[] = _("Cannot throw a ball!\nThere are two Pokémon out there!\p"); static const u8 sText_CantThrowPokeBall_SemiInvulnerable[] = _("Cannot throw a ball!\nThere's no Pokémon in sight!\p"); static const u8 sText_CantThrowPokeBall_Disabled[] = _("POKé BALLS cannot be used\nright now!\p"); + +static bool32 IteamHealsMonVolatile(u32 battler, u16 itemId) +{ + const u8 *effect = GetItemEffect(itemId); + if (effect[3] & ITEM3_STATUS_ALL) + return (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0); + else if (effect[0] & ITEM0_INFATUATION) + return gBattleMons[battler].volatiles.infatuation; + else if (effect[3] & ITEM3_CONFUSION) + return gBattleMons[battler].volatiles.confusionTurns > 0; + + return FALSE; +} + +static bool32 SelectedMonHasVolatile(u16 itemId) +{ + if (gPartyMenu.slotId == 0) + return IteamHealsMonVolatile(0, itemId); + else if (gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI) && gPartyMenu.slotId == 1) + return IteamHealsMonVolatile(2, itemId); + return FALSE; +} + // Returns whether an item can be used in battle and sets the fail text. bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) { @@ -1002,8 +1026,8 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) u16 hp = GetMonData(mon, MON_DATA_HP); // Embargo Check - if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) - || (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) + if ((gPartyMenu.slotId == 0 && gBattleMons[B_POSITION_PLAYER_LEFT].volatiles.embargo) + || (gPartyMenu.slotId == 1 && gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.embargo)) { return TRUE; } @@ -1016,7 +1040,7 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) cannotUse = TRUE; break; case EFFECT_ITEM_SET_FOCUS_ENERGY: - if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY) + if (gBattleMons[gBattlerInMenuId].volatiles.dragonCheer || gBattleMons[gBattlerInMenuId].volatiles.focusEnergy) cannotUse = TRUE; break; case EFFECT_ITEM_SET_MIST: @@ -1064,13 +1088,13 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) break; case EFFECT_ITEM_CURE_STATUS: if (!((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + || SelectedMonHasVolatile(itemId))) cannotUse = TRUE; break; case EFFECT_ITEM_HEAL_AND_CURE_STATUS: if ((hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId)))) + || SelectedMonHasVolatile(itemId))) cannotUse = TRUE; break; case EFFECT_ITEM_REVIVE: @@ -1078,11 +1102,11 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) cannotUse = TRUE; break; case EFFECT_ITEM_RESTORE_PP: - if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP) + if (GetItemEffect(itemId)[4] == ITEM4_HEAL_PP) { for (i = 0; i < MAX_MON_MOVES; i++) { - if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i)); + if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i)) break; } if (i == MAX_MON_MOVES) @@ -1111,7 +1135,7 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) case ITEM_EFFECT_CURE_POISON: case ITEM_EFFECT_CURE_SLEEP: case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: case ITEM_EFFECT_CURE_PARALYSIS: case ITEM_EFFECT_CURE_ALL_STATUS: case ITEM_EFFECT_ATK_EV: @@ -1120,29 +1144,30 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) case ITEM_EFFECT_SPDEF_EV: case ITEM_EFFECT_SPEED_EV: case ITEM_EFFECT_DEF_EV: - gTasks[taskId].data[4] = 1; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_PARTY_MENU; ItemUseOutOfBattle_Medicine(taskId); break; case ITEM_EFFECT_SACRED_ASH: - gTasks[taskId].data[4] = 1; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_PARTY_MENU; ItemUseOutOfBattle_SacredAsh(taskId); break; case ITEM_EFFECT_RAISE_LEVEL: - gTasks[taskId].data[4] = 1; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_PARTY_MENU; ItemUseOutOfBattle_RareCandy(taskId); break; case ITEM_EFFECT_PP_UP: case ITEM_EFFECT_PP_MAX: - gTasks[taskId].data[4] = 1; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_PARTY_MENU; ItemUseOutOfBattle_PPUp(taskId); break; case ITEM_EFFECT_HEAL_PP: - gTasks[taskId].data[4] = 1; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_PARTY_MENU; ItemUseOutOfBattle_PPRecovery(taskId); break; default: - gTasks[taskId].data[4] = 4; + gTasks[taskId].tEnigmaBerryType = ITEM_USE_BAG_MENU; ItemUseOutOfBattle_CannotUse(taskId); + break; } } diff --git a/src/math_util.c b/src/math_util.c index b47a0c58b..019d43712 100644 --- a/src/math_util.c +++ b/src/math_util.c @@ -171,3 +171,11 @@ s32 MathUtil_Inv32(s32 y) return x / y; } +u32 MathUtil_Exponent(u32 x, u32 y) +{ + u32 result = 1; + for (u32 index = 0; index < y; index++) + result *= x; + + return result; +} diff --git a/src/overworld.c b/src/overworld.c index e8d40ba87..966898812 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -352,10 +352,11 @@ void Overworld_ResetBattleFlagsAndVars(void) FlagClear(B_FLAG_INVERSE_BATTLE); FlagClear(B_FLAG_FORCE_DOUBLE_WILD); FlagClear(B_SMART_WILD_AI_FLAG); - FlagClear(B_FLAG_NO_BAG_USE); FlagClear(B_FLAG_NO_CATCHING); + FlagClear(B_FLAG_NO_RUNNING); FlagClear(B_FLAG_DYNAMAX_BATTLE); FlagClear(B_FLAG_SKY_BATTLE); + FlagClear(B_FLAG_NO_WHITEOUT); } #endif diff --git a/src/party_menu.c b/src/party_menu.c index 21bf6bd7c..b2127fcd7 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4545,7 +4545,7 @@ static bool8 IsHPRecoveryItem(u16 item) return FALSE; } -static void GetMedicineItemEffectMessage(u16 item) +static void GetMedicineItemEffectMessage(u16 item, u32 statusCured) { switch (GetItemEffectType(item)) { @@ -4558,8 +4558,11 @@ static void GetMedicineItemEffectMessage(u16 item) case ITEM_EFFECT_CURE_BURN: StringExpandPlaceholders(gStringVar4, gText_PkmnBurnHealed); break; - case ITEM_EFFECT_CURE_FREEZE: - StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: + if (statusCured & STATUS1_FREEZE) + StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + if (statusCured & STATUS1_FROSTBITE) + StringExpandPlaceholders(gStringVar4, gText_PkmnFrostbiteHealed); break; case ITEM_EFFECT_CURE_PARALYSIS: StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis); @@ -5013,6 +5016,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc func) struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; u16 item = gSpecialVar_ItemId; bool8 canHeal, cannotUse; + u32 oldStatus = GetMonData(mon, MON_DATA_STATUS); if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE) { cannotUse = TRUE; @@ -5062,7 +5066,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc func) else { GetMonNickname(mon, gStringVar1); - GetMedicineItemEffectMessage(item); + GetMedicineItemEffectMessage(item, oldStatus); DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = func; @@ -5353,7 +5357,7 @@ static void ItemUseCB_RestorePP(u8 taskId, TaskFunc func) RemoveBagItem(gSpecialVar_ItemId, 1); move = GetMonData(mon, gPartyMenu.ppMoveSlot + MON_DATA_MOVE1); StringCopy(gStringVar1, gMovesInfo[move].name); - GetMedicineItemEffectMessage(gSpecialVar_ItemId); + GetMedicineItemEffectMessage(gSpecialVar_ItemId, 0); DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = Task_ClosePartyMenuAfterText; @@ -6127,16 +6131,16 @@ u8 GetItemEffectType(u16 item) u32 statusCure; const u8 *itemEffect = GetItemEffect(item); - // Read the item's effect properties. if (itemEffect == NULL) return ITEM_EFFECT_NONE; - if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & ITEM3_GUARD_SPEC)) + if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1] || (itemEffect[3] & ITEM3_GUARD_SPEC)) return ITEM_EFFECT_X_ITEM; else if (itemEffect[0] & ITEM0_SACRED_ASH) return ITEM_EFFECT_SACRED_ASH; else if (itemEffect[3] & ITEM3_LEVEL_UP) return ITEM_EFFECT_RAISE_LEVEL; + statusCure = itemEffect[3] & ITEM3_STATUS_ALL; if (statusCure || (itemEffect[0] >> 7)) { @@ -6147,7 +6151,7 @@ u8 GetItemEffectType(u16 item) else if (statusCure == ITEM3_BURN) return ITEM_EFFECT_CURE_BURN; else if (statusCure == ITEM3_FREEZE) - return ITEM_EFFECT_CURE_FREEZE; + return ITEM_EFFECT_CURE_FREEZE_FROSTBITE; else if (statusCure == ITEM3_PARALYSIS) return ITEM_EFFECT_CURE_PARALYSIS; else if (statusCure == ITEM3_CONFUSION) @@ -6157,6 +6161,7 @@ u8 GetItemEffectType(u16 item) else return ITEM_EFFECT_CURE_ALL_STATUS; } + if (itemEffect[4] & (ITEM4_REVIVE | ITEM4_HEAL_HP)) return ITEM_EFFECT_HEAL_HP; else if (itemEffect[4] & ITEM4_EV_ATK) diff --git a/src/pokemon.c b/src/pokemon.c index 0712f86e7..42a593649 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -37,6 +37,7 @@ #include "pokemon_storage_system.h" #include "random.h" #include "recorded_battle.h" +#include "regions.h" #include "rtc.h" #include "sound.h" #include "string_util.h" @@ -76,11 +77,12 @@ struct SpeciesItem }; static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); -static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); +static u16 CalculateBoxMonChecksumDecrypt(struct BoxPokemon *boxMon); +static u16 CalculateBoxMonChecksumReencrypt(struct BoxPokemon *boxMon); +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, enum SubstructType substructType); static void EncryptBoxMon(struct BoxPokemon *boxMon); static void DecryptBoxMon(struct BoxPokemon *boxMon); static void Task_PlayMapChosenOrBattleBGM(u8 taskId); -static bool8 ShouldSkipFriendshipChange(void); void TrySpecialOverworldEvo(); EWRAM_DATA static u8 sLearningMoveTableID = 0; @@ -116,10 +118,11 @@ static const struct CombinedMove sCombinedMoves[2] = // NOTE: The order of the elements in the array below is irrelevant. // To reorder the pokedex, see the values in include/constants/pokedex.h. +#define KANTO_TO_NATIONAL(name) [KANTO_DEX_##name - 1] = NATIONAL_DEX_##name #define HOENN_TO_NATIONAL(name) [HOENN_DEX_##name - 1] = NATIONAL_DEX_##name -#define KANTO_TO_NATIONAL(name) [KANTO_DEX_##name] = NATIONAL_DEX_##name -static const enum NationalDexOrder sKantoDexNumToNationalDexNum[KANTO_DEX_COUNT + 1] = + +static const enum NationalDexOrder sKantoDexNumToNationalDexNum[KANTO_DEX_COUNT] = { // Kanto KANTO_TO_NATIONAL(BULBASAUR), @@ -380,6 +383,7 @@ static const enum NationalDexOrder sKantoDexNumToNationalDexNum[KANTO_DEX_COUNT KANTO_TO_NATIONAL(MEW), }; + // Assigns all Hoenn Dex Indexes to a National Dex Index static const enum NationalDexOrder sHoennToNationalOrder[HOENN_DEX_COUNT - 1] = { @@ -977,71 +981,15 @@ const struct SpriteTemplate gBattlerSpriteTemplates[MAX_BATTLERS_COUNT] = }, }; -static const struct SpriteTemplate sTrainerBackSpriteTemplates[] = +static const struct SpriteTemplate sTrainerBackSpriteTemplate = { - [TRAINER_BACK_PIC_RED] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_Red, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_LEAF] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_Leaf, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_RSBrendan, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_RUBY_SAPPHIRE_MAY] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_RSMay, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_POKEDUDE] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_Pokedude, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_OLD_MAN] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_OldMan, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, - [TRAINER_BACK_PIC_STEVEN] = { - .tileTag = TAG_NONE, - .paletteTag = 0, - .oam = &gOamData_BattleSpritePlayerSide, - .anims = NULL, - .images = gTrainerBackPicTable_Steven, - .affineAnims = gAffineAnims_BattleSpritePlayerSide, - .callback = SpriteCB_BattleSpriteStartSlideLeft, - }, + .tileTag = TAG_NONE, + .paletteTag = 0, + .oam = &gOamData_BattleSpritePlayerSide, + .anims = NULL, + .images = NULL, + .affineAnims = gAffineAnims_BattleSpritePlayerSide, + .callback = SpriteCB_BattleSpriteStartSlideLeft, }; #define NUM_SECRET_BASE_CLASSES 5 @@ -1095,14 +1043,6 @@ static const s8 sFriendshipEventModifiers[][3] = [FRIENDSHIP_EVENT_FAINT_LARGE] = {-5, -5, -10 }, }; -#define HM_MOVES_END 0xFFFF - -static const u16 sHMMoves[] = -{ - MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH, - MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END -}; - static const struct SpeciesItem sAlteringCaveWildMonHeldItems[] = { {SPECIES_NONE, ITEM_NONE}, @@ -1305,7 +1245,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, { isShiny = TRUE; } - // else if (P_ONLY_OBTAINABLE_SHINIES && InBattlePyramid()) + // else if (P_ONLY_OBTAINABLE_SHINIES && (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || (B_FLAG_NO_CATCHING != 0 && FlagGet(B_FLAG_NO_CATCHING)))) // { // isShiny = FALSE; // } @@ -1888,24 +1828,36 @@ void CreateEnemyEventMon(void) static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) { - u16 checksum = 0; - union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0); - union PokemonSubstruct *substruct1 = GetSubstruct(boxMon, boxMon->personality, 1); - union PokemonSubstruct *substruct2 = GetSubstruct(boxMon, boxMon->personality, 2); - union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3); - s32 i; + u32 checksum = 0; - for (i = 0; i < (s32)ARRAY_COUNT(substruct0->raw); i++) - checksum += substruct0->raw[i]; + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); - for (i = 0; i < (s32)ARRAY_COUNT(substruct1->raw); i++) - checksum += substruct1->raw[i]; + return checksum; +} - for (i = 0; i < (s32)ARRAY_COUNT(substruct2->raw); i++) - checksum += substruct2->raw[i]; +static u16 CalculateBoxMonChecksumDecrypt(struct BoxPokemon *boxMon) +{ + u32 checksum = 0; - for (i = 0; i < (s32)ARRAY_COUNT(substruct3->raw); i++) - checksum += substruct3->raw[i]; + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + { + boxMon->secure.raw[i] ^= (boxMon->otId ^ boxMon->personality); + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); + } + + return checksum; +} + +static u16 CalculateBoxMonChecksumReencrypt(struct BoxPokemon *boxMon) +{ + u32 checksum = 0; + + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + { + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); + boxMon->secure.raw[i] ^= (boxMon->otId ^ boxMon->personality); + } return checksum; } @@ -2399,7 +2351,8 @@ void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerPicId, u8 battlerPosition gMultiuseSpriteTemplate.paletteTag = trainerPicId; if (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_PLAYER_RIGHT) { - gMultiuseSpriteTemplate = sTrainerBackSpriteTemplates[trainerPicId]; + gMultiuseSpriteTemplate = sTrainerBackSpriteTemplate; + gMultiuseSpriteTemplate.images = &gTrainerBacksprites[trainerPicId].backPic; gMultiuseSpriteTemplate.anims = gTrainerBacksprites[trainerPicId].animation; } else @@ -2425,8 +2378,7 @@ void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPositio static void EncryptBoxMon(struct BoxPokemon *boxMon) { - u32 i; - for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->personality; boxMon->secure.raw[i] ^= boxMon->otId; @@ -2435,70 +2387,26 @@ static void EncryptBoxMon(struct BoxPokemon *boxMon) static void DecryptBoxMon(struct BoxPokemon *boxMon) { - u32 i; - for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->otId; boxMon->secure.raw[i] ^= boxMon->personality; } } -#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \ -case n: \ - { \ - \ - switch (substructType) \ - { \ - case 0: \ - substruct = &boxMon->secure.substructs[v1]; \ - break; \ - case 1: \ - substruct = &boxMon->secure.substructs[v2]; \ - break; \ - case 2: \ - substruct = &boxMon->secure.substructs[v3]; \ - break; \ - case 3: \ - substruct = &boxMon->secure.substructs[v4]; \ - break; \ - } \ - break; \ - } \ - - -static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) +static const u8 sSubstructOffsets[4][24] = { - union PokemonSubstruct *substruct = NULL; + [SUBSTRUCT_TYPE_0] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3}, + [SUBSTRUCT_TYPE_1] = {1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2}, + [SUBSTRUCT_TYPE_2] = {2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 3, 2, 3, 2, 1, 1}, + [SUBSTRUCT_TYPE_3] = {3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0}, +}; - switch (personality % 24) - { - SUBSTRUCT_CASE( 0,0,1,2,3) - SUBSTRUCT_CASE( 1,0,1,3,2) - SUBSTRUCT_CASE( 2,0,2,1,3) - SUBSTRUCT_CASE( 3,0,3,1,2) - SUBSTRUCT_CASE( 4,0,2,3,1) - SUBSTRUCT_CASE( 5,0,3,2,1) - SUBSTRUCT_CASE( 6,1,0,2,3) - SUBSTRUCT_CASE( 7,1,0,3,2) - SUBSTRUCT_CASE( 8,2,0,1,3) - SUBSTRUCT_CASE( 9,3,0,1,2) - SUBSTRUCT_CASE(10,2,0,3,1) - SUBSTRUCT_CASE(11,3,0,2,1) - SUBSTRUCT_CASE(12,1,2,0,3) - SUBSTRUCT_CASE(13,1,3,0,2) - SUBSTRUCT_CASE(14,2,1,0,3) - SUBSTRUCT_CASE(15,3,1,0,2) - SUBSTRUCT_CASE(16,2,3,0,1) - SUBSTRUCT_CASE(17,3,2,0,1) - SUBSTRUCT_CASE(18,1,2,3,0) - SUBSTRUCT_CASE(19,1,3,2,0) - SUBSTRUCT_CASE(20,2,1,3,0) - SUBSTRUCT_CASE(21,3,1,2,0) - SUBSTRUCT_CASE(22,2,3,1,0) - SUBSTRUCT_CASE(23,3,2,1,0) - } +ARM_FUNC NOINLINE static u32 ConstantMod24(u32 a) { return a % 24; } - return substruct; +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, enum SubstructType substructType) +{ + return &boxMon->secure.substructs[sSubstructOffsets[substructType][ConstantMod24(personality)]]; } /* GameFreak called GetMonData with either 2 or 3 arguments, for type @@ -2568,19 +2476,58 @@ u32 GetMonData2(struct Pokemon *mon, s32 field) return GetMonData3(mon, field, NULL); } -struct EvolutionTrackerBitfield -{ - u16 a: 5; - u16 b: 5; - u16 unused: 6; -}; union EvolutionTracker { - u16 value; - struct EvolutionTrackerBitfield asField; + u16 combinedValue:10; + struct { + u16 tracker1: 5; + u16 tracker2: 5; + }; }; +static ALWAYS_INLINE struct PokemonSubstruct0 *GetSubstruct0(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_0)->type0); +} + +static ALWAYS_INLINE struct PokemonSubstruct1 *GetSubstruct1(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_1)->type1); +} + +static ALWAYS_INLINE struct PokemonSubstruct2 *GetSubstruct2(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_2)->type2); +} + +static ALWAYS_INLINE struct PokemonSubstruct3 *GetSubstruct3(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_3)->type3); +} + +static bool32 IsBadEgg(struct BoxPokemon *boxMon) +{ + if (boxMon->isBadEgg) + return TRUE; + + if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + { + boxMon->isBadEgg = TRUE; + boxMon->isEgg = TRUE; + GetSubstruct3(boxMon)->isEgg = TRUE; + + return TRUE; + } + + return FALSE; +} + +static ALWAYS_INLINE bool32 IsEggOrBadEgg(struct BoxPokemon *boxMon) +{ + return GetSubstruct3(boxMon)->isEgg || IsBadEgg(boxMon); +} + /* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type * safety we have a GetBoxMonData macro (in include/pokemon.h) which * dispatches to either GetBoxMonData2 or GetBoxMonData3 based on the @@ -2589,35 +2536,18 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) { s32 i; u32 retVal = 0; - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - union EvolutionTracker evoTracker; // Any field greater than MON_DATA_ENCRYPT_SEPARATOR is encrypted and must be treated as such if (field > MON_DATA_ENCRYPT_SEPARATOR) { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - DecryptBoxMon(boxMon); - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) - { - boxMon->isBadEgg = TRUE; - boxMon->isEgg = TRUE; - substruct3->isEgg = TRUE; - } - switch (field) { case MON_DATA_NICKNAME: case MON_DATA_NICKNAME10: { - if (boxMon->isBadEgg) + if (IsBadEgg(boxMon)) { for (retVal = 0; retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; @@ -2656,6 +2586,7 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) // so if both are 0 we assume that this is a vanilla // Pokémon and replace them with EOS. This means that // two CHAR_SPACE at the end of a nickname are trimmed. + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); if (field != MON_DATA_NICKNAME10 && POKEMON_NAME_LENGTH >= 12) { if (substruct0->nickname11 == 0 && substruct0->nickname12 == 0) @@ -2686,182 +2617,184 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) break; } case MON_DATA_SPECIES: - retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species; + retVal = IsBadEgg(boxMon) ? SPECIES_EGG : GetSubstruct0(boxMon)->species; break; case MON_DATA_HELD_ITEM: - retVal = substruct0->heldItem; + retVal = GetSubstruct0(boxMon)->heldItem; break; case MON_DATA_EXP: - retVal = substruct0->experience; + retVal = GetSubstruct0(boxMon)->experience; break; case MON_DATA_PP_BONUSES: - retVal = substruct0->ppBonuses; + retVal = GetSubstruct0(boxMon)->ppBonuses; break; case MON_DATA_FRIENDSHIP: - retVal = substruct0->friendship; + retVal = GetSubstruct0(boxMon)->friendship; break; case MON_DATA_MOVE1: - retVal = substruct1->move1; + retVal = GetSubstruct1(boxMon)->move1; break; case MON_DATA_MOVE2: - retVal = substruct1->move2; + retVal = GetSubstruct1(boxMon)->move2; break; case MON_DATA_MOVE3: - retVal = substruct1->move3; + retVal = GetSubstruct1(boxMon)->move3; break; case MON_DATA_MOVE4: - retVal = substruct1->move4; + retVal = GetSubstruct1(boxMon)->move4; break; case MON_DATA_PP1: - retVal = substruct1->pp1; + retVal = GetSubstruct1(boxMon)->pp1; break; case MON_DATA_PP2: - retVal = substruct1->pp2; + retVal = GetSubstruct1(boxMon)->pp2; break; case MON_DATA_PP3: - retVal = substruct1->pp3; + retVal = GetSubstruct1(boxMon)->pp3; break; case MON_DATA_PP4: - retVal = substruct1->pp4; + retVal = GetSubstruct1(boxMon)->pp4; break; case MON_DATA_HP_EV: - retVal = substruct2->hpEV; + retVal = GetSubstruct2(boxMon)->hpEV; break; case MON_DATA_ATK_EV: - retVal = substruct2->attackEV; + retVal = GetSubstruct2(boxMon)->attackEV; break; case MON_DATA_DEF_EV: - retVal = substruct2->defenseEV; + retVal = GetSubstruct2(boxMon)->defenseEV; break; case MON_DATA_SPEED_EV: - retVal = substruct2->speedEV; + retVal = GetSubstruct2(boxMon)->speedEV; break; case MON_DATA_SPATK_EV: - retVal = substruct2->spAttackEV; + retVal = GetSubstruct2(boxMon)->spAttackEV; break; case MON_DATA_SPDEF_EV: - retVal = substruct2->spDefenseEV; + retVal = GetSubstruct2(boxMon)->spDefenseEV; break; case MON_DATA_COOL: - retVal = substruct2->cool; + retVal = GetSubstruct2(boxMon)->cool; break; case MON_DATA_BEAUTY: - retVal = substruct2->beauty; + retVal = GetSubstruct2(boxMon)->beauty; break; case MON_DATA_CUTE: - retVal = substruct2->cute; + retVal = GetSubstruct2(boxMon)->cute; break; case MON_DATA_SMART: - retVal = substruct2->smart; + retVal = GetSubstruct2(boxMon)->smart; break; case MON_DATA_TOUGH: - retVal = substruct2->tough; + retVal = GetSubstruct2(boxMon)->tough; break; case MON_DATA_SHEEN: - retVal = substruct2->sheen; + retVal = GetSubstruct2(boxMon)->sheen; break; case MON_DATA_POKERUS: - retVal = substruct3->pokerus; + retVal = GetSubstruct3(boxMon)->pokerus; break; case MON_DATA_MET_LOCATION: - retVal = substruct3->metLocation; + retVal = GetSubstruct3(boxMon)->metLocation; break; case MON_DATA_MET_LEVEL: - retVal = substruct3->metLevel; + retVal = GetSubstruct3(boxMon)->metLevel; break; case MON_DATA_MET_GAME: - retVal = substruct3->metGame; + retVal = GetSubstruct3(boxMon)->metGame; break; case MON_DATA_POKEBALL: - retVal = substruct0->pokeball; + retVal = GetSubstruct0(boxMon)->pokeball; break; case MON_DATA_OT_GENDER: - retVal = substruct3->otGender; + retVal = GetSubstruct3(boxMon)->otGender; break; case MON_DATA_HP_IV: - retVal = substruct3->hpIV; + retVal = GetSubstruct3(boxMon)->hpIV; break; case MON_DATA_ATK_IV: - retVal = substruct3->attackIV; + retVal = GetSubstruct3(boxMon)->attackIV; break; case MON_DATA_DEF_IV: - retVal = substruct3->defenseIV; + retVal = GetSubstruct3(boxMon)->defenseIV; break; case MON_DATA_SPEED_IV: - retVal = substruct3->speedIV; + retVal = GetSubstruct3(boxMon)->speedIV; break; case MON_DATA_SPATK_IV: - retVal = substruct3->spAttackIV; + retVal = GetSubstruct3(boxMon)->spAttackIV; break; case MON_DATA_SPDEF_IV: - retVal = substruct3->spDefenseIV; + retVal = GetSubstruct3(boxMon)->spDefenseIV; break; case MON_DATA_IS_EGG: - retVal = substruct3->isEgg; + retVal = IsEggOrBadEgg(boxMon); break; case MON_DATA_ABILITY_NUM: - retVal = substruct3->abilityNum; + retVal = GetSubstruct3(boxMon)->abilityNum; break; case MON_DATA_COOL_RIBBON: - retVal = substruct3->coolRibbon; + retVal = GetSubstruct3(boxMon)->coolRibbon; break; case MON_DATA_BEAUTY_RIBBON: - retVal = substruct3->beautyRibbon; + retVal = GetSubstruct3(boxMon)->beautyRibbon; break; case MON_DATA_CUTE_RIBBON: - retVal = substruct3->cuteRibbon; + retVal = GetSubstruct3(boxMon)->cuteRibbon; break; case MON_DATA_SMART_RIBBON: - retVal = substruct3->smartRibbon; + retVal = GetSubstruct3(boxMon)->smartRibbon; break; case MON_DATA_TOUGH_RIBBON: - retVal = substruct3->toughRibbon; + retVal = GetSubstruct3(boxMon)->toughRibbon; break; case MON_DATA_CHAMPION_RIBBON: - retVal = substruct3->championRibbon; + retVal = GetSubstruct3(boxMon)->championRibbon; break; case MON_DATA_WINNING_RIBBON: - retVal = substruct3->winningRibbon; + retVal = GetSubstruct3(boxMon)->winningRibbon; break; case MON_DATA_VICTORY_RIBBON: - retVal = substruct3->victoryRibbon; + retVal = GetSubstruct3(boxMon)->victoryRibbon; break; case MON_DATA_ARTIST_RIBBON: - retVal = substruct3->artistRibbon; + retVal = GetSubstruct3(boxMon)->artistRibbon; break; case MON_DATA_EFFORT_RIBBON: - retVal = substruct3->effortRibbon; + retVal = GetSubstruct3(boxMon)->effortRibbon; break; case MON_DATA_MARINE_RIBBON: - retVal = substruct3->marineRibbon; + retVal = GetSubstruct3(boxMon)->marineRibbon; break; case MON_DATA_LAND_RIBBON: - retVal = substruct3->landRibbon; + retVal = GetSubstruct3(boxMon)->landRibbon; break; case MON_DATA_SKY_RIBBON: - retVal = substruct3->skyRibbon; + retVal = GetSubstruct3(boxMon)->skyRibbon; break; case MON_DATA_COUNTRY_RIBBON: - retVal = substruct3->countryRibbon; + retVal = GetSubstruct3(boxMon)->countryRibbon; break; case MON_DATA_NATIONAL_RIBBON: - retVal = substruct3->nationalRibbon; + retVal = GetSubstruct3(boxMon)->nationalRibbon; break; case MON_DATA_EARTH_RIBBON: - retVal = substruct3->earthRibbon; + retVal = GetSubstruct3(boxMon)->earthRibbon; break; case MON_DATA_WORLD_RIBBON: - retVal = substruct3->worldRibbon; + retVal = GetSubstruct3(boxMon)->worldRibbon; break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: - retVal = substruct3->modernFatefulEncounter; + retVal = GetSubstruct3(boxMon)->modernFatefulEncounter; break; case MON_DATA_SPECIES_OR_EGG: - retVal = substruct0->species; - if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg)) + retVal = GetSubstruct0(boxMon)->species; + if (retVal && IsEggOrBadEgg(boxMon)) retVal = SPECIES_EGG; break; case MON_DATA_IVS: + { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) @@ -2869,9 +2802,11 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); break; + } case MON_DATA_KNOWN_MOVES: - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); u16 *moves = (u16 *)data; s32 i = 0; @@ -2888,9 +2823,10 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) } break; case MON_DATA_RIBBON_COUNT: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); + retVal = 0; retVal += substruct3->coolRibbon; retVal += substruct3->beautyRibbon; retVal += substruct3->cuteRibbon; @@ -2911,75 +2847,81 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) } break; case MON_DATA_RIBBONS: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); retVal = substruct3->championRibbon - | (substruct3->coolRibbon << 1) - | (substruct3->beautyRibbon << 4) - | (substruct3->cuteRibbon << 7) - | (substruct3->smartRibbon << 10) - | (substruct3->toughRibbon << 13) - | (substruct3->winningRibbon << 16) - | (substruct3->victoryRibbon << 17) - | (substruct3->artistRibbon << 18) - | (substruct3->effortRibbon << 19) - | (substruct3->marineRibbon << 20) - | (substruct3->landRibbon << 21) - | (substruct3->skyRibbon << 22) - | (substruct3->countryRibbon << 23) - | (substruct3->nationalRibbon << 24) - | (substruct3->earthRibbon << 25) - | (substruct3->worldRibbon << 26); + | (substruct3->coolRibbon << 1) + | (substruct3->beautyRibbon << 4) + | (substruct3->cuteRibbon << 7) + | (substruct3->smartRibbon << 10) + | (substruct3->toughRibbon << 13) + | (substruct3->winningRibbon << 16) + | (substruct3->victoryRibbon << 17) + | (substruct3->artistRibbon << 18) + | (substruct3->effortRibbon << 19) + | (substruct3->marineRibbon << 20) + | (substruct3->landRibbon << 21) + | (substruct3->skyRibbon << 22) + | (substruct3->countryRibbon << 23) + | (substruct3->nationalRibbon << 24) + | (substruct3->earthRibbon << 25) + | (substruct3->worldRibbon << 26); } break; case MON_DATA_HYPER_TRAINED_HP: - retVal = substruct1->hyperTrainedHP; + retVal = GetSubstruct1(boxMon)->hyperTrainedHP; break; case MON_DATA_HYPER_TRAINED_ATK: - retVal = substruct1->hyperTrainedAttack; + retVal = GetSubstruct1(boxMon)->hyperTrainedAttack; break; case MON_DATA_HYPER_TRAINED_DEF: - retVal = substruct1->hyperTrainedDefense; + retVal = GetSubstruct1(boxMon)->hyperTrainedDefense; break; case MON_DATA_HYPER_TRAINED_SPEED: - retVal = substruct1->hyperTrainedSpeed; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpeed; break; case MON_DATA_HYPER_TRAINED_SPATK: - retVal = substruct1->hyperTrainedSpAttack; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpAttack; break; case MON_DATA_HYPER_TRAINED_SPDEF: - retVal = substruct1->hyperTrainedSpDefense; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpDefense; break; case MON_DATA_IS_SHADOW: - retVal = substruct3->isShadow; + retVal = GetSubstruct3(boxMon)->isShadow; break; case MON_DATA_DYNAMAX_LEVEL: - retVal = substruct3->dynamaxLevel; + retVal = GetSubstruct3(boxMon)->dynamaxLevel; break; case MON_DATA_GIGANTAMAX_FACTOR: - retVal = substruct3->gigantamaxFactor; + retVal = GetSubstruct3(boxMon)->gigantamaxFactor; break; case MON_DATA_TERA_TYPE: - if (gSpeciesInfo[substruct0->species].forceTeraType) { - retVal = gSpeciesInfo[substruct0->species].forceTeraType; - } - else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality - { - const u8 *types = gSpeciesInfo[substruct0->species].types; - retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; - } - else - { - retVal = substruct0->teraType; + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); + if (gSpeciesInfo[substruct0->species].forceTeraType) + { + retVal = gSpeciesInfo[substruct0->species].forceTeraType; + } + else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality + { + const u8 *types = gSpeciesInfo[substruct0->species].types; + retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; + } + else + { + retVal = substruct0->teraType; + } } break; case MON_DATA_EVOLUTION_TRACKER: - evoTracker.asField.a = substruct1->evolutionTracker1; - evoTracker.asField.b = substruct1->evolutionTracker2; - evoTracker.asField.unused = 0; - retVal = evoTracker.value; + { + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); + retVal = (union EvolutionTracker) { + .tracker1 = substruct1->evolutionTracker1, + .tracker2 = substruct1->evolutionTracker2, + }.combinedValue; + } break; default: break; @@ -3129,25 +3071,13 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) { const u8 *data = dataArg; - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - if (field > MON_DATA_ENCRYPT_SEPARATOR) { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - - DecryptBoxMon(boxMon); - - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + if (CalculateBoxMonChecksumDecrypt(boxMon) != boxMon->checksum) { boxMon->isBadEgg = TRUE; boxMon->isEgg = TRUE; - substruct3->isEgg = TRUE; + GetSubstruct3(boxMon)->isEgg = TRUE; EncryptBoxMon(boxMon); return; } @@ -3158,6 +3088,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) case MON_DATA_NICKNAME10: { s32 i; + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); for (i = 0; i < min(sizeof(boxMon->nickname), POKEMON_NAME_LENGTH); i++) boxMon->nickname[i] = data[i]; if (field != MON_DATA_NICKNAME10) @@ -3176,6 +3107,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) } case MON_DATA_SPECIES: { + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); SET16(substruct0->species); if (substruct0->species) boxMon->hasSpecies = TRUE; @@ -3184,180 +3116,178 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) break; } case MON_DATA_HELD_ITEM: - SET16(substruct0->heldItem); + SET16(GetSubstruct0(boxMon)->heldItem); break; case MON_DATA_EXP: - SET32(substruct0->experience); + SET32(GetSubstruct0(boxMon)->experience); break; case MON_DATA_PP_BONUSES: - SET8(substruct0->ppBonuses); + SET8(GetSubstruct0(boxMon)->ppBonuses); break; case MON_DATA_FRIENDSHIP: - SET8(substruct0->friendship); + SET8(GetSubstruct0(boxMon)->friendship); break; case MON_DATA_MOVE1: - SET16(substruct1->move1); + SET16(GetSubstruct1(boxMon)->move1); break; case MON_DATA_MOVE2: - SET16(substruct1->move2); + SET16(GetSubstruct1(boxMon)->move2); break; case MON_DATA_MOVE3: - SET16(substruct1->move3); + SET16(GetSubstruct1(boxMon)->move3); break; case MON_DATA_MOVE4: - SET16(substruct1->move4); + SET16(GetSubstruct1(boxMon)->move4); break; case MON_DATA_PP1: - SET8(substruct1->pp1); + SET8(GetSubstruct1(boxMon)->pp1); break; case MON_DATA_PP2: - SET8(substruct1->pp2); + SET8(GetSubstruct1(boxMon)->pp2); break; case MON_DATA_PP3: - SET8(substruct1->pp3); + SET8(GetSubstruct1(boxMon)->pp3); break; case MON_DATA_PP4: - SET8(substruct1->pp4); + SET8(GetSubstruct1(boxMon)->pp4); break; case MON_DATA_HP_EV: - SET8(substruct2->hpEV); + SET8(GetSubstruct2(boxMon)->hpEV); break; case MON_DATA_ATK_EV: - SET8(substruct2->attackEV); + SET8(GetSubstruct2(boxMon)->attackEV); break; case MON_DATA_DEF_EV: - SET8(substruct2->defenseEV); + SET8(GetSubstruct2(boxMon)->defenseEV); break; case MON_DATA_SPEED_EV: - SET8(substruct2->speedEV); + SET8(GetSubstruct2(boxMon)->speedEV); break; case MON_DATA_SPATK_EV: - SET8(substruct2->spAttackEV); + SET8(GetSubstruct2(boxMon)->spAttackEV); break; case MON_DATA_SPDEF_EV: - SET8(substruct2->spDefenseEV); + SET8(GetSubstruct2(boxMon)->spDefenseEV); break; case MON_DATA_COOL: - SET8(substruct2->cool); + SET8(GetSubstruct2(boxMon)->cool); break; case MON_DATA_BEAUTY: - SET8(substruct2->beauty); + SET8(GetSubstruct2(boxMon)->beauty); break; case MON_DATA_CUTE: - SET8(substruct2->cute); + SET8(GetSubstruct2(boxMon)->cute); break; case MON_DATA_SMART: - SET8(substruct2->smart); + SET8(GetSubstruct2(boxMon)->smart); break; case MON_DATA_TOUGH: - SET8(substruct2->tough); + SET8(GetSubstruct2(boxMon)->tough); break; case MON_DATA_SHEEN: - SET8(substruct2->sheen); + SET8(GetSubstruct2(boxMon)->sheen); break; case MON_DATA_POKERUS: - SET8(substruct3->pokerus); + SET8(GetSubstruct3(boxMon)->pokerus); break; case MON_DATA_MET_LOCATION: - SET8(substruct3->metLocation); + SET8(GetSubstruct3(boxMon)->metLocation); break; case MON_DATA_MET_LEVEL: - SET8(substruct3->metLevel); + SET8(GetSubstruct3(boxMon)->metLevel); break; case MON_DATA_MET_GAME: - SET8(substruct3->metGame); + SET8(GetSubstruct3(boxMon)->metGame); break; case MON_DATA_POKEBALL: - SET8(substruct0->pokeball); + SET8(GetSubstruct0(boxMon)->pokeball); break; case MON_DATA_OT_GENDER: - SET8(substruct3->otGender); + SET8(GetSubstruct3(boxMon)->otGender); break; case MON_DATA_HP_IV: - SET8(substruct3->hpIV); + SET8(GetSubstruct3(boxMon)->hpIV); break; case MON_DATA_ATK_IV: - SET8(substruct3->attackIV); + SET8(GetSubstruct3(boxMon)->attackIV); break; case MON_DATA_DEF_IV: - SET8(substruct3->defenseIV); + SET8(GetSubstruct3(boxMon)->defenseIV); break; case MON_DATA_SPEED_IV: - SET8(substruct3->speedIV); + SET8(GetSubstruct3(boxMon)->speedIV); break; case MON_DATA_SPATK_IV: - SET8(substruct3->spAttackIV); + SET8(GetSubstruct3(boxMon)->spAttackIV); break; case MON_DATA_SPDEF_IV: - SET8(substruct3->spDefenseIV); + SET8(GetSubstruct3(boxMon)->spDefenseIV); break; case MON_DATA_IS_EGG: - SET8(substruct3->isEgg); - if (substruct3->isEgg) - boxMon->isEgg = TRUE; - else - boxMon->isEgg = FALSE; + SET8(GetSubstruct3(boxMon)->isEgg); + SET8(boxMon->isEgg); break; case MON_DATA_ABILITY_NUM: - SET8(substruct3->abilityNum); + SET8(GetSubstruct3(boxMon)->abilityNum); break; case MON_DATA_COOL_RIBBON: - SET8(substruct3->coolRibbon); + SET8(GetSubstruct3(boxMon)->coolRibbon); break; case MON_DATA_BEAUTY_RIBBON: - SET8(substruct3->beautyRibbon); + SET8(GetSubstruct3(boxMon)->beautyRibbon); break; case MON_DATA_CUTE_RIBBON: - SET8(substruct3->cuteRibbon); + SET8(GetSubstruct3(boxMon)->cuteRibbon); break; case MON_DATA_SMART_RIBBON: - SET8(substruct3->smartRibbon); + SET8(GetSubstruct3(boxMon)->smartRibbon); break; case MON_DATA_TOUGH_RIBBON: - SET8(substruct3->toughRibbon); + SET8(GetSubstruct3(boxMon)->toughRibbon); break; case MON_DATA_CHAMPION_RIBBON: - SET8(substruct3->championRibbon); + SET8(GetSubstruct3(boxMon)->championRibbon); break; case MON_DATA_WINNING_RIBBON: - SET8(substruct3->winningRibbon); + SET8(GetSubstruct3(boxMon)->winningRibbon); break; case MON_DATA_VICTORY_RIBBON: - SET8(substruct3->victoryRibbon); + SET8(GetSubstruct3(boxMon)->victoryRibbon); break; case MON_DATA_ARTIST_RIBBON: - SET8(substruct3->artistRibbon); + SET8(GetSubstruct3(boxMon)->artistRibbon); break; case MON_DATA_EFFORT_RIBBON: - SET8(substruct3->effortRibbon); + SET8(GetSubstruct3(boxMon)->effortRibbon); break; case MON_DATA_MARINE_RIBBON: - SET8(substruct3->marineRibbon); + SET8(GetSubstruct3(boxMon)->marineRibbon); break; case MON_DATA_LAND_RIBBON: - SET8(substruct3->landRibbon); + SET8(GetSubstruct3(boxMon)->landRibbon); break; case MON_DATA_SKY_RIBBON: - SET8(substruct3->skyRibbon); + SET8(GetSubstruct3(boxMon)->skyRibbon); break; case MON_DATA_COUNTRY_RIBBON: - SET8(substruct3->countryRibbon); + SET8(GetSubstruct3(boxMon)->countryRibbon); break; case MON_DATA_NATIONAL_RIBBON: - SET8(substruct3->nationalRibbon); + SET8(GetSubstruct3(boxMon)->nationalRibbon); break; case MON_DATA_EARTH_RIBBON: - SET8(substruct3->earthRibbon); + SET8(GetSubstruct3(boxMon)->earthRibbon); break; case MON_DATA_WORLD_RIBBON: - SET8(substruct3->worldRibbon); + SET8(GetSubstruct3(boxMon)->worldRibbon); break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: - SET8(substruct3->modernFatefulEncounter); + SET8(GetSubstruct3(boxMon)->modernFatefulEncounter); break; case MON_DATA_IVS: { u32 ivs; + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); SET32(ivs); substruct3->hpIV = ivs & MAX_IV_MASK; substruct3->attackIV = (ivs >> 5) & MAX_IV_MASK; @@ -3368,43 +3298,42 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) break; } case MON_DATA_HYPER_TRAINED_HP: - SET8(substruct1->hyperTrainedHP); + SET8(GetSubstruct1(boxMon)->hyperTrainedHP); break; case MON_DATA_HYPER_TRAINED_ATK: - SET8(substruct1->hyperTrainedAttack); + SET8(GetSubstruct1(boxMon)->hyperTrainedAttack); break; case MON_DATA_HYPER_TRAINED_DEF: - SET8(substruct1->hyperTrainedDefense); + SET8(GetSubstruct1(boxMon)->hyperTrainedDefense); break; case MON_DATA_HYPER_TRAINED_SPEED: - SET8(substruct1->hyperTrainedSpeed); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpeed); break; case MON_DATA_HYPER_TRAINED_SPATK: - SET8(substruct1->hyperTrainedSpAttack); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpAttack); break; case MON_DATA_HYPER_TRAINED_SPDEF: - SET8(substruct1->hyperTrainedSpDefense); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpDefense); break; case MON_DATA_IS_SHADOW: - SET8(substruct3->isShadow); + SET8(GetSubstruct3(boxMon)->isShadow); break; case MON_DATA_DYNAMAX_LEVEL: - SET8(substruct3->dynamaxLevel); + SET8(GetSubstruct3(boxMon)->dynamaxLevel); break; case MON_DATA_GIGANTAMAX_FACTOR: - SET8(substruct3->gigantamaxFactor); + SET8(GetSubstruct3(boxMon)->gigantamaxFactor); break; case MON_DATA_TERA_TYPE: - SET8(substruct0->teraType); + SET8(GetSubstruct0(boxMon)->teraType); break; case MON_DATA_EVOLUTION_TRACKER: { union EvolutionTracker evoTracker; - u32 evoTrackerValue; - SET32(evoTrackerValue); - evoTracker.value = evoTrackerValue; - substruct1->evolutionTracker1 = evoTracker.asField.a; - substruct1->evolutionTracker2 = evoTracker.asField.b; + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); + SET32(evoTracker.combinedValue); + substruct1->evolutionTracker1 = evoTracker.tracker1; + substruct1->evolutionTracker2 = evoTracker.tracker2; break; } default: @@ -3479,10 +3408,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) } if (field > MON_DATA_ENCRYPT_SEPARATOR) - { - boxMon->checksum = CalculateBoxMonChecksum(boxMon); - EncryptBoxMon(boxMon); - } + boxMon->checksum = CalculateBoxMonChecksumReencrypt(boxMon); } void CopyMon(void *dest, void *src, size_t size) @@ -3636,7 +3562,7 @@ u8 GetMonsStateToDoubles_2(void) return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; } -u16 GetAbilityBySpecies(u16 species, u8 abilityNum) +enum Ability GetAbilityBySpecies(u16 species, u8 abilityNum) { int i; @@ -3661,7 +3587,7 @@ u16 GetAbilityBySpecies(u16 species, u8 abilityNum) return gLastUsedAbility; } -u16 GetMonAbility(struct Pokemon *mon) +enum Ability GetMonAbility(struct Pokemon *mon) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u8 abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL); @@ -3777,7 +3703,7 @@ u32 GetSpeciesType(u16 species, u8 slot) return gSpeciesInfo[SanitizeSpeciesId(species)].types[slot]; } -u32 GetSpeciesAbility(u16 species, u8 slot) +enum Ability GetSpeciesAbility(u16 species, u8 slot) { return gSpeciesInfo[SanitizeSpeciesId(species)].abilities[slot]; } @@ -3924,7 +3850,7 @@ void PokemonToBattleMon(struct Pokemon *src, struct BattlePokemon *dst) for (i = 0; i < NUM_BATTLE_STATS; i++) dst->statStages[i] = DEFAULT_STAT_STAGE; - dst->status2 = 0; + memset(&dst->volatiles, 0, sizeof(struct Volatiles)); } void CopyPartyMonToBattleData(u32 battler, u32 partyIndex) @@ -4723,7 +4649,7 @@ bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct Evoluti { // Gen 2 case IF_GENDER: - if (gender == GetMonGender(mon)) + if (gender == params[i].arg1) currentCondition = TRUE; break; case IF_MIN_FRIENDSHIP: @@ -4969,6 +4895,14 @@ bool32 DoesMonMeetAdditionalConditions(struct Pokemon *mon, const struct Evoluti *canStopEvo = FALSE; } break; + case IF_REGION: + if (GetCurrentRegion() == params[i].arg1) + currentCondition = TRUE; + break; + case IF_NOT_REGION: + if (GetCurrentRegion() != params[i].arg1) + currentCondition = TRUE; + break; case CONDITIONS_END: break; } @@ -5141,7 +5075,6 @@ u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 switch (evolutions[i].method) { - case EVO_SCRIPT_TRIGGER: case EVO_SPIN: if (gSpecialVar_0x8000 == evolutions[i].param) conditionsMet = TRUE; @@ -5159,6 +5092,23 @@ u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 } } break; + case EVO_MODE_SCRIPT_TRIGGER: + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) + { + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) + continue; + if (evolutions[i].method != EVO_SCRIPT_TRIGGER) + continue; + if (DoesMonMeetAdditionalConditions(mon, evolutions[i].params, NULL, PARTY_SIZE, canStopEvo, evoState)) + { + // All checks passed, so stop checking the rest of the evolutions. + // This is different from vanilla where the loop continues. + // If you have overlapping evolutions, put the ones you want to happen first on top of the list. + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; } // Pikachu, Meowth, Eevee and Duraludon cannot evolve if they have the @@ -6176,19 +6126,21 @@ const u16 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFema } } -bool8 IsMoveHM(u16 move) -{ - int i = 0; +#define OR_MOVE_IS_HM(_hm) || (move == MOVE_##_hm) - if (P_CAN_FORGET_HIDDEN_MOVE && B_CATCH_SWAP_CHECK_HMS == FALSE) +bool32 IsMoveHM(u16 move) +{ + return FALSE FOREACH_HM(OR_MOVE_IS_HM); +} + +#undef OR_MOVE_IS_HM + +bool32 CannotForgetMove(u16 move) +{ + if (P_CAN_FORGET_HIDDEN_MOVE) return FALSE; - while (sHMMoves[i] != HM_MOVES_END) - { - if (sHMMoves[i++] == move) - return TRUE; - } - return FALSE; + return IsMoveHM(move); } bool8 IsMonSpriteNotFlipped(u16 species) @@ -6286,7 +6238,7 @@ static s32 GetWildMonTableIdInAlteringCave(u16 species) static inline bool32 CanFirstMonBoostHeldItemRarity(void) { - u32 ability; + enum Ability ability; if (GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG)) return FALSE; @@ -6433,7 +6385,7 @@ void DoMonFrontSpriteAnimation(struct Sprite *sprite, u16 species, bool8 noCry, pan = 0; break; } - if (panModeAnimFlag & SKIP_FRONT_ANIM) + if (panModeAnimFlag & SKIP_FRONT_ANIM || (gBattleTypeFlags & BATTLE_TYPE_GHOST)) { // No animation, only check if cry needs to be played if (!noCry) @@ -6589,11 +6541,11 @@ bool8 HasTwoFramesAnimation(u16 species) && !gTestRunnerHeadless; } -static bool8 ShouldSkipFriendshipChange(void) +bool8 ShouldSkipFriendshipChange(void) { if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) return TRUE; - // if (!gMain.inBattle && (InBattlePike() || InBattlePyramid())) + // if (!gMain.inBattle && (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)) // return TRUE; return FALSE; } @@ -6817,7 +6769,7 @@ u32 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, enum FormChanges u32 targetSpecies = species; const struct FormChange *formChanges = GetSpeciesFormChanges(species); u16 heldItem; - u32 ability; + enum Ability ability; if (formChanges != NULL) { @@ -7007,6 +6959,37 @@ void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv) } // Attempts to perform non-level/item related overworld evolutions; called by tryspecialevo command. +void TryScriptEvolution(void) +{ + u8 i; + bool32 canStopEvo = gSpecialVar_0x8001; + u16 tryMultiple = gSpecialVar_0x8002; + + for (i = 0; i < PARTY_SIZE; i++) + { + u32 targetSpecies = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_SCRIPT_TRIGGER, 0, NULL, &canStopEvo, CHECK_EVO); + + if (targetSpecies != SPECIES_NONE && !(sTriedEvolving & (1u << i))) + { + GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_SCRIPT_TRIGGER, 0, NULL, &canStopEvo, DO_EVO); + sTriedEvolving |= 1u << i; + if(gMain.callback2 == TryScriptEvolution) // This fixes small graphics glitches. + EvolutionScene(&gPlayerParty[i], targetSpecies, canStopEvo, i); + else + BeginEvolutionScene(&gPlayerParty[i], targetSpecies, canStopEvo, i); + + if (tryMultiple) + gCB2_AfterEvolution = TryScriptEvolution; + else + gCB2_AfterEvolution = CB2_ReturnToField; + return; + } + } + + sTriedEvolving = 0; + SetMainCallback2(CB2_ReturnToField); +} + void TrySpecialOverworldEvo(void) { u8 i; @@ -7063,8 +7046,8 @@ bool32 TryFormChange(u32 monId, u32 side, enum FormChanges method) u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); u32 targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies == currentSpecies && gBattleStruct != NULL && gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) - targetSpecies = gBattleStruct->changedSpecies[side][monId]; + if (targetSpecies == currentSpecies && gBattleStruct != NULL && gBattleStruct->partyState[side][monId].changedSpecies != SPECIES_NONE) + targetSpecies = gBattleStruct->partyState[side][monId].changedSpecies; if (targetSpecies != currentSpecies) { @@ -7173,15 +7156,15 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) u32 teraType = GetBoxMonData(boxMon, MON_DATA_TERA_TYPE, NULL); old = *boxMon; - old0 = &(GetSubstruct(&old, old.personality, 0)->type0); - old1 = &(GetSubstruct(&old, old.personality, 1)->type1); - old2 = &(GetSubstruct(&old, old.personality, 2)->type2); - old3 = &(GetSubstruct(&old, old.personality, 3)->type3); + old0 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_0)->type0); + old1 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_1)->type1); + old2 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_2)->type2); + old3 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_3)->type3); - new0 = &(GetSubstruct(boxMon, personality, 0)->type0); - new1 = &(GetSubstruct(boxMon, personality, 1)->type1); - new2 = &(GetSubstruct(boxMon, personality, 2)->type2); - new3 = &(GetSubstruct(boxMon, personality, 3)->type3); + new0 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_0)->type0); + new1 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_1)->type1); + new2 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_2)->type2); + new3 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_3)->type3); DecryptBoxMon(&old); boxMon->personality = personality; @@ -7189,8 +7172,7 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) *new1 = *old1; *new2 = *old2; *new3 = *old3; - boxMon->checksum = CalculateBoxMonChecksum(boxMon); - EncryptBoxMon(boxMon); + boxMon->checksum = CalculateBoxMonChecksumReencrypt(boxMon); SetBoxMonData(boxMon, MON_DATA_IS_SHINY, &isShiny); SetBoxMonData(boxMon, MON_DATA_HIDDEN_NATURE, &hiddenNature); @@ -7389,6 +7371,14 @@ void SavePlayerPartyMon(u32 index, struct Pokemon *mon) gSaveBlock1Ptr->playerParty[index] = *mon; } +u32 IsSpeciesOfType(u32 species, u32 type) +{ + if (gSpeciesInfo[species].types[0] == type + || gSpeciesInfo[species].types[1] == type) + return TRUE; + return FALSE; +} + //pokefirered specific u8 GetPlayerPartyHighestLevel(void) { diff --git a/src/pokemon_animation.c b/src/pokemon_animation.c index 6bd32ee51..bf9327c87 100644 --- a/src/pokemon_animation.c +++ b/src/pokemon_animation.c @@ -523,6 +523,11 @@ static void Task_HandleMonAnimation(u8 taskId) sprite->data[2] = gTasks[taskId].tSpeciesId; sprite->data[1] = 0; + // Task_HandleMonAnimation handles more than just KO animations, + // but if the counter is non-zero then only KO animations are running. + // This assumption is not checked. + if (gBattleStruct->battlerKOAnimsRunning > 0) + gBattleStruct->battlerKOAnimsRunning--; DestroyTask(taskId); } } diff --git a/src/recorded_battle.c b/src/recorded_battle.c index a3b258c91..632bb87b7 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -346,35 +346,35 @@ void RecordedBattle_CopyBattlerMoves(u32 battler) void RecordedBattle_CheckMovesetChanges(u8 mode) { - s32 battlerId, j, k; + s32 battler, j, k; if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) return; - for (battlerId = 0; battlerId < gBattlersCount; battlerId++) + for (battler = 0; battler < gBattlersCount; battler++) { // Player's side only - if (GetBattlerSide(battlerId) != B_SIDE_OPPONENT) + if (IsOnPlayerSide(battler)) { if (mode == B_RECORD_MODE_RECORDING) { // Check if any of the battler's moves have changed. for (j = 0; j < MAX_MON_MOVES; j++) { - if (gBattleMons[battlerId].moves[j] != sPlayerMonMoves[battlerId / 2][j]) + if (gBattleMons[battler].moves[j] != sPlayerMonMoves[battler / 2][j]) break; } if (j != MAX_MON_MOVES) { // At least one of the moves has been changed - RecordedBattle_SetBattlerAction(battlerId, ACTION_MOVE_CHANGE); + RecordedBattle_SetBattlerAction(battler, ACTION_MOVE_CHANGE); for (j = 0; j < MAX_MON_MOVES; j++) { for (k = 0; k < MAX_MON_MOVES; k++) { - if (gBattleMons[battlerId].moves[j] == sPlayerMonMoves[battlerId / 2][k]) + if (gBattleMons[battler].moves[j] == sPlayerMonMoves[battler / 2][k]) { - RecordedBattle_SetBattlerAction(battlerId, k); + RecordedBattle_SetBattlerAction(battler, k); break; } } @@ -383,7 +383,7 @@ void RecordedBattle_CheckMovesetChanges(u8 mode) } else // B_RECORD_MODE_PLAYBACK { - if (sBattleRecords[battlerId][sBattlerRecordSizes[battlerId]] == ACTION_MOVE_CHANGE) + if (sBattleRecords[battler][sBattlerRecordSizes[battler]] == ACTION_MOVE_CHANGE) { u8 ppBonuses[MAX_MON_MOVES]; u8 moveSlots[MAX_MON_MOVES]; @@ -393,55 +393,56 @@ void RecordedBattle_CheckMovesetChanges(u8 mode) // We know the current action is ACTION_MOVE_CHANGE, retrieve // it without saving it to move on to the next action. - RecordedBattle_GetBattlerAction(RECORDED_BYTE, battlerId); + RecordedBattle_GetBattlerAction(RECORDED_BYTE, battler); for (j = 0; j < MAX_MON_MOVES; j++) - ppBonuses[j] = ((gBattleMons[battlerId].ppBonuses & (3 << (j << 1))) >> (j << 1)); + ppBonuses[j] = ((gBattleMons[battler].ppBonuses & (3 << (j << 1))) >> (j << 1)); for (j = 0; j < MAX_MON_MOVES; j++) { - moveSlots[j] = RecordedBattle_GetBattlerAction(RECORDED_BYTE, battlerId); - movePp.moves[j] = gBattleMons[battlerId].moves[moveSlots[j]]; - movePp.currentPp[j] = gBattleMons[battlerId].pp[moveSlots[j]]; + moveSlots[j] = RecordedBattle_GetBattlerAction(RECORDED_BYTE, battler); + movePp.moves[j] = gBattleMons[battler].moves[moveSlots[j]]; + movePp.currentPp[j] = gBattleMons[battler].pp[moveSlots[j]]; movePp.maxPp[j] = ppBonuses[moveSlots[j]]; - mimickedMoveSlots[j] = (gDisableStructs[battlerId].mimickedMoves & gBitTable[j]) >> j; + mimickedMoveSlots[j] = (gDisableStructs[battler].mimickedMoves & (1u << j)) >> j; } for (j = 0; j < MAX_MON_MOVES; j++) { - gBattleMons[battlerId].moves[j] = movePp.moves[j]; - gBattleMons[battlerId].pp[j] = movePp.currentPp[j]; + gBattleMons[battler].moves[j] = movePp.moves[j]; + gBattleMons[battler].pp[j] = movePp.currentPp[j]; } - gBattleMons[battlerId].ppBonuses = 0; - gDisableStructs[battlerId].mimickedMoves = 0; + gBattleMons[battler].ppBonuses = 0; + gDisableStructs[battler].mimickedMoves = 0; for (j = 0; j < MAX_MON_MOVES; j++) { - gBattleMons[battlerId].ppBonuses |= movePp.maxPp[j] << (j << 1); - gDisableStructs[battlerId].mimickedMoves |= mimickedMoveSlots[j] << j; + gBattleMons[battler].ppBonuses |= movePp.maxPp[j] << (j << 1); + gDisableStructs[battler].mimickedMoves |= mimickedMoveSlots[j] << j; } - if (!(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battler].volatiles.transformed)) { + struct Pokemon *mon = GetBattlerMon(battler); for (j = 0; j < MAX_MON_MOVES; j++) - ppBonuses[j] = (GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP_BONUSES, NULL) & ((3 << (j << 1)))) >> (j << 1); + ppBonuses[j] = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & ((3 << (j << 1)))) >> (j << 1); for (j = 0; j < MAX_MON_MOVES; j++) { - movePp.moves[j] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_MOVE1 + moveSlots[j], NULL); - movePp.currentPp[j] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP1 + moveSlots[j], NULL); + movePp.moves[j] = GetMonData(mon, MON_DATA_MOVE1 + moveSlots[j], NULL); + movePp.currentPp[j] = GetMonData(mon, MON_DATA_PP1 + moveSlots[j], NULL); movePp.maxPp[j] = ppBonuses[moveSlots[j]]; } for (j = 0; j < MAX_MON_MOVES; j++) { - SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_MOVE1 + j, &movePp.moves[j]); - SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP1 + j, &movePp.currentPp[j]); + SetMonData(mon, MON_DATA_MOVE1 + j, &movePp.moves[j]); + SetMonData(mon, MON_DATA_PP1 + j, &movePp.currentPp[j]); } ppBonusSet = 0; for (j = 0; j < MAX_MON_MOVES; j++) ppBonusSet |= movePp.maxPp[j] << (j << 1); - SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP_BONUSES, &ppBonusSet); + SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonusSet); } - gChosenMoveByBattler[battlerId] = gBattleMons[battlerId].moves[*(gBattleStruct->chosenMovePositions + battlerId)]; + gChosenMoveByBattler[battler] = GetChosenMoveFromPosition(battler); } } } diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c index 4e79bf242..3869d5902 100644 --- a/src/reshow_battle_screen.c +++ b/src/reshow_battle_screen.c @@ -291,17 +291,17 @@ static bool8 LoadBattlerSpriteGfx(u8 battler) { if (GetBattlerSide(battler) != B_SIDE_PLAYER) { - if (IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)) - DecompressGhostFrontPic(&gEnemyParty[gBattlerPartyIndexes[battler]], battler); + if (IsGhostBattleWithoutScope()) + DecompressGhostFrontPic(battler); else if (!gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) BattleLoadMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battler]], battler); else BattleLoadSubstituteOrMonSpriteGfx(battler, FALSE); } else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler. - DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, battler); + DecompressTrainerBackPic(gSaveBlock2Ptr->playerGender, battler); else if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler. - DecompressTrainerBackPalette(TRAINER_BACK_PIC_OLD_MAN, battler); + DecompressTrainerBackPic(TRAINER_BACK_PIC_OLD_MAN, battler); else if (!gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battler]], battler); else @@ -317,7 +317,7 @@ void CreateBattlerSprite(u32 battler) { u8 posY; - if (IS_BATTLE_TYPE_GHOST_WITHOUT_SCOPE(gBattleTypeFlags)) + if (IsGhostBattleWithoutScope()) posY = GetGhostSpriteDefault_Y(battler); else if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute) posY = GetSubstituteSpriteDefault_Y(battler); diff --git a/src/sprite.c b/src/sprite.c index d0cdd8702..b74357d9c 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -82,7 +82,6 @@ static void ApplyAffineAnimFrameRelativeAndUpdateMatrix(u8 matrixNum, struct Aff static s16 ConvertScaleParam(s16 scale); static void GetAffineAnimFrame(u8 matrixNum, struct Sprite *sprite, struct AffineAnimFrameCmd *frameCmd); static void ApplyAffineAnimFrame(u8 matrixNum, struct AffineAnimFrameCmd *frameCmd); -static u8 IndexOfSpriteTileTag(u16 tag); static void AllocSpriteTileRange(u16 tag, u16 start, u16 count); static void DoLoadSpritePalette(const u16 *src, u16 paletteOffset); static void UpdateSpriteMatrixAnchorPos(struct Sprite *, s32, s32); diff --git a/src/strings.c b/src/strings.c index 352bc35df..7de33c951 100644 --- a/src/strings.c +++ b/src/strings.c @@ -309,6 +309,7 @@ const u8 gText_PkmnCuredOfPoison[] = _("{STR_VAR_1} was cured of its\npoisoning. const u8 gText_PkmnCuredOfParalysis[] = _("{STR_VAR_1} was cured of\nparalysis.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnWokeUp2[] = _("{STR_VAR_1} woke up.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnBurnHealed[] = _("{STR_VAR_1}'s burn was healed.{PAUSE_UNTIL_PRESS}"); +const u8 gText_PkmnFrostbiteHealed[] = _("{STR_VAR_1}'s frostbite was healed.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnThawedOut[] = _("{STR_VAR_1} was thawed out.{PAUSE_UNTIL_PRESS}"); const u8 gText_PPWasRestored[] = _("PP was restored.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnRegainhedHealth[] = _("{STR_VAR_1}は\nげんきを とりもどした!{PAUSE_UNTIL_PRESS}"); diff --git a/src/teachy_tv.c b/src/teachy_tv.c index 020afc0cd..6057aea45 100644 --- a/src/teachy_tv.c +++ b/src/teachy_tv.c @@ -1,4 +1,5 @@ #include "global.h" +#include "battle_main.h" #include "task.h" #include "gflib.h" #include "menu_helpers.h" @@ -16,7 +17,6 @@ #include "event_data.h" #include "load_save.h" #include "battle_transition.h" -#include "battle_main.h" #include "battle.h" #include "battle_controllers.h" #include "global.fieldmap.h" diff --git a/src/trainer_pokemon_sprites.c b/src/trainer_pokemon_sprites.c index ec48cb16b..7a9ee6128 100644 --- a/src/trainer_pokemon_sprites.c +++ b/src/trainer_pokemon_sprites.c @@ -63,7 +63,7 @@ static bool16 DecompressPic(u16 species, u32 personality, bool8 isFrontPic, u8 * if (isFrontPic) DecompressPicFromTable(&gTrainerSprites[species].frontPic, dest); else - DecompressPicFromTable(&gTrainerBacksprites[species].backPic, dest); + CopyTrainerBackspriteFramesToDest(species, dest); } return FALSE; } @@ -334,3 +334,23 @@ u16 CreateTrainerCardTrainerPicSprite(u16 species, bool8 isFrontPic, u16 destX, { return CreateTrainerCardSprite(species, 0, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE); } + +u16 PlayerGenderToFrontTrainerPicId_Debug(u8 gender, bool8 getClass) +{ + if (getClass == TRUE) + { + if (gender != MALE) + return gFacilityClassToPicIndex[FACILITY_CLASS_MAY]; + else + return gFacilityClassToPicIndex[FACILITY_CLASS_BRENDAN]; + } + return gender; +} + +void CopyTrainerBackspriteFramesToDest(u8 trainerPicId, u8 *dest) +{ + const struct SpriteFrameImage *frame = &gTrainerBacksprites[trainerPicId].backPic; + // y_offset is repurposed to indicates how many frames does the trainer pic have. + u32 size = (frame->size * gTrainerBacksprites[trainerPicId].coordinates.y_offset); + CpuSmartCopy16(frame->data, dest, size); +} diff --git a/src/trainer_pools.c b/src/trainer_pools.c index a2db4d81f..6f0e57fdb 100644 --- a/src/trainer_pools.c +++ b/src/trainer_pools.c @@ -1,5 +1,6 @@ #include "global.h" #include "data.h" +#include "item.h" #include "malloc.h" #include "pokemon.h" #include "random.h" @@ -169,7 +170,7 @@ static u32 PickMonFromPool(const struct Trainer *trainer, u8 *poolIndexArray, u3 u32 chosenTags = trainer->party[monIndex].tags; u16 chosenSpecies = trainer->party[monIndex].species; u16 chosenItem = trainer->party[monIndex].heldItem; - u16 chosenNatDex = gSpeciesInfo[chosenSpecies].natDexNum; + enum NationalDexOrder chosenNatDex = gSpeciesInfo[chosenSpecies].natDexNum; // If tag was required, change pool rule to account for the required tag already being picked u32 tagsToEliminate = 0; for (u32 currTag = 0; currTag < POOL_NUM_TAGS; currTag++) @@ -197,7 +198,7 @@ static u32 PickMonFromPool(const struct Trainer *trainer, u8 *poolIndexArray, u3 u32 currentTags = trainer->party[poolIndexArray[currIndex]].tags; u16 currentSpecies = trainer->party[poolIndexArray[currIndex]].species; u16 currentItem = trainer->party[poolIndexArray[currIndex]].heldItem; - u16 currentNatDex = gSpeciesInfo[currentSpecies].natDexNum; + enum NationalDexOrder currentNatDex = gSpeciesInfo[currentSpecies].natDexNum; if (currentTags & tagsToEliminate) { poolIndexArray[currIndex] = POOL_SLOT_DISABLED; @@ -227,6 +228,10 @@ static u32 PickMonFromPool(const struct Trainer *trainer, u8 *poolIndexArray, u3 poolIndexArray[currIndex] = POOL_SLOT_DISABLED; } } + if (rules->megaStoneClause && gItemsInfo[currentItem].sortType == ITEM_TYPE_MEGA_STONE && gItemsInfo[chosenItem].sortType == ITEM_TYPE_MEGA_STONE) + poolIndexArray[currIndex] = POOL_SLOT_DISABLED; + if (rules->zCrystalClause && gItemsInfo[currentItem].sortType == ITEM_TYPE_Z_CRYSTAL && gItemsInfo[chosenItem].sortType == ITEM_TYPE_Z_CRYSTAL) + poolIndexArray[currIndex] = POOL_SLOT_DISABLED; } } return monIndex; diff --git a/test/battle/trainer_control.h b/test/battle/trainer_control.h index 482e7a0a6..5f1cafe5c 100644 --- a/test/battle/trainer_control.h +++ b/test/battle/trainer_control.h @@ -1,9 +1,7 @@ // // DO NOT MODIFY THIS FILE! It is auto-generated from test/battle/trainer_control.party // -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'test/battle/trainer_control.h' to remove #line markers. +// If you want to modify this file see expansion PR #7154 // #line 1 "test/battle/trainer_control.party" @@ -22,6 +20,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 7 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -102,6 +102,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 39 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -133,6 +135,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 51 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -164,6 +168,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 63 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -195,6 +201,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 75 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -225,6 +233,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 87 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 88 .partySize = 1, .poolSize = 4, @@ -290,6 +300,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 104 .battleType = TRAINER_BATTLE_TYPE_SINGLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 105 .partySize = 3, .poolSize = 6, @@ -387,6 +399,8 @@ .battleType = TRAINER_BATTLE_TYPE_DOUBLES, #line 131 .poolRuleIndex = POOL_RULESET_WEATHER_DOUBLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 130 .partySize = 3, .poolSize = 10, @@ -536,6 +550,8 @@ .battleType = TRAINER_BATTLE_TYPE_SINGLES, #line 169 .poolRuleIndex = POOL_RULESET_BASIC, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 168 .partySize = 2, .poolSize = 3, @@ -600,6 +616,8 @@ .poolRuleIndex = POOL_RULESET_BASIC, #line 189 .poolPruneIndex = POOL_PRUNE_TEST, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 187 .partySize = 2, .poolSize = 3, @@ -660,6 +678,8 @@ .poolRuleIndex = POOL_RULESET_BASIC, #line 207 .poolPickIndex = POOL_PICK_LOWEST, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 205 .partySize = 2, .poolSize = 3, @@ -718,6 +738,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 223 .battleType = TRAINER_BATTLE_TYPE_DOUBLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 224 .partySize = 2, .poolSize = 2, @@ -761,6 +783,8 @@ TRAINER_ENCOUNTER_MUSIC_MALE, #line 236 .battleType = TRAINER_BATTLE_TYPE_DOUBLES, +#line 0 + .trainerBackPic = TRAINER_PIC_RED, #line 237 .partySize = 2, .poolSize = 2, diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index ce4fd8f33..10330f177 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -517,8 +517,53 @@ bool AsmFile::ParseEnum() long fallbackPosition = m_pos; std::string headerFilename = ""; - long currentHeaderLine = SkipWhitespaceAndEol(); - std::string enumName = ReadIdentifier(); + long currentHeaderLine = 0; + std::string enumName; + while (true) + { + currentHeaderLine += SkipWhitespaceAndEol(); + std::string identifier = ReadIdentifier(); + if (identifier == "__attribute__") + { + if (m_pos + 1 >= m_size + || m_buffer[m_pos] != '(' + || m_buffer[m_pos + 1] != '(') + { + m_pos = fallbackPosition - 4; + return false; + } + + m_pos += 2; + int parens = 2; + while (true) + { + char c = m_buffer[m_pos++]; + if (c == '\n') + currentHeaderLine++; + + if (c == '(') + { + parens++; + } + else if (c == ')') + { + parens--; + if (parens == 0) + break; + } + else if (parens < 2 || m_pos == m_size) + { + m_pos = fallbackPosition - 4; + return false; + } + } + } + else + { + enumName = identifier; + break; + } + } currentHeaderLine += SkipWhitespaceAndEol(); std::string enumBase = "0"; long enumCounter = 0; @@ -575,6 +620,10 @@ bool AsmFile::ParseEnum() } enumCounter = 0; } + // HACK(#7394): Make the definitions global so that C 'asm' + // statements are able to reference them (if they happen to + // be available in an assembled object file). + std::printf(".global %s; ", currentIdentName.c_str()); std::printf(".equiv %s, (%s) + %ld\n", currentIdentName.c_str(), enumBase.c_str(), enumCounter); enumCounter++; symbolCount++; @@ -679,7 +728,7 @@ void AsmFile::RaiseWarning(const char* format, ...) int AsmFile::SkipWhitespaceAndEol() { int newlines = 0; - while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\n') + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') { if (m_buffer[m_pos] == '\n') newlines++; @@ -702,12 +751,14 @@ int AsmFile::FindLastLineNumber(std::string& filename) if (pos < 0) RaiseError("line indicator for header file not found before `enum`"); + pos++; while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t') pos++; if (!IsAsciiDigit(m_buffer[pos])) RaiseError("malformatted line indicator found before `enum`, expected line number"); + unsigned n = 0; int digit = 0; while ((digit = ConvertDigit(m_buffer[pos++], 10)) != -1) @@ -742,6 +793,7 @@ int AsmFile::FindLastLineNumber(std::string& filename) filename += c; } + return n + linebreaks - 1; } diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index e9d0ced2b..b90e1c019 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -353,7 +353,7 @@ void CFile::TryConvertIncbin() // INCBIN_COMP; include *compressed* version of file if (incbinType == 7) - path = path.append(".lz"); + path = path.append(".smol"); m_pos++; diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 20c2de51b..ac9496d70 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -26,6 +26,11 @@ #include "c_file.h" #include "charmap.h" +#ifdef _WIN32 +#include +#include +#endif + static void UsageAndExit(const char *program); Charmap* g_charmap; @@ -179,6 +184,11 @@ int main(int argc, char **argv) g_charmap = new Charmap(charmap); +#ifdef _WIN32 + // On Windows, piping from stdout can break newlines. Treat stdout as binary stream to avoid this. + _setmode(_fileno(stdout), _O_BINARY); +#endif + const char* extension = GetFileExtension(source); if (!extension) diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp index a978b9a50..d34b1aa23 100644 --- a/tools/scaninc/c_file.cpp +++ b/tools/scaninc/c_file.cpp @@ -257,7 +257,7 @@ void CFile::CheckIncbin() // INCBIN_COMP; include *compressed* version of file if (incbinType == 6) - path = path.append(".lz"); + path = path.append(".smol"); SkipWhitespace(); diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 478f35dd3..c3a39dc5a 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -149,6 +149,15 @@ struct Trainer struct String pool_prune; int pool_prune_line; + + struct String copy_pool; + int copy_pool_line; + + struct String macro; + int macro_line; + + struct String back_pic; + int back_pic_line; }; static bool is_empty_string(struct String s) @@ -169,7 +178,7 @@ static bool is_literal_string(struct String s1, const char *s2) } } -static bool starts_with(struct String s, const char *prefix) +static bool __attribute__((unused)) starts_with(struct String s, const char *prefix) { int n = strlen(prefix); return strncmp((const char *)s.string, prefix, n) == 0; @@ -1280,14 +1289,35 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct trainer->pool_prune_line = value.location.line; trainer->pool_prune = token_string(&value); } + else if (is_literal_token(&key, "Copy Pool")) + { + if (trainer->copy_pool_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Copy Pool'"); + trainer->copy_pool_line = value.location.line; + trainer->copy_pool = token_string(&value); + } + else if (is_literal_token(&key, "Macro")) + { + if (trainer->macro_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Macro'"); + trainer->macro_line = value.location.line; + trainer->macro = token_string(&value); + } + else if (is_literal_token(&key, "Back Pic")) + { + if (trainer->back_pic_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Back Pic'"); + trainer->back_pic_line = value.location.line; + trainer->back_pic = token_string(&value); + } else { any_error = !set_show_parse_error(p, key.location, "expected one of 'Name', 'Class', 'Pic', 'Gender', 'Music', 'Items', 'Battle Type', 'Difficulty', 'Party Size', 'Pool Rules', 'Pool Pick Functions', 'Pool Prune' or 'AI'"); } } - if (!trainer->pic_line) + if (!trainer->pic_line && !trainer->macro_line) any_error = !set_show_parse_error(p, p->location, "expected 'Pic' before Pokemon"); - if (!trainer->name_line) + if (!trainer->name_line && !trainer->macro_line) any_error = !set_show_parse_error(p, p->location, "expected 'Name' before Pokemon"); if (!match_empty_line(p)) { @@ -1307,7 +1337,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct while (match_empty_line(p)) {} if (!parse_pokemon_header(p, &nickname, &species, &gender, &item)) { - if (i > 0 || ends_with(trainer->id, "_NONE")) + if (i > 0 || ends_with(trainer->id, "_NONE") || !is_empty_string(trainer->copy_pool)) break; if (!p->error) set_parse_error(p, p->location, "expected nickname or species"); @@ -1321,6 +1351,12 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct } trainer->pokemon_n++; + if (!is_empty_string(trainer->copy_pool)) + { + set_show_parse_error(p, p->location, "trainer is set to copy mons from other trainer, but defines their own party"); + } + + pokemon->nickname = token_string(&nickname); pokemon->species = token_string(&species); if (is_empty_token(&gender)) @@ -1519,7 +1555,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct } } - if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n) + if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n && is_empty_string(trainer->copy_pool)) { set_show_parse_error(p, p->location, "partySize larger than supplied pool"); } @@ -1707,9 +1743,7 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, "//\n"); fprintf(f, "// DO NOT MODIFY THIS FILE! It is auto-generated from %s\n", parsed->source->path); fprintf(f, "//\n"); - fprintf(f, "// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE\n"); - fprintf(f, "// in include/config/general.h and remove this notice.\n"); - fprintf(f, "// Use sed -i '/^#line/d' '%s' to remove #line markers.\n", output_path); + fprintf(f, "// If you want to modify this file see expansion PR #7154\n"); fprintf(f, "//\n"); fprintf(f, "\n"); @@ -1752,10 +1786,7 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par { fprintf(f, "#line %d\n", trainer->pic_line); fprintf(f, " .trainerPic = "); - if (starts_with(trainer->id, "PARTNER_")) - fprint_constant(f, "TRAINER_BACK_PIC", trainer->pic); - else - fprint_constant(f, "TRAINER_PIC", trainer->pic); + fprint_constant(f, "TRAINER_PIC", trainer->pic); fprintf(f, ",\n"); } @@ -1853,21 +1884,55 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, ",\n"); } + if (!is_empty_string(trainer->copy_pool)) + { + fprintf(f, "#line %d\n", trainer->copy_pool_line); + fprintf(f, " .overrideTrainer = "); + fprint_string(f, trainer->copy_pool); + fprintf(f, ",\n"); + } + if (!is_empty_string(trainer->back_pic)) + { + fprintf(f, "#line %d\n", trainer->back_pic_line); + fprintf(f, " .trainerBackPic = "); + fprint_constant(f, "TRAINER_BACK_PIC", trainer->back_pic); + fprintf(f, ",\n"); + } + else // defaults to front pic in absence of defined back pic + { + fprintf(f, "#line %d\n", trainer->back_pic_line); + fprintf(f, " .trainerBackPic = "); + fprint_constant(f, "TRAINER_PIC", trainer->pic); + fprintf(f, ",\n"); + } + + if (trainer->macro_line) + { + fprintf(f, "#line %d\n", trainer->macro_line); + fprintf(f, " "); + fprint_string(f, trainer->macro); + fprintf(f, "\n"); + } + if (trainer->party_size_line) { fprintf(f, "#line %d\n", trainer->party_size_line); fprintf(f, " .partySize = %d,\n", trainer->party_size); - fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n); - fprintf(f, " .party = (const struct TrainerMon[])\n"); - fprintf(f, " {\n"); + if (is_empty_string(trainer->copy_pool)) + { + fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n); + fprintf(f, " .party = (const struct TrainerMon[])\n"); + fprintf(f, " {\n"); + } } - else + else if (is_empty_string(trainer->copy_pool)) { fprintf(f, " .partySize = %d,\n", trainer->pokemon_n); fprintf(f, " .party = (const struct TrainerMon[])\n"); fprintf(f, " {\n"); } - for (int j = 0; j < trainer->pokemon_n; j++) + + for (int j = 0; j < trainer->pokemon_n && is_empty_string(trainer->copy_pool); j++) { struct Pokemon *pokemon = &trainer->pokemon[j]; fprintf(f, " {\n"); @@ -2030,7 +2095,8 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, " },\n"); } - fprintf(f, " },\n"); + if (is_empty_string(trainer->copy_pool)) + fprintf(f, " },\n"); fprintf(f, " },\n"); } } diff --git a/trainer_rules.mk b/trainer_rules.mk new file mode 100644 index 000000000..c5df373a1 --- /dev/null +++ b/trainer_rules.mk @@ -0,0 +1,10 @@ +# party files are run through trainerproc, which is a tool that converts party data to an output file +# matching the current trainer .h formatting + +AUTO_GEN_TARGETS += src/data/trainers.h +AUTO_GEN_TARGETS += src/data/battle_partners.h +AUTO_GEN_TARGETS += test/battle/trainer_control.h +AUTO_GEN_TARGETS += src/data/debug_trainers.h + +%.h: %.party + $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< -