From 8b8c593bf6fc3dea6af8546c33493a28366389d9 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Wed, 5 Nov 2025 10:04:30 +0100 Subject: [PATCH 01/35] Fix preproc not correctly reading skipped lines symbols inside enum (#2197) --- tools/preproc/asm_file.cpp | 50 +++++++++++++++++++++++++++++++++++++- tools/preproc/asm_file.h | 1 + 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 69b412b24e..fcc996d66d 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -584,7 +584,11 @@ bool AsmFile::ParseEnum() RaiseError("%s:%ld: empty enum is invalid", headerFilename.c_str(), currentHeaderLine); } - if (m_buffer[m_pos] != ',') + if (m_buffer[m_pos] == '#') + { + currentHeaderLine = ParseLineSkipInEnum(); + } + else if (m_buffer[m_pos] != ',') { currentHeaderLine += SkipWhitespaceAndEol(); if (m_buffer[m_pos++] == '}' && m_buffer[m_pos++] == ';') @@ -688,6 +692,50 @@ int AsmFile::SkipWhitespaceAndEol() return newlines; } +int AsmFile::ParseLineSkipInEnum(void) +{ + m_pos++; + while (m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\t') + m_pos++; + + if (!IsAsciiDigit(m_buffer[m_pos])) + RaiseError("malformatted line indicator found inside `enum`, expected line number"); + + unsigned n = 0; + int digit = 0; + while ((digit = ConvertDigit(m_buffer[m_pos++], 10)) != -1) + n = 10 * n + digit; + + while (m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\t') + m_pos++; + + if (m_buffer[m_pos++] != '"') + RaiseError("malformatted line indicator found before `enum`, expected filename"); + + while (m_buffer[m_pos] != '"') + { + unsigned char c = m_buffer[m_pos++]; + + if (c == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in line indicator"); + else + RaiseError("unexpected null character in line indicator"); + } + + if (!IsAsciiPrintable(c)) + RaiseError("unexpected character '\\x%02X' in line indicator", c); + + if (c == '\\') + { + c = m_buffer[m_pos]; + RaiseError("unexpected escape '\\%c' in line indicator", c); + } + } + return n - 1; +} + // returns the last line indicator and its corresponding file name without modifying the token index int AsmFile::FindLastLineNumber(std::string& filename) { diff --git a/tools/preproc/asm_file.h b/tools/preproc/asm_file.h index 33e6ce5c49..9cab32a97f 100644 --- a/tools/preproc/asm_file.h +++ b/tools/preproc/asm_file.h @@ -73,6 +73,7 @@ private: void VerifyStringLength(int length); int SkipWhitespaceAndEol(); int FindLastLineNumber(std::string& filename); + int ParseLineSkipInEnum(void); std::string ReadIdentifier(); long ReadInteger(std::string filename, long line); }; From fdcaac917569b6e0f171e2a576ab4c0aa7eeec16 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:27:16 -0800 Subject: [PATCH 02/35] Added some music documentation (#2198) --- sound/song_table.inc | 1225 +++++++++++++++++++++--------------------- src/sound.c | 1 + 2 files changed, 616 insertions(+), 610 deletions(-) diff --git a/sound/song_table.inc b/sound/song_table.inc index c551a656b9..6e4237b998 100644 --- a/sound/song_table.inc +++ b/sound/song_table.inc @@ -1,616 +1,621 @@ + .equiv MUSIC_PLAYER_BGM,0 + .equiv MUSIC_PLAYER_SE1,1 + .equiv MUSIC_PLAYER_SE2,2 + .equiv MUSIC_PLAYER_SE3,3 + .align 2 gSongTable:: - song mus_dummy, 0, 0 - song se_use_item, 1, 1 - song se_pc_login, 1, 1 - song se_pc_off, 1, 1 - song se_pc_on, 1, 1 - song se_select, 2, 2 - song se_win_open, 1, 1 - song se_wall_hit, 2, 2 - song se_door, 1, 1 - song se_exit, 1, 1 - song se_ledge, 1, 1 - song se_bike_bell, 1, 1 - song se_not_effective, 1, 1 - song se_effective, 1, 1 - song se_super_effective, 1, 1 - song se_ball_open, 1, 1 - song se_faint, 1, 1 - song se_flee, 1, 1 - song se_sliding_door, 1, 1 - song se_ship, 1, 1 - song se_bang, 1, 1 - song se_pin, 1, 1 - song se_boo, 1, 1 - song se_ball, 1, 1 - song se_contest_place, 2, 2 - song se_a, 1, 1 - song se_i, 1, 1 - song se_u, 1, 1 - song se_e, 1, 1 - song se_o, 1, 1 - song se_n, 1, 1 - song se_success, 1, 1 - song se_failure, 1, 1 - song se_exp, 1, 1 - song se_bike_hop, 1, 1 - song se_switch, 1, 1 - song se_click, 1, 1 - song se_fu_zaku, 1, 1 - song se_contest_condition_lose, 1, 1 - song se_lavaridge_fall_warp, 1, 1 - song se_ice_stairs, 1, 1 - song se_ice_break, 1, 1 - song se_ice_crack, 1, 1 - song se_fall, 1, 1 - song se_unlock, 2, 2 - song se_warp_in, 1, 1 - song se_warp_out, 1, 1 - song se_repel, 1, 1 - song se_rotating_gate, 1, 1 - song se_truck_move, 1, 1 - song se_truck_stop, 1, 1 - song se_truck_unload, 2, 2 - song se_truck_door, 1, 1 - song se_berry_blender, 2, 2 - song se_card, 1, 1 - song se_save, 1, 1 - song se_ball_bounce_1, 1, 1 - song se_ball_bounce_2, 1, 1 - song se_ball_bounce_3, 1, 1 - song se_ball_bounce_4, 1, 1 - song se_ball_trade, 2, 2 - song se_ball_throw, 1, 1 - song se_note_c, 2, 2 - song se_note_d, 2, 2 - song se_note_e, 2, 2 - song se_note_f, 2, 2 - song se_note_g, 2, 2 - song se_note_a, 2, 2 - song se_note_b, 2, 2 - song se_note_c_high, 2, 2 - song se_puddle, 2, 2 - song se_bridge_walk, 2, 2 - song se_itemfinder, 1, 1 - song se_ding_dong, 1, 1 - song se_balloon_red, 2, 2 - song se_balloon_blue, 2, 2 - song se_balloon_yellow, 2, 2 - song se_breakable_door, 2, 2 - song se_mud_ball, 2, 2 - song se_field_poison, 1, 1 - song se_escalator, 1, 1 - song se_thunderstorm, 3, 3 - song se_thunderstorm_stop, 3, 3 - song se_downpour, 3, 3 - song se_downpour_stop, 3, 3 - song se_rain, 3, 3 - song se_rain_stop, 3, 3 - song se_thunder, 1, 1 - song se_thunder2, 1, 1 - song se_elevator, 1, 1 - song se_low_health, 3, 3 - song se_exp_max, 1, 1 - song se_roulette_ball, 2, 2 - song se_roulette_ball2, 2, 2 - song se_taillow_wing_flap, 1, 1 - song se_shop, 1, 1 - song se_contest_heart, 1, 1 - song se_contest_curtain_rise, 1, 1 - song se_contest_curtain_fall, 1, 1 - song se_contest_icon_change, 1, 1 - song se_contest_icon_clear, 1, 1 - song se_contest_mons_turn, 1, 1 - song se_shiny, 1, 1 - song se_intro_blast, 1, 1 - song se_mugshot, 1, 1 - song se_applause, 1, 1 - song se_vend, 1, 1 - song se_orb, 1, 1 - song se_dex_scroll, 1, 1 - song se_dex_page, 1, 1 - song se_pokenav_on, 1, 1 - song se_pokenav_off, 1, 1 - song se_dex_search, 1, 1 - song se_egg_hatch, 1, 1 - song se_ball_tray_enter, 1, 1 - song se_ball_tray_ball, 1, 1 - song se_ball_tray_exit, 2, 2 - song se_glass_flute, 1, 1 - song se_m_thunderbolt, 2, 2 - song se_m_thunderbolt2, 1, 1 - song se_m_harden, 1, 1 - song se_m_nightmare, 1, 1 - song se_m_vital_throw, 1, 1 - song se_m_vital_throw2, 1, 1 - song se_m_bubble, 1, 1 - song se_m_bubble2, 1, 1 - song se_m_bubble3, 1, 1 - song se_m_rain_dance, 1, 1 - song se_m_cut, 1, 1 - song se_m_string_shot, 1, 1 - song se_m_string_shot2, 1, 1 - song se_m_rock_throw, 1, 1 - song se_m_gust, 2, 2 - song se_m_gust2, 2, 2 - song se_m_double_slap, 1, 1 - song se_m_double_team, 1, 1 - song se_m_razor_wind, 1, 1 - song se_m_icy_wind, 1, 1 - song se_m_thunder_wave, 1, 1 - song se_m_comet_punch, 1, 1 - song se_m_mega_kick, 1, 1 - song se_m_mega_kick2, 1, 1 - song se_m_crabhammer, 1, 1 - song se_m_jump_kick, 1, 1 - song se_m_flame_wheel, 1, 1 - song se_m_flame_wheel2, 1, 1 - song se_m_flamethrower, 1, 1 - song se_m_fire_punch, 1, 1 - song se_m_toxic, 1, 1 - song se_m_sacred_fire, 1, 1 - song se_m_sacred_fire2, 2, 2 - song se_m_ember, 1, 1 - song se_m_take_down, 2, 2 - song se_m_blizzard, 1, 1 - song se_m_blizzard2, 1, 1 - song se_m_scratch, 1, 1 - song se_m_vicegrip, 1, 1 - song se_m_wing_attack, 1, 1 - song se_m_fly, 1, 1 - song se_m_sand_attack, 1, 1 - song se_m_razor_wind2, 1, 1 - song se_m_bite, 1, 1 - song se_m_headbutt, 1, 1 - song se_m_surf, 1, 1 - song se_m_hydro_pump, 1, 1 - song se_m_whirlpool, 1, 1 - song se_m_horn_attack, 1, 1 - song se_m_tail_whip, 2, 2 - song se_m_mist, 1, 1 - song se_m_poison_powder, 1, 1 - song se_m_bind, 2, 2 - song se_m_dragon_rage, 1, 1 - song se_m_sing, 1, 1 - song se_m_perish_song, 1, 1 - song se_m_pay_day, 1, 1 - song se_m_dig, 1, 1 - song se_m_dizzy_punch, 1, 1 - song se_m_self_destruct, 1, 1 - song se_m_explosion, 1, 1 - song se_m_absorb_2, 1, 1 - song se_m_absorb, 1, 1 - song se_m_screech, 1, 1 - song se_m_bubble_beam, 1, 1 - song se_m_bubble_beam2, 1, 1 - song se_m_supersonic, 1, 1 - song se_m_belly_drum, 1, 1 - song se_m_metronome, 1, 1 - song se_m_bonemerang, 1, 1 - song se_m_lick, 1, 1 - song se_m_psybeam, 1, 1 - song se_m_faint_attack, 1, 1 - song se_m_swords_dance, 1, 1 - song se_m_leer, 1, 1 - song se_m_swagger, 1, 1 - song se_m_swagger2, 1, 1 - song se_m_heal_bell, 1, 1 - song se_m_confuse_ray, 1, 1 - song se_m_snore, 1, 1 - song se_m_brick_break, 1, 1 - song se_m_giga_drain, 1, 1 - song se_m_psybeam2, 1, 1 - song se_m_solar_beam, 2, 2 - song se_m_petal_dance, 1, 1 - song se_m_teleport, 1, 1 - song se_m_minimize, 1, 1 - song se_m_sketch, 1, 1 - song se_m_swift, 1, 1 - song se_m_reflect, 1, 1 - song se_m_barrier, 1, 1 - song se_m_detect, 2, 2 - song se_m_lock_on, 1, 1 - song se_m_moonlight, 1, 1 - song se_m_charm, 1, 1 - song se_m_charge, 1, 1 - song se_m_strength, 1, 1 - song se_m_hyper_beam, 1, 1 - song se_m_waterfall, 1, 1 - song se_m_reversal, 1, 1 - song se_m_acid_armor, 1, 1 - song se_m_sandstorm, 1, 1 - song se_m_tri_attack, 1, 1 - song se_m_tri_attack2, 1, 1 - song se_m_encore, 1, 1 - song se_m_encore2, 2, 2 - song se_m_baton_pass, 1, 1 - song se_m_milk_drink, 1, 1 - song se_m_attract, 1, 1 - song se_m_attract2, 1, 1 - song se_m_morning_sun, 1, 1 - song se_m_flatter, 1, 1 - song se_m_sand_tomb, 1, 1 - song se_m_grasswhistle, 1, 1 - song se_m_spit_up, 1, 1 - song se_m_dive, 1, 1 - song se_m_earthquake, 2, 2 - song se_m_twister, 2, 2 - song se_m_sweet_scent, 1, 1 - song se_m_yawn, 1, 1 - song se_m_sky_uppercut, 2, 2 - song se_m_stat_increase, 1, 1 - song se_m_heat_wave, 1, 1 - song se_m_uproar, 1, 1 - song se_m_hail, 1, 1 - song se_m_cosmic_power, 2, 2 - song se_m_teeter_dance, 1, 1 - song se_m_stat_decrease, 1, 1 - song se_m_haze, 1, 1 - song se_m_hyper_beam2, 1, 1 - song se_rg_door, 1, 1 - song se_rg_card_flip, 1, 1 - song se_rg_card_flipping, 1, 1 - song se_rg_card_open, 1, 1 - song se_rg_bag_cursor, 1, 1 - song se_rg_bag_pocket, 1, 1 - song se_rg_ball_click, 1, 1 - song se_rg_shop, 1, 1 - song se_rg_ss_anne_horn, 1, 1 - song se_rg_help_open, 1, 1 - song se_rg_help_close, 1, 1 - song se_rg_help_error, 1, 1 - song se_rg_deoxys_move, 1, 1 - song se_rg_poke_jump_success, 1, 1 - song se_rg_poke_jump_failure, 1, 1 - song se_pokenav_call, 1, 1 - song se_pokenav_hang_up, 1, 1 - song se_arena_timeup1, 1, 1 - song se_arena_timeup2, 1, 1 - song se_pike_curtain_close, 1, 1 - song se_pike_curtain_open, 1, 1 - song se_sudowoodo_shake, 1, 1 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song dummy_song_header, 0, 0 - song mus_littleroot_test, 0, 0 - song mus_gsc_route38, 0, 0 - song mus_caught, 0, 0 - song mus_victory_wild, 0, 0 - song mus_victory_gym_leader, 0, 0 - song mus_victory_league, 0, 0 - song mus_c_comm_center, 0, 0 - song mus_gsc_pewter, 0, 0 - song mus_c_vs_legend_beast, 0, 0 - song mus_route101, 0, 0 - song mus_route110, 0, 0 - song mus_route120, 0, 0 - song mus_petalburg, 0, 0 - song mus_oldale, 0, 0 - song mus_gym, 0, 0 - song mus_surf, 0, 0 - song mus_petalburg_woods, 0, 0 - song mus_level_up, 2, 2 - song mus_heal, 2, 2 - song mus_obtain_badge, 2, 2 - song mus_obtain_item, 2, 2 - song mus_evolved, 2, 2 - song mus_obtain_tmhm, 2, 2 - song mus_lilycove_museum, 0, 0 - song mus_route122, 0, 0 - song mus_oceanic_museum, 0, 0 - song mus_evolution_intro, 2, 2 - song mus_evolution, 0, 0 - song mus_move_deleted, 2, 2 - song mus_encounter_girl, 0, 0 - song mus_encounter_male, 0, 0 - song mus_abandoned_ship, 0, 0 - song mus_fortree, 0, 0 - song mus_birch_lab, 0, 0 - song mus_b_tower_rs, 0, 0 - song mus_encounter_swimmer, 0, 0 - song mus_cave_of_origin, 0, 0 - song mus_obtain_berry, 2, 2 - song mus_awaken_legend, 2, 2 - song mus_slots_jackpot, 2, 2 - song mus_slots_win, 2, 2 - song mus_too_bad, 2, 2 - song mus_roulette, 0, 0 - song mus_link_contest_p1, 0, 0 - song mus_link_contest_p2, 0, 0 - song mus_link_contest_p3, 0, 0 - song mus_link_contest_p4, 0, 0 - song mus_encounter_rich, 0, 0 - song mus_verdanturf, 0, 0 - song mus_rustboro, 0, 0 - song mus_poke_center, 0, 0 - song mus_route104, 0, 0 - song mus_route119, 0, 0 - song mus_cycling, 0, 0 - song mus_poke_mart, 0, 0 - song mus_littleroot, 0, 0 - song mus_mt_chimney, 0, 0 - song mus_encounter_female, 0, 0 - song mus_lilycove, 0, 0 - song mus_route111, 0, 0 - song mus_help, 0, 0 - song mus_underwater, 0, 0 - song mus_victory_trainer, 0, 0 - song mus_title, 0, 0 - song mus_intro, 0, 0 - song mus_encounter_may, 0, 0 - song mus_encounter_intense, 0, 0 - song mus_encounter_cool, 0, 0 - song mus_route113, 0, 0 - song mus_encounter_aqua, 0, 0 - song mus_follow_me, 0, 0 - song mus_encounter_brendan, 0, 0 - song mus_ever_grande, 0, 0 - song mus_encounter_suspicious, 0, 0 - song mus_victory_aqua_magma, 0, 0 - song mus_cable_car, 0, 0 - song mus_game_corner, 0, 0 - song mus_dewford, 0, 0 - song mus_safari_zone, 0, 0 - song mus_victory_road, 0, 0 - song mus_aqua_magma_hideout, 0, 0 - song mus_sailing, 0, 0 - song mus_mt_pyre, 0, 0 - song mus_slateport, 0, 0 - song mus_mt_pyre_exterior, 0, 0 - song mus_school, 0, 0 - song mus_hall_of_fame, 0, 0 - song mus_fallarbor, 0, 0 - song mus_sealed_chamber, 0, 0 - song mus_contest_winner, 0, 0 - song mus_contest, 0, 0 - song mus_encounter_magma, 0, 0 - song mus_intro_battle, 0, 0 - song mus_abnormal_weather, 0, 0 - song mus_weather_groudon, 0, 0 - song mus_sootopolis, 0, 0 - song mus_contest_results, 0, 0 - song mus_hall_of_fame_room, 0, 0 - song mus_trick_house, 0, 0 - song mus_encounter_twins, 0, 0 - song mus_encounter_elite_four, 0, 0 - song mus_encounter_hiker, 0, 0 - song mus_contest_lobby, 0, 0 - song mus_encounter_interviewer, 0, 0 - song mus_encounter_champion, 0, 0 - song mus_credits, 0, 0 - song mus_end, 0, 0 - song mus_b_frontier, 0, 0 - song mus_b_arena, 0, 0 - song mus_obtain_b_points, 2, 2 - song mus_register_match_call, 2, 2 - song mus_b_pyramid, 0, 0 - song mus_b_pyramid_top, 0, 0 - song mus_b_palace, 0, 0 - song mus_rayquaza_appears, 0, 0 - song mus_b_tower, 0, 0 - song mus_obtain_symbol, 2, 2 - song mus_b_dome, 0, 0 - song mus_b_pike, 0, 0 - song mus_b_factory, 0, 0 - song mus_vs_rayquaza, 0, 0 - song mus_vs_frontier_brain, 0, 0 - song mus_vs_mew, 0, 0 - song mus_b_dome_lobby, 0, 0 - song mus_vs_wild, 0, 0 - song mus_vs_aqua_magma, 0, 0 - song mus_vs_trainer, 0, 0 - song mus_vs_gym_leader, 0, 0 - song mus_vs_champion, 0, 0 - song mus_vs_regi, 0, 0 - song mus_vs_kyogre_groudon, 0, 0 - song mus_vs_rival, 0, 0 - song mus_vs_elite_four, 0, 0 - song mus_vs_aqua_magma_leader, 0, 0 - song mus_rg_follow_me, 0, 0 - song mus_rg_game_corner, 0, 0 - song mus_rg_rocket_hideout, 0, 0 - song mus_rg_gym, 0, 0 - song mus_rg_jigglypuff, 2, 2 - song mus_rg_intro_fight, 0, 0 - song mus_rg_title, 0, 0 - song mus_rg_cinnabar, 0, 0 - song mus_rg_lavender, 0, 0 - song mus_rg_heal, 0, 0 - song mus_rg_cycling, 0, 0 - song mus_rg_encounter_rocket, 0, 0 - song mus_rg_encounter_girl, 0, 0 - song mus_rg_encounter_boy, 0, 0 - song mus_rg_hall_of_fame, 0, 0 - song mus_rg_viridian_forest, 0, 0 - song mus_rg_mt_moon, 0, 0 - song mus_rg_poke_mansion, 0, 0 - song mus_rg_credits, 0, 0 - song mus_rg_route1, 0, 0 - song mus_rg_route24, 0, 0 - song mus_rg_route3, 0, 0 - song mus_rg_route11, 0, 0 - song mus_rg_victory_road, 0, 0 - song mus_rg_vs_gym_leader, 0, 0 - song mus_rg_vs_trainer, 0, 0 - song mus_rg_vs_wild, 0, 0 - song mus_rg_vs_champion, 0, 0 - song mus_rg_pallet, 0, 0 - song mus_rg_oak_lab, 0, 0 - song mus_rg_oak, 0, 0 - song mus_rg_poke_center, 0, 0 - song mus_rg_ss_anne, 0, 0 - song mus_rg_surf, 0, 0 - song mus_rg_poke_tower, 0, 0 - song mus_rg_silph, 0, 0 - song mus_rg_fuchsia, 0, 0 - song mus_rg_celadon, 0, 0 - song mus_rg_victory_trainer, 0, 0 - song mus_rg_victory_wild, 0, 0 - song mus_rg_victory_gym_leader, 0, 0 - song mus_rg_vermillion, 0, 0 - song mus_rg_pewter, 0, 0 - song mus_rg_encounter_rival, 0, 0 - song mus_rg_rival_exit, 0, 0 - song mus_rg_dex_rating, 2, 2 - song mus_rg_obtain_key_item, 2, 2 - song mus_rg_caught_intro, 2, 2 - song mus_rg_photo, 2, 2 - song mus_rg_game_freak, 0, 0 - song mus_rg_caught, 0, 0 - song mus_rg_new_game_instruct, 0, 0 - song mus_rg_new_game_intro, 0, 0 - song mus_rg_new_game_exit, 0, 0 - song mus_rg_poke_jump, 0, 0 - song mus_rg_union_room, 0, 0 - song mus_rg_net_center, 0, 0 - song mus_rg_mystery_gift, 0, 0 - song mus_rg_berry_pick, 0, 0 - song mus_rg_sevii_cave, 0, 0 - song mus_rg_teachy_tv_show, 0, 0 - song mus_rg_sevii_route, 0, 0 - song mus_rg_sevii_dungeon, 0, 0 - song mus_rg_sevii_123, 0, 0 - song mus_rg_sevii_45, 0, 0 - song mus_rg_sevii_67, 0, 0 - song mus_rg_poke_flute, 2, 2 - song mus_rg_vs_deoxys, 0, 0 - song mus_rg_vs_mewtwo, 0, 0 - song mus_rg_vs_legend, 0, 0 - song mus_rg_encounter_gym_leader, 0, 0 - song mus_rg_encounter_deoxys, 0, 0 - song mus_rg_trainer_tower, 0, 0 - song mus_rg_slow_pallet, 0, 0 - song mus_rg_teachy_tv_menu, 0, 0 - song ph_trap_blend, 2, 2 - song ph_trap_held, 2, 2 - song ph_trap_solo, 2, 2 - song ph_face_blend, 2, 2 - song ph_face_held, 2, 2 - song ph_face_solo, 2, 2 - song ph_cloth_blend, 2, 2 - song ph_cloth_held, 2, 2 - song ph_cloth_solo, 2, 2 - song ph_dress_blend, 2, 2 - song ph_dress_held, 2, 2 - song ph_dress_solo, 2, 2 - song ph_fleece_blend, 2, 2 - song ph_fleece_held, 2, 2 - song ph_fleece_solo, 2, 2 - song ph_kit_blend, 2, 2 - song ph_kit_held, 2, 2 - song ph_kit_solo, 2, 2 - song ph_price_blend, 2, 2 - song ph_price_held, 2, 2 - song ph_price_solo, 2, 2 - song ph_lot_blend, 2, 2 - song ph_lot_held, 2, 2 - song ph_lot_solo, 2, 2 - song ph_goat_blend, 2, 2 - song ph_goat_held, 2, 2 - song ph_goat_solo, 2, 2 - song ph_thought_blend, 2, 2 - song ph_thought_held, 2, 2 - song ph_thought_solo, 2, 2 - song ph_choice_blend, 2, 2 - song ph_choice_held, 2, 2 - song ph_choice_solo, 2, 2 - song ph_mouth_blend, 2, 2 - song ph_mouth_held, 2, 2 - song ph_mouth_solo, 2, 2 - song ph_foot_blend, 2, 2 - song ph_foot_held, 2, 2 - song ph_foot_solo, 2, 2 - song ph_goose_blend, 2, 2 - song ph_goose_held, 2, 2 - song ph_goose_solo, 2, 2 - song ph_strut_blend, 2, 2 - song ph_strut_held, 2, 2 - song ph_strut_solo, 2, 2 - song ph_cure_blend, 2, 2 - song ph_cure_held, 2, 2 - song ph_cure_solo, 2, 2 - song ph_nurse_blend, 2, 2 - song ph_nurse_held, 2, 2 - song ph_nurse_solo, 2, 2 + song mus_dummy, MUSIC_PLAYER_BGM, 0 + song se_use_item, MUSIC_PLAYER_SE1, 1 + song se_pc_login, MUSIC_PLAYER_SE1, 1 + song se_pc_off, MUSIC_PLAYER_SE1, 1 + song se_pc_on, MUSIC_PLAYER_SE1, 1 + song se_select, MUSIC_PLAYER_SE2, 2 + song se_win_open, MUSIC_PLAYER_SE1, 1 + song se_wall_hit, MUSIC_PLAYER_SE2, 2 + song se_door, MUSIC_PLAYER_SE1, 1 + song se_exit, MUSIC_PLAYER_SE1, 1 + song se_ledge, MUSIC_PLAYER_SE1, 1 + song se_bike_bell, MUSIC_PLAYER_SE1, 1 + song se_not_effective, MUSIC_PLAYER_SE1, 1 + song se_effective, MUSIC_PLAYER_SE1, 1 + song se_super_effective, MUSIC_PLAYER_SE1, 1 + song se_ball_open, MUSIC_PLAYER_SE1, 1 + song se_faint, MUSIC_PLAYER_SE1, 1 + song se_flee, MUSIC_PLAYER_SE1, 1 + song se_sliding_door, MUSIC_PLAYER_SE1, 1 + song se_ship, MUSIC_PLAYER_SE1, 1 + song se_bang, MUSIC_PLAYER_SE1, 1 + song se_pin, MUSIC_PLAYER_SE1, 1 + song se_boo, MUSIC_PLAYER_SE1, 1 + song se_ball, MUSIC_PLAYER_SE1, 1 + song se_contest_place, MUSIC_PLAYER_SE2, 2 + song se_a, MUSIC_PLAYER_SE1, 1 + song se_i, MUSIC_PLAYER_SE1, 1 + song se_u, MUSIC_PLAYER_SE1, 1 + song se_e, MUSIC_PLAYER_SE1, 1 + song se_o, MUSIC_PLAYER_SE1, 1 + song se_n, MUSIC_PLAYER_SE1, 1 + song se_success, MUSIC_PLAYER_SE1, 1 + song se_failure, MUSIC_PLAYER_SE1, 1 + song se_exp, MUSIC_PLAYER_SE1, 1 + song se_bike_hop, MUSIC_PLAYER_SE1, 1 + song se_switch, MUSIC_PLAYER_SE1, 1 + song se_click, MUSIC_PLAYER_SE1, 1 + song se_fu_zaku, MUSIC_PLAYER_SE1, 1 + song se_contest_condition_lose, MUSIC_PLAYER_SE1, 1 + song se_lavaridge_fall_warp, MUSIC_PLAYER_SE1, 1 + song se_ice_stairs, MUSIC_PLAYER_SE1, 1 + song se_ice_break, MUSIC_PLAYER_SE1, 1 + song se_ice_crack, MUSIC_PLAYER_SE1, 1 + song se_fall, MUSIC_PLAYER_SE1, 1 + song se_unlock, MUSIC_PLAYER_SE2, 2 + song se_warp_in, MUSIC_PLAYER_SE1, 1 + song se_warp_out, MUSIC_PLAYER_SE1, 1 + song se_repel, MUSIC_PLAYER_SE1, 1 + song se_rotating_gate, MUSIC_PLAYER_SE1, 1 + song se_truck_move, MUSIC_PLAYER_SE1, 1 + song se_truck_stop, MUSIC_PLAYER_SE1, 1 + song se_truck_unload, MUSIC_PLAYER_SE2, 2 + song se_truck_door, MUSIC_PLAYER_SE1, 1 + song se_berry_blender, MUSIC_PLAYER_SE2, 2 + song se_card, MUSIC_PLAYER_SE1, 1 + song se_save, MUSIC_PLAYER_SE1, 1 + song se_ball_bounce_1, MUSIC_PLAYER_SE1, 1 + song se_ball_bounce_2, MUSIC_PLAYER_SE1, 1 + song se_ball_bounce_3, MUSIC_PLAYER_SE1, 1 + song se_ball_bounce_4, MUSIC_PLAYER_SE1, 1 + song se_ball_trade, MUSIC_PLAYER_SE2, 2 + song se_ball_throw, MUSIC_PLAYER_SE1, 1 + song se_note_c, MUSIC_PLAYER_SE2, 2 + song se_note_d, MUSIC_PLAYER_SE2, 2 + song se_note_e, MUSIC_PLAYER_SE2, 2 + song se_note_f, MUSIC_PLAYER_SE2, 2 + song se_note_g, MUSIC_PLAYER_SE2, 2 + song se_note_a, MUSIC_PLAYER_SE2, 2 + song se_note_b, MUSIC_PLAYER_SE2, 2 + song se_note_c_high, MUSIC_PLAYER_SE2, 2 + song se_puddle, MUSIC_PLAYER_SE2, 2 + song se_bridge_walk, MUSIC_PLAYER_SE2, 2 + song se_itemfinder, MUSIC_PLAYER_SE1, 1 + song se_ding_dong, MUSIC_PLAYER_SE1, 1 + song se_balloon_red, MUSIC_PLAYER_SE2, 2 + song se_balloon_blue, MUSIC_PLAYER_SE2, 2 + song se_balloon_yellow, MUSIC_PLAYER_SE2, 2 + song se_breakable_door, MUSIC_PLAYER_SE2, 2 + song se_mud_ball, MUSIC_PLAYER_SE2, 2 + song se_field_poison, MUSIC_PLAYER_SE1, 1 + song se_escalator, MUSIC_PLAYER_SE1, 1 + song se_thunderstorm, MUSIC_PLAYER_SE3, 3 + song se_thunderstorm_stop, MUSIC_PLAYER_SE3, 3 + song se_downpour, MUSIC_PLAYER_SE3, 3 + song se_downpour_stop, MUSIC_PLAYER_SE3, 3 + song se_rain, MUSIC_PLAYER_SE3, 3 + song se_rain_stop, MUSIC_PLAYER_SE3, 3 + song se_thunder, MUSIC_PLAYER_SE1, 1 + song se_thunder2, MUSIC_PLAYER_SE1, 1 + song se_elevator, MUSIC_PLAYER_SE1, 1 + song se_low_health, MUSIC_PLAYER_SE3, 3 + song se_exp_max, MUSIC_PLAYER_SE1, 1 + song se_roulette_ball, MUSIC_PLAYER_SE2, 2 + song se_roulette_ball2, MUSIC_PLAYER_SE2, 2 + song se_taillow_wing_flap, MUSIC_PLAYER_SE1, 1 + song se_shop, MUSIC_PLAYER_SE1, 1 + song se_contest_heart, MUSIC_PLAYER_SE1, 1 + song se_contest_curtain_rise, MUSIC_PLAYER_SE1, 1 + song se_contest_curtain_fall, MUSIC_PLAYER_SE1, 1 + song se_contest_icon_change, MUSIC_PLAYER_SE1, 1 + song se_contest_icon_clear, MUSIC_PLAYER_SE1, 1 + song se_contest_mons_turn, MUSIC_PLAYER_SE1, 1 + song se_shiny, MUSIC_PLAYER_SE1, 1 + song se_intro_blast, MUSIC_PLAYER_SE1, 1 + song se_mugshot, MUSIC_PLAYER_SE1, 1 + song se_applause, MUSIC_PLAYER_SE1, 1 + song se_vend, MUSIC_PLAYER_SE1, 1 + song se_orb, MUSIC_PLAYER_SE1, 1 + song se_dex_scroll, MUSIC_PLAYER_SE1, 1 + song se_dex_page, MUSIC_PLAYER_SE1, 1 + song se_pokenav_on, MUSIC_PLAYER_SE1, 1 + song se_pokenav_off, MUSIC_PLAYER_SE1, 1 + song se_dex_search, MUSIC_PLAYER_SE1, 1 + song se_egg_hatch, MUSIC_PLAYER_SE1, 1 + song se_ball_tray_enter, MUSIC_PLAYER_SE1, 1 + song se_ball_tray_ball, MUSIC_PLAYER_SE1, 1 + song se_ball_tray_exit, MUSIC_PLAYER_SE2, 2 + song se_glass_flute, MUSIC_PLAYER_SE1, 1 + song se_m_thunderbolt, MUSIC_PLAYER_SE2, 2 + song se_m_thunderbolt2, MUSIC_PLAYER_SE1, 1 + song se_m_harden, MUSIC_PLAYER_SE1, 1 + song se_m_nightmare, MUSIC_PLAYER_SE1, 1 + song se_m_vital_throw, MUSIC_PLAYER_SE1, 1 + song se_m_vital_throw2, MUSIC_PLAYER_SE1, 1 + song se_m_bubble, MUSIC_PLAYER_SE1, 1 + song se_m_bubble2, MUSIC_PLAYER_SE1, 1 + song se_m_bubble3, MUSIC_PLAYER_SE1, 1 + song se_m_rain_dance, MUSIC_PLAYER_SE1, 1 + song se_m_cut, MUSIC_PLAYER_SE1, 1 + song se_m_string_shot, MUSIC_PLAYER_SE1, 1 + song se_m_string_shot2, MUSIC_PLAYER_SE1, 1 + song se_m_rock_throw, MUSIC_PLAYER_SE1, 1 + song se_m_gust, MUSIC_PLAYER_SE2, 2 + song se_m_gust2, MUSIC_PLAYER_SE2, 2 + song se_m_double_slap, MUSIC_PLAYER_SE1, 1 + song se_m_double_team, MUSIC_PLAYER_SE1, 1 + song se_m_razor_wind, MUSIC_PLAYER_SE1, 1 + song se_m_icy_wind, MUSIC_PLAYER_SE1, 1 + song se_m_thunder_wave, MUSIC_PLAYER_SE1, 1 + song se_m_comet_punch, MUSIC_PLAYER_SE1, 1 + song se_m_mega_kick, MUSIC_PLAYER_SE1, 1 + song se_m_mega_kick2, MUSIC_PLAYER_SE1, 1 + song se_m_crabhammer, MUSIC_PLAYER_SE1, 1 + song se_m_jump_kick, MUSIC_PLAYER_SE1, 1 + song se_m_flame_wheel, MUSIC_PLAYER_SE1, 1 + song se_m_flame_wheel2, MUSIC_PLAYER_SE1, 1 + song se_m_flamethrower, MUSIC_PLAYER_SE1, 1 + song se_m_fire_punch, MUSIC_PLAYER_SE1, 1 + song se_m_toxic, MUSIC_PLAYER_SE1, 1 + song se_m_sacred_fire, MUSIC_PLAYER_SE1, 1 + song se_m_sacred_fire2, MUSIC_PLAYER_SE2, 2 + song se_m_ember, MUSIC_PLAYER_SE1, 1 + song se_m_take_down, MUSIC_PLAYER_SE2, 2 + song se_m_blizzard, MUSIC_PLAYER_SE1, 1 + song se_m_blizzard2, MUSIC_PLAYER_SE1, 1 + song se_m_scratch, MUSIC_PLAYER_SE1, 1 + song se_m_vicegrip, MUSIC_PLAYER_SE1, 1 + song se_m_wing_attack, MUSIC_PLAYER_SE1, 1 + song se_m_fly, MUSIC_PLAYER_SE1, 1 + song se_m_sand_attack, MUSIC_PLAYER_SE1, 1 + song se_m_razor_wind2, MUSIC_PLAYER_SE1, 1 + song se_m_bite, MUSIC_PLAYER_SE1, 1 + song se_m_headbutt, MUSIC_PLAYER_SE1, 1 + song se_m_surf, MUSIC_PLAYER_SE1, 1 + song se_m_hydro_pump, MUSIC_PLAYER_SE1, 1 + song se_m_whirlpool, MUSIC_PLAYER_SE1, 1 + song se_m_horn_attack, MUSIC_PLAYER_SE1, 1 + song se_m_tail_whip, MUSIC_PLAYER_SE2, 2 + song se_m_mist, MUSIC_PLAYER_SE1, 1 + song se_m_poison_powder, MUSIC_PLAYER_SE1, 1 + song se_m_bind, MUSIC_PLAYER_SE2, 2 + song se_m_dragon_rage, MUSIC_PLAYER_SE1, 1 + song se_m_sing, MUSIC_PLAYER_SE1, 1 + song se_m_perish_song, MUSIC_PLAYER_SE1, 1 + song se_m_pay_day, MUSIC_PLAYER_SE1, 1 + song se_m_dig, MUSIC_PLAYER_SE1, 1 + song se_m_dizzy_punch, MUSIC_PLAYER_SE1, 1 + song se_m_self_destruct, MUSIC_PLAYER_SE1, 1 + song se_m_explosion, MUSIC_PLAYER_SE1, 1 + song se_m_absorb_2, MUSIC_PLAYER_SE1, 1 + song se_m_absorb, MUSIC_PLAYER_SE1, 1 + song se_m_screech, MUSIC_PLAYER_SE1, 1 + song se_m_bubble_beam, MUSIC_PLAYER_SE1, 1 + song se_m_bubble_beam2, MUSIC_PLAYER_SE1, 1 + song se_m_supersonic, MUSIC_PLAYER_SE1, 1 + song se_m_belly_drum, MUSIC_PLAYER_SE1, 1 + song se_m_metronome, MUSIC_PLAYER_SE1, 1 + song se_m_bonemerang, MUSIC_PLAYER_SE1, 1 + song se_m_lick, MUSIC_PLAYER_SE1, 1 + song se_m_psybeam, MUSIC_PLAYER_SE1, 1 + song se_m_faint_attack, MUSIC_PLAYER_SE1, 1 + song se_m_swords_dance, MUSIC_PLAYER_SE1, 1 + song se_m_leer, MUSIC_PLAYER_SE1, 1 + song se_m_swagger, MUSIC_PLAYER_SE1, 1 + song se_m_swagger2, MUSIC_PLAYER_SE1, 1 + song se_m_heal_bell, MUSIC_PLAYER_SE1, 1 + song se_m_confuse_ray, MUSIC_PLAYER_SE1, 1 + song se_m_snore, MUSIC_PLAYER_SE1, 1 + song se_m_brick_break, MUSIC_PLAYER_SE1, 1 + song se_m_giga_drain, MUSIC_PLAYER_SE1, 1 + song se_m_psybeam2, MUSIC_PLAYER_SE1, 1 + song se_m_solar_beam, MUSIC_PLAYER_SE2, 2 + song se_m_petal_dance, MUSIC_PLAYER_SE1, 1 + song se_m_teleport, MUSIC_PLAYER_SE1, 1 + song se_m_minimize, MUSIC_PLAYER_SE1, 1 + song se_m_sketch, MUSIC_PLAYER_SE1, 1 + song se_m_swift, MUSIC_PLAYER_SE1, 1 + song se_m_reflect, MUSIC_PLAYER_SE1, 1 + song se_m_barrier, MUSIC_PLAYER_SE1, 1 + song se_m_detect, MUSIC_PLAYER_SE2, 2 + song se_m_lock_on, MUSIC_PLAYER_SE1, 1 + song se_m_moonlight, MUSIC_PLAYER_SE1, 1 + song se_m_charm, MUSIC_PLAYER_SE1, 1 + song se_m_charge, MUSIC_PLAYER_SE1, 1 + song se_m_strength, MUSIC_PLAYER_SE1, 1 + song se_m_hyper_beam, MUSIC_PLAYER_SE1, 1 + song se_m_waterfall, MUSIC_PLAYER_SE1, 1 + song se_m_reversal, MUSIC_PLAYER_SE1, 1 + song se_m_acid_armor, MUSIC_PLAYER_SE1, 1 + song se_m_sandstorm, MUSIC_PLAYER_SE1, 1 + song se_m_tri_attack, MUSIC_PLAYER_SE1, 1 + song se_m_tri_attack2, MUSIC_PLAYER_SE1, 1 + song se_m_encore, MUSIC_PLAYER_SE1, 1 + song se_m_encore2, MUSIC_PLAYER_SE2, 2 + song se_m_baton_pass, MUSIC_PLAYER_SE1, 1 + song se_m_milk_drink, MUSIC_PLAYER_SE1, 1 + song se_m_attract, MUSIC_PLAYER_SE1, 1 + song se_m_attract2, MUSIC_PLAYER_SE1, 1 + song se_m_morning_sun, MUSIC_PLAYER_SE1, 1 + song se_m_flatter, MUSIC_PLAYER_SE1, 1 + song se_m_sand_tomb, MUSIC_PLAYER_SE1, 1 + song se_m_grasswhistle, MUSIC_PLAYER_SE1, 1 + song se_m_spit_up, MUSIC_PLAYER_SE1, 1 + song se_m_dive, MUSIC_PLAYER_SE1, 1 + song se_m_earthquake, MUSIC_PLAYER_SE2, 2 + song se_m_twister, MUSIC_PLAYER_SE2, 2 + song se_m_sweet_scent, MUSIC_PLAYER_SE1, 1 + song se_m_yawn, MUSIC_PLAYER_SE1, 1 + song se_m_sky_uppercut, MUSIC_PLAYER_SE2, 2 + song se_m_stat_increase, MUSIC_PLAYER_SE1, 1 + song se_m_heat_wave, MUSIC_PLAYER_SE1, 1 + song se_m_uproar, MUSIC_PLAYER_SE1, 1 + song se_m_hail, MUSIC_PLAYER_SE1, 1 + song se_m_cosmic_power, MUSIC_PLAYER_SE2, 2 + song se_m_teeter_dance, MUSIC_PLAYER_SE1, 1 + song se_m_stat_decrease, MUSIC_PLAYER_SE1, 1 + song se_m_haze, MUSIC_PLAYER_SE1, 1 + song se_m_hyper_beam2, MUSIC_PLAYER_SE1, 1 + song se_rg_door, MUSIC_PLAYER_SE1, 1 + song se_rg_card_flip, MUSIC_PLAYER_SE1, 1 + song se_rg_card_flipping, MUSIC_PLAYER_SE1, 1 + song se_rg_card_open, MUSIC_PLAYER_SE1, 1 + song se_rg_bag_cursor, MUSIC_PLAYER_SE1, 1 + song se_rg_bag_pocket, MUSIC_PLAYER_SE1, 1 + song se_rg_ball_click, MUSIC_PLAYER_SE1, 1 + song se_rg_shop, MUSIC_PLAYER_SE1, 1 + song se_rg_ss_anne_horn, MUSIC_PLAYER_SE1, 1 + song se_rg_help_open, MUSIC_PLAYER_SE1, 1 + song se_rg_help_close, MUSIC_PLAYER_SE1, 1 + song se_rg_help_error, MUSIC_PLAYER_SE1, 1 + song se_rg_deoxys_move, MUSIC_PLAYER_SE1, 1 + song se_rg_poke_jump_success, MUSIC_PLAYER_SE1, 1 + song se_rg_poke_jump_failure, MUSIC_PLAYER_SE1, 1 + song se_pokenav_call, MUSIC_PLAYER_SE1, 1 + song se_pokenav_hang_up, MUSIC_PLAYER_SE1, 1 + song se_arena_timeup1, MUSIC_PLAYER_SE1, 1 + song se_arena_timeup2, MUSIC_PLAYER_SE1, 1 + song se_pike_curtain_close, MUSIC_PLAYER_SE1, 1 + song se_pike_curtain_open, MUSIC_PLAYER_SE1, 1 + song se_sudowoodo_shake, MUSIC_PLAYER_SE1, 1 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song dummy_song_header, MUSIC_PLAYER_BGM, 0 + song mus_littleroot_test, MUSIC_PLAYER_BGM, 0 + song mus_gsc_route38, MUSIC_PLAYER_BGM, 0 + song mus_caught, MUSIC_PLAYER_BGM, 0 + song mus_victory_wild, MUSIC_PLAYER_BGM, 0 + song mus_victory_gym_leader, MUSIC_PLAYER_BGM, 0 + song mus_victory_league, MUSIC_PLAYER_BGM, 0 + song mus_c_comm_center, MUSIC_PLAYER_BGM, 0 + song mus_gsc_pewter, MUSIC_PLAYER_BGM, 0 + song mus_c_vs_legend_beast, MUSIC_PLAYER_BGM, 0 + song mus_route101, MUSIC_PLAYER_BGM, 0 + song mus_route110, MUSIC_PLAYER_BGM, 0 + song mus_route120, MUSIC_PLAYER_BGM, 0 + song mus_petalburg, MUSIC_PLAYER_BGM, 0 + song mus_oldale, MUSIC_PLAYER_BGM, 0 + song mus_gym, MUSIC_PLAYER_BGM, 0 + song mus_surf, MUSIC_PLAYER_BGM, 0 + song mus_petalburg_woods, MUSIC_PLAYER_BGM, 0 + song mus_level_up, MUSIC_PLAYER_SE2, 2 + song mus_heal, MUSIC_PLAYER_SE2, 2 + song mus_obtain_badge, MUSIC_PLAYER_SE2, 2 + song mus_obtain_item, MUSIC_PLAYER_SE2, 2 + song mus_evolved, MUSIC_PLAYER_SE2, 2 + song mus_obtain_tmhm, MUSIC_PLAYER_SE2, 2 + song mus_lilycove_museum, MUSIC_PLAYER_BGM, 0 + song mus_route122, MUSIC_PLAYER_BGM, 0 + song mus_oceanic_museum, MUSIC_PLAYER_BGM, 0 + song mus_evolution_intro, MUSIC_PLAYER_SE2, 2 + song mus_evolution, MUSIC_PLAYER_BGM, 0 + song mus_move_deleted, MUSIC_PLAYER_SE2, 2 + song mus_encounter_girl, MUSIC_PLAYER_BGM, 0 + song mus_encounter_male, MUSIC_PLAYER_BGM, 0 + song mus_abandoned_ship, MUSIC_PLAYER_BGM, 0 + song mus_fortree, MUSIC_PLAYER_BGM, 0 + song mus_birch_lab, MUSIC_PLAYER_BGM, 0 + song mus_b_tower_rs, MUSIC_PLAYER_BGM, 0 + song mus_encounter_swimmer, MUSIC_PLAYER_BGM, 0 + song mus_cave_of_origin, MUSIC_PLAYER_BGM, 0 + song mus_obtain_berry, MUSIC_PLAYER_SE2, 2 + song mus_awaken_legend, MUSIC_PLAYER_SE2, 2 + song mus_slots_jackpot, MUSIC_PLAYER_SE2, 2 + song mus_slots_win, MUSIC_PLAYER_SE2, 2 + song mus_too_bad, MUSIC_PLAYER_SE2, 2 + song mus_roulette, MUSIC_PLAYER_BGM, 0 + song mus_link_contest_p1, MUSIC_PLAYER_BGM, 0 + song mus_link_contest_p2, MUSIC_PLAYER_BGM, 0 + song mus_link_contest_p3, MUSIC_PLAYER_BGM, 0 + song mus_link_contest_p4, MUSIC_PLAYER_BGM, 0 + song mus_encounter_rich, MUSIC_PLAYER_BGM, 0 + song mus_verdanturf, MUSIC_PLAYER_BGM, 0 + song mus_rustboro, MUSIC_PLAYER_BGM, 0 + song mus_poke_center, MUSIC_PLAYER_BGM, 0 + song mus_route104, MUSIC_PLAYER_BGM, 0 + song mus_route119, MUSIC_PLAYER_BGM, 0 + song mus_cycling, MUSIC_PLAYER_BGM, 0 + song mus_poke_mart, MUSIC_PLAYER_BGM, 0 + song mus_littleroot, MUSIC_PLAYER_BGM, 0 + song mus_mt_chimney, MUSIC_PLAYER_BGM, 0 + song mus_encounter_female, MUSIC_PLAYER_BGM, 0 + song mus_lilycove, MUSIC_PLAYER_BGM, 0 + song mus_route111, MUSIC_PLAYER_BGM, 0 + song mus_help, MUSIC_PLAYER_BGM, 0 + song mus_underwater, MUSIC_PLAYER_BGM, 0 + song mus_victory_trainer, MUSIC_PLAYER_BGM, 0 + song mus_title, MUSIC_PLAYER_BGM, 0 + song mus_intro, MUSIC_PLAYER_BGM, 0 + song mus_encounter_may, MUSIC_PLAYER_BGM, 0 + song mus_encounter_intense, MUSIC_PLAYER_BGM, 0 + song mus_encounter_cool, MUSIC_PLAYER_BGM, 0 + song mus_route113, MUSIC_PLAYER_BGM, 0 + song mus_encounter_aqua, MUSIC_PLAYER_BGM, 0 + song mus_follow_me, MUSIC_PLAYER_BGM, 0 + song mus_encounter_brendan, MUSIC_PLAYER_BGM, 0 + song mus_ever_grande, MUSIC_PLAYER_BGM, 0 + song mus_encounter_suspicious, MUSIC_PLAYER_BGM, 0 + song mus_victory_aqua_magma, MUSIC_PLAYER_BGM, 0 + song mus_cable_car, MUSIC_PLAYER_BGM, 0 + song mus_game_corner, MUSIC_PLAYER_BGM, 0 + song mus_dewford, MUSIC_PLAYER_BGM, 0 + song mus_safari_zone, MUSIC_PLAYER_BGM, 0 + song mus_victory_road, MUSIC_PLAYER_BGM, 0 + song mus_aqua_magma_hideout, MUSIC_PLAYER_BGM, 0 + song mus_sailing, MUSIC_PLAYER_BGM, 0 + song mus_mt_pyre, MUSIC_PLAYER_BGM, 0 + song mus_slateport, MUSIC_PLAYER_BGM, 0 + song mus_mt_pyre_exterior, MUSIC_PLAYER_BGM, 0 + song mus_school, MUSIC_PLAYER_BGM, 0 + song mus_hall_of_fame, MUSIC_PLAYER_BGM, 0 + song mus_fallarbor, MUSIC_PLAYER_BGM, 0 + song mus_sealed_chamber, MUSIC_PLAYER_BGM, 0 + song mus_contest_winner, MUSIC_PLAYER_BGM, 0 + song mus_contest, MUSIC_PLAYER_BGM, 0 + song mus_encounter_magma, MUSIC_PLAYER_BGM, 0 + song mus_intro_battle, MUSIC_PLAYER_BGM, 0 + song mus_abnormal_weather, MUSIC_PLAYER_BGM, 0 + song mus_weather_groudon, MUSIC_PLAYER_BGM, 0 + song mus_sootopolis, MUSIC_PLAYER_BGM, 0 + song mus_contest_results, MUSIC_PLAYER_BGM, 0 + song mus_hall_of_fame_room, MUSIC_PLAYER_BGM, 0 + song mus_trick_house, MUSIC_PLAYER_BGM, 0 + song mus_encounter_twins, MUSIC_PLAYER_BGM, 0 + song mus_encounter_elite_four, MUSIC_PLAYER_BGM, 0 + song mus_encounter_hiker, MUSIC_PLAYER_BGM, 0 + song mus_contest_lobby, MUSIC_PLAYER_BGM, 0 + song mus_encounter_interviewer, MUSIC_PLAYER_BGM, 0 + song mus_encounter_champion, MUSIC_PLAYER_BGM, 0 + song mus_credits, MUSIC_PLAYER_BGM, 0 + song mus_end, MUSIC_PLAYER_BGM, 0 + song mus_b_frontier, MUSIC_PLAYER_BGM, 0 + song mus_b_arena, MUSIC_PLAYER_BGM, 0 + song mus_obtain_b_points, MUSIC_PLAYER_SE2, 2 + song mus_register_match_call, MUSIC_PLAYER_SE2, 2 + song mus_b_pyramid, MUSIC_PLAYER_BGM, 0 + song mus_b_pyramid_top, MUSIC_PLAYER_BGM, 0 + song mus_b_palace, MUSIC_PLAYER_BGM, 0 + song mus_rayquaza_appears, MUSIC_PLAYER_BGM, 0 + song mus_b_tower, MUSIC_PLAYER_BGM, 0 + song mus_obtain_symbol, MUSIC_PLAYER_SE2, 2 + song mus_b_dome, MUSIC_PLAYER_BGM, 0 + song mus_b_pike, MUSIC_PLAYER_BGM, 0 + song mus_b_factory, MUSIC_PLAYER_BGM, 0 + song mus_vs_rayquaza, MUSIC_PLAYER_BGM, 0 + song mus_vs_frontier_brain, MUSIC_PLAYER_BGM, 0 + song mus_vs_mew, MUSIC_PLAYER_BGM, 0 + song mus_b_dome_lobby, MUSIC_PLAYER_BGM, 0 + song mus_vs_wild, MUSIC_PLAYER_BGM, 0 + song mus_vs_aqua_magma, MUSIC_PLAYER_BGM, 0 + song mus_vs_trainer, MUSIC_PLAYER_BGM, 0 + song mus_vs_gym_leader, MUSIC_PLAYER_BGM, 0 + song mus_vs_champion, MUSIC_PLAYER_BGM, 0 + song mus_vs_regi, MUSIC_PLAYER_BGM, 0 + song mus_vs_kyogre_groudon, MUSIC_PLAYER_BGM, 0 + song mus_vs_rival, MUSIC_PLAYER_BGM, 0 + song mus_vs_elite_four, MUSIC_PLAYER_BGM, 0 + song mus_vs_aqua_magma_leader, MUSIC_PLAYER_BGM, 0 + song mus_rg_follow_me, MUSIC_PLAYER_BGM, 0 + song mus_rg_game_corner, MUSIC_PLAYER_BGM, 0 + song mus_rg_rocket_hideout, MUSIC_PLAYER_BGM, 0 + song mus_rg_gym, MUSIC_PLAYER_BGM, 0 + song mus_rg_jigglypuff, MUSIC_PLAYER_SE2, 2 + song mus_rg_intro_fight, MUSIC_PLAYER_BGM, 0 + song mus_rg_title, MUSIC_PLAYER_BGM, 0 + song mus_rg_cinnabar, MUSIC_PLAYER_BGM, 0 + song mus_rg_lavender, MUSIC_PLAYER_BGM, 0 + song mus_rg_heal, MUSIC_PLAYER_BGM, 0 + song mus_rg_cycling, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_rocket, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_girl, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_boy, MUSIC_PLAYER_BGM, 0 + song mus_rg_hall_of_fame, MUSIC_PLAYER_BGM, 0 + song mus_rg_viridian_forest, MUSIC_PLAYER_BGM, 0 + song mus_rg_mt_moon, MUSIC_PLAYER_BGM, 0 + song mus_rg_poke_mansion, MUSIC_PLAYER_BGM, 0 + song mus_rg_credits, MUSIC_PLAYER_BGM, 0 + song mus_rg_route1, MUSIC_PLAYER_BGM, 0 + song mus_rg_route24, MUSIC_PLAYER_BGM, 0 + song mus_rg_route3, MUSIC_PLAYER_BGM, 0 + song mus_rg_route11, MUSIC_PLAYER_BGM, 0 + song mus_rg_victory_road, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_gym_leader, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_trainer, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_wild, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_champion, MUSIC_PLAYER_BGM, 0 + song mus_rg_pallet, MUSIC_PLAYER_BGM, 0 + song mus_rg_oak_lab, MUSIC_PLAYER_BGM, 0 + song mus_rg_oak, MUSIC_PLAYER_BGM, 0 + song mus_rg_poke_center, MUSIC_PLAYER_BGM, 0 + song mus_rg_ss_anne, MUSIC_PLAYER_BGM, 0 + song mus_rg_surf, MUSIC_PLAYER_BGM, 0 + song mus_rg_poke_tower, MUSIC_PLAYER_BGM, 0 + song mus_rg_silph, MUSIC_PLAYER_BGM, 0 + song mus_rg_fuchsia, MUSIC_PLAYER_BGM, 0 + song mus_rg_celadon, MUSIC_PLAYER_BGM, 0 + song mus_rg_victory_trainer, MUSIC_PLAYER_BGM, 0 + song mus_rg_victory_wild, MUSIC_PLAYER_BGM, 0 + song mus_rg_victory_gym_leader, MUSIC_PLAYER_BGM, 0 + song mus_rg_vermillion, MUSIC_PLAYER_BGM, 0 + song mus_rg_pewter, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_rival, MUSIC_PLAYER_BGM, 0 + song mus_rg_rival_exit, MUSIC_PLAYER_BGM, 0 + song mus_rg_dex_rating, MUSIC_PLAYER_SE2, 2 + song mus_rg_obtain_key_item, MUSIC_PLAYER_SE2, 2 + song mus_rg_caught_intro, MUSIC_PLAYER_SE2, 2 + song mus_rg_photo, MUSIC_PLAYER_SE2, 2 + song mus_rg_game_freak, MUSIC_PLAYER_BGM, 0 + song mus_rg_caught, MUSIC_PLAYER_BGM, 0 + song mus_rg_new_game_instruct, MUSIC_PLAYER_BGM, 0 + song mus_rg_new_game_intro, MUSIC_PLAYER_BGM, 0 + song mus_rg_new_game_exit, MUSIC_PLAYER_BGM, 0 + song mus_rg_poke_jump, MUSIC_PLAYER_BGM, 0 + song mus_rg_union_room, MUSIC_PLAYER_BGM, 0 + song mus_rg_net_center, MUSIC_PLAYER_BGM, 0 + song mus_rg_mystery_gift, MUSIC_PLAYER_BGM, 0 + song mus_rg_berry_pick, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_cave, MUSIC_PLAYER_BGM, 0 + song mus_rg_teachy_tv_show, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_route, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_dungeon, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_123, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_45, MUSIC_PLAYER_BGM, 0 + song mus_rg_sevii_67, MUSIC_PLAYER_BGM, 0 + song mus_rg_poke_flute, MUSIC_PLAYER_SE2, 2 + song mus_rg_vs_deoxys, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_mewtwo, MUSIC_PLAYER_BGM, 0 + song mus_rg_vs_legend, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_gym_leader, MUSIC_PLAYER_BGM, 0 + song mus_rg_encounter_deoxys, MUSIC_PLAYER_BGM, 0 + song mus_rg_trainer_tower, MUSIC_PLAYER_BGM, 0 + song mus_rg_slow_pallet, MUSIC_PLAYER_BGM, 0 + song mus_rg_teachy_tv_menu, MUSIC_PLAYER_BGM, 0 + song ph_trap_blend, MUSIC_PLAYER_SE2, 2 + song ph_trap_held, MUSIC_PLAYER_SE2, 2 + song ph_trap_solo, MUSIC_PLAYER_SE2, 2 + song ph_face_blend, MUSIC_PLAYER_SE2, 2 + song ph_face_held, MUSIC_PLAYER_SE2, 2 + song ph_face_solo, MUSIC_PLAYER_SE2, 2 + song ph_cloth_blend, MUSIC_PLAYER_SE2, 2 + song ph_cloth_held, MUSIC_PLAYER_SE2, 2 + song ph_cloth_solo, MUSIC_PLAYER_SE2, 2 + song ph_dress_blend, MUSIC_PLAYER_SE2, 2 + song ph_dress_held, MUSIC_PLAYER_SE2, 2 + song ph_dress_solo, MUSIC_PLAYER_SE2, 2 + song ph_fleece_blend, MUSIC_PLAYER_SE2, 2 + song ph_fleece_held, MUSIC_PLAYER_SE2, 2 + song ph_fleece_solo, MUSIC_PLAYER_SE2, 2 + song ph_kit_blend, MUSIC_PLAYER_SE2, 2 + song ph_kit_held, MUSIC_PLAYER_SE2, 2 + song ph_kit_solo, MUSIC_PLAYER_SE2, 2 + song ph_price_blend, MUSIC_PLAYER_SE2, 2 + song ph_price_held, MUSIC_PLAYER_SE2, 2 + song ph_price_solo, MUSIC_PLAYER_SE2, 2 + song ph_lot_blend, MUSIC_PLAYER_SE2, 2 + song ph_lot_held, MUSIC_PLAYER_SE2, 2 + song ph_lot_solo, MUSIC_PLAYER_SE2, 2 + song ph_goat_blend, MUSIC_PLAYER_SE2, 2 + song ph_goat_held, MUSIC_PLAYER_SE2, 2 + song ph_goat_solo, MUSIC_PLAYER_SE2, 2 + song ph_thought_blend, MUSIC_PLAYER_SE2, 2 + song ph_thought_held, MUSIC_PLAYER_SE2, 2 + song ph_thought_solo, MUSIC_PLAYER_SE2, 2 + song ph_choice_blend, MUSIC_PLAYER_SE2, 2 + song ph_choice_held, MUSIC_PLAYER_SE2, 2 + song ph_choice_solo, MUSIC_PLAYER_SE2, 2 + song ph_mouth_blend, MUSIC_PLAYER_SE2, 2 + song ph_mouth_held, MUSIC_PLAYER_SE2, 2 + song ph_mouth_solo, MUSIC_PLAYER_SE2, 2 + song ph_foot_blend, MUSIC_PLAYER_SE2, 2 + song ph_foot_held, MUSIC_PLAYER_SE2, 2 + song ph_foot_solo, MUSIC_PLAYER_SE2, 2 + song ph_goose_blend, MUSIC_PLAYER_SE2, 2 + song ph_goose_held, MUSIC_PLAYER_SE2, 2 + song ph_goose_solo, MUSIC_PLAYER_SE2, 2 + song ph_strut_blend, MUSIC_PLAYER_SE2, 2 + song ph_strut_held, MUSIC_PLAYER_SE2, 2 + song ph_strut_solo, MUSIC_PLAYER_SE2, 2 + song ph_cure_blend, MUSIC_PLAYER_SE2, 2 + song ph_cure_held, MUSIC_PLAYER_SE2, 2 + song ph_cure_solo, MUSIC_PLAYER_SE2, 2 + song ph_nurse_blend, MUSIC_PLAYER_SE2, 2 + song ph_nurse_held, MUSIC_PLAYER_SE2, 2 + song ph_nurse_solo, MUSIC_PLAYER_SE2, 2 .align 2 dummy_song_header: diff --git a/src/sound.c b/src/sound.c index d35e07d273..171678cddb 100644 --- a/src/sound.c +++ b/src/sound.c @@ -33,6 +33,7 @@ static void CreateFanfareTask(void); static void Task_DuckBGMForPokemonCry(u8 taskId); static void RestoreBGMVolumeAfterPokemonCry(void); +// The 1st argument in the table is the length of the fanfare, measured in frames. This is calculated by taking the duration of the midi file, multiplying by 59.72750056960583, and rounding up to the next nearest integer. static const struct Fanfare sFanfares[] = { [FANFARE_LEVEL_UP] = { MUS_LEVEL_UP, 80 }, [FANFARE_OBTAIN_ITEM] = { MUS_OBTAIN_ITEM, 160 }, From 1a9fbbcfbad5ea4a2d5603006f9fbc8cbb31b112 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Thu, 6 Nov 2025 11:15:13 +0000 Subject: [PATCH 03/35] Fix copyvar with non-var argument --- asm/macros/event.inc | 5 ++++- data/maps/LilycoveCity_ContestLobby/scripts.inc | 6 +++++- data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc | 6 +++++- data/maps/SkyPillar_2F/scripts.inc | 6 +++++- data/maps/SkyPillar_4F/scripts.inc | 6 +++++- data/scripts/cave_hole.inc | 6 +++++- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 7075481750..e4ed1c3ef0 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -169,7 +169,10 @@ .endm @ Copies the value of source into destination. - .macro copyvar destination:req, source:req + .macro copyvar destination:req, source:req, warn=TRUE + .if \warn && !((\source >= VARS_START && \source <= VARS_END) || (\source >= SPECIAL_VARS_START && \source <= SPECIAL_VARS_END)) + .warning "copyvar with a value that is not a VAR_ constant; did you mean setvar instead?" + .endif .byte SCR_OP_COPYVAR .2byte \destination .2byte \source diff --git a/data/maps/LilycoveCity_ContestLobby/scripts.inc b/data/maps/LilycoveCity_ContestLobby/scripts.inc index 862a5ef37d..660b87f846 100644 --- a/data/maps/LilycoveCity_ContestLobby/scripts.inc +++ b/data/maps/LilycoveCity_ContestLobby/scripts.inc @@ -349,7 +349,11 @@ LilycoveCity_ContestLobby_EventScript_SetMasterContestType:: @ Functionally unused LilycoveCity_ContestLobby_EventScript_SetDebug:: setflag FLAG_HIDE_LILYCOVE_MUSEUM_CURATOR - copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 +#if UBFIX + setvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 +#else + copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1, warn=FALSE +#endif additem ITEM_CONTEST_PASS setvar VAR_0x800B, 8 setvar VAR_CONTEST_RANK, CONTEST_RANK_MASTER diff --git a/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc b/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc index e00c7bcb3c..8f08e01808 100644 --- a/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc +++ b/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc @@ -76,7 +76,11 @@ LilycoveCity_LilycoveMuseum_2F_EventScript_ShowExhibitHall:: applymovement LOCALID_PLAYER, LilycoveCity_LilycoveMuseum_2F_Movement_PlayerWalkInPlaceLeft waitmovement 0 msgbox LilycoveCity_LilycoveMuseum_2F_Text_PleaseObtainPaintingsForExhibit, MSGBOX_SIGN - copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 +#if UBFIX + setvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 +#else + copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1, warn=FALSE +#endif releaseall end diff --git a/data/maps/SkyPillar_2F/scripts.inc b/data/maps/SkyPillar_2F/scripts.inc index bad2488f0b..9a75a4d951 100644 --- a/data/maps/SkyPillar_2F/scripts.inc +++ b/data/maps/SkyPillar_2F/scripts.inc @@ -6,7 +6,11 @@ SkyPillar_2F_MapScripts:: SkyPillar_2F_OnTransition: call_if_lt VAR_SKY_PILLAR_STATE, 2, SkyPillar_2F_EventScript_CleanFloor - copyvar VAR_ICE_STEP_COUNT, 1 +#if UBFIX + setvar VAR_ICE_STEP_COUNT, 1 +#else + copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE +#endif end SkyPillar_2F_EventScript_CleanFloor:: diff --git a/data/maps/SkyPillar_4F/scripts.inc b/data/maps/SkyPillar_4F/scripts.inc index 9e8f1e80ea..b3f6020105 100644 --- a/data/maps/SkyPillar_4F/scripts.inc +++ b/data/maps/SkyPillar_4F/scripts.inc @@ -6,7 +6,11 @@ SkyPillar_4F_MapScripts:: SkyPillar_4F_OnTransition: call_if_lt VAR_SKY_PILLAR_STATE, 2, SkyPillar_4F_EventScript_CleanFloor - copyvar VAR_ICE_STEP_COUNT, 1 +#if UBFIX + setvar VAR_ICE_STEP_COUNT, 1 +#else + copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE +#endif end SkyPillar_4F_EventScript_CleanFloor:: diff --git a/data/scripts/cave_hole.inc b/data/scripts/cave_hole.inc index fc4962912a..ca2a8404be 100644 --- a/data/scripts/cave_hole.inc +++ b/data/scripts/cave_hole.inc @@ -3,7 +3,11 @@ CaveHole_CheckFallDownHole: .2byte 0 CaveHole_FixCrackedGround: - copyvar VAR_ICE_STEP_COUNT, 1 +#if UBFIX + setvar VAR_ICE_STEP_COUNT, 1 +#else + copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE +#endif end EventScript_FallDownHole:: From 2dc36a8ba08f4ee1ab6b5298bdc48b98a5cd971c Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 11 Nov 2025 09:52:24 -0300 Subject: [PATCH 04/35] Wrote some missing tests (#8203) --- include/constants/generational_changes.h | 1 + include/generational_changes.h | 3 +- src/battle_script_commands.c | 2 +- test/battle/ability/bad_dreams.c | 16 +++- test/battle/ability/leaf_guard.c | 105 +++++++++++++++++++++-- test/battle/move_effect/brine.c | 23 ++++- test/battle/move_effect/rest.c | 16 ---- test/battle/move_effect/return.c | 44 +++++++++- 8 files changed, 179 insertions(+), 31 deletions(-) diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 88584e9978..381c77ca13 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -47,6 +47,7 @@ enum GenConfigTag GEN_CONFIG_TOXIC_NEVER_MISS, GEN_CONFIG_PARALYZE_ELECTRIC, GEN_CONFIG_BADGE_BOOST, + GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index e8b701d096..0068d74428 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -49,7 +49,8 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_OBLIVIOUS_TAUNT] = B_OBLIVIOUS_TAUNT, [GEN_CONFIG_TOXIC_NEVER_MISS] = B_TOXIC_NEVER_MISS, [GEN_CONFIG_PARALYZE_ELECTRIC] = B_PARALYZE_ELECTRIC, - [GEN_CONFIG_BADGE_BOOST] = B_BADGE_BOOST + [GEN_CONFIG_BADGE_BOOST] = B_BADGE_BOOST, + [GEN_CONFIG_LEAF_GUARD_PREVENTS_REST] = B_LEAF_GUARD_PREVENTS_REST, }; #if TESTING diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a98e023ff6..8674d34e2d 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -18279,7 +18279,7 @@ void BS_JumpIfAbilityPreventsRest(void) NATIVE_ARGS(u8 battler, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); u32 ability = GetBattlerAbility(battler); - if (B_LEAF_GUARD_PREVENTS_REST >= GEN_5 && IsLeafGuardProtected(battler, ability)) + if (GetGenConfig(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST) >= GEN_5 && IsLeafGuardProtected(battler, ability)) gBattlescriptCurrInstr = cmd->jumpInstr; else if (IsShieldsDownProtected(battler, ability)) gBattlescriptCurrInstr = cmd->jumpInstr; diff --git a/test/battle/ability/bad_dreams.c b/test/battle/ability/bad_dreams.c index 491d5a91a2..cb724e2411 100644 --- a/test/battle/ability/bad_dreams.c +++ b/test/battle/ability/bad_dreams.c @@ -35,7 +35,21 @@ SINGLE_BATTLE_TEST("Bad Dreams causes the sleeping enemy Pokemon to lose 1/8 of } } -TO_DO_BATTLE_TEST("Bad Dreams affects Pokémon with Comatose") +SINGLE_BATTLE_TEST("Bad Dreams causes Pokémon with Comatose to lose 1/8 of HP") +{ + GIVEN { + PLAYER(SPECIES_DARKRAI); + OPPONENT(SPECIES_KOMALA) { Ability(ABILITY_COMATOSE); } + } WHEN { + TURN {;} + } SCENE { + ABILITY_POPUP(player, ABILITY_BAD_DREAMS); + MESSAGE("The opposing Komala is tormented!"); + HP_BAR(opponent); + } THEN { + EXPECT_EQ(opponent->hp, opponent->maxHP - opponent->maxHP / 8); + } +} DOUBLE_BATTLE_TEST("Bad Dreams does not activate if only the partner Pokemon is sleeping") { diff --git a/test/battle/ability/leaf_guard.c b/test/battle/ability/leaf_guard.c index 94785bd29b..182f07787b 100644 --- a/test/battle/ability/leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -31,7 +31,41 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") } } -TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent non-volatile status conditions if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Leaf Guard doesn't prevent non-volatile status conditions if Cloud Nine/Air Lock is on the field") +{ + u32 move, species, ability; + u16 status; + PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + // PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; } // Pointless since you can't freeze in sunlight anyway + GIVEN { + ASSUME(GetMoveEffect(MOVE_WILL_O_WISP) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_WILL_O_WISP) == MOVE_EFFECT_BURN); + ASSUME(GetMoveEffect(MOVE_HYPNOSIS) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_HYPNOSIS) == MOVE_EFFECT_SLEEP); + ASSUME(GetMoveEffect(MOVE_THUNDER_WAVE) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_THUNDER_WAVE) == MOVE_EFFECT_PARALYSIS); + ASSUME(GetMoveEffect(MOVE_TOXIC) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_TOXIC) == MOVE_EFFECT_TOXIC); + PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + NONE_OF { + ABILITY_POPUP(player, ABILITY_LEAF_GUARD); + MESSAGE("It doesn't affect Leafeon…"); + } + STATUS_ICON(player, status); + } +} SINGLE_BATTLE_TEST("Leaf Guard prevents status conditions from Flame Orb and Toxic Orb") { @@ -50,29 +84,82 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents status conditions from Flame Orb and Tox NONE_OF { MESSAGE("Leafeon was burned!"); STATUS_ICON(player, burn: TRUE); } } else { - NONE_OF { MESSAGE("Leafeon was badly poisoned!"); STATUS_ICON(player, poison: TRUE); } + NONE_OF { MESSAGE("Leafeon was badly poisoned!"); STATUS_ICON(player, badPoison: TRUE); } } } } -TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent status conditions from Flame Orb and Toxic Orb if Cloud Nine/Air Lock is on the field"); - -SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun") +SINGLE_BATTLE_TEST("Leaf Guard doesn't prevent status conditions from Flame Orb and Toxic Orb if Cloud Nine/Air Lock is on the field") { + u32 item, species, ability; + PARAMETRIZE { item = ITEM_FLAME_ORB; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { item = ITEM_TOXIC_ORB; species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { item = ITEM_FLAME_ORB; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + PARAMETRIZE { item = ITEM_TOXIC_ORB; species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } GIVEN { - ASSUME(B_LEAF_GUARD_PREVENTS_REST >= GEN_5); + ASSUME(gItemsInfo[ITEM_FLAME_ORB].holdEffect == HOLD_EFFECT_FLAME_ORB); + ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB); + PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); Item(item); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); } + } SCENE { + if (item == ITEM_FLAME_ORB) { + MESSAGE("Leafeon was burned!"); + STATUS_ICON(player, burn: TRUE); + } + else { + MESSAGE("Leafeon was badly poisoned!"); + STATUS_ICON(player, badPoison: TRUE); + } + } +} + +SINGLE_BATTLE_TEST("Leaf Guard prevents Rest during sun (Gen 5+)") +{ + u32 gen; + PARAMETRIZE { gen = GEN_4; } + PARAMETRIZE { gen = GEN_5; } + GIVEN { + WITH_CONFIG(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, gen); ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_REST); } } SCENE { - MESSAGE("But it failed!"); - NONE_OF { + if (gen >= GEN_5) { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player); + STATUS_ICON(player, sleep: TRUE); + HP_BAR(player); + } + } + else { STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player); HP_BAR(player); } } } -TO_DO_BATTLE_TEST("Leaf Guard doesn't prevent Rest if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Leaf Guard doesn't prevent Rest if Cloud Nine/Air Lock is on the field") +{ + u32 species, ability; + PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_GOLDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + GIVEN { + WITH_CONFIG(GEN_CONFIG_LEAF_GUARD_PREVENTS_REST, GEN_5); + ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); + PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); HP(100); MaxHP(200); } + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_REST); } + } SCENE { + STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player); + HP_BAR(player); + } +} diff --git a/test/battle/move_effect/brine.c b/test/battle/move_effect/brine.c index 9165257859..5f1504437d 100644 --- a/test/battle/move_effect/brine.c +++ b/test/battle/move_effect/brine.c @@ -1,4 +1,25 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Brine's power doubles if the target is at 50% or below max HP"); +SINGLE_BATTLE_TEST("Brine's power doubles if the target is at 50% or below max HP", s16 damage) +{ + bool32 halfHP; + PARAMETRIZE { halfHP = FALSE; } + PARAMETRIZE { halfHP = TRUE; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_BRINE) == EFFECT_BRINE); + PLAYER(SPECIES_SQUIRTLE); + OPPONENT(SPECIES_BLISSEY){ + if (halfHP) { + HP((GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP) / 2) - 1); + } + } + } WHEN { + TURN { MOVE(player, MOVE_BRINE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BRINE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} diff --git a/test/battle/move_effect/rest.c b/test/battle/move_effect/rest.c index fcf2b15567..af1fb19c8c 100644 --- a/test/battle/move_effect/rest.c +++ b/test/battle/move_effect/rest.c @@ -35,22 +35,6 @@ SINGLE_BATTLE_TEST("Rest fails if the user is at full HP") } } -SINGLE_BATTLE_TEST("Rest fails if the user is protected by Leaf Guard") -{ - GIVEN { - ASSUME(GetMoveEffect(MOVE_SUNNY_DAY) == EFFECT_SUNNY_DAY); - ASSUME(B_LEAF_GUARD_PREVENTS_REST >= GEN_5); - PLAYER(SPECIES_CHIKORITA) { Ability(ABILITY_LEAF_GUARD); HP(1); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, MOVE_REST); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_REST, player); - } THEN { - EXPECT(!(player->status1 & STATUS1_SLEEP)); - } -} - SINGLE_BATTLE_TEST("Rest fails if the user is protected by Shields Down") { GIVEN { diff --git a/test/battle/move_effect/return.c b/test/battle/move_effect/return.c index 2a2614200d..2727b1b46e 100644 --- a/test/battle/move_effect/return.c +++ b/test/battle/move_effect/return.c @@ -1,6 +1,46 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Return's power increases the higher friendship of the user is") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_RETURN) == EFFECT_RETURN); +} + +SINGLE_BATTLE_TEST("Return's power increases the higher friendship of the user is", s16 damage) +{ + u32 friendship; + PARAMETRIZE { friendship = 0; } + PARAMETRIZE { friendship = 100; } + PARAMETRIZE { friendship = 200; } + PARAMETRIZE { friendship = 255; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Friendship(friendship); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_RETURN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RETURN, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (i > 0) + EXPECT_GT(results[i].damage, results[i-1].damage); + } +} + TO_DO_BATTLE_TEST("Return does 0 damage at min Friendship (Gen2)") -TO_DO_BATTLE_TEST("Return does 1 damage at min Friendship (Gen3+)") + +SINGLE_BATTLE_TEST("Return does 1 damage at min Friendship (Gen3+)") +{ + s16 damage; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Friendship(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_RETURN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RETURN, player); + HP_BAR(opponent, captureDamage: &damage); + } THEN { + EXPECT_EQ(damage, 1); + } +} From 2e8545ba451bc103c848c3f5f69b78894565be7b Mon Sep 17 00:00:00 2001 From: Estellar <137097857+estellarc@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:00:12 -0300 Subject: [PATCH 05/35] Fix some followers sprites (#8208) --- graphics/pokemon/chesnaught/overworld.png | Bin 1026 -> 1004 bytes graphics/pokemon/chespin/overworld.png | Bin 501 -> 505 bytes graphics/pokemon/delphox/overworld.png | Bin 895 -> 833 bytes graphics/pokemon/diggersby/overworld.png | Bin 672 -> 703 bytes graphics/pokemon/espurr/overworld.png | Bin 534 -> 523 bytes graphics/pokemon/fletchinder/overworld.png | Bin 925 -> 884 bytes graphics/pokemon/fletchling/overworld.png | Bin 462 -> 422 bytes graphics/pokemon/greninja/overworld.png | Bin 1002 -> 956 bytes graphics/pokemon/lillipup/overworld.png | Bin 596 -> 584 bytes graphics/pokemon/litleo/overworld.png | Bin 538 -> 569 bytes graphics/pokemon/pancham/overworld.png | Bin 524 -> 506 bytes graphics/pokemon/scatterbug/overworld.png | Bin 512 -> 548 bytes graphics/pokemon/talonflame/overworld.png | Bin 1093 -> 1097 bytes graphics/pokemon/watchog/overworld.png | Bin 735 -> 733 bytes 14 files changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/chesnaught/overworld.png b/graphics/pokemon/chesnaught/overworld.png index 7902feaf575810ea2cb8c61a53e8734a0b75f65c..99c5d10cba7f1234cb21d065f47c73571f4f5733 100644 GIT binary patch delta 945 zcmV;i15W&c2y%p3w*-Aa0H3>1|GPUSbsF? z6+Yo@#CnGwM(~k;e}w^N$87I!SCfG)w-LK^XgPu#e$}@(@W?@qUA=={-QWHVw-M_d zdKkeC{{jPDUsX66*mKnRGF+!@F@hU@%Co@Z2KUV2RUkXIU&qelGtQ^HCUG%>JKp5g z)uq*0?KL|N??T{U1_Ot%FtFvX0qaLHc@Fl(nk)?8dy z>Kk4KIw0qN9CFAx1CEfz+n~dH$(Z8&Rlu|N?~RSwo~X*Rh?G@dmdGw zt_zc>@|Xw*vQRmWqmX1A6IX*Kpc)h*I=2}n61jD7;=MqsFCb;sm1QYy&@cM8Tm|4b zfG7eDk*NIvm0|`;p(SquszDOiR%rnUb%V7)6Ym9oIu86wb!UM0zOB^jHv5KG0h$-1 zXvA0_miBQADocKL$P7Z{lnA@-25W&9ycI}OQphQ#6l09yy{*yVB(mkL!Us5H&4@WP zduL92bmLt>H8^)@7{LWET?B&F7two@=vc<1R^t-AEO@IhF$bIRus&|w`AfiQuy<%M z_$ttU$X^9gch#8pQ6!4L88~@OsN8CKtuX02*Hv1#>{-8U-pVa=6mY(Qy(`}gz6vz( zDWKy4X3-4m6Gwx+K#eb7Uq6n-?hf!QP#x-W zs@&<{ky5YNqd?p;XM?N?A78Kf`Jq5Z6l(x~S)CRFdxpLkn2)3dWhd}ru%OKMZyj`Y zi^W;fp7q{6bx<4NMPc2v7iZ?0@dw}MbSr~^rRVGd00U%6L_t(Y$L*FqYui8=$M3utI_Yc$CvgY+ zBnq`B>(mb*=?H~P!cjx<6q=T1Yam7xPhC=b^b%~cB&LDJn?r*M`U3q}eeU!w6q1k* z9r}P@es|pe|2&UQC!zoGPed*LQ&CF!*->wQMSnD4gufN0l=8DfWvvRO6ltbX z%8zRyEvRM~GecvHQPwNxN42nG=k>FU9g}emUsgFo%Vb5F7UuY21MYB2b%$H!tTHMq zN?Vv`8G6AW$2HSn%rFh5oS|i+A|unn96xMOcSJ^-qm(nWj57uwtDHqZ%Scu~$GGo* z=%#LJj(ZPt&=ZPQISW0wV7<)7$usVM+M)E-&Ih-gE0oDFXgP}&Cad?TeGebM8_%{o zo3m5b7g$aCODG6CR`gs;ZomRly$@H-GVF4$x_h5z*VjL1hps0Shbixeh7QxABO0?p z!<1!0NMmN-)R}5V6%~0npqrEN@5#7-_Idz{)xrCiyOE*F*fM2?v$9xIS7DZKphaYyLVBAF|R~IX!~ID_H>UiC%W;9yfIL4V?{`FO;Bxrd4ZM- z;D8VU+yntI>=F)PHQVRXU>b8vB!pgmn~V=U4+O()TVxPG*bjpBF_^cZ!cNLU01TS} z5qg2rlr2nIB!uwkZ2a9Hd5+x<_h^AZ0I5g5|Md_G5;egmW+4EEvLaDo)WU>CLI@v? z4;r37>hFekzToC?oib#s@66|aXFNWIQNmI{7>bHcl(>Zn%Y=|H^G562NKkMv+y`#> zavv+G!tJfO%8XdQ!pyCCjoXm`7;@h~i40{z5hr)<$WwPmt92*{9E@Dxz>CiU)+0m; zM$B!v$T`DqpvQ(HAr73*qpBCwxTPk7sNt=EO)EYwJ8gLgr-Hp`FfmkrgPZKU5&X&| zghscn&D*J<7~m~TlIO+cWlk_Oyu8R5k~eO8cw%mOy-bB@=&kC8k`aV~L=9zKB7syp z7DRO~U5>~`U%{EvdU2(wR(8eWN`1;32_^*LdUi#f$iX<41m_-aF!1zO9-Li4inA{| pxeCzY$6tDC5Zq4002ovPDHLkV1l56xTF98 diff --git a/graphics/pokemon/chespin/overworld.png b/graphics/pokemon/chespin/overworld.png index 5056ad774a4afc35a644c00597e21c89ebdc244f..92df00e97da25809041cf0e22b058f0a7a5daaed 100644 GIT binary patch delta 435 zcmV;k0Zjh&1Nj4x7#0Wv0001UMu)cm0004VQb$4nuFf3kks&;PdPzhh%F4>h9;ENfod0={32;j$ zkU1jy_4VnueQ%JF(+MO_%m~40qeBuRsN zxbk;q9LSW+FzT;#KqI~RG%YygmFNAH4rG=#SovOHX45`@`kQqa3*08XiHMnr$mfa! z&WOyJdqL#T)Sq&ZmfqwpO;!8*q%&TTC%re=?)T=Ia-!zX8EX_AqT1Q-lFXSYbbw~o znlWF4g37(X6Yf#Y?o1pzwC-8Kbd{`002ovPDHLkV1ijC-9`Wa delta 431 zcmV;g0Z{(=1N8%t7zqRe0002CwraMKEpit7778kj(vgB&9)Q*wol+A6dd{_y^})kPVyDv&?Wyt z_+9>dUrrIAN|h>AenLEGU_N{SBYniA4n%#FwLIa}TwvPaE_Ep@ZJD5DEU+Cg-{*f` zc>`&*bne-q$)It7LE6O}BuO&x%9}{{pxDrq2Z>wWyM>6!SuY(X5n?s4*l;m47ut4` zqjcQt7kf956&fzbP1H^#uEdNLo2x4$7Gj1OoLI*> zX?B;c5RdBIbVPO6M5=S&(}}pAP7seyC}KJAeY0K{8~j`>UOdFFL1g%u2f86&=KLNp z{I|EvFx Z`3ArAodF*2!V~}i002ovPDHLkV1ml?$#4Jw diff --git a/graphics/pokemon/delphox/overworld.png b/graphics/pokemon/delphox/overworld.png index e490e31cd818e9bc0129d3892fd94d3072626b83..dbf3da76ea4d36b68f2ad14943cb5baabc982eac 100644 GIT binary patch delta 766 zcmVVi|K~z|U?Un0p zD%}$ykPbr-!@gC02&H7RRC4^CDlNosyes8Kmw{@15toCRE{}ng|}L$*2yias)N@F zHvMKmLV>vBfdfk+gP9`-TD9{@fC(%lEL5S|o_JG5bzY_hjjIxo>Qo^7f9KQnU0wxS zlZqTzK<7eF9-68aRaPxU+r&UK;9LWPs(wOqfo`yW^XYt-r*^|=F7O&a{v1BF;s#W$ zHcFlMG1TH*D=-mYOM8uz&Uky^ll7Z6JKAwmCU3VDJ#RLCb%{y$dnI`MrDt4p@B@EnX^2ley!(sRzoakFcg0~7zIa#|SUn@1TcZr;dlOx(?VGd00P@dL_t(Y$L-U-Yui8+0Pyo=DHw`v1Rk=; z7sV1-g|trH+3GW*g)U9x&TYsMNEW+FJasXJ2;%OY(?B3o>!A_EbPy#GNOa9wJasVn z8+vvc>CVZyA4`|K!RB|md+(iehi>CG{x}MMb4yZJQHlL#)T^Pt^*A!tL!p4+a#hPA zq%73bfAct$`l3)kaG5@03yL+W%Dg;IDD@us>De7c8OOlz5V`-k|)31Y=6+YEEfV`by$;2Xacok$4>W`VQrP zHZ^N>g*>+@R4ZEx#enX;bbj<~LP3h9je(0=>?Kl#%PYSFbZbMTh z&C7((Rf&Hkl$o74fONw*m~?h+d$+C1yzrm{cDpL`+`?htcN{vD9 zbTmt5y!zx28p(#Qc|7z19`7T$iIp#ZSgO>e1{1AUNiE~ibbQJ5c~T1dH6B)KnFWcjRt36n|&?;-c?IE-fsnCuLN~7 zOo|%uJ$Pnxljmlv+qM~`^Cyl~zC#P@T!CzlIjvwsFWpu*{(j|A@Xmd+nHC&>1yO!J zN)wt9bCAwQSx;*Na4q{?=2kvQ5N&;p>6c`|#b@SCuHfJk)cbq`%!5H%!0(Y*;Sy%O zz*GQ|gFG}s&)Z19J2o~vFC<9x4^a8r`jblRkfO3_pxGSHjTe4_ZYBsPNXn=8R2pdg`SKaS)gr zo^Vhx@rOKr^o5IphX8HfE?E40BMjp%_qf;Vg#i+S2nB}XJ;6iWws_mNI6w6F_!Z`! z*H@00000NkvXX Hu0mjfv^|D= diff --git a/graphics/pokemon/diggersby/overworld.png b/graphics/pokemon/diggersby/overworld.png index 03d6b59066749858955b258ae1b4631cdd610037..39f72f55311bac5b29f696da577d6ec110f7bb8d 100644 GIT binary patch delta 640 zcmV-`0)PFW1-}K57#0Wv0001UMu)cm0004VQb$4nuFf3kks&sJMoC0LR9J=W*Ikq9 zAPfdz2uWU%{{P>5CZTm)<)dYtopWKXst<*vYXcj?H@@+WZ~PAtEgIK<<&W=MFn6Mq zQsRn{?E}#z=NIQoeym~At6=2B>`6IBzhY*(X=LybSJws7l^8jC= zzZZ-h@J4GrUK#H{)48jvSa`?1>^3Cpv1PA0RPXuToBo7LjYSW*Tal`r{H9JqHM%e1 z%#T=e+b3*)`WV;Tn?&Z^YZG&qT45){nOlB2=Oj@&ZF1tIG3CrTr`UYUPB;|{TJsPn zdY6nTwV(0W$xljABA~BF-LqcGhOLw(4}l5**k-G=wK5!gUBF|Iz{EFLhD#m-S#2I$ zyMURimd&EH8}%u#2`;&1xYdL9R!Y0Vv7=^K-VTai4?eup<$ig8K&g+ol+y0=6AyMu z_v2EBQ}RaAYvaGZ-*+1E{}*}=^GMwp?7X4eO>khJx!-sD;SfxRp#Ok|_L=+fks;ss a%lHQjPa-3v77x|{0000e|%6bEo~i&qdusN2;! z=#VbxaY9|eJ!U{ol(CffhAbAz;U#O74?t9jFVLuK2bRmk(g8kHd=TY)u6;sPmrC&f z_j~W&-x8b;p||z6{>7@)YOkMvlKg~fj!d9g>V&L%4LURc!2>&O9h4{Rs&Et35E%k(7WmTPDc}fGq({Q$ihi5jRF`9y1v`(O9*+1aR7yr zU|L3WNTZ=}nqM-;W2X`RPAPc<~wA-zxWmbW1BX6hP z-P>PIqs7&3%i~vKo>?5<$LUR)U!}rngy-t*r1?5zM55#S>fo@kUXTkm`l#Q4a5Qx4 vh(3;}C>CyJ#w}8~bwpoEqk#X6_)pg}7Lp^fuBfn%00000NkvXXu0mjf2KO$A diff --git a/graphics/pokemon/espurr/overworld.png b/graphics/pokemon/espurr/overworld.png index f7ba8e08a0a7c3e9a0d848d31e705c34465b1077..6df4dddb3e97693f63a651a40dbe95ca83d36191 100644 GIT binary patch delta 472 zcmV;}0Vn>J1d9Za7#0Wv0001UMu)cm0004VQb$4nuFf3kkv=JZ0iH=jK~z|U?Uw6q z1R)58J%BTP|0iznHrpyaH8}QPYLRC zp99R%3?Tk)R$B4itpE z2>`qas({YlA^;NsF{hjv($A5RpK>1DtY7Z=VTbd@oek(7wt&H5Ut<9MfZA>1k=qH{ z@e?Qfftw}lmn{1Nv<%tlLj*p~gUbM`KvOPKkBG<}-rGojb{9CX$rYa;XB(co#FWby z`!UxUj`I*EXMv3?e&Y@_yTcPiYa{HeZ_ZgrY5B1psu>q)Rklkw<0(-o5ZrfQ%1NuN z)wMrYmUyY|Jzh46+1%bWo_d@6Ev~y9t#8ID>mws(lV0R-UV$ZEI&p?|!52BzcOuxr zId^VoVGd00D$aL_t(Y$L-YJZNnfC0N{fOOmN@*I{=*B zKHFx2B+3Mhi#sq!f=ADr(16T=o;Y_Y|E3XwK1vZR6WB58qH z%3`OrAU&Bg$zY*gG2_~I=MJ7=w>FsirMACulstg*0t`Y4I z^?iDAL5$S(V(lw55;Z-O(ENxBC&d1MZjZU$urJ7aXR^SfL{#1_I{SQkW-=(~tjJqt!W}8OHj90Num{!&l7DkX3To_s zg9a@gNCPhC*XK7?tU5P{W>~d*>n$y48=jiL*UQVhzZJ0?bBl4!P|s%_6r9hM`PmL^ z46BCxdYKHlrmdsi0`jx=&M}jBSnXhd0Fm@O}akBWMe#M$<3z1`Pj|{N`mwrtAQi z*9{+qoTV3`_9B$*OmP6bGZSo@Q&o_peVsZ8zuP2-Kn7=WDoD20_e19}d9~2oauF2Y{M?NkqgW$do0v84$&QoO5UcbODyd1lG^& z3CzU9&%}Ix^6UbW8-Q*4(%_-z5R;`*R23H0=*}PqK)E7-z||i@APhgq2Bs`Cfu*EG zM5<1eAe9CnYz1{vL6lQe2s9>FKJx&yr#<}wUKvw={@Y1yU1j%gBeTF#%4%t*dKS1W zD1)F)bw(&X#AS}381?{U`#S5l4laTzzsasPbm#9wj=+krTAob;7pxs1uw7ZD+^fJ^ zCrD+T!bcVW9)Pw7GEoAMQi@=%;i~oC?`HYh^&7z~a3RRLTJ}(|u8i|aSewo3hZ?pW z&~Ti8gBpc}%k^FUBmZIoO`<_M0{w(1cO-i7g} zjcR|ylPlB38!GVnKOR~)_y=3}ckShWTfFTTf3`mcc^ua^Wouyo0000VGd00RF>L_t(Y$L*E9PuoBk#_x0@b8OndqYVq2 z$=M}QS%}X=)ec2IOGIKog(mGVEJN;+{?Jx{yISy~B?-`J zyP($X0?=qnK&58@bkPyX|HJtSn8XFWBsld3}DAukf14AYs_5$?e(CR^m=EA z$cQTa2Vg_(?`j>w3Q*S5nA;_PV81y+HQzi9P1;{64j}0gZv1FE7y_J<=@XW9^&Ez3i*2sOscu#(A$r4JS z-ojpzQq=&ibl^?_{5%&0`tKVW!OBN}?kmRLae(Zx0;(1$-AhwSBcVBvYZ3s>@Ho!1 zx_ExPRrWA(fLR_Leqo;vJDH5A0s<|hG);#pAQEtWDm$tSeJTUMIALiV%VV&z(cu=u zuQS;ID1rJ938km$sTAuwL8*7hnr1lc6D zX>t+^eN}iQ^u3>gaFsUGuflDG&=UBOh7#ZfaU>Flrd_|)hGQthq8O*r5NvZmI|%*D z+al4g^WywkxILz%1YVL@o(cAUi|<$jz`uzTtwP@}iXY>fp)dri``2W5%?re)?eTal z_pg(v0#c$r|4+l`Q(ya8jrPaaAy$UgC?ZZ>-9dhYV7y$eRxP15QJgb5e00000NkvXXu0mjfRG*2T diff --git a/graphics/pokemon/fletchling/overworld.png b/graphics/pokemon/fletchling/overworld.png index acfc95f616a7a143700a34d7ff1b91aa622d5236..4c35d25d1727517e2e90ee0ce1f8a97f56140bda 100644 GIT binary patch delta 364 zcmV-y0h9jD1EvFz7#0Wv0001UMu)cm0004VQb$4nuFf3kkv=bf0W(QNK~z|U?UYe& z12G5%ZQudv{SRE>q*B}1X0uV$RAQw48o&?B+SZDqD2k#eilQircc2G<=9A{sx7I1x zobXcL_syyQnxCBTGT*;R=Ewag5h9XJfXqL+fZQa5?;~bDDxgB5Se}r1VjABW->;)X zvH|!VF!NDzfeVR$p9$cVLVr z=?tjdivpQ~L*R z5s?|bE?|$}$kOwze|+K^oBj0000< KMNUMnLSTXryskO` delta 404 zcmV;F0c-xI1I`1G7$yV*0002CwraKj0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuEQP010qNS#tmY4#NNd4#NS*Z>VGd00A~hL_t(Y$L-KTYlAQp!0{(RC_AYX%8sTM zcFdLqd#$jo=egAEEcOcoo1I&Pp7)7YFPjEla%f=}|F>Vn=Zi2kH8pj!f;e{i>JmyL zm%Vv53@D|k!~Q%QUi|^zfMiLR!!Ozn;_(lEvkgH;v((|a;Nm&Lomls=4au%}eUDIw zU$T^{McrRG0>Ur@+^b^y8KDmKq2B8jbwG>DK*1Se2%laaR)qk}M0ZM_H0pWQ(3G^2 zA%?J~-Er9fX40&c5;f{`)_td>`5kB*Nc*_mh{1-IA(!W_Vwh+0_(3;frxEu9&0^7G z;s(OG;xO>K@S1@HrsU}MrUJ5?tD0000?jP38P;|J-Twc7`(%^dCJPQ-y`E0GD<7(^W*{@z2D2=`<9Gay|IDDlfA8S`;z(&( z7UYL6$`}x?@ShuG<6S)6Zcl+233S2*{!;@sm_q{*4rvAq!Lks)3UtB+?wmu0jr`4U zlc%amYotHMA<_(gtONzE0|Sz-aOdzdKs+=s!5649vv2a-cyfUouPYSm%3D_hBIycm z0`~xg1}a3Vz;zGM8W_05Nr^T@^5-~^1RGK1YDDRSG{H@OpfWMBu8iK_1V`RJ>b7ku zl`@z-#akMoQq@WoQU(IA@g%SsBWBi7fF?M$ZI^d1DWxesFhNNKAFBG%4y9{+a1_I< z%>E2BY=Wos`S~eQM3Tt;-YGocJ;4@65g}G4k%IoLr4!Dl`;drG3gFiyf&k8N5s{LT zosy;8@96@6?+JFsA{CL_?dJOQd|?xj@&N~{;xwI-m_%FLzSAq5;XrbAep{eO=iq>M z1k$W9N|Cm@-Fe4vwBKL&0?kUt>Dq)P-zW52OlN!)gUz;S|1SDkJ>f3|>oB}WXw3!@ z_$bg7GU$ohnR2)f0chJ=lUPc6O%e~_5l_P`vi*I33LM~MNf;3PC)jJ9sgf%?F0G(S zJC1ICoBjxpoyo5mdJG`i)!zwJWl}=ejXnthZkJTHWU4C$2C-H+P8z%yo&hw0hxvm5 zo(YeSWYuc*6bLjzt%z{4LWb|au$!{@fz%6lxC9=@BvZN_^|b)<;~0fE=)D1g+Unz0 z?~5>hZuQ(it=8>v4wi5P%(V^;kdg(MO+tHN94(kV@XmQWL0a$M6 zGA(G=%puTdk+O^Yo3h~Fp9heF`TJuRpg_e|UjOl%8JandlH;2!1fhA0<*&x^28GDi z(pmFVLdb&G=iL7_%a$KIjFBVfTQv}{EPcNbff;L(g8$_BJOBUJ@dt=~As5P@@8bXf N002ovPDHLkV1l<_p~L_H delta 933 zcmV;W16usN2kHlq7$yV*0002CwraKj0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuE-e010qNS#tmY4#NNd4#NS*Z>VGd00TowL_t(Y$L*CrYui8=#_xPzz*iMj1rMrB z(2zy)Yh*RfmQYN_Lg=h22)ksm2^tImAtO}i61p^F8tCBB9y}Pb1WE$lx^(E250JHE zd$uh3bhaR&bZXzh;`iR&^Z5R}cj$loD}l3rpUwPdQBqO8%)U>JWkM79K|yJ`h__zP z1&vIwbg1U|AwdAVauGL}frAWuv=k&KYK~cE(N{u6jEEfvXQ+r9T~zN#;q%PES98oV z4k8GqwvC12g?d<@UurGk1l&rGmP5akW>jAcjK-`^`@GSPNgVHh8zg4^AH zJR{ORv&~POfxvX;)DJF#Z@V^)4#M^s<*G zL?)d`mfyQ-0h5Ct!_V8Jm7c)!McS==s5Hh!tlOUBwHs;ylOfZ)8fhYHnE}>&-{Wt- zD)5Vx8>UBPXJsI=_UmWg*H7WQDfF{dU1Q%L zRiSxxmt&aTFCFcuHaR);$L(cxQ|0Y~t#~0p;wSwvz@%SI1xo^xng%8!%~O?U1e3%O z4?RoGZERddXaXW|Dgk^wA#Y9)er z5Seo>6L(RJU_;aIYt!m-O)!lT)>o$j%(-AzyF@aTkbTm-!9dn<_@yF+kn|2KGGikh z0Ele+{VM3mA0%Js1Q5*X{y1Wj!ejrRCB& zqne+sQ9ZtnbGK=0X7j8>5SY?`s`h}Ip~a0L^JD33B?e%d4r3RU-lQY29a`Mo$95^^ z?>=TQ^Wcc%c^k!yKe7s~^5FXjYfPm(Dw zK>>R?gWLqyQp9r%!mlXpH$&39wI?d@ zDH1rL&@84%J%Y`!lw02eK4m&HGhqGMj4^X5d5 zu1?9_8%0Dimj!2k2oni`3zrp#L6EOb$zzYg1tQhL+D?YcT zo80Z;4fo~I2w5MLf_Lj?T{Z^xytz3A%y-(_z@Eqcn)*@$8xAwG?gH0`tl}Y16lU}K zoKJ-!nf`*)LZRsF65o17#l69(#46dH^o)P$+pIv!UEjxlWu{7y(J&wJ$kA@o=6aPX z?lS~q>{nn6EN2N{X1uJccm;mzQx%`}?H$=0-17!PF@`dovpNP8OU`#`)iGAbyyB5_ zeORni_67?M@9{BhG9Ebj93jm*-i>P2rVHL0`xQ2M^|il(w~#M;0}>Y2oaEhT6N@)r zR{-xVvfcx36^~IDoiZ~pXTa`bKw?s7rzkMe1Sq?`Ue=i%;y*llg(777_c6)H6i14Q zzvisKJbg$qs74QOQ|sp)k+gJ{kU&0Z;yXI6epi^koc?`Ha22(LpFR11#wV5n4TrM3 RItBm$002ovPDHLkV1m%H`H%nr delta 539 zcmV+$0_6S31k?nO7$yV*0002CwraKj0004VQb$4nuFf3k00004XF*Lt006O%3;baP zkuEQP010qNS#tmY4#NNd4#NS*Z>VGd00F#7L_t(Y$L*9$PQx$|hR2fG*Kw%C(s6~< zWimN{^Ppl~Q1^w#NSuHJAXvk$7vP*YLMSt)E=v~lm%8}ecz(~rhLcV@>7;)pbqrOs zqz>%(MZ$2-X7o?%0Aw{waaeItI2Rkp*nob2A+Qvnah75L?RY*h12p*&7KrBxsR3tD zXlOn^7?dmu>KU;_%nYJSvDg}xPt2jFO;O~u#+;?C5N+jBe74Ii@<4n;r zv=*^iK#I=>zh(vzgQ#$>a9RqiwuGTA5DRL+dG3d`B~uY|2x#ZqiW+c+(2~#;Nb$;l z`*rE2*^C*azT6CVWs<{*gIETXrGI$2uXCr}VGimx-VZe-S(=M?p26~Mx+(Hw_j0p* zUwn^M%;SlC5IteUqAB+^ox^Ug^NB-A?r=YKJ?7x~>iv^TvoNUH%V0|+kBM9j8Ip?^ zGr-le_t&>+7N{*Zs7ktD_T${nIMWYm^06dMnuQIMPYuE?U~hpa4ALfLh0?S{`s(rH zmNt3hk_2cM9dB~olI=mOMO!ljK^MAR-{&+y)AuX7K{gph=uFNZWa*@1`1PY4OS&U? dXv3cf;1hofbH*$q?8pEB002ovPDHLkV1hsM_KyGn diff --git a/graphics/pokemon/litleo/overworld.png b/graphics/pokemon/litleo/overworld.png index 2c128f3184b29a633f3dbdcaaaa9ac5e6fba6c5a..a419a8327df1e9da894d57be225994387de6b37f 100644 GIT binary patch delta 508 zcmVI|9>k3kycu4?`Cu8fjLx2k2>Q9PiRV8TU%ROTU-B0%)f91)g%79nEVE8 z4y1&PvADsX5mRv+usMj3IP+M1&mR&8C&=U=BEpf6vG|%lr27NVeX(R=rvZmQBWC{% zI2?tjh)NfW1_J(nh*$(7b_Xu!Qn(w`#SQ**046{LS$|k5;&UGUM2zP|ToYoJHr}(( zH5`O9i<2TAPmoJ%gAvz=nx(m{!rJGcQf5l%V&UKCuLg}b7;ru^NG^x(4Fnvde;Q2* z5m`3ibKO$Ay=qOU&vEE@I0hp=Gh*b#@(s9rL{zPnE&o1$zXoI)eDfFaajwP*U4LvN zt}`}vm>qbWMOrITpaZ(_7x5=j1U!P$yexT~ zmj)xAAmEZ)3!B$W&>~~eA&*xI8G1+KBo*jVz(3&OgXH5;I!OTM zob%73OsjQvdhYHFOp61Iz4o$uL@kVL9sSUhbJ4vPuq`g*e0LM0m)s||&1L*_cVvGH zaQBF^w#AdUMO-huy#@)aMx z8`;&~@te%8zD_?Eq@&#FqQAWT{N`m};ojXdTO`(BrjgEV?(|^&`1SVkhoBpif<;}| zAL#Lmn%(6|oUwwrp(?JIffh)v*aA<1Fm)8z0=jUIjugxddgIAs2+cz{SgC^)kRJyAK}#L5Cd$?OuXlmY1YV>0_g_{x=l{)b=oOp$ T^WXRh00000NkvXXu0mjfO_=Z& diff --git a/graphics/pokemon/pancham/overworld.png b/graphics/pokemon/pancham/overworld.png index 90d10d9bfa62ae9c0210d830c919ce2e25665569..a54ddda99d4376e8cfb577d653bcceb4b959a60c 100644 GIT binary patch delta 448 zcmV;x0YCnX1o{Jz7#0Wv0001UMu)cm0004VQb$4nuFf3kks&aDheP3FH0d030FyqC-;o|VP z$VKXm4-C%u(IQ&Fn0q{u;}P9QH0RBqd;by7cp8L9ow4pAnelX}0@1#|Pxz^eJm(_~ zIxk?v3xNHZ+q1Xyi?j8IKf3

@B1oE}$DsI3n=e%`Ad{1)RJafOv@}m;^j`m_!#Eo7Q(6F)u zNQb6jt$iL(-^mQL%s7@#j%&3lzw5iGc=r?a1*8cg}7n8 zZMM6@ZbvHB%uYG!*o0&6US#yzS`Dj2DU}pfn=SR|L}SD1Ig0m%-HxfJTDz;*V_P;h zh?{ps4+Rc(iLXsPVhBtFauTa(C*^si}glt8x4iuRVCN+K%s71j$vWb5oCNqEI|LC8`CmV-tMCevCh5!Hn07*qo IM6N<$g5^cuy#N3J diff --git a/graphics/pokemon/scatterbug/overworld.png b/graphics/pokemon/scatterbug/overworld.png index 2da700223db7629920956ab34f61ec2faed2fabc..41de917984a6bb834063e94019735e718e9a3532 100644 GIT binary patch delta 535 zcmZo*S;8_wqMn19fq|jet$jO?Vk{1FcVbv~PUa<$V-VmI;yUBP0wom{2Spz`)S(%F)$8d91)cO#TnhoJF24jv*1PZ>M_p9W~%^IUMllpLt&6=iTN!fotMw zPNv)lco6RCv+nhg&U#^Wzd05krN2C7IO5#=-)slFgNx4<&tw0pH*!139C!Oa@x!bS z-xxY}7F&F+XS?yFoUx3zui-*tJ-35P=;KM-|FSzMT~pi7?ND`HyxZpGeI}=lUFJJD z1)i?9%QyHspW)$Fm!+;jyTvzzGfZy0_<*G&G+NpqLMLH^%mQy?|Dn!yKfck zVOzH6hxxPRPuSR+g%>KwcP!zGKC^3W zegRX>b5{K^E#@3tcc(rnUK2KkR-isf48~7{dr|>4EPtbj}cJ+JSI)=~ld4K*g zk6*>m(#xv)AY}rt!`bsb46lCKJJfr#%l={H{LQ?;>0sfLx9-h)2AlQvetN3@flgTe~DWM4f(P!Xy delta 498 zcmV9Wh5-#7c1xd*2`xD6d}= zRgLc~Y*kT*O8K{Qj_a!B*&q`@jNS(+El1L0TTv5i-)Ce3af|HcD*?fC^#P_0Ocgd-wV|5VX6;3$lUTJ#`VG=q{sQf~&p$0BB1(pd+>| z0WhIB)!0PpD^T9P7BbgvK<_}T_It7t6N(dJtiA&K;cEv0XZ5xc>)U~lihiuPFvluZ zUxDk}n+o=_8`OpT7iiYHBtOdTT}0{$nEOlheTIf@O#y79RQi5d>7!=^YmC|diV+P! o-;wuBz{n2nRtSb`_`!e87g-Z?7Gd^Z7ytkO07*qoM6N<$f(7i@$p8QV diff --git a/graphics/pokemon/talonflame/overworld.png b/graphics/pokemon/talonflame/overworld.png index 43760d9e85129bdd00baf5000f877f19a3f93e6a..67fc802f44e7c649c175fdbfe4d5ec8b6033851d 100644 GIT binary patch delta 1040 zcmV+r1n>LB2+0VL7#0Wv0001UMu)cm0004VQb$4nuFf3kks&jG(@8`@R9J=GSkbbq zC=8q?F^T&B|GSldiV#oDac^yHT^^>UXo2o@2;%4S7c}5E-G6@kzilWF1RnaQ=jdVl zL;n|znST)hlyoJ~*8(2KzZSqm{P}>FFA4nL1UP?U@baAil-z63cR2)l9RE@QKt#bm zS1_a&N^gN&>z8kT1#lK?co^RZ02BxROn~F}j>4A!(L({Ka3VmaodomO+-YUzY?r)DGR6gM4*&nQlBujx`bFMUkf18X}r?x zONVFlO;uH(q_DO4`n?4wKJ({NR##A;(E4{Rvjr&uH$X#wftXKVF0Cua>o1w%&=24pbQbb1Wv@X(GG%^Th-w+ zf7)&1x=F3Ae%k>DE~x^p0!($^cV8f;;5+|MCvX5nI|~j2bV}9}Pxv!oZyB;TY?iDNs0;&AurIEKvAXSDbTiUgc%8c190MavY=)Wd<*#NIBxun{LCkk6mJ3m zJPAN25UBvrMnqeBIq~-u73v(Cf6U;zTqh8j0CI}N^HsRg?eU)kJhUJ|Jia1t zemAyV8ZUui=13FRH*9nLYiw`$?-lsAjeF_~0iStPI!}%5oSFyO4u4|-$ETWCUkc{M zkOl(CG7x9M?r^+f^7dm>me#+R=;71jD<<#0xMpGfuRh)W?d>0m3MJp^#g54U0000< KMNUMnLSTZvi|MQY delta 1036 zcmV+n1oQjJ2*n7H7zqRe0002CwraMKE;E1JNklRur#W0P2tS5KGmkPJmK1vex>|6Cs_k<{JES2RHS zpy7Rb;`hDxNQyL!?{21}efJyU|7s&=*q4T!VgHU<$&F+*X`o#5$&f%VPVN(kLt}ru z`i=q?i5JTO0dv+P2xfQVK``jw{Sc9H`aowO+hxuka?cjY&ISZRoi+*&3z!oWELW+c zu@vxx09|tePYKxnQNW}dGTlb29+vJX`mqzRpG1mF2)3*-k7qniVinI+T%?mxhAyTa zKGj%#I>HrvUsr3xevO9&NFn1Fsu+KPHGj_7*~MmuaXSYBt6DsKxwdP@DkI;k7HI-A zoX^*G!^+B_bJ?O6E1NP_QU(G^I|m#qeG}uyYnw4v7&*qBKr7hB31e%!q zRz?|XD!SSE$190TUE#?0s~iZM3`*=;&w z<1RxXxK{N8_heF1JxE|BfWCf!No`B*FLU{%6@;B*;qL8t3OCs>~Q3DW*6x6f1ov;>^%WyBYXhh6kpo_Ns&<_i;rlhHO!Uyo1Zc=mt`>V=q%((U%= zBMEI*0sf`dTg}3-KnRJiTSn_GowGt?*lfpXs{cb-Aq0;KmEy=tPka9Q zUP;lxuaQfn5hL! zN6#1Epe=R}Uoz0)5HQ?!ZkjXb-X^){8mp)Ko9?>*xBUaov_dgQ-zbg%00000)+kF1>FUZZGT%yL_t(oh3%Jtj^rQ+hKs*4;`=}F2JOsPM4h|M-X)uoNt^Ve z@Po8tkK?x6ZoBQa+kS~rIL|cU^s`(I3%2EmARlj^oW;g*#s31Ag!i__qb%RU!QiZ~Ed?;Eo>$Qh#dkQ}P8|I6M3)aCZNa zr`RT>TVGytBLOizQY5M;N8y!oww&Typx31x*Y>2OM>^$Qa~N)M6DW^V4-o@4JP!qQ z6XwhqZ}>r!9yR_6IrAll;TBf`MIIo+LyC5IETHH4%6U@&X9h0|019evPN*6B9EMw5 zT}mkh?dV|3dw&hOT#WFPH@+veADQR;IJi`M7iV%=6xs#zaXmaZbqz002ovPDHLkV1k`0E#?3K delta 637 zcmV-@0)qYB1>XgbZGT-!L_t(oh3%KolEWYfMFXf&|Nny*)HaO)Y_~J}uoI@6&g9U` zg(Sw^wma^)*OAZH!dy^mMx%{cb#An=#*Ru0EMSH0-VV~z~2Wim&7o}uzqDpNv zSIH6Aby8-MlfhGMar8Bnn7QVFpRihUu9cs!1?LN7 z_}fMYIAh@=YH${8lX*5am6*BafN!)IQ;HFmoRa2W{6Q(=uaxW0$>oV3Q(ooE(Exc| zaje>iAKg4SVYItyUz*v&ZMl@Dj-wcVtF=BncM8VuZ}dpeaa%_~w6l?LaKnG| zKpBw}jsLiqqsb#>$KH|Pl$S6K3Ta^qJT%y#%~=HW{_N84CX5oFlMfPq%RX~(#~;QI X*en_zmV#fD00000NkvXXu0mjfiKaY9 From 03b6200af5bf4d7e275ca7c3801babf1d07def5a Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:41:56 +0100 Subject: [PATCH 06/35] Fixes Drain Punch / Parental Bond / Scale Shot interaction (#8198) --- src/battle_script_commands.c | 6 ++++-- test/battle/ability/parental_bond.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8674d34e2d..dd8b2d17f2 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6478,7 +6478,7 @@ static void Cmd_moveend(void) if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gMultiHitCounter - && !(moveEffect == EFFECT_PRESENT && gBattleStruct->presentBasePower == 0)) // Silly edge case + && !(moveEffect == EFFECT_PRESENT && gBattleStruct->presentBasePower == 0)) // Parental Bond edge case { gMultiHitCounter--; if (!IsBattlerAlive(gBattlerTarget) && moveEffect != EFFECT_DRAGON_DARTS) @@ -6487,7 +6487,9 @@ static void Cmd_moveend(void) gBattleScripting.multihitString[4]++; if (gMultiHitCounter == 0) { - if (GetMoveEffectArg_MoveProperty(gCurrentMove) == MOVE_EFFECT_SCALE_SHOT && !NoAliveMonsForEitherParty()) + if (moveEffect == EFFECT_MULTI_HIT + && GetMoveEffectArg_MoveProperty(gCurrentMove) == MOVE_EFFECT_SCALE_SHOT + && !NoAliveMonsForEitherParty()) BattleScriptCall(BattleScript_ScaleShot); else BattleScriptCall(BattleScript_MultiHitPrintStrings); diff --git a/test/battle/ability/parental_bond.c b/test/battle/ability/parental_bond.c index b82f16cc26..fc128dba64 100644 --- a/test/battle/ability/parental_bond.c +++ b/test/battle/ability/parental_bond.c @@ -352,6 +352,22 @@ SINGLE_BATTLE_TEST("Parental Bond does not trigger on two turn attacks") } } +SINGLE_BATTLE_TEST("Parental Bond does not trigger Scale Shot effect on Drain Punch") +{ + GIVEN { + PLAYER(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DRAIN_PUNCH, gimmick: GIMMICK_MEGA); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} + TO_DO_BATTLE_TEST("Parental Bond tests"); // Temporary TODO: Convert Bulbapedia description into tests. From 1545e22d0a21d0e1217554f8364f549ea97a9e49 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 12 Nov 2025 15:29:45 -0300 Subject: [PATCH 07/35] Clean usage of gMovesInfo (#8234) --- src/battle_ai_main.c | 2 +- src/battle_ai_switch_items.c | 4 +- src/battle_ai_util.c | 29 +- src/battle_anim_effects_1.c | 4 +- src/battle_anim_new.c | 2 +- src/battle_util.c | 4 +- src/item_menu.c | 4 +- src/party_menu.c | 3 +- test/battle/ability/filter.c | 2 +- test/battle/ability/prism_armor.c | 2 +- test/battle/ability/solid_rock.c | 2 +- test/battle/ai/ai.c | 2 +- test/battle/move_animations/all_anims.c | 416 ++++++++++++------------ test/battle/move_effect/ally_switch.c | 4 +- test/battle/move_effect/heal_bell.c | 4 +- 15 files changed, 249 insertions(+), 235 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 23c008fdc3..d2d81c2a53 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4008,7 +4008,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) 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)); + bool32 moveTargetsBothOpponents = hasTwoOpponents && (GetMoveTarget(move) & (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. diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index f300741675..e4a560ca6e 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -387,7 +387,7 @@ static u32 FindMonWithMoveOfEffectiveness(u32 battler, u32 opposingBattler, uq4_ for (j = 0; j < MAX_MON_MOVES; j++) { move = GetMonData(&party[i], MON_DATA_MOVE1 + j); - if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= effectiveness && gMovesInfo[move].power != 0) + if (move != MOVE_NONE && AI_GetMoveEffectiveness(move, battler, opposingBattler) >= effectiveness && GetMovePower(move) != 0) return SetSwitchinAndSwitch(battler, i); } } @@ -422,7 +422,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > 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 + && (!ALL_MOVES_BAD_STATUS_MOVES_BAD || GetMovePower(aiMove) != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero return FALSE; } } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index db7ab937b1..e39e80a2d2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3965,7 +3965,7 @@ bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 p // 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 (GetMoveTarget(move) == MOVE_TARGET_SELECTED && GetMoveTarget(partnerMove) == MOVE_TARGET_SELECTED) { if (battlerDef == gBattleStruct->moveTarget[battlerAtkPartner]) return TRUE; @@ -4111,7 +4111,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 if (GetMoveEffect(move) == GetMoveEffect(partnerMove) && partnerMove != MOVE_NONE) { - if (gMovesInfo[move].target == MOVE_TARGET_SELECTED && gMovesInfo[partnerMove].target == MOVE_TARGET_SELECTED) + if (GetMoveTarget(move) == MOVE_TARGET_SELECTED && GetMoveTarget(partnerMove) == MOVE_TARGET_SELECTED) { return gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef; } @@ -4512,7 +4512,7 @@ bool32 IsRecycleEncouragedItem(u32 item) static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiIsFaster) { - s32 i; + s32 i, j; u16 *moves = GetMovesArray(battlerId); for (i = 0; i < MAX_MON_MOVES; i++) @@ -4524,16 +4524,21 @@ static bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, if (GetMovePriority(moves[i]) > 0) return TRUE; - switch (gMovesInfo[moves[i]].additionalEffects[i].moveEffect) + u32 additionalEffectCount = GetMoveAdditionalEffectCount(moves[i]); + for (j = 0; j < additionalEffectCount; j++) { - case MOVE_EFFECT_SPD_MINUS_1: - case MOVE_EFFECT_SPD_MINUS_2: - { - if(aiIsFaster) - return TRUE; - } - default: - break; + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(moves[i], j); + switch (additionalEffect->moveEffect) + { + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + { + if(aiIsFaster) + return TRUE; + } + default: + break; + } } } } diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 128862994b..49ec4e5e3a 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -5189,7 +5189,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) { if (gBattleAnimArgs[0] == 0) { - if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) + if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimAttacker, TRUE, &a, &b); } @@ -5201,7 +5201,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) } else { - if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) + if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &a, &b); } diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 1263632ab7..378fde42a4 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -9431,7 +9431,7 @@ static void SpriteCB_MaxFlutterby(struct Sprite* sprite) { s16 target_x; s16 target_y; - if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) + if (GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &target_x, &target_y); } diff --git a/src/battle_util.c b/src/battle_util.c index a5039231e4..76f6d36f6d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11486,9 +11486,9 @@ bool32 IsAnyTargetAffected(u32 battlerAtk) void UpdateStallMons(void) { - if (IsBattlerTurnDamaged(gBattlerTarget) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || gMovesInfo[gCurrentMove].category == DAMAGE_CATEGORY_STATUS) + if (IsBattlerTurnDamaged(gBattlerTarget) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || GetMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_STATUS) return; - if (!IsDoubleBattle() || gMovesInfo[gCurrentMove].target == MOVE_TARGET_SELECTED) + if (!IsDoubleBattle() || GetMoveTarget(gCurrentMove) == MOVE_TARGET_SELECTED) { u32 moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); diff --git a/src/item_menu.c b/src/item_menu.c index 6bb65b5a2e..f19cad0cdc 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -2916,8 +2916,8 @@ static s32 CompareItemsAlphabetically(enum Pocket pocketId, struct ItemSlot item if (pocketId == POCKET_TM_HM) { - name1 = gMovesInfo[GetTMHMMoveId(GetItemTMHMIndex(item1.itemId))].name; - name2 = gMovesInfo[GetTMHMMoveId(GetItemTMHMIndex(item2.itemId))].name; + name1 = GetMoveName(GetTMHMMoveId(GetItemTMHMIndex(item1.itemId))); + name2 = GetMoveName(GetTMHMMoveId(GetItemTMHMIndex(item2.itemId))); } else { diff --git a/src/party_menu.c b/src/party_menu.c index 3964716afa..ce18d0a0db 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -6320,8 +6320,9 @@ static void SwapFusionMonMoves(struct Pokemon *mon, const u16 moveTable[][2], u3 { if (move == moveTable[j][oldMoveIndex]) { + u32 pp = GetMovePP(moveTable[j][newMoveIndex]); SetMonData(mon, MON_DATA_MOVE1 + i, &moveTable[j][newMoveIndex]); - SetMonData(mon, MON_DATA_PP1 + i, &gMovesInfo[moveTable[j][newMoveIndex]].pp); + SetMonData(mon, MON_DATA_PP1 + i, &pp); } } } diff --git a/test/battle/ability/filter.c b/test/battle/ability/filter.c index c9a742c48d..69c0e96278 100644 --- a/test/battle/ability/filter.c +++ b/test/battle/ability/filter.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Filter reduces damage to Super Effective moves by 0.75", s16 GIVEN { ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[0] == TYPE_PSYCHIC); ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[1] == TYPE_FAIRY); - ASSUME(gMovesInfo[MOVE_POISON_JAB].type == TYPE_POISON); + ASSUME(GetMoveType(MOVE_POISON_JAB) == TYPE_POISON); ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0)); ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0)); PLAYER(SPECIES_MR_MIME) { Ability(ability); } diff --git a/test/battle/ability/prism_armor.c b/test/battle/ability/prism_armor.c index 60c8e238cf..69bdde0a0f 100644 --- a/test/battle/ability/prism_armor.c +++ b/test/battle/ability/prism_armor.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Prism Armor reduces damage to Super Effective moves by 0.75" GIVEN { ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[0] == TYPE_PSYCHIC); ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[1] == TYPE_PSYCHIC); - ASSUME(gMovesInfo[MOVE_DARK_PULSE].type == TYPE_DARK); + ASSUME(GetMoveType(MOVE_DARK_PULSE) == TYPE_DARK); ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0)); ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0)); PLAYER(SPECIES_NECROZMA); diff --git a/test/battle/ability/solid_rock.c b/test/battle/ability/solid_rock.c index b3dea4ae5e..d15b87e236 100644 --- a/test/battle/ability/solid_rock.c +++ b/test/battle/ability/solid_rock.c @@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Solid Rock reduces damage to Super Effective moves by 0.75", GIVEN { ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[0] == TYPE_WATER); ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[1] == TYPE_ROCK); - ASSUME(gMovesInfo[MOVE_CLOSE_COMBAT].type == TYPE_FIGHTING); + ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING); ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_ROCK] > UQ_4_12(1.0)); ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_WATER] == UQ_4_12(1.0)); PLAYER(SPECIES_CARRACOSTA) { Ability(ability); } diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 4c86673473..3e8f45717e 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -690,7 +690,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use thawing moves if target is frozen unless it ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE); ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL); ASSUME(GetMoveCategory(MOVE_WATER_GUN) == DAMAGE_CATEGORY_SPECIAL); - ASSUME(gMovesInfo[MOVE_SCALD].thawsUser == TRUE); + ASSUME(MoveThawsUser(MOVE_SCALD) == TRUE); AI_FLAGS(aiFlags | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE); Status1(status); } OPPONENT(SPECIES_VULPIX) { Moves(MOVE_TACKLE, aiMove); } diff --git a/test/battle/move_animations/all_anims.c b/test/battle/move_animations/all_anims.c index c929921d3f..acf5dcbb56 100644 --- a/test/battle/move_animations/all_anims.c +++ b/test/battle/move_animations/all_anims.c @@ -11,42 +11,43 @@ static void ParametrizeMovesAndSpecies(u32 j, u32 *pMove, u32 *pSpecies) { - if (gMovesInfo[j].effect == EFFECT_DARK_VOID) // User needs to be Darkrai + enum BattleMoveEffects effect = GetMoveEffect(j); + if (effect == EFFECT_DARK_VOID) // User needs to be Darkrai { *pMove = j; *pSpecies = SPECIES_DARKRAI; } - else if (gMovesInfo[j].effect == EFFECT_HYPERSPACE_FURY) // User needs to be Hoopa Unbound + else if (effect == EFFECT_HYPERSPACE_FURY) // User needs to be Hoopa Unbound { *pMove = j; *pSpecies = SPECIES_HOOPA_UNBOUND; } - else if (gMovesInfo[j].effect == EFFECT_AURA_WHEEL) // User needs to be Morpeko + else if (effect == EFFECT_AURA_WHEEL) // User needs to be Morpeko { *pMove = j; *pSpecies = SPECIES_MORPEKO_FULL_BELLY; } - else if (gMovesInfo[j].effect == EFFECT_ROTOTILLER || gMovesInfo[j].effect == EFFECT_FLOWER_SHIELD) // User needs to be Grass-type + else if (effect == EFFECT_ROTOTILLER || effect == EFFECT_FLOWER_SHIELD) // User needs to be Grass-type { *pMove = j; *pSpecies = SPECIES_TANGELA; } - else if (gMovesInfo[j].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE && gMovesInfo[j].argument.type == TYPE_FIRE) // User needs to be Fire-type + else if (effect == EFFECT_FAIL_IF_NOT_ARG_TYPE && GetMoveArgType(j) == TYPE_FIRE) // User needs to be Fire-type { *pMove = j; *pSpecies = SPECIES_FLAREON; } - else if (gMovesInfo[j].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE && gMovesInfo[j].argument.type == TYPE_ELECTRIC) // User needs to be Electric-type + else if (effect == EFFECT_FAIL_IF_NOT_ARG_TYPE && GetMoveArgType(j) == TYPE_ELECTRIC) // User needs to be Electric-type { *pMove = j; *pSpecies = SPECIES_JOLTEON; } - else if (gMovesInfo[j].effect == EFFECT_MAGNETIC_FLUX || gMovesInfo[j].effect == EFFECT_GEAR_UP) // User needs to have Plus + else if (effect == EFFECT_MAGNETIC_FLUX || effect == EFFECT_GEAR_UP) // User needs to have Plus { *pMove = j; *pSpecies = SPECIES_KLINKLANG; } - else if (gMovesInfo[j].effect == EFFECT_PLACEHOLDER) // Ignore placeholder *pMoves + else if (effect == EFFECT_PLACEHOLDER) // Ignore placeholder *pMoves { *pMove = MOVE_POUND; *pSpecies = SPECIES_WOBBUFFET; @@ -60,100 +61,104 @@ static void ParametrizeMovesAndSpecies(u32 j, u32 *pMove, u32 *pSpecies) static bool32 TargetHasToMove(u32 move) // Opponent needs to hit the player first { - if (gMovesInfo[move].effect == EFFECT_COUNTER - || gMovesInfo[move].effect == EFFECT_MIRROR_MOVE - || gMovesInfo[move].effect == EFFECT_CONVERSION_2 - || gMovesInfo[move].effect == EFFECT_MIRROR_COAT - || gMovesInfo[move].effect == EFFECT_METAL_BURST - || gMovesInfo[move].effect == EFFECT_COPYCAT - || gMovesInfo[move].effect == EFFECT_SUCKER_PUNCH - || gMovesInfo[move].effect == EFFECT_INSTRUCT) + enum BattleMoveEffects effect = GetMoveEffect(move); + if (effect == EFFECT_COUNTER + || effect == EFFECT_MIRROR_MOVE + || effect == EFFECT_CONVERSION_2 + || effect == EFFECT_MIRROR_COAT + || effect == EFFECT_METAL_BURST + || effect == EFFECT_COPYCAT + || effect == EFFECT_SUCKER_PUNCH + || effect == EFFECT_INSTRUCT) return TRUE; return FALSE; } static bool32 AttackerHasToSwitch(u32 move) // User needs to send out a different team member { - if (gMovesInfo[move].effect == EFFECT_TELEPORT - || gMovesInfo[move].effect == EFFECT_EXPLOSION - || gMovesInfo[move].effect == EFFECT_MISTY_EXPLOSION - || gMovesInfo[move].effect == EFFECT_BATON_PASS - || gMovesInfo[move].effect == EFFECT_MEMENTO - || gMovesInfo[move].effect == EFFECT_HEALING_WISH - || gMovesInfo[move].effect == EFFECT_HIT_ESCAPE - || gMovesInfo[move].effect == EFFECT_FINAL_GAMBIT - || gMovesInfo[move].effect == EFFECT_PARTING_SHOT - || gMovesInfo[move].effect == EFFECT_SHED_TAIL - || gMovesInfo[move].effect == EFFECT_CHILLY_RECEPTION) + enum BattleMoveEffects effect = GetMoveEffect(move); + if (effect == EFFECT_TELEPORT + || effect == EFFECT_EXPLOSION + || effect == EFFECT_MISTY_EXPLOSION + || effect == EFFECT_BATON_PASS + || effect == EFFECT_MEMENTO + || effect == EFFECT_HEALING_WISH + || effect == EFFECT_HIT_ESCAPE + || effect == EFFECT_FINAL_GAMBIT + || effect == EFFECT_PARTING_SHOT + || effect == EFFECT_SHED_TAIL + || effect == EFFECT_CHILLY_RECEPTION) return TRUE; return FALSE; } static bool32 UserHasToGoFirst(u32 move) // Player needs to go first { - if (gMovesInfo[move].effect == EFFECT_PROTECT - || gMovesInfo[move].effect == EFFECT_ENDURE - || gMovesInfo[move].effect == EFFECT_FOLLOW_ME - || gMovesInfo[move].effect == EFFECT_MAGIC_COAT - || gMovesInfo[move].effect == EFFECT_ME_FIRST - || gMovesInfo[move].effect == EFFECT_QUASH - || gMovesInfo[move].effect == EFFECT_MAT_BLOCK - || gMovesInfo[move].effect == EFFECT_ELECTRIFY - || gMovesInfo[move].effect == EFFECT_SHELL_TRAP) + enum BattleMoveEffects effect = GetMoveEffect(move); + if (effect == EFFECT_PROTECT + || effect == EFFECT_ENDURE + || effect == EFFECT_FOLLOW_ME + || effect == EFFECT_MAGIC_COAT + || effect == EFFECT_ME_FIRST + || effect == EFFECT_QUASH + || effect == EFFECT_MAT_BLOCK + || effect == EFFECT_ELECTRIFY + || effect == EFFECT_SHELL_TRAP) return TRUE; return FALSE; } static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *defender) { + enum BattleMoveEffects effect = GetMoveEffect(move); // Setup turn - if (gMovesInfo[move].effect == EFFECT_SNORE - || gMovesInfo[move].effect == EFFECT_SLEEP_TALK) + if (effect == EFFECT_SNORE + || effect == EFFECT_SLEEP_TALK) { // attacker needs to be asleep TURN { MOVE(attacker, MOVE_REST); } } - else if (gMovesInfo[move].effect == EFFECT_SPIT_UP - || gMovesInfo[move].effect == EFFECT_SWALLOW) + else if (effect == EFFECT_SPIT_UP + || effect == EFFECT_SWALLOW) { // attacker needs to have used Stockpile TURN { MOVE(attacker, MOVE_STOCKPILE); } } - else if ((gMovesInfo[move].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && gMovesInfo[move].argument.status == STATUS1_PARALYSIS)) + else if ((effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && GetMoveEffectArg_Status(move) == STATUS1_PARALYSIS)) { // defender needs to be paralyzed TURN { MOVE(attacker, MOVE_THUNDER_WAVE); } } - else if (gMovesInfo[move].effect == EFFECT_RECYCLE - || gMovesInfo[move].effect == EFFECT_BELCH) + else if (effect == EFFECT_RECYCLE + || effect == EFFECT_BELCH) { // attacker needs to have eaten its Berry TURN { MOVE(attacker, MOVE_STUFF_CHEEKS); } } - else if (gMovesInfo[move].effect == EFFECT_REFRESH - || gMovesInfo[move].effect == EFFECT_PSYCHO_SHIFT) + else if (effect == EFFECT_REFRESH + || effect == EFFECT_PSYCHO_SHIFT) { // attacker needs to be paralyzed TURN { MOVE(defender, MOVE_THUNDER_WAVE); } } - else if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) + else if (effect == EFFECT_LAST_RESORT) { // attacker needs to have used all other moves TURN { MOVE(attacker, MOVE_POUND); } } - else if (gMovesInfo[move].effect == EFFECT_DREAM_EATER - || gMovesInfo[move].effect == EFFECT_NIGHTMARE) + else if (effect == EFFECT_DREAM_EATER + || effect == EFFECT_NIGHTMARE) { // defender needs to be asleep TURN { MOVE(defender, MOVE_REST); } } - else if (gMovesInfo[move].effect == EFFECT_VENOM_DRENCH - || gMovesInfo[move].effect == EFFECT_PURIFY) + else if (effect == EFFECT_VENOM_DRENCH + || effect == EFFECT_PURIFY) { // defender needs to be poisoned TURN { MOVE(attacker, MOVE_POISON_POWDER); } } - else if (gMovesInfo[move].effect == EFFECT_TOPSY_TURVY) + else if (effect == EFFECT_TOPSY_TURVY) { // defender needs to have its stats buffed TURN { MOVE(defender, MOVE_SWORDS_DANCE); } } - else if (gMovesInfo[move].effect == EFFECT_AURORA_VEIL) + else if (effect == EFFECT_AURORA_VEIL) { // Has to be hailing TURN { MOVE(attacker, MOVE_HAIL); } } - else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER) + else if (effect == EFFECT_STEEL_ROLLER) { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } @@ -161,15 +166,15 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP TURN { if (TargetHasToMove(move)) { - MOVE(defender, gMovesInfo[move].effect == EFFECT_MIRROR_COAT ? MOVE_SWIFT : MOVE_POUND); + MOVE(defender, effect == EFFECT_MIRROR_COAT ? MOVE_SWIFT : MOVE_POUND); MOVE(attacker, move); } - else if (gMovesInfo[move].effect == EFFECT_SNATCH) + else if (effect == EFFECT_SNATCH) { // defender needs to steal the defender's buffing move MOVE(attacker, move); MOVE(defender, MOVE_SWORDS_DANCE); } - else if (gMovesInfo[move].effect == EFFECT_OHKO || gMovesInfo[move].effect == EFFECT_SHEER_COLD) + else if (effect == EFFECT_OHKO || effect == EFFECT_SHEER_COLD) { // defender needs to send out a different team member MOVE(attacker, move); SEND_OUT(defender, 1); @@ -184,17 +189,17 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP MOVE(attacker, move); MOVE(defender, MOVE_POUND); } - else if (gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING) + else if (effect == EFFECT_REVIVAL_BLESSING) { // attacker selects party member MOVE(attacker, move, partyIndex: 1); MOVE(defender, MOVE_HELPING_HAND); } - else if (gMovesInfo[move].effect == EFFECT_UPPER_HAND) + else if (effect == EFFECT_UPPER_HAND) { // defender needs to choose priority move MOVE(attacker, move); MOVE(defender, MOVE_QUICK_ATTACK); } - else if (gMovesInfo[move].effect == EFFECT_ACUPRESSURE) + else if (effect == EFFECT_ACUPRESSURE) { MOVE(attacker, move, target: attacker); } @@ -208,22 +213,23 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP static void SceneSingles(u32 move, struct BattlePokemon *mon) { - if (gMovesInfo[move].effect == EFFECT_FOLLOW_ME - || gMovesInfo[move].effect == EFFECT_HELPING_HAND - || gMovesInfo[move].effect == EFFECT_AFTER_YOU - || gMovesInfo[move].effect == EFFECT_ALLY_SWITCH - || gMovesInfo[move].effect == EFFECT_AROMATIC_MIST + enum BattleMoveEffects effect = GetMoveEffect(move); + if (effect == EFFECT_FOLLOW_ME + || effect == EFFECT_HELPING_HAND + || effect == EFFECT_AFTER_YOU + || effect == EFFECT_ALLY_SWITCH + || effect == EFFECT_AROMATIC_MIST || move == MOVE_HOLD_HANDS // Hack here because it shares its effect with Splash and Celebrate - || gMovesInfo[move].effect == EFFECT_COACHING - || gMovesInfo[move].effect == EFFECT_DRAGON_CHEER) + || effect == EFFECT_COACHING + || effect == EFFECT_DRAGON_CHEER) { // Moves that fail in Single Battles } - else if (gMovesInfo[move].effect == EFFECT_MIRROR_MOVE) // Copy the opponent's move + else if (effect == EFFECT_MIRROR_MOVE) // Copy the opponent's move { ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, mon); } - else if (gMovesInfo[move].effect == EFFECT_NATURE_POWER) // Recorded battles always use BATTLE_ENVIRONMENT_BUILDING + else if (effect == EFFECT_NATURE_POWER) // Recorded battles always use BATTLE_ENVIRONMENT_BUILDING { ANIMATION(ANIM_TYPE_MOVE, B_NATURE_POWER_MOVES >= GEN_4 ? MOVE_TRI_ATTACK : MOVE_SWIFT, mon); } @@ -235,54 +241,55 @@ static void SceneSingles(u32 move, struct BattlePokemon *mon) static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattlePokemon *target, struct BattlePokemon *ignore1, struct BattlePokemon *ignore2) { + enum BattleMoveEffects effect = GetMoveEffect(move); // Setup turn - if (gMovesInfo[move].effect == EFFECT_SNORE - || gMovesInfo[move].effect == EFFECT_SLEEP_TALK) + if (effect == EFFECT_SNORE + || effect == EFFECT_SLEEP_TALK) { // Player needs to be asleep TURN { MOVE(attacker, MOVE_REST); } } - else if (gMovesInfo[move].effect == EFFECT_SPIT_UP - || gMovesInfo[move].effect == EFFECT_SWALLOW) + else if (effect == EFFECT_SPIT_UP + || effect == EFFECT_SWALLOW) { // Player needs to have used Stockpile TURN { MOVE(attacker, MOVE_STOCKPILE); } } - else if ((gMovesInfo[move].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && gMovesInfo[move].argument.status == STATUS1_PARALYSIS)) + else if ((effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS && GetMoveEffectArg_Status(move) == STATUS1_PARALYSIS)) { // Opponent needs to be paralyzed TURN { MOVE(attacker, MOVE_THUNDER_WAVE, target: target); } } - else if (gMovesInfo[move].effect == EFFECT_RECYCLE - || gMovesInfo[move].effect == EFFECT_BELCH) + else if (effect == EFFECT_RECYCLE + || effect == EFFECT_BELCH) { // Player needs to have eaten its Berry TURN { MOVE(attacker, MOVE_STUFF_CHEEKS); } } - else if (gMovesInfo[move].effect == EFFECT_REFRESH - || gMovesInfo[move].effect == EFFECT_PSYCHO_SHIFT) + else if (effect == EFFECT_REFRESH + || effect == EFFECT_PSYCHO_SHIFT) { // Player needs to be paralyzed TURN { MOVE(target, MOVE_THUNDER_WAVE, target: attacker); } } - else if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) + else if (effect == EFFECT_LAST_RESORT) { // Player needs to have used all other moves TURN { MOVE(attacker, MOVE_POUND, target: target); } } - else if (gMovesInfo[move].effect == EFFECT_DREAM_EATER - || gMovesInfo[move].effect == EFFECT_NIGHTMARE) + else if (effect == EFFECT_DREAM_EATER + || effect == EFFECT_NIGHTMARE) { // Opponent needs to be asleep TURN { MOVE(target, MOVE_REST); } } - else if (gMovesInfo[move].effect == EFFECT_VENOM_DRENCH - || gMovesInfo[move].effect == EFFECT_PURIFY) + else if (effect == EFFECT_VENOM_DRENCH + || effect == EFFECT_PURIFY) { // Opponent needs to be poisoned TURN { MOVE(attacker, MOVE_POISON_POWDER, target: target); } } - else if (gMovesInfo[move].effect == EFFECT_TOPSY_TURVY) + else if (effect == EFFECT_TOPSY_TURVY) { // Opponent needs to have its stats buffed TURN { MOVE(target, MOVE_SWORDS_DANCE); } } - else if (gMovesInfo[move].effect == EFFECT_AURORA_VEIL) + else if (effect == EFFECT_AURORA_VEIL) { // Has to be hailing TURN { MOVE(attacker, MOVE_HAIL); } } - else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER) + else if (effect == EFFECT_STEEL_ROLLER) { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } @@ -290,15 +297,15 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP TURN { if (TargetHasToMove(move)) { // Opponent needs to hit the player first - MOVE(target, gMovesInfo[move].effect == EFFECT_MIRROR_COAT ? MOVE_SWIFT : MOVE_POUND, target: attacker); + MOVE(target, effect == EFFECT_MIRROR_COAT ? MOVE_SWIFT : MOVE_POUND, target: attacker); MOVE(attacker, move, target: target); } - else if (gMovesInfo[move].effect == EFFECT_SNATCH) + else if (effect == EFFECT_SNATCH) { // Opponent needs to steal the opponent's buffing move MOVE(attacker, move, target: target); MOVE(target, MOVE_SWORDS_DANCE); } - else if (gMovesInfo[move].effect == EFFECT_OHKO || gMovesInfo[move].effect == EFFECT_SHEER_COLD) + else if (effect == EFFECT_OHKO || effect == EFFECT_SHEER_COLD) { // Opponent needs to send out a different team member MOVE(attacker, move, target: target); SEND_OUT(target, 2); @@ -313,19 +320,19 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP MOVE(attacker, move, target: target); MOVE(target, MOVE_POUND, target: attacker); } - else if (gMovesInfo[move].effect == EFFECT_AFTER_YOU) + else if (effect == EFFECT_AFTER_YOU) { // Player goes first, opponent third MOVE(attacker, move, target: target); MOVE(ignore1, MOVE_CELEBRATE); MOVE(target, MOVE_POUND, target: attacker); MOVE(ignore2, MOVE_CELEBRATE); } - else if (gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING) + else if (effect == EFFECT_REVIVAL_BLESSING) { // Player selects party member MOVE(attacker, move, partyIndex: 2); MOVE(target, MOVE_LAST_RESORT, target: attacker); // Last Resort, so there's no anim on the opponent's side. } - else if (gMovesInfo[move].effect == EFFECT_UPPER_HAND) + else if (effect == EFFECT_UPPER_HAND) { // Opponent needs to choose priority move MOVE(attacker, move, target: target); MOVE(target, MOVE_QUICK_ATTACK, target: attacker); @@ -335,7 +342,7 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP MOVE(target, MOVE_LAST_RESORT, target: attacker); // Last Resort, so there's no anim on the opponent's side. MOVE(attacker, move, target: target); } - if (gMovesInfo[move].effect != EFFECT_AFTER_YOU) + if (effect != EFFECT_AFTER_YOU) { // Actions for the remaining battlers MOVE(ignore1, MOVE_CELEBRATE); @@ -346,15 +353,16 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP static void DoublesScene(u32 move, struct BattlePokemon *attacker) { - if (gMovesInfo[move].effect == EFFECT_MAGNETIC_FLUX || gMovesInfo[move].effect == EFFECT_GEAR_UP) // For some reason, Magnetic Flux and Gear Up are failing in Double Battles here + enum BattleMoveEffects effect = GetMoveEffect(move); + if (effect == EFFECT_MAGNETIC_FLUX || effect == EFFECT_GEAR_UP) // For some reason, Magnetic Flux and Gear Up are failing in Double Battles here { // Moves that fail in Double Battles } - else if (gMovesInfo[move].effect == EFFECT_MIRROR_MOVE) + else if (effect == EFFECT_MIRROR_MOVE) { // Copy the opponent's move ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, attacker); } - else if (gMovesInfo[move].effect == EFFECT_NATURE_POWER) + else if (effect == EFFECT_NATURE_POWER) { // Recorded battles always use BATTLE_ENVIRONMENT_BUILDING ANIMATION(ANIM_TYPE_MOVE, B_NATURE_POWER_MOVES >= GEN_4 ? MOVE_TRI_ATTACK : MOVE_SWIFT, attacker); } @@ -382,16 +390,16 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (player to op PLAYER(species) { HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) + if (GetMoveEffect(move) != EFFECT_BESTOW) Item(ITEM_ORAN_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } @@ -402,7 +410,7 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (player to op } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -420,16 +428,16 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (opponent to OPPONENT(species) { HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) + if (GetMoveEffect(move) != EFFECT_BESTOW) Item(ITEM_ORAN_BERRY); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } @@ -440,7 +448,7 @@ SINGLE_BATTLE_TEST("Move Animations don't leak when used - Singles (opponent to } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -463,7 +471,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -472,22 +480,22 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) + if (GetMoveEffect(move) != EFFECT_BESTOW) Item(ITEM_ORAN_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) + if (GetMoveEffect(move) != EFFECT_BESTOW) Item(ITEM_ORAN_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } @@ -498,7 +506,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -521,7 +529,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -529,23 +537,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -557,7 +565,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -580,7 +588,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -588,23 +596,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -616,7 +624,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -639,7 +647,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -647,23 +655,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -675,7 +683,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -698,7 +706,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -706,23 +714,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -734,7 +742,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -757,7 +765,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -765,23 +773,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -793,7 +801,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentLeft } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -816,7 +824,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -824,23 +832,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == playerRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -852,7 +860,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -875,7 +883,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -883,23 +891,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -911,7 +919,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -935,7 +943,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -943,23 +951,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -971,7 +979,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerLeft t } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -994,7 +1002,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -1002,23 +1010,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -1030,7 +1038,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (playerRight } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1053,7 +1061,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentleft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -1061,23 +1069,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentleft HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -1089,7 +1097,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentleft } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1112,7 +1120,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentLeft) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } @@ -1120,23 +1128,23 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (attacker == opponentRight) { if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND, MOVE_CELEBRATE); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) { + if (GetMoveEffect(move) != EFFECT_BESTOW) { Item(ITEM_ORAN_BERRY); } } @@ -1148,7 +1156,7 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1167,27 +1175,27 @@ SINGLE_BATTLE_TEST("Move Animations occur before their stat change animations - PLAYER(species) { HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY); if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE); - if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); + if (GetMoveEffect(move) == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND); if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS); } PLAYER(SPECIES_WOBBUFFET) { Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND); - HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998); + HP(GetMoveEffect(move) == EFFECT_REVIVAL_BLESSING ? 0 : 9998); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY); - if (gMovesInfo[move].effect != EFFECT_BESTOW) + if (GetMoveEffect(move) != EFFECT_BESTOW) Item(ITEM_ORAN_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); } } WHEN { WhenSingles(move, player, opponent); } SCENE { - if (!(gMovesInfo[move].effect == EFFECT_RECYCLE - || gMovesInfo[move].effect == EFFECT_BELCH - || gMovesInfo[move].effect == EFFECT_SPIT_UP - || gMovesInfo[move].effect == EFFECT_SWALLOW - || gMovesInfo[move].effect == EFFECT_TOPSY_TURVY)) // require a move that boosts stats before using this move + if (!(GetMoveEffect(move) == EFFECT_RECYCLE + || GetMoveEffect(move) == EFFECT_BELCH + || GetMoveEffect(move) == EFFECT_SPIT_UP + || GetMoveEffect(move) == EFFECT_SWALLOW + || GetMoveEffect(move) == EFFECT_TOPSY_TURVY)) // require a move that boosts stats before using this move { NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); @@ -1198,7 +1206,7 @@ SINGLE_BATTLE_TEST("Move Animations occur before their stat change animations - } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1266,7 +1274,7 @@ SINGLE_BATTLE_TEST("Z-Moves don't leak when used - Singles (player to opponent)" } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1295,7 +1303,7 @@ SINGLE_BATTLE_TEST("Z-Moves don't leak when used - Singles (opponent to player)" } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1326,7 +1334,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (playerLeft to oppone } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1357,7 +1365,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (playerLeft to oppone } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1388,7 +1396,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (playerRight to oppon } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1419,7 +1427,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (playerRight to oppon } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1450,7 +1458,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (opponentLeft to play } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1481,7 +1489,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (opponentLeft to play } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1512,7 +1520,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (opponentRight to pla } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1543,7 +1551,7 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (opponentRight to pla } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1588,7 +1596,7 @@ SINGLE_BATTLE_TEST("Tera Blast doesn't leak when used - Singles (player to oppon } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1610,7 +1618,7 @@ SINGLE_BATTLE_TEST("Tera Blast doesn't leak when used - Singles (opponent to pla } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1634,7 +1642,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerLeft to o } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1658,7 +1666,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerLeft to o } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1682,7 +1690,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerRight to } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1706,7 +1714,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerRight to } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1730,7 +1738,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentLeft to } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1754,7 +1762,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentLeft to } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1778,7 +1786,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentRight t } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } @@ -1802,7 +1810,7 @@ DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentRight t } THEN { FORCE_MOVE_ANIM(FALSE); if (gLoadFail) - DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + DebugPrintf("Move failed: %S (%u)", GetMoveName(move), move); EXPECT_EQ(gLoadFail, FALSE); } } diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index e3f99cb73b..8300c7b9c8 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -170,7 +170,7 @@ DOUBLE_BATTLE_TEST("Ally Switch - move fails if the target was ally which change DOUBLE_BATTLE_TEST("Ally Switch doesn't make self-targeting status moves fail") { GIVEN { - ASSUME(gMovesInfo[MOVE_HARDEN].target == MOVE_TARGET_USER); + ASSUME(GetMoveTarget(MOVE_HARDEN) == MOVE_TARGET_USER); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); @@ -366,7 +366,7 @@ DOUBLE_BATTLE_TEST("Ally Switch does not update leech seed battler") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_LEECH_SEED_DRAIN, playerLeft); HP_BAR(playerLeft); HP_BAR(opponentLeft); - + MESSAGE("The opposing Ralts used Ally Switch!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentRight); MESSAGE("The opposing Ralts and the opposing Bulbasaur switched places!"); diff --git a/test/battle/move_effect/heal_bell.c b/test/battle/move_effect/heal_bell.c index 67bdfda1b8..b3f6af0c45 100644 --- a/test/battle/move_effect/heal_bell.c +++ b/test/battle/move_effect/heal_bell.c @@ -3,8 +3,8 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_HEAL_BELL].effect == EFFECT_HEAL_BELL); - ASSUME(gMovesInfo[MOVE_AROMATHERAPY].effect == EFFECT_HEAL_BELL); + ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); + ASSUME(GetMoveEffect(MOVE_AROMATHERAPY) == EFFECT_HEAL_BELL); ASSUME(MoveHasAdditionalEffect(MOVE_SPARKLY_SWIRL, MOVE_EFFECT_AROMATHERAPY)); } From 7d778af9462934c1870090d71cda5b2ec0c3a3a5 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Wed, 12 Nov 2025 20:00:19 +0100 Subject: [PATCH 08/35] Fix wrong ditto sprite on capture (#8226) --- src/battle_script_commands.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dd8b2d17f2..d0bee7dd4a 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14271,13 +14271,16 @@ static void Cmd_displaydexinfo(void) { CMD_ARGS(); - struct Pokemon *mon = GetBattlerMon(GetCatchingBattler()); + u32 caughtBattler = GetCatchingBattler(); + struct Pokemon *mon = GetBattlerMon(caughtBattler); u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); switch (gBattleCommunication[0]) { case 0: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); + ClearTemporarySpeciesSpriteData(caughtBattler, FALSE, FALSE); + BattleLoadMonSpriteGfx(mon, caughtBattler); gBattleCommunication[0]++; break; case 1: From 49838a004e7c2d8ec033c5f18b322209c123fb66 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 12 Nov 2025 17:48:27 -0300 Subject: [PATCH 09/35] A couple more tests (#8209) Co-authored-by: hedara90 <90hedara@gmail.com> --- test/battle/ability/fur_coat.c | 43 +++++++++++++++++++++- test/battle/ability/iron_fist.c | 24 ++++++++++++- test/battle/ability/libero.c | 2 +- test/battle/ability/protean.c | 62 ++++++++++++++++++++++---------- test/battle/ability/sharpness.c | 2 +- test/battle/gimmick/terastal.c | 12 ++++--- test/battle/move_effect/curse.c | 9 +++-- test/battle/move_effect/powder.c | 9 +++-- 8 files changed, 131 insertions(+), 32 deletions(-) diff --git a/test/battle/ability/fur_coat.c b/test/battle/ability/fur_coat.c index 56fb197114..84b8549e42 100644 --- a/test/battle/ability/fur_coat.c +++ b/test/battle/ability/fur_coat.c @@ -1,4 +1,45 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fur Coat (Ability) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); +} + +SINGLE_BATTLE_TEST("Fur Coat doubles Defense", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_FUR_COAT; } + PARAMETRIZE { ability = ABILITY_RATTLED; } + + GIVEN { + PLAYER(SPECIES_PERSIAN_ALOLA) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); } + } SCENE { + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Fur Coat has no effect on self-inflicted confusion damage", s16 damage) +{ + KNOWN_FAILING; + u32 ability; + PARAMETRIZE { ability = ABILITY_FUR_COAT; } + PARAMETRIZE { ability = ABILITY_RATTLED; } + + GIVEN { + PLAYER(SPECIES_PERSIAN_ALOLA) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CONFUSE_RAY); MOVE(player, MOVE_POUND, WITH_RNG(RNG_CONFUSION, TRUE)); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/battle/ability/iron_fist.c b/test/battle/ability/iron_fist.c index ae26f9cdd0..360b3606be 100644 --- a/test/battle/ability/iron_fist.c +++ b/test/battle/ability/iron_fist.c @@ -1,4 +1,26 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Iron Fist (Ability) test titles") +SINGLE_BATTLE_TEST("Iron Fist increases the power of punching moves by 20%", s16 damage) +{ + u32 move, ability; + PARAMETRIZE { move = MOVE_BULLET_PUNCH; ability = ABILITY_IRON_FIST; } + PARAMETRIZE { move = MOVE_BULLET_PUNCH; ability = ABILITY_BLAZE; } + PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_IRON_FIST; } + PARAMETRIZE { move = MOVE_SCRATCH; ability = ABILITY_BLAZE; } + + GIVEN { + ASSUME(IsPunchingMove(MOVE_BULLET_PUNCH)); + ASSUME(!IsPunchingMove(MOVE_SCRATCH)); + ASSUME(GetMovePower(MOVE_BULLET_PUNCH) == GetMovePower(MOVE_SCRATCH)); + PLAYER(SPECIES_CHIMCHAR) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.2), results[0].damage); // Iron Fist affects punching moves + EXPECT_EQ(results[2].damage, results[3].damage); // Iron Fist does not affect non-punching moves + } +} diff --git a/test/battle/ability/libero.c b/test/battle/ability/libero.c index 8ea93df3c0..b2ebf5cd5b 100644 --- a/test/battle/ability/libero.c +++ b/test/battle/ability/libero.c @@ -1,4 +1,4 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Libero (Ability) test titles") +// Tests for Libero are handled in test/battle/ability/protean.c diff --git a/test/battle/ability/protean.c b/test/battle/ability/protean.c index fe4ae25e60..c41fa58cca 100644 --- a/test/battle/ability/protean.c +++ b/test/battle/ability/protean.c @@ -1,12 +1,15 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Protean changes the type of the user to the move used every time (Gen6-8)") +SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user to the move used every time (Gen6-8)") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_6); PLAYER(SPECIES_REGIROCK); - OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_WATER_GUN); } @@ -15,24 +18,36 @@ SINGLE_BATTLE_TEST("Protean changes the type of the user to the move used every TURN { SWITCH(opponent, 0); } TURN { MOVE(opponent, MOVE_WATER_GUN); } } SCENE { - ABILITY_POPUP(opponent, ABILITY_PROTEAN); - MESSAGE("The opposing Kecleon transformed into the Water type!"); + ABILITY_POPUP(opponent, ability); + if (species == SPECIES_KECLEON) + MESSAGE("The opposing Kecleon transformed into the Water type!"); + else + MESSAGE("The opposing Raboot transformed into the Water type!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); - ABILITY_POPUP(opponent, ABILITY_PROTEAN); - MESSAGE("The opposing Kecleon transformed into the Normal type!"); + ABILITY_POPUP(opponent, ability); + if (species == SPECIES_KECLEON) + MESSAGE("The opposing Kecleon transformed into the Normal type!"); + else + MESSAGE("The opposing Raboot transformed into the Normal type!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); - ABILITY_POPUP(opponent, ABILITY_PROTEAN); - MESSAGE("The opposing Kecleon transformed into the Water type!"); + ABILITY_POPUP(opponent, ability); + if (species == SPECIES_KECLEON) + MESSAGE("The opposing Kecleon transformed into the Water type!"); + else + MESSAGE("The opposing Raboot transformed into the Water type!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); } } -SINGLE_BATTLE_TEST("Protean changes the type of the user only once per switch in (Gen9+)") +SINGLE_BATTLE_TEST("Protean/Libero changes the type of the user only once per switch in (Gen9+)") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_9); PLAYER(SPECIES_REGIROCK); - OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_WATER_GUN); } @@ -41,31 +56,42 @@ SINGLE_BATTLE_TEST("Protean changes the type of the user only once per switch in TURN { SWITCH(opponent, 0); } TURN { MOVE(opponent, MOVE_WATER_GUN); } } SCENE { - ABILITY_POPUP(opponent, ABILITY_PROTEAN); - MESSAGE("The opposing Kecleon transformed into the Water type!"); + ABILITY_POPUP(opponent, ability); + if (species == SPECIES_KECLEON) + MESSAGE("The opposing Kecleon transformed into the Water type!"); + else + MESSAGE("The opposing Raboot transformed into the Water type!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); NONE_OF { - ABILITY_POPUP(opponent, ABILITY_PROTEAN); + ABILITY_POPUP(opponent, ability); MESSAGE("The opposing Kecleon transformed into the Normal type!"); + MESSAGE("The opposing Raboot transformed into the Normal type!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); - ABILITY_POPUP(opponent, ABILITY_PROTEAN); - MESSAGE("The opposing Kecleon transformed into the Water type!"); + ABILITY_POPUP(opponent, ability); + if (species == SPECIES_KECLEON) + MESSAGE("The opposing Kecleon transformed into the Water type!"); + else + MESSAGE("The opposing Raboot transformed into the Water type!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); } } -SINGLE_BATTLE_TEST("Protean does not change the user's type when using Struggle") +SINGLE_BATTLE_TEST("Protean/Libero does not change the user's type when using Struggle") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_GRENINJA; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { PLAYER(SPECIES_REGIROCK); - OPPONENT(SPECIES_GRENINJA) { Ability(ABILITY_PROTEAN); } + OPPONENT(species) { Ability(ability); } } WHEN { TURN { MOVE(opponent, MOVE_STRUGGLE); } } SCENE { NONE_OF { - ABILITY_POPUP(opponent, ABILITY_PROTEAN); + ABILITY_POPUP(opponent, ability); MESSAGE("The opposing Greninja transformed into the Normal type!"); + MESSAGE("The opposing Raboot transformed into the Normal type!"); } ANIMATION(ANIM_TYPE_MOVE, MOVE_STRUGGLE, opponent); } diff --git a/test/battle/ability/sharpness.c b/test/battle/ability/sharpness.c index 38ed79f86f..9b89614c36 100644 --- a/test/battle/ability/sharpness.c +++ b/test/battle/ability/sharpness.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Sharpness increases the power of slicing moves", s16 damage) +SINGLE_BATTLE_TEST("Sharpness increases the power of slicing moves by 50%", s16 damage) { u32 move; u16 ability; diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index 37a6d515b3..d238ea0d51 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -639,17 +639,21 @@ SINGLE_BATTLE_TEST("(TERA) Terastallizing into the Stellar type boosts all moves } } -SINGLE_BATTLE_TEST("(TERA) Protean cannot change the type of a Terastallized Pokemon") +SINGLE_BATTLE_TEST("(TERA) Protean/Libero cannot change the type of a Terastallized Pokemon") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_GRENINJA; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { - PLAYER(SPECIES_GRENINJA) { Ability(ABILITY_PROTEAN); TeraType(TYPE_GRASS); } + PLAYER(species) { Ability(ability); TeraType(TYPE_GRASS); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_BUBBLE, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_EMBER); } } SCENE { - MESSAGE("Greninja used Bubble!"); - MESSAGE("The opposing Wobbuffet used Ember!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BUBBLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); MESSAGE("It's super effective!"); } } diff --git a/test/battle/move_effect/curse.c b/test/battle/move_effect/curse.c index bb1de42fba..355972e74e 100644 --- a/test/battle/move_effect/curse.c +++ b/test/battle/move_effect/curse.c @@ -37,16 +37,19 @@ SINGLE_BATTLE_TEST("Curse cuts the user's HP in half when used by Ghost-types") } } -SINGLE_BATTLE_TEST("Curse applies to the user if used with Protean") +SINGLE_BATTLE_TEST("Curse applies to the user if used with Protean/Libero") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_KECLEON; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { - PLAYER(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_CURSE, target: player); } } SCENE { s32 playerMaxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - ABILITY_POPUP(player, ABILITY_PROTEAN); + ABILITY_POPUP(player, ability); ANIMATION(ANIM_TYPE_MOVE, MOVE_CURSE, player); HP_BAR(player, damage: playerMaxHP / 2); HP_BAR(player, damage: playerMaxHP / 4); diff --git a/test/battle/move_effect/powder.c b/test/battle/move_effect/powder.c index da8eba4caf..ea2f80e793 100644 --- a/test/battle/move_effect/powder.c +++ b/test/battle/move_effect/powder.c @@ -223,17 +223,20 @@ DOUBLE_BATTLE_TEST("Powder still blocks the target's Fire type moves even if it } } -SINGLE_BATTLE_TEST("Powder prevents Protean from changing its user to Fire type") +SINGLE_BATTLE_TEST("Powder prevents Protean/Libero from changing its user to Fire type") { + u32 ability, species; + PARAMETRIZE { ability = ABILITY_PROTEAN; species = SPECIES_GRENINJA; } + PARAMETRIZE { ability = ABILITY_LIBERO; species = SPECIES_RABOOT; } GIVEN { - PLAYER(SPECIES_GRENINJA) { Ability(ABILITY_PROTEAN); } + PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_VIVILLON); } WHEN { TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent); NONE_OF { - ABILITY_POPUP(player, ABILITY_PROTEAN); + ABILITY_POPUP(player, ability); ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); HP_BAR(opponent); } From eaa768fe797091389a224e76fc435f7d4a47da54 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Wed, 12 Nov 2025 22:22:57 +0100 Subject: [PATCH 10/35] Fix match call regression (#8227) Co-authored-by: Bassoonian --- src/trainer_see.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trainer_see.c b/src/trainer_see.c index 2ec23dfa4f..348ec14c2d 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -474,7 +474,7 @@ static u8 CheckTrainer(u8 objectEventId) if (GetTrainerFlagFromScriptPointer(trainerBattlePtr)) { //If there is a rematch, we want to trigger the approach sequence - if (GetRematchFromScriptPointer(trainerBattlePtr)) + if (I_VS_SEEKER_CHARGING && GetRematchFromScriptPointer(trainerBattlePtr)) { trainerBattlePtr = NULL; numTrainers = 0xFF; From c8cc45fe62d9e87b8efa84545a8c16347556c940 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 13:45:36 -0800 Subject: [PATCH 11/35] add leo60228 as a contributor for doc, and data (#8238) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ CREDITS.md | 1 + 2 files changed, 11 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 52810517f1..aa76ec1a65 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -468,6 +468,16 @@ "contributions": [ "code" ] + }, + { + "login": "leo60228", + "name": "leo60228", + "avatar_url": "https://avatars.githubusercontent.com/u/8355305?v=4", + "profile": "https://vriska.dev", + "contributions": [ + "doc", + "data" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 31f2302313..e9d1e53354 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -77,6 +77,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d MandL27
MandL27

💻 cawtds
cawtds

💻 Frank DeBlasio
Frank DeBlasio

💻 + leo60228
leo60228

📖 🔣 From d85f97b3f77670c7f55d90a126304d790a7aeee4 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Thu, 13 Nov 2025 11:23:48 +0100 Subject: [PATCH 12/35] Fix mew sprite not appearing correctly (#8235) --- src/faraway_island.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/faraway_island.c b/src/faraway_island.c index e275bcfa37..67acf5cc6d 100755 --- a/src/faraway_island.c +++ b/src/faraway_island.c @@ -393,6 +393,7 @@ void SetMewAboveGrass(void) LoadSpritePalette(&gSpritePalette_GeneralFieldEffect1); UpdateSpritePaletteWithWeather(IndexOfSpritePaletteTag(gSpritePalette_GeneralFieldEffect1.tag), FALSE); + gSprites[mew->spriteId].subspriteTableNum = 1; x = mew->currentCoords.x; y = mew->currentCoords.y; From db9460c67092fc4950578e4aaa5216600488e0ce Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Thu, 13 Nov 2025 11:36:26 +0100 Subject: [PATCH 13/35] Fix wrong palette for types sprites in hgss dex after catching mon (#8153) Co-authored-by: Bassoonian --- src/pokedex_plus_hgss.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index d02eb0eda1..03cf7bb8d2 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -4088,6 +4088,12 @@ static void UNUSED HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused) #define tPersonalityLo data[14] #define tPersonalityHi data[15] +// Types palettes need to be loaded at a different slot than anticipated by gTypesInfo +// to avoid overlapping with caught mon sprite palette slot +// Normal type info palette slots: 13, 14 and 15 +// Caught mon palette slot: 15 +#define TYPE_INFO_PALETTE_NUM_OFFSET -1 + void Task_DisplayCaughtMonDexPageHGSS(u8 taskId) { u8 spriteId; @@ -4349,9 +4355,9 @@ static void SetTypeIconPosAndPal(u8 typeId, u8 x, u8 y, u8 spriteArrayId) sprite = &gSprites[sPokedexView->typeIconSpriteIds[spriteArrayId]]; StartSpriteAnim(sprite, typeId); if (typeId < NUMBER_OF_MON_TYPES) - sprite->oam.paletteNum = gTypesInfo[typeId].palette; + sprite->oam.paletteNum = gTypesInfo[typeId].palette + TYPE_INFO_PALETTE_NUM_OFFSET; else - sprite->oam.paletteNum = sContestCategoryToOamPaletteNum[typeId - NUMBER_OF_MON_TYPES]; + sprite->oam.paletteNum = sContestCategoryToOamPaletteNum[typeId - NUMBER_OF_MON_TYPES] + TYPE_INFO_PALETTE_NUM_OFFSET; sprite->x = x + 16; sprite->y = y + 8; SetSpriteInvisibility(spriteArrayId, FALSE); @@ -4392,7 +4398,8 @@ static void CreateTypeIconSprites(void) u8 i; LoadCompressedSpriteSheet(&gSpriteSheet_MoveTypes); - LoadPalette(gMoveTypes_Pal, 0x1D0, 0x60); + u32 paletteNum = gTypesInfo[TYPE_NORMAL].palette + TYPE_INFO_PALETTE_NUM_OFFSET; + LoadPalette(gMoveTypes_Pal, OBJ_PLTT_ID(paletteNum), 3 * PLTT_SIZE_4BPP); for (i = 0; i < 2; i++) { if (sPokedexView->typeIconSpriteIds[i] == 0xFF) @@ -4572,6 +4579,7 @@ static u16 CreateSizeScreenTrainerPic(u16 species, s16 x, s16 y, s8 paletteSlot) return CreateTrainerPicSprite(species, TRUE, x, y, paletteSlot, TAG_NONE); } +#undef TYPE_INFO_PALETTE_NUM_OFFSET //************************************ //* * From 8c83a2567677fb01c521e7bad766f7113dbed926 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Thu, 13 Nov 2025 05:37:17 -0500 Subject: [PATCH 14/35] Fixed an issue related to same turn Encore targeting (#8230) Co-authored-by: LinathanZel --- include/battle.h | 5 +++++ src/battle_script_commands.c | 7 +++++++ 2 files changed, 12 insertions(+) mode change 100644 => 100755 include/battle.h diff --git a/include/battle.h b/include/battle.h old mode 100644 new mode 100755 index 15b37d62c8..05328fa845 --- a/include/battle.h +++ b/include/battle.h @@ -1249,4 +1249,9 @@ 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]]; +} + #endif // GUARD_BATTLE_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d0bee7dd4a..112e0dc566 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11519,6 +11519,13 @@ static void Cmd_trysetencore(void) { gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; gDisableStructs[gBattlerTarget].encoredMovePos = i; + + // If the target's selected move is not the same as the move being Encored into, + // the target will select a random opposing target + // Redirection such as Follow Me is already covered in HandleAction_UseMove of battle_util.c + if (gDisableStructs[gBattlerTarget].encoredMove != GetChosenMoveFromPosition(gBattlerTarget)) + gBattleStruct->moveTarget[gBattlerTarget] = SetRandomTarget(gBattlerTarget); + // Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn. if (HasBattlerActedThisTurn(gBattlerTarget)) gDisableStructs[gBattlerTarget].encoreTimer = 4; From b72c2b244bc4796154d7df77b68799758a1c793d Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 13 Nov 2025 18:50:21 -0300 Subject: [PATCH 15/35] Fixed some failing tests with GEN_LATEST = GEN_5 (#8241) --- test/battle/ability/magic_bounce.c | 1 + test/battle/ability/overcoat.c | 18 +++++++++++++++--- test/battle/hold_effect/life_orb.c | 1 + test/battle/move_effect/metronome.c | 1 + test/battle/move_effect/mirror_move.c | 1 + test/battle/move_effect/powder.c | 2 +- test/battle/move_effect/psychic_terrain.c | 2 ++ .../move_effect_secondary/remove_status.c | 1 + 8 files changed, 23 insertions(+), 4 deletions(-) diff --git a/test/battle/ability/magic_bounce.c b/test/battle/ability/magic_bounce.c index 56c9a32332..9ef36de4af 100644 --- a/test/battle/ability/magic_bounce.c +++ b/test/battle/ability/magic_bounce.c @@ -42,6 +42,7 @@ SINGLE_BATTLE_TEST("Magic Bounce bounces back powder moves") SINGLE_BATTLE_TEST("Magic Bounce cannot bounce back powder moves against Grass Types") { GIVEN { + WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS); PLAYER(SPECIES_ODDISH); diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c index cfdbad7de3..5edda7c3d5 100644 --- a/test/battle/ability/overcoat.c +++ b/test/battle/ability/overcoat.c @@ -71,17 +71,29 @@ DOUBLE_BATTLE_TEST("Overcoat blocks damage from hail") } } -SINGLE_BATTLE_TEST("Overcoat blocks Effect Spore's effect") +SINGLE_BATTLE_TEST("Overcoat blocks Effect Spore's effect (Gen6+)") { + u32 config; + PARAMETRIZE { config = GEN_5; } + PARAMETRIZE { config = GEN_6; } GIVEN { + WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, config); PLAYER(SPECIES_PINECO) {Ability(ABILITY_OVERCOAT);} OPPONENT(SPECIES_SHROOMISH) {Ability(ABILITY_EFFECT_SPORE);} } WHEN { TURN { MOVE(player, MOVE_TACKLE, WITH_RNG(RNG_EFFECT_SPORE, 1)); } } SCENE { MESSAGE("Pineco used Tackle!"); - NOT ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + if (config == GEN_6) { + NOT ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + } + else { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + } } THEN { - EXPECT_EQ(player->status1, 0); + if (config == GEN_6) + EXPECT_EQ(player->status1, 0); + else + EXPECT_NE(player->status1, 0); } } diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c index 81ddd614db..e983537b83 100644 --- a/test/battle/hold_effect/life_orb.c +++ b/test/battle/hold_effect/life_orb.c @@ -34,6 +34,7 @@ SINGLE_BATTLE_TEST("Life Orb activates if it hits a Substitute") SINGLE_BATTLE_TEST("Life Orb does not activate if using status move on a Substitute") { GIVEN { + ASSUME(MoveIgnoresSubstitute(MOVE_GROWL)); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/metronome.c b/test/battle/move_effect/metronome.c index 2419ecb1e4..91865b05cf 100644 --- a/test/battle/move_effect/metronome.c +++ b/test/battle/move_effect/metronome.c @@ -25,6 +25,7 @@ SINGLE_BATTLE_TEST("Metronome picks a random move") SINGLE_BATTLE_TEST("Metronome's called powder move fails against Grass Types") { GIVEN { + WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_POISON_POWDER)); ASSUME(GetSpeciesType(SPECIES_TANGELA, 0) == TYPE_GRASS); ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); diff --git a/test/battle/move_effect/mirror_move.c b/test/battle/move_effect/mirror_move.c index 642998cbcf..2f3c65b827 100644 --- a/test/battle/move_effect/mirror_move.c +++ b/test/battle/move_effect/mirror_move.c @@ -41,6 +41,7 @@ SINGLE_BATTLE_TEST("Mirror Move fails if no move was used before") SINGLE_BATTLE_TEST("Mirror Move's called powder move fails against Grass Types") { GIVEN { + WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); ASSUME(GetSpeciesType(SPECIES_ODDISH, 0) == TYPE_GRASS); ASSUME(GetMoveEffect(MOVE_STUN_SPORE) == EFFECT_NON_VOLATILE_STATUS); diff --git a/test/battle/move_effect/powder.c b/test/battle/move_effect/powder.c index ea2f80e793..0cfeeb0a8d 100644 --- a/test/battle/move_effect/powder.c +++ b/test/battle/move_effect/powder.c @@ -168,7 +168,7 @@ SINGLE_BATTLE_TEST("Powder fails if the target is Grass type (Gen6+)") SINGLE_BATTLE_TEST("Powder fails if the target has Overcoat (Gen6+)") { GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, GEN_6); + WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, GEN_6); PLAYER(SPECIES_FORRETRESS) { Ability(ABILITY_OVERCOAT); } OPPONENT(SPECIES_VIVILLON); } WHEN { diff --git a/test/battle/move_effect/psychic_terrain.c b/test/battle/move_effect/psychic_terrain.c index 2c5089c704..51fdb236ef 100644 --- a/test/battle/move_effect/psychic_terrain.c +++ b/test/battle/move_effect/psychic_terrain.c @@ -120,6 +120,8 @@ SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves against semi-in PARAMETRIZE { move = MOVE_SOLAR_BEAM; shouldWork = FALSE;} PARAMETRIZE { move = MOVE_FLY; shouldWork = TRUE;} GIVEN { + WITH_CONFIG(GEN_CONFIG_TOXIC_NEVER_MISS, GEN_6); + ASSUME(IsSpeciesOfType(SPECIES_SHROODLE, TYPE_POISON)); PLAYER(SPECIES_SHROODLE) { Ability(ABILITY_PRANKSTER); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect_secondary/remove_status.c b/test/battle/move_effect_secondary/remove_status.c index 0a07ef6368..4e62ca55e9 100644 --- a/test/battle/move_effect_secondary/remove_status.c +++ b/test/battle/move_effect_secondary/remove_status.c @@ -118,6 +118,7 @@ TO_DO_BATTLE_TEST("Wake-Up Slap gets increased power against Pokémon with Comat DOUBLE_BATTLE_TEST("Sparkling Aria cures burns from all Pokemon on the field and behind substitutes") { GIVEN { + ASSUME(MoveIgnoresSubstitute(MOVE_SPARKLING_ARIA)); ASSUME(MoveHasAdditionalEffect(MOVE_SPARKLING_ARIA, MOVE_EFFECT_REMOVE_STATUS) == TRUE); ASSUME(GetMoveEffectArg_Status(MOVE_SPARKLING_ARIA) == STATUS1_BURN); PLAYER(SPECIES_PRIMARINA); From 82d09571fd6506b7ec5e9c2838cba18fd8b78114 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 13 Nov 2025 22:51:07 +0100 Subject: [PATCH 16/35] Fixes Shell Trap not activating on contact but no damage (#8243) --- src/battle_script_commands.c | 3 ++- test/battle/move_effect/shell_trap.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 112e0dc566..dbf0b0025f 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6294,9 +6294,10 @@ static void Cmd_moveend(void) // Set ShellTrap to activate after the attacker's turn if target was hit by a physical move. if (GetMoveEffect(gChosenMoveByBattler[gBattlerTarget]) == EFFECT_SHELL_TRAP + && IsBattleMovePhysical(gCurrentMove) + && IsBattlerTurnDamaged(gBattlerTarget) && gBattlerTarget != gBattlerAttacker && !IsBattlerAlly(gBattlerTarget, gBattlerAttacker) - && gProtectStructs[gBattlerTarget].physicalDmg && gProtectStructs[gBattlerTarget].physicalBattlerId == gBattlerAttacker && !TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) { diff --git a/test/battle/move_effect/shell_trap.c b/test/battle/move_effect/shell_trap.c index 435c79a652..903f984929 100644 --- a/test/battle/move_effect/shell_trap.c +++ b/test/battle/move_effect/shell_trap.c @@ -198,3 +198,19 @@ DOUBLE_BATTLE_TEST("Shell Trap targets correctly if one of the opponents has fai ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); } } + +SINGLE_BATTLE_TEST("Shell Trap activates if user is hit with a physical move but does no damage") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_FALSE_SWIPE) == EFFECT_FALSE_SWIPE); + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, MOVE_FALSE_SWIPE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } +} From 85568422fdc81a17a0841959bd5ae25950cbddf0 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Thu, 13 Nov 2025 22:51:44 +0100 Subject: [PATCH 17/35] Add test for mold breaker/ice scales interaction (#8240) Co-authored-by: Bassoonian --- test/battle/ability/mold_breaker.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/battle/ability/mold_breaker.c b/test/battle/ability/mold_breaker.c index 2c04deeeef..fb6f9d11ab 100644 --- a/test/battle/ability/mold_breaker.c +++ b/test/battle/ability/mold_breaker.c @@ -1,4 +1,22 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Mold Breaker (Ability) test titles") +SINGLE_BATTLE_TEST("Mold Breaker cancels damage reduction from Ice Scales", s16 damage) +{ + u16 ability; + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER; } + GIVEN { + ASSUME(GetMoveCategory(MOVE_PSYCHIC) == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_FROSMOTH) { Ability(ABILITY_ICE_SCALES); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[1].damage, UQ_4_12(0.5), results[0].damage); + } +} + +TO_DO_BATTLE_TEST("TODO: Write more Mold Breaker (Ability) test titles") From 3f74d30a54d1e9f3b15dc76a35339fa8dfadbddb Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Fri, 14 Nov 2025 18:25:27 +0100 Subject: [PATCH 18/35] Make tailwind anim mirror based on side (#8249) --- data/battle_anim_scripts.s | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 4df85854dc..d0fc4e9ac8 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -255,23 +255,23 @@ gBattleAnimMove_Tailwind:: createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 24, 6, 4, 4 createvisualtask AnimTask_TraceMonBlended, 2, 0, 4, 7, 10 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 1 delay 12 - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 1 delay 10 - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 1 waitforvisualfinish stopsound call UnsetHighSpeedBg @@ -285,23 +285,23 @@ gBattleAnimGeneral_Tailwind:: playsewithpan SE_M_GUST, SOUND_PAN_ATTACKER call SetHighSpeedBg setalpha 12, 8 - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 10, 2304, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 90, 2048, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 50, 2560, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 20, 2304, 96, 1 delay 12 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 70, 1984, 96, 1 delay 12 - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 0, 2816, 96, 1 delay 10 - createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 0 + createsprite gFlyingSandCrescentSpriteTemplate, ANIM_ATTACKER, 40, 60, 2560, 96, 1 waitforvisualfinish stopsound call UnsetHighSpeedBg From d9d3e51a9ce75bc6f6bd571fb0a9787fbc4e9aed Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sat, 15 Nov 2025 12:03:16 +0100 Subject: [PATCH 19/35] Fix mirage tower ceiling crumble color (#8081) --- src/mirage_tower.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/mirage_tower.c b/src/mirage_tower.c index e2ed74a21a..bf73692a36 100644 --- a/src/mirage_tower.c +++ b/src/mirage_tower.c @@ -202,7 +202,7 @@ static const struct OamData sOamData_CeilingCrumbleSmall = static const struct SpriteTemplate sSpriteTemplate_CeilingCrumbleSmall = { .tileTag = TAG_CEILING_CRUMBLE, - .paletteTag = TAG_NONE, + .paletteTag = TAG_CEILING_CRUMBLE, .oam = &sOamData_CeilingCrumbleSmall, .anims = sAnims_CeilingCrumbleSmall, .images = NULL, @@ -241,7 +241,7 @@ static const struct OamData sOamData_CeilingCrumbleLarge = static const struct SpriteTemplate sSpriteTemplate_CeilingCrumbleLarge = { .tileTag = TAG_CEILING_CRUMBLE, - .paletteTag = TAG_NONE, + .paletteTag = TAG_CEILING_CRUMBLE, .oam = &sOamData_CeilingCrumbleLarge, .anims = sAnims_CeilingCrumbleLarge, .images = NULL, @@ -420,6 +420,7 @@ static void IncrementCeilingCrumbleFinishedCount(void) void DoMirageTowerCeilingCrumble(void) { + LoadSpritePaletteWithTag(sMirageTowerCrumbles_Palette, TAG_CEILING_CRUMBLE); LoadSpriteSheets(sCeilingCrumbleSpriteSheets); CreateCeilingCrumbleSprites(); CreateTask(WaitCeilingCrumble, 8); @@ -454,17 +455,12 @@ static void CreateCeilingCrumbleSprites(void) { spriteId = CreateSprite(&sSpriteTemplate_CeilingCrumbleLarge, sCeilingCrumblePositions[i][0] + 120, sCeilingCrumblePositions[i][1], 8); gSprites[spriteId].oam.priority = 0; - // These sprites use color index 11 from the player's sprite palette. This probably wasn't intentional. - // The palettes for Brendan and May have different shades of green at this index, so the color of these sprites changes - // depending on the player's gender (and neither shade of green particularly fits a crumbling yellow/brown ceiling). - gSprites[spriteId].oam.paletteNum = PALSLOT_PLAYER; gSprites[spriteId].sIndex = i; } for (i = 0; i < ARRAY_COUNT(sCeilingCrumblePositions); i++) { spriteId = CreateSprite(&sSpriteTemplate_CeilingCrumbleSmall, sCeilingCrumblePositions[i][0] + 115, sCeilingCrumblePositions[i][1] - 3, 8); gSprites[spriteId].oam.priority = 0; - gSprites[spriteId].oam.paletteNum = PALSLOT_PLAYER; gSprites[spriteId].sIndex = i; } } From 73ec0813e13ebcb9333b45eb280c1a1e2a1b5417 Mon Sep 17 00:00:00 2001 From: mitsunee Date: Sat, 15 Nov 2025 12:11:32 +0100 Subject: [PATCH 20/35] Standardize spelling of "canceler" just a quick grep -r and regex substitution, but didn't see anything wrong in the diffs during a quick proofread --- include/battle.h | 2 +- include/battle_util.h | 2 +- src/battle_script_commands.c | 2 +- src/battle_util.c | 98 ++++++++++++++++++------------------ 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/include/battle.h b/include/battle.h index 4bd8aaaf35..8585415b74 100644 --- a/include/battle.h +++ b/include/battle.h @@ -431,7 +431,7 @@ struct BattleStruct u8 wishPerishSongState; u8 wishPerishSongBattlerId; bool8 overworldWeatherDone; - u8 atkCancellerTracker; + u8 atkCancelerTracker; struct BattleTvMovePoints tvMovePoints; struct BattleTv tv; u8 unused_7[0x28]; diff --git a/include/battle_util.h b/include/battle_util.h index 3416451535..318cf4d439 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -84,7 +84,7 @@ u8 DoBattlerEndTurnEffects(void); bool8 HandleWishPerishSongOnTurnEnd(void); bool8 HandleFaintedMonActions(void); void TryClearRageStatuses(void); -u8 AtkCanceller_UnableToUseMove(void); +u8 AtkCanceler_UnableToUseMove(void); bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2); u8 CastformDataTypeChange(u8 battler); u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveArg); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 429551e889..65663f77d3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -927,7 +927,7 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (AtkCanceller_UnableToUseMove()) + if (AtkCanceler_UnableToUseMove()) return; if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBattlerTarget, 0, 0, 0)) return; diff --git a/src/battle_util.c b/src/battle_util.c index ffe5f38743..96c5dbc6f2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -90,7 +90,7 @@ void HandleAction_UseMove(void) gCritMultiplier = 1; gBattleScripting.dmgMultiplier = 1; - gBattleStruct->atkCancellerTracker = 0; + gBattleStruct->atkCancelerTracker = 0; gMoveResultFlags = 0; gMultiHitCounter = 0; gBattleCommunication[MISS_TYPE] = 0; @@ -1982,37 +1982,37 @@ void TryClearRageStatuses(void) enum { - CANCELLER_FLAGS, - CANCELLER_ASLEEP, - CANCELLER_FROZEN, - CANCELLER_TRUANT, - CANCELLER_RECHARGE, - CANCELLER_FLINCH, - CANCELLER_DISABLED, - CANCELLER_TAUNTED, - CANCELLER_IMPRISONED, - CANCELLER_CONFUSED, - CANCELLER_PARALYSED, - CANCELLER_IN_LOVE, - CANCELLER_BIDE, - CANCELLER_THAW, - CANCELLER_END, + CANCELER_FLAGS, + CANCELER_ASLEEP, + CANCELER_FROZEN, + CANCELER_TRUANT, + CANCELER_RECHARGE, + CANCELER_FLINCH, + CANCELER_DISABLED, + CANCELER_TAUNTED, + CANCELER_IMPRISONED, + CANCELER_CONFUSED, + CANCELER_PARALYSED, + CANCELER_IN_LOVE, + CANCELER_BIDE, + CANCELER_THAW, + CANCELER_END, }; -u8 AtkCanceller_UnableToUseMove(void) +u8 AtkCanceler_UnableToUseMove(void) { u8 effect = 0; s32 *bideDmg = &gBattleScripting.bideDmg; do { - switch (gBattleStruct->atkCancellerTracker) + switch (gBattleStruct->atkCancelerTracker) { - case CANCELLER_FLAGS: // flags clear + case CANCELER_FLAGS: // flags clear gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND; gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_ASLEEP: // check being asleep + case CANCELER_ASLEEP: // check being asleep if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) { if (UproarWakeUpCheck(gBattlerAttacker)) @@ -2054,9 +2054,9 @@ u8 AtkCanceller_UnableToUseMove(void) } } } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_FROZEN: // check being frozen + case CANCELER_FROZEN: // check being frozen if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) { if (Random() % 5) @@ -2068,7 +2068,7 @@ u8 AtkCanceller_UnableToUseMove(void) } else { - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; } } @@ -2081,9 +2081,9 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 2; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_TRUANT: // truant + case CANCELER_TRUANT: // truant if (gBattleMons[gBattlerAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) { CancelMultiTurnMoves(gBattlerAttacker); @@ -2093,9 +2093,9 @@ u8 AtkCanceller_UnableToUseMove(void) gMoveResultFlags |= MOVE_RESULT_MISSED; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_RECHARGE: // recharge + case CANCELER_RECHARGE: // recharge if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) { gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RECHARGE; @@ -2105,9 +2105,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_FLINCH: // flinch + case CANCELER_FLINCH: // flinch if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) { gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_FLINCHED; @@ -2117,9 +2117,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_DISABLED: // disabled move + case CANCELER_DISABLED: // disabled move if (gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) { gProtectStructs[gBattlerAttacker].usedDisabledMove = 1; @@ -2129,9 +2129,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_TAUNTED: // taunt + case CANCELER_TAUNTED: // taunt if (gDisableStructs[gBattlerAttacker].tauntTimer && gBattleMoves[gCurrentMove].power == 0) { gProtectStructs[gBattlerAttacker].usedTauntedMove = 1; @@ -2140,9 +2140,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_IMPRISONED: // imprisoned + case CANCELER_IMPRISONED: // imprisoned if (GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) { gProtectStructs[gBattlerAttacker].usedImprisonedMove = 1; @@ -2151,9 +2151,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_CONFUSED: // confusion + case CANCELER_CONFUSED: // confusion if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) { gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); @@ -2183,9 +2183,9 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_PARALYSED: // paralysis + case CANCELER_PARALYSED: // paralysis if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && (Random() % 4) == 0) { gProtectStructs[gBattlerAttacker].prlzImmobility = 1; @@ -2195,9 +2195,9 @@ u8 AtkCanceller_UnableToUseMove(void) gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_IN_LOVE: // infatuation + case CANCELER_IN_LOVE: // infatuation if (gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) { gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10); @@ -2215,9 +2215,9 @@ u8 AtkCanceller_UnableToUseMove(void) gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_BIDE: // bide + case CANCELER_BIDE: // bide if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) { gBattleMons[gBattlerAttacker].status2 -= STATUS2_BIDE_TURN(1); @@ -2245,9 +2245,9 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 1; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_THAW: // move thawing + case CANCELER_THAW: // move thawing if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) { if (gBattleMoves[gCurrentMove].effect == EFFECT_THAW_HIT) @@ -2259,13 +2259,13 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 2; } - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancelerTracker++; break; - case CANCELLER_END: + case CANCELER_END: break; } - } while (gBattleStruct->atkCancellerTracker != CANCELLER_END && effect == 0); + } while (gBattleStruct->atkCancelerTracker != CANCELER_END && effect == 0); if (effect == 2) { From e472d277d247ccdf5f2789485e29e8efba7c35c3 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Sat, 15 Nov 2025 15:14:17 +0100 Subject: [PATCH 21/35] Fix light flickering when different types of light sprite are present (#8043) --- src/event_object_movement.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 0c17f5c445..8fdd7057b4 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2627,37 +2627,29 @@ void UpdateLightSprite(struct Sprite *sprite) return; } - // Note: Don't set window registers during hardware fade! - switch (sprite->sLightType) + if (sprite->sLightType == LIGHT_TYPE_BALL) { - default: - case LIGHT_TYPE_BALL: if (gPaletteFade.active) // if palette fade is active, don't flicker since the timer won't be updated { - Weather_SetBlendCoeffs(7, BASE_SHADOW_INTENSITY); sprite->invisible = FALSE; } else if (gPlayerAvatar.tileTransitionState) { - Weather_SetBlendCoeffs(7, BASE_SHADOW_INTENSITY); // As long as the second coefficient stays 12, shadows will not change sprite->invisible = FALSE; if (GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum) == OBJ_EVENT_PAL_TAG_LIGHT_2) LoadSpritePaletteInSlot(&sObjectEventSpritePalettes[FindObjectEventPaletteIndexByTag(OBJ_EVENT_PAL_TAG_LIGHT)], sprite->oam.paletteNum); } else if ((sprite->invisible = gTimeUpdateCounter & 1)) { - Weather_SetBlendCoeffs(7, BASE_SHADOW_INTENSITY); sprite->invisible = FALSE; if (GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum) == OBJ_EVENT_PAL_TAG_LIGHT_2) LoadSpritePaletteInSlot(&sObjectEventSpritePalettes[FindObjectEventPaletteIndexByTag(OBJ_EVENT_PAL_TAG_LIGHT)], sprite->oam.paletteNum); } - break; - case LIGHT_TYPE_PKMN_CENTER_SIGN: - case LIGHT_TYPE_POKE_MART_SIGN: - Weather_SetBlendCoeffs(12, BASE_SHADOW_INTENSITY); + } else { sprite->invisible = FALSE; - break; } + // Note: Don't set window registers during hardware fade! + Weather_SetBlendCoeffs(7, BASE_SHADOW_INTENSITY); } // Spawn a light at a map coordinate From e445160c92b2ca19d235eb9eea4fc9436f3bbc0c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:44:16 +0100 Subject: [PATCH 22/35] Adjust Canceler naming to contain only one l (#8258) --- asm/macros/battle_script.inc | 1 - docs/changelogs/1.11.x/1.11.0.md | 2 +- docs/changelogs/1.13.x/1.13.0.md | 4 +- docs/changelogs/1.6.x/1.6.0.md | 2 +- include/battle.h | 4 +- include/battle_util.h | 66 ++++----- include/constants/battle_script_commands.h | 2 +- src/battle_main.c | 2 +- src/battle_script_commands.c | 19 ++- src/battle_util.c | 165 ++++++++++----------- 10 files changed, 132 insertions(+), 135 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index e5da506a4d..754a5221f6 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1841,7 +1841,6 @@ .macro setmoveeffect effect:req sethword sMOVE_EFFECT, \effect - sethword sSAVED_MOVE_EFFECT, \effect .endm .macro sethword dst:req, value:req diff --git a/docs/changelogs/1.11.x/1.11.0.md b/docs/changelogs/1.11.x/1.11.0.md index 1b2e97db6e..98100cd81f 100644 --- a/docs/changelogs/1.11.x/1.11.0.md +++ b/docs/changelogs/1.11.x/1.11.0.md @@ -8,7 +8,7 @@ ## 🌋 *REFACTORS* 🌋 📜 = Uses a migration script. * Pursuit refactor by @PhallenTree in [#5707](https://github.com/rh-hideout/pokeemerald-expansion/pull/5707) -* Atk Canceller refactor / reorder / clean up by @AlexOn1ine in [#5885](https://github.com/rh-hideout/pokeemerald-expansion/pull/5885) +* Atk Canceler refactor / reorder / clean up by @AlexOn1ine in [#5885](https://github.com/rh-hideout/pokeemerald-expansion/pull/5885) * Battle Weather Refactor by @AlexOn1ine in [#5833](https://github.com/rh-hideout/pokeemerald-expansion/pull/5833) * Replace WEATHER_HAS_EFFECT with HasWeatherEffect by @AlexOn1ine in [#6069](https://github.com/rh-hideout/pokeemerald-expansion/pull/6069) * Cleaned up Trainer Slides, added automated Trainer Slide tests, add new Enemy Critical Hit Slide by @pkmnsnfrn and @AlexOn1ine, @hedara90, @AsparagusEduardo, @mrgriffin in [#6018](https://github.com/rh-hideout/pokeemerald-expansion/pull/6018) diff --git a/docs/changelogs/1.13.x/1.13.0.md b/docs/changelogs/1.13.x/1.13.0.md index 52babd0b43..4b81118c61 100644 --- a/docs/changelogs/1.13.x/1.13.0.md +++ b/docs/changelogs/1.13.x/1.13.0.md @@ -212,7 +212,7 @@ * Untangle `InitBtlControllers` functions by @AsparagusEduardo in [#6748](https://github.com/rh-hideout/pokeemerald-expansion/pull/6748) * Increase party action limit by @cawtds in [#7119](https://github.com/rh-hideout/pokeemerald-expansion/pull/7119) * Adds Gen5+ Encore config by @AlexOn1ine in [#7051](https://github.com/rh-hideout/pokeemerald-expansion/pull/7051) -* Attackcanceller clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) +* Attackcanceler clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) * Remove redundant move result flag checks by @AlexOn1ine in [#7223](https://github.com/rh-hideout/pokeemerald-expansion/pull/7223) * Use dedicated functions for Mud/Water Sport by @AlexOn1ine in [#7248](https://github.com/rh-hideout/pokeemerald-expansion/pull/7248) * Script clean up for Flame Burst and Costar by @AlexOn1ine in [#7264](https://github.com/rh-hideout/pokeemerald-expansion/pull/7264) @@ -400,7 +400,7 @@ * Add assumes for bag tests by @Bassoonian in [#7188](https://github.com/rh-hideout/pokeemerald-expansion/pull/7188) * Fixes Booster Energy timing activation + Clean up by @AlexOn1ine in [#7175](https://github.com/rh-hideout/pokeemerald-expansion/pull/7175) * Update .gitignore to add heal locations by @Bassoonian in [#7050](https://github.com/rh-hideout/pokeemerald-expansion/pull/7050) -* Attackcanceller clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) +* Attackcanceler clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) * Remove redundant move result flag checks by @AlexOn1ine in [#7223](https://github.com/rh-hideout/pokeemerald-expansion/pull/7223) * Add P_ASK_MOVE_CONFIRMATION by @pkmnsnfrn in [#7132](https://github.com/rh-hideout/pokeemerald-expansion/pull/7132) - This will change the behavior of the game for players, as a new default is being set. diff --git a/docs/changelogs/1.6.x/1.6.0.md b/docs/changelogs/1.6.x/1.6.0.md index f215ffb673..909ce25904 100644 --- a/docs/changelogs/1.6.x/1.6.0.md +++ b/docs/changelogs/1.6.x/1.6.0.md @@ -128,7 +128,7 @@ * Unified multi-strike move flags by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/3126 * Some `gActiveBattler` fixes by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/3259 * ***Got rid of the `gActiveBattler` variable by @DizzyEggg*** in https://github.com/rh-hideout/pokeemerald-expansion/pull/3262 -* Scale Shot now uses Multi-hit Moves' canceller by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/3290 +* Scale Shot now uses Multi-hit Moves' canceler by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/3290 * Callnative functions now take ScriptContext arguments to allow using macros with .byte fields similar to vanilla battle script functions by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/3294 * Converted some `VARIOUS`s to `callnative`s by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/3269 * Refactored battle terrain text string tables and removed `EFFECT_REMOVE_TERRAIN` by @LOuroboros in https://github.com/rh-hideout/pokeemerald-expansion/pull/3247 diff --git a/include/battle.h b/include/battle.h index 05328fa845..6c93e91d66 100755 --- a/include/battle.h +++ b/include/battle.h @@ -693,7 +693,7 @@ struct BattleStruct u8 fickleBeamBoosted:1; u8 poisonPuppeteerConfusion:1; u16 startingStatusTimer; - u8 atkCancellerTracker; + u8 atkCancelerTracker; struct BattleTvMovePoints tvMovePoints; struct BattleTv tv; u8 AI_monToSwitchIntoId[MAX_BATTLERS_COUNT]; @@ -904,7 +904,7 @@ struct BattleScripting u8 specialTrainerBattleType; bool8 monCaught; s32 savedDmg; - u16 savedMoveEffect; // For moves hitting multiple targets. + u16 unused_0x2c; u16 moveEffect; u16 multihitMoveEffect; u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. diff --git a/include/battle_util.h b/include/battle_util.h index fc88ee02c6..c88f4723dd 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -106,35 +106,35 @@ struct TypePower enum MoveSuccessOrder { - CANCELLER_FLAGS, - CANCELLER_STANCE_CHANGE_1, - CANCELLER_SKY_DROP, - CANCELLER_RECHARGE, - CANCELLER_ASLEEP_OR_FROZEN, - CANCELLER_OBEDIENCE, - CANCELLER_TRUANT, - CANCELLER_FLINCH, - CANCELLER_DISABLED, - CANCELLER_VOLATILE_BLOCKED, - CANCELLER_TAUNTED, - CANCELLER_IMPRISONED, - CANCELLER_CONFUSED, - CANCELLER_PARALYSED, - CANCELLER_INFATUATION, - CANCELLER_BIDE, - CANCELLER_THAW, - CANCELLER_STANCE_CHANGE_2, - CANCELLER_CHOICE_LOCK, - CANCELLER_WEATHER_PRIMAL, - CANCELLER_DYNAMAX_BLOCKED, - CANCELLER_POWDER_STATUS, - CANCELLER_PROTEAN, - CANCELLER_PSYCHIC_TERRAIN, - CANCELLER_EXPLODING_DAMP, - CANCELLER_MULTIHIT_MOVES, - CANCELLER_Z_MOVES, - CANCELLER_MULTI_TARGET_MOVES, - CANCELLER_END, + CANCELER_FLAGS, + CANCELER_STANCE_CHANGE_1, + CANCELER_SKY_DROP, + CANCELER_RECHARGE, + CANCELER_ASLEEP_OR_FROZEN, + CANCELER_OBEDIENCE, + CANCELER_TRUANT, + CANCELER_FLINCH, + CANCELER_DISABLED, + CANCELER_VOLATILE_BLOCKED, + CANCELER_TAUNTED, + CANCELER_IMPRISONED, + CANCELER_CONFUSED, + CANCELER_PARALYSED, + CANCELER_INFATUATION, + CANCELER_BIDE, + CANCELER_THAW, + CANCELER_STANCE_CHANGE_2, + CANCELER_CHOICE_LOCK, + CANCELER_WEATHER_PRIMAL, + CANCELER_DYNAMAX_BLOCKED, + CANCELER_POWDER_STATUS, + CANCELER_PROTEAN, + CANCELER_PSYCHIC_TERRAIN, + CANCELER_EXPLODING_DAMP, + CANCELER_MULTIHIT_MOVES, + CANCELER_Z_MOVES, + CANCELER_MULTI_TARGET_MOVES, + CANCELER_END, }; enum Obedience @@ -147,7 +147,7 @@ enum Obedience DISOBEYS_RANDOM_MOVE, }; -enum MoveCanceller +enum MoveCanceler { MOVE_STEP_SUCCESS, MOVE_STEP_BREAK, @@ -186,7 +186,7 @@ enum SleepClauseBlock enum SkyDropState { SKY_DROP_IGNORE, - SKY_DROP_ATTACKCANCELLER_CHECK, + SKY_DROP_ATTACKCANCELER_CHECK, SKY_DROP_GRAVITY_ON_AIRBORNE, SKY_DROP_CANCEL_MULTI_TURN_MOVES, SKY_DROP_STATUS_YAWN, @@ -239,8 +239,8 @@ bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck); u32 DoEndTurnEffects(void); bool32 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); -enum MoveCanceller AtkCanceller_MoveSuccessOrder(void); -void SetAtkCancellerForCalledMove(void); +enum MoveCanceler AtkCanceler_MoveSuccessOrder(void); +void SetAtkCancelerForCalledMove(void); bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2); bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, u32 ability); bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag); diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 94d2a2bd48..2cadf215af 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -31,7 +31,7 @@ #define sSPECIAL_TRAINER_BATTLE_TYPE (gBattleScripting + 0x26) // specialTrainerBattleType #define sMON_CAUGHT (gBattleScripting + 0x27) // monCaught #define sSAVED_DMG (gBattleScripting + 0x28) // savedDmg -#define sSAVED_MOVE_EFFECT (gBattleScripting + 0x2C) // savedMoveEffect +#define sUNUSED_0x2C (gBattleScripting + 0x2C) // unused_0x2c #define sMOVE_EFFECT (gBattleScripting + 0x2E) // moveEffect #define sMULTIHIT_EFFECT (gBattleScripting + 0x30) // multihitMoveEffect #define sILLUSION_NICK_HACK (gBattleScripting + 0x32) // illusionNickHack diff --git a/src/battle_main.c b/src/battle_main.c index 702550c22d..5620b584b6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5152,7 +5152,7 @@ static void TurnValuesCleanUp(bool8 var0) gSideTimers[B_SIDE_PLAYER].followmeTimer = 0; gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0; - gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceller + gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceler ClearPursuitValues(); ClearDamageCalcResults(); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dbf0b0025f..4c2ac13178 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1097,7 +1097,7 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (AtkCanceller_MoveSuccessOrder() != MOVE_STEP_SUCCESS) + if (AtkCanceler_MoveSuccessOrder() != MOVE_STEP_SUCCESS) return; if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF @@ -1162,7 +1162,7 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_FailedFromAtkString; if (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); return; } @@ -1175,7 +1175,7 @@ static void Cmd_attackcanceler(void) // Edge case for bouncing a powder move against a grass type pokemon. ClearDamageCalcResults(); - SetAtkCancellerForCalledMove(); + SetAtkCancelerForCalledMove(); gEffectBattler = gBattlerTarget; if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE)) { @@ -1209,7 +1209,7 @@ static void Cmd_attackcanceler(void) if (gBattleStruct->bouncedMoveIsUsed) { ClearDamageCalcResults(); - SetAtkCancellerForCalledMove(); // Edge case for bouncing a powder move against a grass type pokemon. + SetAtkCancelerForCalledMove(); // Edge case for bouncing a powder move against a grass type pokemon. BattleScriptCall(BattleScript_MagicBounce); gBattlerAbility = battler; return; @@ -1262,7 +1262,7 @@ static void Cmd_attackcanceler(void) { if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; gLastLandedMoves[gBattlerTarget] = 0; gLastHitByType[gBattlerTarget] = 0; @@ -1824,7 +1824,7 @@ static void Cmd_typecalc(void) { CMD_ARGS(); - if (!IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove))) // Handled in CANCELLER_MULTI_TARGET_MOVES for Spread Moves + if (!IsSpreadMove(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove))) // Handled in CANCELER_MULTI_TARGET_MOVES for Spread Moves { struct DamageContext ctx = {0}; ctx.battlerAtk = gBattlerAttacker; @@ -6433,7 +6433,6 @@ static void Cmd_moveend(void) gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = nextTarget; // Fix for moxie spread moves gBattleScripting.moveendState = 0; MoveValuesCleanUp(); - gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION // Edge case for Explosion not changing targets || moveEffect == EFFECT_SYNCHRONOISE) // So we don't go back to the Synchronoise script @@ -8504,9 +8503,9 @@ static void Cmd_hidepartystatussummary(void) static void ResetValuesForCalledMove(void) { if (gBattlerByTurnOrder[gCurrentTurnActionNumber] != gBattlerAttacker) - gBattleStruct->atkCancellerTracker = 0; + gBattleStruct->atkCancelerTracker = 0; else - SetAtkCancellerForCalledMove(); + SetAtkCancelerForCalledMove(); gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker); @@ -11526,7 +11525,7 @@ static void Cmd_trysetencore(void) // Redirection such as Follow Me is already covered in HandleAction_UseMove of battle_util.c if (gDisableStructs[gBattlerTarget].encoredMove != GetChosenMoveFromPosition(gBattlerTarget)) gBattleStruct->moveTarget[gBattlerTarget] = SetRandomTarget(gBattlerTarget); - + // Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn. if (HasBattlerActedThisTurn(gBattlerTarget)) gDisableStructs[gBattlerTarget].encoreTimer = 4; diff --git a/src/battle_util.c b/src/battle_util.c index 76f6d36f6d..d4fb0d38a6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -390,12 +390,11 @@ void HandleAction_UseMove(void) return; } - gBattleStruct->atkCancellerTracker = 0; + gBattleStruct->atkCancelerTracker = 0; ClearDamageCalcResults(); gMultiHitCounter = 0; gBattleScripting.savedDmg = 0; gBattleCommunication[MISS_TYPE] = 0; - gBattleScripting.savedMoveEffect = 0; gCurrMovePos = gChosenMovePos = gBattleStruct->chosenMovePositions[gBattlerAttacker]; // choose move @@ -1077,7 +1076,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) // Set confused status gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; - if (skyDropState == SKY_DROP_ATTACKCANCELLER_CHECK) + if (skyDropState == SKY_DROP_ATTACKCANCELER_CHECK) { gBattleStruct->skyDropTargets[battler] = SKY_DROP_RELEASED_TARGET; } @@ -1893,13 +1892,13 @@ static inline bool32 TryActivatePowderStatus(u32 move) return FALSE; } -void SetAtkCancellerForCalledMove(void) +void SetAtkCancelerForCalledMove(void) { - gBattleStruct->atkCancellerTracker = CANCELLER_VOLATILE_BLOCKED; + gBattleStruct->atkCancelerTracker = CANCELER_VOLATILE_BLOCKED; gBattleStruct->isAtkCancelerForCalledMove = TRUE; } -static enum MoveCanceller CancellerFlags(void) +static enum MoveCanceler CancelerFlags(void) { gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE; gBattleMons[gBattlerAttacker].volatiles.grudge = FALSE; @@ -1907,14 +1906,14 @@ static enum MoveCanceller CancellerFlags(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerStanceChangeOne(void) +static enum MoveCanceler CancelerStanceChangeOne(void) { if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) return MOVE_STEP_BREAK; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerSkyDrop(void) +static enum MoveCanceler CancelerSkyDrop(void) { // If Pokemon is being held in Sky Drop if (gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_SKY_DROP) @@ -1926,11 +1925,11 @@ static enum MoveCanceller CancellerSkyDrop(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerRecharge(void) +static enum MoveCanceler CancelerRecharge(void) { if (gDisableStructs[gBattlerAttacker].rechargeTimer > 0) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -1938,7 +1937,7 @@ static enum MoveCanceller CancellerRecharge(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerAsleepOrFrozen(void) +static enum MoveCanceler CancelerAsleepOrFrozen(void) { if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) { @@ -2003,7 +2002,7 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerObedience(void) +static enum MoveCanceler CancelerObedience(void) { enum Obedience obedienceResult = GetAttackerObedienceForAction(); if (!(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves @@ -2048,7 +2047,7 @@ static enum MoveCanceller CancellerObedience(void) break; case DISOBEYS_RANDOM_MOVE: gCalledMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; - SetAtkCancellerForCalledMove(); + SetAtkCancelerForCalledMove(); gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gHitMarker |= HITMARKER_OBEYS; @@ -2060,11 +2059,11 @@ static enum MoveCanceller CancellerObedience(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerTruant(void) +static enum MoveCanceler CancelerTruant(void) { if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING; gBattlerAbility = gBattlerAttacker; @@ -2075,12 +2074,12 @@ static enum MoveCanceller CancellerTruant(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerFlinch(void) +static enum MoveCanceler CancelerFlinch(void) { if (gBattleMons[gBattlerAttacker].volatiles.flinched) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2088,13 +2087,13 @@ static enum MoveCanceller CancellerFlinch(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerDisabled(void) +static enum MoveCanceler CancelerDisabled(void) { if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2102,13 +2101,13 @@ static enum MoveCanceller CancellerDisabled(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerVolatileBlocked(void) +static enum MoveCanceler CancelerVolatileBlocked(void) { if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gBattleMons[gBattlerAttacker].volatiles.healBlock && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2117,7 +2116,7 @@ static enum MoveCanceller CancellerVolatileBlocked(void) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; gBattleScripting.battler = gBattlerAttacker; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2125,7 +2124,7 @@ static enum MoveCanceller CancellerVolatileBlocked(void) else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer > gBattleTurnCounter && IsSoundMove(gCurrentMove)) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2133,12 +2132,12 @@ static enum MoveCanceller CancellerVolatileBlocked(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerTaunted(void) +static enum MoveCanceler CancelerTaunted(void) { if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IsBattleMoveStatus(gCurrentMove)) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2146,12 +2145,12 @@ static enum MoveCanceller CancellerTaunted(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerImprisoned(void) +static enum MoveCanceler CancelerImprisoned(void) { if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove)) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2159,7 +2158,7 @@ static enum MoveCanceller CancellerImprisoned(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerConfused(void) +static enum MoveCanceler CancelerConfused(void) { if (gBattleStruct->isAtkCancelerForCalledMove) return MOVE_STEP_SUCCESS; @@ -2203,7 +2202,7 @@ static enum MoveCanceller CancellerConfused(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerParalysed(void) +static enum MoveCanceler CancelerParalysed(void) { if (!gBattleStruct->isAtkCancelerForCalledMove && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) @@ -2212,7 +2211,7 @@ static enum MoveCanceller CancellerParalysed(void) { gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; // This is removed in FRLG and Emerald for some reason - //CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + //CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2220,7 +2219,7 @@ static enum MoveCanceller CancellerParalysed(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerInfatuation(void) +static enum MoveCanceler CancelerInfatuation(void) { if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].volatiles.infatuation) { @@ -2234,7 +2233,7 @@ static enum MoveCanceller CancellerInfatuation(void) BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; } return MOVE_STEP_BREAK; @@ -2242,7 +2241,7 @@ static enum MoveCanceller CancellerInfatuation(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerBide(void) +static enum MoveCanceler CancelerBide(void) { if (gBattleMons[gBattlerAttacker].volatiles.bideTurns) { @@ -2272,7 +2271,7 @@ static enum MoveCanceller CancellerBide(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerThaw(void) +static enum MoveCanceler CancelerThaw(void) { if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE) { @@ -2297,14 +2296,14 @@ static enum MoveCanceller CancellerThaw(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerStanceChangeTwo(void) +static enum MoveCanceler CancelerStanceChangeTwo(void) { if (B_STANCE_CHANGE_FAIL >= GEN_7 && !gBattleStruct->isAtkCancelerForCalledMove && TryFormChangeBeforeMove()) return MOVE_STEP_BREAK; return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerChoiceLock(void) +static enum MoveCanceler CancelerChoiceLock(void) { u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker]; enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); @@ -2327,9 +2326,9 @@ static enum MoveCanceller CancellerChoiceLock(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerWeatherPrimal(void) +static enum MoveCanceler CancelerWeatherPrimal(void) { - enum MoveCanceller effect = MOVE_STEP_SUCCESS; + enum MoveCanceler effect = MOVE_STEP_SUCCESS; if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0) { u32 moveType = GetBattleMoveType(gCurrentMove); @@ -2347,7 +2346,7 @@ static enum MoveCanceller CancellerWeatherPrimal(void) { gBattleScripting.moveEffect = MOVE_EFFECT_NONE; gProtectStructs[gBattlerAttacker].chargingTurn = FALSE; - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; BattleScriptCall(BattleScript_PrimalWeatherBlocksMove); } @@ -2355,7 +2354,7 @@ static enum MoveCanceller CancellerWeatherPrimal(void) return effect; } -static enum MoveCanceller CancellerDynamaxBlocked(void) +static enum MoveCanceler CancelerDynamaxBlocked(void) { if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove)) { @@ -2366,7 +2365,7 @@ static enum MoveCanceller CancellerDynamaxBlocked(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerPowderStatus(void) +static enum MoveCanceler CancelerPowderStatus(void) { if (TryActivatePowderStatus(gCurrentMove)) { @@ -2383,7 +2382,7 @@ static enum MoveCanceller CancellerPowderStatus(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerProtean(void) +static enum MoveCanceler CancelerProtean(void) { u32 moveType = GetBattleMoveType(gCurrentMove); if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType)) @@ -2400,7 +2399,7 @@ static enum MoveCanceller CancellerProtean(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerPsychicTerrain(void) +static enum MoveCanceler CancelerPsychicTerrain(void) { if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_PSYCHIC_TERRAIN) && GetChosenMovePriority(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) > 0 @@ -2408,7 +2407,7 @@ static enum MoveCanceller CancellerPsychicTerrain(void) && GetMoveTarget(gCurrentMove) != MOVE_TARGET_OPPONENTS_FIELD && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; return MOVE_STEP_BREAK; @@ -2416,7 +2415,7 @@ static enum MoveCanceller CancellerPsychicTerrain(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerExplodingDamp(void) +static enum MoveCanceler CancelerExplodingDamp(void) { u32 dampBattler = IsAbilityOnField(ABILITY_DAMP); if (dampBattler && IsMoveDampBanned(gCurrentMove)) @@ -2429,7 +2428,7 @@ static enum MoveCanceller CancellerExplodingDamp(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerMultihitMoves(void) +static enum MoveCanceler CancelerMultihitMoves(void) { if (GetMoveEffect(gCurrentMove) == EFFECT_MULTI_HIT) { @@ -2501,7 +2500,7 @@ static enum MoveCanceller CancellerMultihitMoves(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerZMoves(void) +static enum MoveCanceler CancelerZMoves(void) { if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) { @@ -2533,7 +2532,7 @@ static enum MoveCanceller CancellerZMoves(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller CancellerMultiTargetMoves(void) +static enum MoveCanceler CancelerMultiTargetMoves(void) { u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); @@ -2581,46 +2580,46 @@ static enum MoveCanceller CancellerMultiTargetMoves(void) return MOVE_STEP_SUCCESS; } -static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(void) = +static enum MoveCanceler (*const sMoveSuccessOrderCancelers[])(void) = { - [CANCELLER_FLAGS] = CancellerFlags, - [CANCELLER_STANCE_CHANGE_1] = CancellerStanceChangeOne, - [CANCELLER_SKY_DROP] = CancellerSkyDrop, - [CANCELLER_RECHARGE] = CancellerRecharge, - [CANCELLER_ASLEEP_OR_FROZEN] = CancellerAsleepOrFrozen, - [CANCELLER_OBEDIENCE] = CancellerObedience, - [CANCELLER_TRUANT] = CancellerTruant, - [CANCELLER_FLINCH] = CancellerFlinch, - [CANCELLER_INFATUATION] = CancellerInfatuation, - [CANCELLER_DISABLED] = CancellerDisabled, - [CANCELLER_VOLATILE_BLOCKED] = CancellerVolatileBlocked, - [CANCELLER_TAUNTED] = CancellerTaunted, - [CANCELLER_IMPRISONED] = CancellerImprisoned, - [CANCELLER_CONFUSED] = CancellerConfused, - [CANCELLER_PARALYSED] = CancellerParalysed, - [CANCELLER_BIDE] = CancellerBide, - [CANCELLER_THAW] = CancellerThaw, - [CANCELLER_STANCE_CHANGE_2] = CancellerStanceChangeTwo, - [CANCELLER_CHOICE_LOCK] = CancellerChoiceLock, - [CANCELLER_WEATHER_PRIMAL] = CancellerWeatherPrimal, - [CANCELLER_DYNAMAX_BLOCKED] = CancellerDynamaxBlocked, - [CANCELLER_POWDER_STATUS] = CancellerPowderStatus, - [CANCELLER_PROTEAN] = CancellerProtean, - [CANCELLER_PSYCHIC_TERRAIN] = CancellerPsychicTerrain, - [CANCELLER_EXPLODING_DAMP] = CancellerExplodingDamp, - [CANCELLER_MULTIHIT_MOVES] = CancellerMultihitMoves, - [CANCELLER_Z_MOVES] = CancellerZMoves, - [CANCELLER_MULTI_TARGET_MOVES] = CancellerMultiTargetMoves, + [CANCELER_FLAGS] = CancelerFlags, + [CANCELER_STANCE_CHANGE_1] = CancelerStanceChangeOne, + [CANCELER_SKY_DROP] = CancelerSkyDrop, + [CANCELER_RECHARGE] = CancelerRecharge, + [CANCELER_ASLEEP_OR_FROZEN] = CancelerAsleepOrFrozen, + [CANCELER_OBEDIENCE] = CancelerObedience, + [CANCELER_TRUANT] = CancelerTruant, + [CANCELER_FLINCH] = CancelerFlinch, + [CANCELER_INFATUATION] = CancelerInfatuation, + [CANCELER_DISABLED] = CancelerDisabled, + [CANCELER_VOLATILE_BLOCKED] = CancelerVolatileBlocked, + [CANCELER_TAUNTED] = CancelerTaunted, + [CANCELER_IMPRISONED] = CancelerImprisoned, + [CANCELER_CONFUSED] = CancelerConfused, + [CANCELER_PARALYSED] = CancelerParalysed, + [CANCELER_BIDE] = CancelerBide, + [CANCELER_THAW] = CancelerThaw, + [CANCELER_STANCE_CHANGE_2] = CancelerStanceChangeTwo, + [CANCELER_CHOICE_LOCK] = CancelerChoiceLock, + [CANCELER_WEATHER_PRIMAL] = CancelerWeatherPrimal, + [CANCELER_DYNAMAX_BLOCKED] = CancelerDynamaxBlocked, + [CANCELER_POWDER_STATUS] = CancelerPowderStatus, + [CANCELER_PROTEAN] = CancelerProtean, + [CANCELER_PSYCHIC_TERRAIN] = CancelerPsychicTerrain, + [CANCELER_EXPLODING_DAMP] = CancelerExplodingDamp, + [CANCELER_MULTIHIT_MOVES] = CancelerMultihitMoves, + [CANCELER_Z_MOVES] = CancelerZMoves, + [CANCELER_MULTI_TARGET_MOVES] = CancelerMultiTargetMoves, }; -enum MoveCanceller AtkCanceller_MoveSuccessOrder(void) +enum MoveCanceler AtkCanceler_MoveSuccessOrder(void) { - enum MoveCanceller effect = MOVE_STEP_SUCCESS; + enum MoveCanceler effect = MOVE_STEP_SUCCESS; - while (gBattleStruct->atkCancellerTracker < CANCELLER_END && effect == MOVE_STEP_SUCCESS) + while (gBattleStruct->atkCancelerTracker < CANCELER_END && effect == MOVE_STEP_SUCCESS) { - effect = sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker](); - gBattleStruct->atkCancellerTracker++; + effect = sMoveSuccessOrderCancelers[gBattleStruct->atkCancelerTracker](); + gBattleStruct->atkCancelerTracker++; } if (effect == MOVE_STEP_REMOVES_STATUS) @@ -3061,7 +3060,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) { 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 + CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected battleScriptBlocksMove = BattleScript_DoesntAffectTargetAtkString; } From f8e7a2db5f88b4d77f365a2263b3286457bef264 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 16 Nov 2025 11:33:16 +0100 Subject: [PATCH 23/35] Fix incorrect UBFIX checks (#2206) Co-authored-by: Hedara --- data/maps/LilycoveCity_ContestLobby/scripts.inc | 2 +- data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc | 2 +- data/maps/SkyPillar_2F/scripts.inc | 2 +- data/maps/SkyPillar_4F/scripts.inc | 2 +- data/scripts/cave_hole.inc | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/data/maps/LilycoveCity_ContestLobby/scripts.inc b/data/maps/LilycoveCity_ContestLobby/scripts.inc index 660b87f846..41db53c954 100644 --- a/data/maps/LilycoveCity_ContestLobby/scripts.inc +++ b/data/maps/LilycoveCity_ContestLobby/scripts.inc @@ -349,7 +349,7 @@ LilycoveCity_ContestLobby_EventScript_SetMasterContestType:: @ Functionally unused LilycoveCity_ContestLobby_EventScript_SetDebug:: setflag FLAG_HIDE_LILYCOVE_MUSEUM_CURATOR -#if UBFIX +#ifdef UBFIX setvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 #else copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1, warn=FALSE diff --git a/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc b/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc index 8f08e01808..1ac10a4016 100644 --- a/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc +++ b/data/maps/LilycoveCity_LilycoveMuseum_2F/scripts.inc @@ -76,7 +76,7 @@ LilycoveCity_LilycoveMuseum_2F_EventScript_ShowExhibitHall:: applymovement LOCALID_PLAYER, LilycoveCity_LilycoveMuseum_2F_Movement_PlayerWalkInPlaceLeft waitmovement 0 msgbox LilycoveCity_LilycoveMuseum_2F_Text_PleaseObtainPaintingsForExhibit, MSGBOX_SIGN -#if UBFIX +#ifdef UBFIX setvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1 #else copyvar VAR_LILYCOVE_MUSEUM_2F_STATE, 1, warn=FALSE diff --git a/data/maps/SkyPillar_2F/scripts.inc b/data/maps/SkyPillar_2F/scripts.inc index 9a75a4d951..a530e01113 100644 --- a/data/maps/SkyPillar_2F/scripts.inc +++ b/data/maps/SkyPillar_2F/scripts.inc @@ -6,7 +6,7 @@ SkyPillar_2F_MapScripts:: SkyPillar_2F_OnTransition: call_if_lt VAR_SKY_PILLAR_STATE, 2, SkyPillar_2F_EventScript_CleanFloor -#if UBFIX +#ifdef UBFIX setvar VAR_ICE_STEP_COUNT, 1 #else copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE diff --git a/data/maps/SkyPillar_4F/scripts.inc b/data/maps/SkyPillar_4F/scripts.inc index b3f6020105..603144f04b 100644 --- a/data/maps/SkyPillar_4F/scripts.inc +++ b/data/maps/SkyPillar_4F/scripts.inc @@ -6,7 +6,7 @@ SkyPillar_4F_MapScripts:: SkyPillar_4F_OnTransition: call_if_lt VAR_SKY_PILLAR_STATE, 2, SkyPillar_4F_EventScript_CleanFloor -#if UBFIX +#ifdef UBFIX setvar VAR_ICE_STEP_COUNT, 1 #else copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE diff --git a/data/scripts/cave_hole.inc b/data/scripts/cave_hole.inc index ca2a8404be..e6f9084705 100644 --- a/data/scripts/cave_hole.inc +++ b/data/scripts/cave_hole.inc @@ -3,7 +3,7 @@ CaveHole_CheckFallDownHole: .2byte 0 CaveHole_FixCrackedGround: -#if UBFIX +#ifdef UBFIX setvar VAR_ICE_STEP_COUNT, 1 #else copyvar VAR_ICE_STEP_COUNT, 1, warn=FALSE From 1deeafc0b8e6c1c492799fa8040f26d1e4b799f8 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:08:00 +0100 Subject: [PATCH 24/35] Fix wrongly renamed logs (#8264) --- docs/changelogs/1.11.x/1.11.0.md | 2 +- docs/changelogs/1.13.x/1.13.0.md | 4 ++-- docs/changelogs/1.6.x/1.6.0.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/changelogs/1.11.x/1.11.0.md b/docs/changelogs/1.11.x/1.11.0.md index 98100cd81f..1b2e97db6e 100644 --- a/docs/changelogs/1.11.x/1.11.0.md +++ b/docs/changelogs/1.11.x/1.11.0.md @@ -8,7 +8,7 @@ ## 🌋 *REFACTORS* 🌋 📜 = Uses a migration script. * Pursuit refactor by @PhallenTree in [#5707](https://github.com/rh-hideout/pokeemerald-expansion/pull/5707) -* Atk Canceler refactor / reorder / clean up by @AlexOn1ine in [#5885](https://github.com/rh-hideout/pokeemerald-expansion/pull/5885) +* Atk Canceller refactor / reorder / clean up by @AlexOn1ine in [#5885](https://github.com/rh-hideout/pokeemerald-expansion/pull/5885) * Battle Weather Refactor by @AlexOn1ine in [#5833](https://github.com/rh-hideout/pokeemerald-expansion/pull/5833) * Replace WEATHER_HAS_EFFECT with HasWeatherEffect by @AlexOn1ine in [#6069](https://github.com/rh-hideout/pokeemerald-expansion/pull/6069) * Cleaned up Trainer Slides, added automated Trainer Slide tests, add new Enemy Critical Hit Slide by @pkmnsnfrn and @AlexOn1ine, @hedara90, @AsparagusEduardo, @mrgriffin in [#6018](https://github.com/rh-hideout/pokeemerald-expansion/pull/6018) diff --git a/docs/changelogs/1.13.x/1.13.0.md b/docs/changelogs/1.13.x/1.13.0.md index 4b81118c61..52babd0b43 100644 --- a/docs/changelogs/1.13.x/1.13.0.md +++ b/docs/changelogs/1.13.x/1.13.0.md @@ -212,7 +212,7 @@ * Untangle `InitBtlControllers` functions by @AsparagusEduardo in [#6748](https://github.com/rh-hideout/pokeemerald-expansion/pull/6748) * Increase party action limit by @cawtds in [#7119](https://github.com/rh-hideout/pokeemerald-expansion/pull/7119) * Adds Gen5+ Encore config by @AlexOn1ine in [#7051](https://github.com/rh-hideout/pokeemerald-expansion/pull/7051) -* Attackcanceler clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) +* Attackcanceller clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) * Remove redundant move result flag checks by @AlexOn1ine in [#7223](https://github.com/rh-hideout/pokeemerald-expansion/pull/7223) * Use dedicated functions for Mud/Water Sport by @AlexOn1ine in [#7248](https://github.com/rh-hideout/pokeemerald-expansion/pull/7248) * Script clean up for Flame Burst and Costar by @AlexOn1ine in [#7264](https://github.com/rh-hideout/pokeemerald-expansion/pull/7264) @@ -400,7 +400,7 @@ * Add assumes for bag tests by @Bassoonian in [#7188](https://github.com/rh-hideout/pokeemerald-expansion/pull/7188) * Fixes Booster Energy timing activation + Clean up by @AlexOn1ine in [#7175](https://github.com/rh-hideout/pokeemerald-expansion/pull/7175) * Update .gitignore to add heal locations by @Bassoonian in [#7050](https://github.com/rh-hideout/pokeemerald-expansion/pull/7050) -* Attackcanceler clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) +* Attackcanceller clean up by @AlexOn1ine in [#7210](https://github.com/rh-hideout/pokeemerald-expansion/pull/7210) * Remove redundant move result flag checks by @AlexOn1ine in [#7223](https://github.com/rh-hideout/pokeemerald-expansion/pull/7223) * Add P_ASK_MOVE_CONFIRMATION by @pkmnsnfrn in [#7132](https://github.com/rh-hideout/pokeemerald-expansion/pull/7132) - This will change the behavior of the game for players, as a new default is being set. diff --git a/docs/changelogs/1.6.x/1.6.0.md b/docs/changelogs/1.6.x/1.6.0.md index 909ce25904..f215ffb673 100644 --- a/docs/changelogs/1.6.x/1.6.0.md +++ b/docs/changelogs/1.6.x/1.6.0.md @@ -128,7 +128,7 @@ * Unified multi-strike move flags by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/3126 * Some `gActiveBattler` fixes by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/3259 * ***Got rid of the `gActiveBattler` variable by @DizzyEggg*** in https://github.com/rh-hideout/pokeemerald-expansion/pull/3262 -* Scale Shot now uses Multi-hit Moves' canceler by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/3290 +* Scale Shot now uses Multi-hit Moves' canceller by @AlexOn1ine in https://github.com/rh-hideout/pokeemerald-expansion/pull/3290 * Callnative functions now take ScriptContext arguments to allow using macros with .byte fields similar to vanilla battle script functions by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/3294 * Converted some `VARIOUS`s to `callnative`s by @AsparagusEduardo in https://github.com/rh-hideout/pokeemerald-expansion/pull/3269 * Refactored battle terrain text string tables and removed `EFFECT_REMOVE_TERRAIN` by @LOuroboros in https://github.com/rh-hideout/pokeemerald-expansion/pull/3247 From 6cf13051785567d02bee45a5e5425963ebb023d2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 16 Nov 2025 12:23:38 -0300 Subject: [PATCH 25/35] Yet more tests (#8228) Co-authored-by: hedara90 <90hedara@gmail.com> --- test/battle/ability/aura_break.c | 154 +++++++++++------------ test/battle/ability/dark_aura.c | 106 +++++++++++++++- test/battle/ability/fairy_aura.c | 106 +++++++++++++++- test/battle/ability/flare_boost.c | 19 ++- test/battle/ability/toxic_boost.c | 21 +++- test/battle/move_effect/two_typed_move.c | 10 +- 6 files changed, 334 insertions(+), 82 deletions(-) diff --git a/test/battle/ability/aura_break.c b/test/battle/ability/aura_break.c index 389ab327b1..10c248c87d 100644 --- a/test/battle/ability/aura_break.c +++ b/test/battle/ability/aura_break.c @@ -5,62 +5,62 @@ DOUBLE_BATTLE_TEST("Aura Break inverts Fairy Aura's effect") { s16 damage[3]; - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); SWITCH(playerRight, 2); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); SWITCH(opponentRight, 2); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[0]); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); } + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); SWITCH(playerRight, 2); } + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft); SWITCH(opponentRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[1]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); - } THEN { - EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[1]); - EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[2]); - } + } THEN { + EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[1]); + EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[2]); + } } DOUBLE_BATTLE_TEST("Aura Break inverts Dark Aura's effect") { s16 damage[3]; - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); } - TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); SWITCH(playerRight, 2); } - TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); SWITCH(opponentRight, 2); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[0]); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); } + TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); SWITCH(playerRight, 2); } + TURN { MOVE(playerLeft, MOVE_BITE, target:opponentLeft); SWITCH(opponentRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[1]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); - } THEN { - EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[1]); - EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[2]); - } + } THEN { + EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[1]); + EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[2]); + } } DOUBLE_BATTLE_TEST("Aura Break ignores Mold Breaker abilities") @@ -73,43 +73,43 @@ DOUBLE_BATTLE_TEST("Aura Break ignores Mold Breaker abilities") PARAMETRIZE { species = SPECIES_ZEKROM, ability = ABILITY_TERAVOLT; } PARAMETRIZE { species = SPECIES_RESHIRAM, ability = ABILITY_TURBOBLAZE; } - GIVEN { - PLAYER(species) { Ability(ability); Level(50); } - PLAYER(SPECIES_WOBBUFFET); - PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } - PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } - } WHEN { - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); } - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } - TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); SWITCH(opponentRight, 2); } - TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[0]); + GIVEN { + PLAYER(species) { Ability(ability); Level(50); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } + PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZYGARDE_50) { Ability(ABILITY_AURA_BREAK); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); } + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); } + TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); } + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } + TURN { MOVE(playerLeft, MOVE_BITE, target: opponentLeft); SWITCH(playerRight, 2); SWITCH(opponentRight, 2); } + TURN { MOVE(playerLeft, MOVE_PLAY_ROUGH, target: opponentLeft); SWITCH(playerRight, 3); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[1]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[2]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[3]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[3]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[4]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[4]); - ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); - HP_BAR(opponentLeft, captureDamage: &damage[5]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[5]); } THEN { - EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[2]); - EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[4]); - EXPECT_MUL_EQ(damage[1], UQ_4_12(1.33), damage[3]); - EXPECT_MUL_EQ(damage[1], UQ_4_12(0.75), damage[5]); - } + EXPECT_MUL_EQ(damage[0], UQ_4_12(1.33), damage[2]); + EXPECT_MUL_EQ(damage[0], UQ_4_12(0.75), damage[4]); + EXPECT_MUL_EQ(damage[1], UQ_4_12(1.33), damage[3]); + EXPECT_MUL_EQ(damage[1], UQ_4_12(0.75), damage[5]); + } } diff --git a/test/battle/ability/dark_aura.c b/test/battle/ability/dark_aura.c index eb1bf05246..1371975a28 100644 --- a/test/battle/ability/dark_aura.c +++ b/test/battle/ability/dark_aura.c @@ -1,4 +1,108 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Dark Aura (Ability) test titles") +DOUBLE_BATTLE_TEST("Dark Aura increases the power of all Dark-type attacks by 33%") +{ + s16 damage[8]; + + GIVEN { + PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } + PLAYER(SPECIES_LINOONE); + PLAYER(SPECIES_LINOONE); + OPPONENT(SPECIES_LINOONE); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_SKILL_SWAP, target: playerLeft); } + TURN { SWITCH(playerLeft, 2); } + TURN { + MOVE(playerLeft, MOVE_BITE, target:opponentLeft, secondaryEffect:FALSE); + MOVE(playerRight, MOVE_BITE, target:opponentRight, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_BITE, target:playerRight, secondaryEffect:FALSE); + } + TURN { MOVE(opponentLeft, MOVE_GASTRO_ACID, target:playerRight); } + TURN { + MOVE(playerLeft, MOVE_BITE, target:opponentLeft, secondaryEffect:FALSE); + MOVE(playerRight, MOVE_BITE, target:opponentRight, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_BITE, target:playerRight, secondaryEffect:FALSE); + } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentRight); + HP_BAR(playerRight, captureDamage: &damage[3]); + + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_GASTRO_ACID, opponentLeft); + + // Turn 3 + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[4]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[5]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[6]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentRight); + HP_BAR(playerRight, captureDamage: &damage[7]); + } THEN { + EXPECT_MUL_EQ(damage[4], UQ_4_12(1.33), damage[0]); + EXPECT_MUL_EQ(damage[5], UQ_4_12(1.33), damage[1]); + EXPECT_MUL_EQ(damage[6], UQ_4_12(1.33), damage[2]); + EXPECT_MUL_EQ(damage[7], UQ_4_12(1.33), damage[3]); + } +} + +DOUBLE_BATTLE_TEST("Dark Aura's effect doesn't stack multiple times") +{ + s16 damage[6]; + + GIVEN { + PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } + PLAYER(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + PLAYER(SPECIES_YVELTAL) { Ability(ABILITY_DARK_AURA); } + OPPONENT(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + OPPONENT(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_BITE, target:opponentLeft, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + } + TURN { SWITCH(playerRight, 2); } + TURN { + MOVE(playerLeft, MOVE_BITE, target:opponentLeft, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_BITE, target:playerLeft, secondaryEffect:FALSE); + } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentRight); + HP_BAR(playerLeft, captureDamage: &damage[2]); + + // Turn 2 + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Yveltal"); + + // Turn 3 + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[3]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[4]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BITE, opponentRight); + HP_BAR(playerLeft, captureDamage: &damage[5]); + } THEN { + EXPECT_EQ(damage[3], damage[0]); + EXPECT_EQ(damage[4], damage[1]); + EXPECT_EQ(damage[5], damage[2]); + } +} diff --git a/test/battle/ability/fairy_aura.c b/test/battle/ability/fairy_aura.c index 3b8d400b02..a51abf1be5 100644 --- a/test/battle/ability/fairy_aura.c +++ b/test/battle/ability/fairy_aura.c @@ -1,4 +1,108 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fairy Aura (Ability) test titles") +DOUBLE_BATTLE_TEST("Fairy Aura increases the power of all Fairy-type attacks by 33%") +{ + s16 damage[8]; + + GIVEN { + PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } + PLAYER(SPECIES_LINOONE); + PLAYER(SPECIES_LINOONE); + OPPONENT(SPECIES_LINOONE); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_SKILL_SWAP, target: playerLeft); } + TURN { SWITCH(playerLeft, 2); } + TURN { + MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft, secondaryEffect:FALSE); + MOVE(playerRight, MOVE_PLAY_ROUGH, target:opponentRight, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_PLAY_ROUGH, target:playerRight, secondaryEffect:FALSE); + } + TURN { MOVE(opponentLeft, MOVE_GASTRO_ACID, target:playerRight); } + TURN { + MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft, secondaryEffect:FALSE); + MOVE(playerRight, MOVE_PLAY_ROUGH, target:opponentRight, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_PLAY_ROUGH, target:playerRight, secondaryEffect:FALSE); + } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentRight); + HP_BAR(playerRight, captureDamage: &damage[3]); + + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_GASTRO_ACID, opponentLeft); + + // Turn 3 + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[4]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerRight); + HP_BAR(opponentRight, captureDamage: &damage[5]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[6]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentRight); + HP_BAR(playerRight, captureDamage: &damage[7]); + } THEN { + EXPECT_MUL_EQ(damage[4], UQ_4_12(1.33), damage[0]); + EXPECT_MUL_EQ(damage[5], UQ_4_12(1.33), damage[1]); + EXPECT_MUL_EQ(damage[6], UQ_4_12(1.33), damage[2]); + EXPECT_MUL_EQ(damage[7], UQ_4_12(1.33), damage[3]); + } +} + +DOUBLE_BATTLE_TEST("Fairy Aura's effect doesn't stack multiple times") +{ + s16 damage[6]; + + GIVEN { + PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } + PLAYER(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + PLAYER(SPECIES_XERNEAS) { Ability(ABILITY_FAIRY_AURA); } + OPPONENT(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + OPPONENT(SPECIES_WOBBUFFET) { HP(9999); MaxHP(9999); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + } + TURN { SWITCH(playerRight, 2); } + TURN { + MOVE(playerLeft, MOVE_PLAY_ROUGH, target:opponentLeft, secondaryEffect:FALSE); + MOVE(opponentLeft, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + MOVE(opponentRight, MOVE_PLAY_ROUGH, target:playerLeft, secondaryEffect:FALSE); + } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentRight); + HP_BAR(playerLeft, captureDamage: &damage[2]); + + // Turn 2 + SWITCH_OUT_MESSAGE("Wobbuffet"); + SEND_IN_MESSAGE("Xerneas"); + + // Turn 3 + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damage[3]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damage[4]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PLAY_ROUGH, opponentRight); + HP_BAR(playerLeft, captureDamage: &damage[5]); + } THEN { + EXPECT_EQ(damage[3], damage[0]); + EXPECT_EQ(damage[4], damage[1]); + EXPECT_EQ(damage[5], damage[2]); + } +} diff --git a/test/battle/ability/flare_boost.c b/test/battle/ability/flare_boost.c index a4ff14382a..54bd3b9d38 100644 --- a/test/battle/ability/flare_boost.c +++ b/test/battle/ability/flare_boost.c @@ -1,4 +1,21 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Flare Boost (Ability) test titles") +SINGLE_BATTLE_TEST("Flare Boost increases Sp. Attack by 50% when the Pokémon is burned", s16 damage) +{ + u32 status1; + PARAMETRIZE { status1 = STATUS1_NONE; } + PARAMETRIZE { status1 = STATUS1_BURN; } + GIVEN { + ASSUME(GetMoveCategory(MOVE_SWIFT) == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_DRIFBLIM) { Ability(ABILITY_FLARE_BOOST); Status1(status1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} diff --git a/test/battle/ability/toxic_boost.c b/test/battle/ability/toxic_boost.c index 85960c5b02..35a233ec23 100644 --- a/test/battle/ability/toxic_boost.c +++ b/test/battle/ability/toxic_boost.c @@ -1,4 +1,23 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Toxic Boost (Ability) test titles") +SINGLE_BATTLE_TEST("Toxic Boost increases Attack by 50% when the Pokémon is poisoned", s16 damage) +{ + u32 status1; + PARAMETRIZE { status1 = STATUS1_NONE; } + PARAMETRIZE { status1 = STATUS1_POISON; } + PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; } + GIVEN { + ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_ZANGOOSE) { Ability(ABILITY_TOXIC_BOOST); Status1(status1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[2].damage); + } +} diff --git a/test/battle/move_effect/two_typed_move.c b/test/battle/move_effect/two_typed_move.c index 43c3515739..7372222e83 100644 --- a/test/battle/move_effect/two_typed_move.c +++ b/test/battle/move_effect/two_typed_move.c @@ -1,4 +1,12 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Flying Press (Move Effect) test titles") +TO_DO_BATTLE_TEST("Flying Press does both Fighting and Flying-type for type effectiveness") +TO_DO_BATTLE_TEST("Flying-type Pokémon don't receive STAB on Flying Press") +TO_DO_BATTLE_TEST("Sky Plate doesn't boost Flying Press' power") // Check Fist Plate for comparison +TO_DO_BATTLE_TEST("Sharp Beak doesn't boost Flying Press' power") // Check Black Belt for comparison +TO_DO_BATTLE_TEST("Flying Gem doesn't trigger when using Flying Press") // Check Fighting Gem for comparison +TO_DO_BATTLE_TEST("Coba Berry doesn't trigger when the user is attacked by Flying Press") +TO_DO_BATTLE_TEST("Flying Press triggers Chople Berry, even when it wouldn't be super effective with regular Fighting-type moves") +TO_DO_BATTLE_TEST("Flying Press under Electrify does both Electric and Flying-type for type effectiveness") // Check Electric 1/4 effectiveness +TO_DO_BATTLE_TEST("Flying Press under Normalize does both Normal and Flying-type for type effectiveness") // Check Rock/Steel 1/4 effectiveness From 13bae5d1b2b4cc45575b22671e476110b8acb2fa Mon Sep 17 00:00:00 2001 From: Bivurnum <147376167+Bivurnum@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:15:43 -0600 Subject: [PATCH 26/35] Bug Fix: NPC Followers not working on slow sideways stairs (#8257) --- src/field_player_avatar.c | 1 - src/follower_npc.c | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index bb9723443d..aaf28a6dea 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -2774,7 +2774,6 @@ bool8 ObjectMovingOnRockStairs(struct ObjectEvent *objectEvent, u8 direction) s16 x = objectEvent->currentCoords.x; s16 y = objectEvent->currentCoords.y; - // TODO followers on sideways stairs if (IsFollowerVisible() && GetFollowerObject() != NULL && (objectEvent->isPlayer || objectEvent->localId == OBJ_EVENT_ID_FOLLOWER)) return FALSE; diff --git a/src/follower_npc.c b/src/follower_npc.c index 8bc3a61697..1833d555ab 100644 --- a/src/follower_npc.c +++ b/src/follower_npc.c @@ -954,6 +954,10 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc RETURN_STATE(MOVEMENT_ACTION_WALK_NORMAL_DOWN, direction); + // Slow stairs. + case MOVEMENT_ACTION_WALK_SLOW_STAIRS_DOWN ... MOVEMENT_ACTION_WALK_SLOW_STAIRS_RIGHT: + RETURN_STATE(MOVEMENT_ACTION_WALK_SLOW_STAIRS_DOWN, direction); + default: return MOVEMENT_INVALID; } From 7fd1404354a8bf5c56627dacffde72df0deb7b11 Mon Sep 17 00:00:00 2001 From: moostoet <70690976+moostoet@users.noreply.github.com> Date: Mon, 17 Nov 2025 18:03:41 +0100 Subject: [PATCH 27/35] Fix Magic Coat reflecting hazard moves incorrectly when used by a partner (#8272) --- src/battle_script_commands.c | 21 +++++++++++++++++++- test/battle/move_effect/magic_coat.c | 29 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4c2ac13178..e100d3a9ca 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1167,7 +1167,26 @@ static void Cmd_attackcanceler(void) } u32 isBounceable = MoveCanBeBouncedBack(gCurrentMove); - if (gProtectStructs[gBattlerTarget].bounceMove + bool32 bounceActive = (gProtectStructs[gBattlerTarget].bounceMove && IsBattlerAlive(gBattlerTarget)); + + if (!bounceActive + && !gBattleStruct->bouncedMoveIsUsed + && isBounceable + && GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) == MOVE_TARGET_OPPONENTS_FIELD) + { + u32 partner = BATTLE_PARTNER(gBattlerTarget); + + if (partner < gBattlersCount + && GetBattlerSide(partner) == GetBattlerSide(gBattlerTarget) + && gProtectStructs[partner].bounceMove + && IsBattlerAlive(partner)) + { + gBattlerTarget = partner; + bounceActive = TRUE; + } + } + + if (bounceActive && isBounceable && !gBattleStruct->bouncedMoveIsUsed) { diff --git a/test/battle/move_effect/magic_coat.c b/test/battle/move_effect/magic_coat.c index 50ed79e194..ca7b78883e 100644 --- a/test/battle/move_effect/magic_coat.c +++ b/test/battle/move_effect/magic_coat.c @@ -32,3 +32,32 @@ SINGLE_BATTLE_TEST("Magic Coat prints the correct message when bouncing back a m STATUS_ICON(opponent, sleep: TRUE); } } + +DOUBLE_BATTLE_TEST("Magic Coat reflects hazards regardless of the user's position") +{ + struct BattlePokemon *coatUser = NULL; + PARAMETRIZE { coatUser = playerLeft; } + PARAMETRIZE { coatUser = playerRight; } + ASSUME(GetMoveEffect(MOVE_SPIKES) == EFFECT_SPIKES); + ASSUME(GetMoveEffect(MOVE_STEALTH_ROCK) == EFFECT_STEALTH_ROCK); + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(coatUser, MOVE_MAGIC_COAT); MOVE(opponentRight, MOVE_STEALTH_ROCK); MOVE(opponentLeft, MOVE_SPIKES); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGIC_COAT, coatUser); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponentLeft); + } + } THEN { + EXPECT(!IsHazardOnSide(B_SIDE_PLAYER, HAZARDS_STEALTH_ROCK)); + EXPECT(!IsHazardOnSide(B_SIDE_PLAYER, HAZARDS_SPIKES)); + EXPECT(IsHazardOnSide(B_SIDE_OPPONENT, HAZARDS_STEALTH_ROCK)); + EXPECT(IsHazardOnSide(B_SIDE_OPPONENT, HAZARDS_SPIKES)); + } +} From 0999ca8ff919df44fca31d0319c18054ba6da411 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:29:19 +0100 Subject: [PATCH 28/35] Shell Trap tests and Fix for Encore interaction (#8268) Co-authored-by: PhallenTree <168426989+PhallenTree@users.noreply.github.com> --- src/battle_script_commands.c | 16 +++---- test/battle/move_effect/shell_trap.c | 65 ++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e100d3a9ca..be70970fa7 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11527,14 +11527,16 @@ static void Cmd_trysetencore(void) } if ((IsMoveEncoreBanned(gLastMoves[gBattlerTarget])) + || i == MAX_MON_MOVES || gLastMoves[gBattlerTarget] == MOVE_NONE - || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) + || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE + || gBattleMons[gBattlerTarget].pp[i] == 0 + || gDisableStructs[gBattlerTarget].encoredMove != MOVE_NONE + || GetMoveEffect(gChosenMoveByBattler[gBattlerTarget]) == EFFECT_SHELL_TRAP) { - i = MAX_MON_MOVES; + gBattlescriptCurrInstr = cmd->failInstr; } - - if (gDisableStructs[gBattlerTarget].encoredMove == MOVE_NONE - && i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) + else { gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; gDisableStructs[gBattlerTarget].encoredMovePos = i; @@ -11552,10 +11554,6 @@ static void Cmd_trysetencore(void) gDisableStructs[gBattlerTarget].encoreTimer = 3; gBattlescriptCurrInstr = cmd->nextInstr; } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } } static void Cmd_painsplitdmgcalc(void) diff --git a/test/battle/move_effect/shell_trap.c b/test/battle/move_effect/shell_trap.c index 903f984929..f3f0068d6f 100644 --- a/test/battle/move_effect/shell_trap.c +++ b/test/battle/move_effect/shell_trap.c @@ -214,3 +214,68 @@ SINGLE_BATTLE_TEST("Shell Trap activates if user is hit with a physical move but HP_BAR(opponent); } } + +SINGLE_BATTLE_TEST("Encore fails if target has active Shell Trap waiting") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, MOVE_ENCORE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + MESSAGE("Wobbuffet set a shell trap!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENCORE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + } + } +} + +SINGLE_BATTLE_TEST("Shell Trap fails if an other -3 or lower priority Move is used") +{ + GIVEN { + ASSUME(GetMovePriority(MOVE_DRAGON_TAIL) <= -3); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_SHELL_TRAP); + MOVE(opponent, MOVE_DRAGON_TAIL); + } + } SCENE { + MESSAGE("Wobbuffet set a shell trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + } +} + +DOUBLE_BATTLE_TEST("Shell Trap does not trigger when hit into Substitute") +{ + GIVEN { + ASSUME(GetMoveCategory(MOVE_DOUBLE_EDGE) == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SNORLAX); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SUBSTITUTE); } + TURN { + MOVE(playerLeft, MOVE_SHELL_TRAP); + MOVE(opponentLeft, MOVE_DOUBLE_EDGE, target: playerLeft); + MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, playerLeft); + MESSAGE("Wynaut set a shell trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_EDGE, opponentLeft); + MESSAGE("Wynaut's substitute faded!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft); + } +} From 9b16204705fce7bd7c2ae6ee011642b5769c29ca Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Tue, 18 Nov 2025 17:50:15 +0100 Subject: [PATCH 29/35] Fix not enough memory being allocated when moves load background in contests (#8284) --- src/battle_anim.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/battle_anim.c b/src/battle_anim.c index 76e37b7eea..839f319031 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -13,6 +13,7 @@ #include "graphics.h" #include "main.h" #include "malloc.h" +#include "menu.h" #include "m4a.h" #include "palette.h" #include "pokemon.h" @@ -1568,10 +1569,7 @@ void LoadMoveBg(u16 bgId) { if (IsContest()) { - void *decompressionBuffer = Alloc(0x800); - const u32 *tilemap = gBattleAnimBackgroundTable[bgId].tilemap; - - DecompressDataWithHeaderWram(tilemap, decompressionBuffer); + void *decompressionBuffer = malloc_and_decompress(gBattleAnimBackgroundTable[bgId].tilemap, NULL); RelocateBattleBgPal(GetBattleBgPaletteNum(), decompressionBuffer, 0x100, FALSE); DmaCopy32(3, decompressionBuffer, (void *)BG_SCREEN_ADDR(26), 0x800); DecompressDataWithHeaderVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_SCREEN_ADDR(4)); From 5e40456f45090d48fc0f4c9dd925472c1d1ccdd1 Mon Sep 17 00:00:00 2001 From: moostoet <70690976+moostoet@users.noreply.github.com> Date: Tue, 18 Nov 2025 19:33:49 +0100 Subject: [PATCH 30/35] =?UTF-8?q?Fix=20AI=5FFLAG=5FDOUBLE=5FACE=5FPOKEMON?= =?UTF-8?q?=20sending=20duplicate=20Pok=C3=A9mon=20in=20doubles=20(#8279)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/battle_ai_switch_items.c | 3 ++ src/battle_controller_opponent.c | 54 +++++++++++++++++++++++++++++--- test/battle/ai/ai_double_ace.c | 32 +++++++++++++++++++ 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index e4a560ca6e..29b58ed9e6 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -2414,6 +2414,9 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) if (bestMonId != PARTY_SIZE) return bestMonId; + if (aceMonId != PARTY_SIZE && aliveCount == 0) + return aceMonId; + bestMonId = GetBestMonTypeMatchup(party, firstId, lastId, invalidMons, battler, opposingBattler); if (bestMonId != PARTY_SIZE) return bestMonId; diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 19aeef3f4f..1f1953ea61 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -512,13 +512,57 @@ static inline bool32 IsAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 batt && CountAIAliveNonEggMonsExcept(PARTY_SIZE) != pokemonInBattle; } +static inline bool32 IsDoubleAceSlot(u32 battler, u32 partyId) +{ + u32 partyCountEnd; + + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON)) + return FALSE; + + partyCountEnd = CalculateEnemyPartyCountInSide(battler); + if (partyCountEnd == 0) + return FALSE; + + if (partyId == partyCountEnd - 1) + return TRUE; + if (partyCountEnd > 1 && partyId == partyCountEnd - 2) + return TRUE; + + return FALSE; +} + static inline bool32 IsDoubleAcePokemon(u32 chosenMonId, u32 pokemonInBattle, u32 battler) { - return gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON - && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 1) - && (chosenMonId == CalculateEnemyPartyCountInSide(battler) - 2) - && CountAIAliveNonEggMonsExcept(PARTY_SIZE) != pokemonInBattle - && CountAIAliveNonEggMonsExcept(PARTY_SIZE-1) != pokemonInBattle; + s32 battler1, battler2, firstId, lastId; + s32 i; + + if (!IsDoubleAceSlot(battler, chosenMonId)) + return FALSE; + + if (!IsDoubleBattle()) + { + battler2 = battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + } + else + { + battler1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + battler2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + } + + GetAIPartyIndexes(battler, &firstId, &lastId); + for (i = firstId; i < lastId; i++) + { + if (!IsValidForBattle(&gEnemyParty[i]) + || i == gBattlerPartyIndexes[battler1] + || i == gBattlerPartyIndexes[battler2] + || i == chosenMonId) + continue; + + if (!IsAcePokemon(i, pokemonInBattle, battler) && !IsDoubleAceSlot(battler, i)) + return TRUE; + } + + return FALSE; } static void OpponentHandleChoosePokemon(u32 battler) diff --git a/test/battle/ai/ai_double_ace.c b/test/battle/ai/ai_double_ace.c index 3fa9ce77e0..38b7d1dcd8 100644 --- a/test/battle/ai/ai_double_ace.c +++ b/test/battle/ai/ai_double_ace.c @@ -94,3 +94,35 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_DOUBLE_ACE_POKEMON: Ace mons won't be switched in TURN { EXPECT_SWITCH(opponentLeft, 2); } } } + +AI_DOUBLE_BATTLE_TEST("AI_FLAG_DOUBLE_ACE_POKEMON: sends out Ace mons when no other options remain mid-battle") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_SMART_SWITCHING | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_DOUBLE_ACE_POKEMON); + + PLAYER(SPECIES_WOBBUFFET) { Level(50); Speed(200); Moves(MOVE_THUNDERBOLT, MOVE_CELEBRATE); SpAttack(200); } + PLAYER(SPECIES_WOBBUFFET) { Level(50); Speed(150); Moves(MOVE_THUNDERBOLT, MOVE_CELEBRATE); SpAttack(200); } + + OPPONENT(SPECIES_ZIGZAGOON) { Level(5); HP(1); Speed(1); Moves(MOVE_SPLASH); } + OPPONENT(SPECIES_POOCHYENA) { Level(5); HP(1); Speed(1); Moves(MOVE_SPLASH); } + + // Aces + OPPONENT(SPECIES_MIGHTYENA) { Level(50); Speed(10); Moves(MOVE_CRUNCH); } + OPPONENT(SPECIES_GENGAR) { Level(50); Speed(10); Moves(MOVE_SPLASH); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_THUNDERBOLT, target: opponentLeft); + MOVE(playerRight, MOVE_CELEBRATE); + EXPECT_MOVE(opponentLeft, MOVE_SPLASH); + EXPECT_MOVE(opponentRight, MOVE_SPLASH); + EXPECT_SEND_OUT(opponentLeft, 3); + } + TURN { + MOVE(playerLeft, MOVE_CELEBRATE); + MOVE(playerRight, MOVE_THUNDERBOLT, target: opponentRight); + EXPECT_MOVE(opponentLeft, MOVE_SPLASH); + EXPECT_MOVE(opponentRight, MOVE_SPLASH); + EXPECT_SEND_OUT(opponentRight, 2); + } + } +} From a914c11b301b03d87d57e04e096ebe786cf30d55 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Tue, 18 Nov 2025 23:12:11 +0100 Subject: [PATCH 31/35] Fix max mushroom unable to be selected when one stat is maxed (#8287) --- src/item_use.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/item_use.c b/src/item_use.c index ce1cb074f4..18fdbea192 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1293,11 +1293,12 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) case EFFECT_ITEM_INCREASE_ALL_STATS: { u32 ability = GetBattlerAbility(gBattlerInMenuId); + cannotUse = TRUE; for (i = STAT_ATK; i < NUM_STATS; i++) { - if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL, ability)) + if (!CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL, ability)) { - cannotUse = TRUE; + cannotUse = FALSE; break; } } From 4a69268bd517fbf90c52f55fbe3b17a554f28e65 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Tue, 18 Nov 2025 23:31:47 +0100 Subject: [PATCH 32/35] Make rainbow effect anim change based on side (#8269) --- data/battle_anim_scripts.s | 11 +++++++++- graphics/battle_anims/backgrounds/rainbow.pal | 19 ------------------ graphics/battle_anims/backgrounds/rainbow.png | Bin 20960 -> 0 bytes ...{rainbow.bin => rainbow_opponent_tile.bin} | Bin 2048 -> 2048 bytes .../backgrounds/rainbow_opponent_tile.png | Bin 0 -> 4030 bytes .../backgrounds/rainbow_player_tile.bin | Bin 0 -> 2048 bytes .../backgrounds/rainbow_player_tile.png | Bin 0 -> 3892 bytes include/constants/battle_anim.h | 5 +++-- include/graphics.h | 6 ++++-- src/data/battle_anim.h | 3 ++- src/graphics.c | 8 +++++--- 11 files changed, 24 insertions(+), 28 deletions(-) delete mode 100644 graphics/battle_anims/backgrounds/rainbow.pal delete mode 100644 graphics/battle_anims/backgrounds/rainbow.png rename graphics/battle_anims/backgrounds/{rainbow.bin => rainbow_opponent_tile.bin} (53%) create mode 100644 graphics/battle_anims/backgrounds/rainbow_opponent_tile.png create mode 100644 graphics/battle_anims/backgrounds/rainbow_player_tile.bin create mode 100644 graphics/battle_anims/backgrounds/rainbow_player_tile.png diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index d0fc4e9ac8..158de50992 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -32015,7 +32015,8 @@ gBattleAnimGeneral_Rainbow:: createvisualtask AnimTask_BlendBattleAnimPal, 10, (F_PAL_BG | F_PAL_BATTLERS_2), 1, 6, 0, RGB_WHITE waitforvisualfinish delay 30 - fadetobg BG_RAINBOW + goto SetRainbowBackground +AnimGeneral_RainbowContinue: panse_adjustnone SE_M_ABSORB_2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +1, 0 delay 90 blendoff @@ -32023,6 +32024,14 @@ gBattleAnimGeneral_Rainbow:: waitbgfadein clearmonbg ANIM_ATK_PARTNER end +SetRainbowBackground: + createvisualtask AnimTask_GetAttackerSide, 2 + jumprettrue SetRainbowBgOppoentSide + fadetobg BG_RAINBOW_PLAYER + goto AnimGeneral_RainbowContinue +SetRainbowBgOppoentSide: + fadetobg BG_RAINBOW_OPPONENT + goto AnimGeneral_RainbowContinue gBattleAnimGeneral_SeaOfFire:: loadspritegfx ANIM_TAG_SMALL_EMBER diff --git a/graphics/battle_anims/backgrounds/rainbow.pal b/graphics/battle_anims/backgrounds/rainbow.pal deleted file mode 100644 index 9b62b7b25b..0000000000 --- a/graphics/battle_anims/backgrounds/rainbow.pal +++ /dev/null @@ -1,19 +0,0 @@ -JASC-PAL -0100 -16 -109 92 75 -255 255 255 -255 107 122 -255 200 102 -255 255 107 -143 255 160 -107 255 255 -107 129 255 -220 114 255 -199 255 250 -232 240 248 -224 232 240 -208 224 240 -191 202 224 -183 189 202 -157 166 181 diff --git a/graphics/battle_anims/backgrounds/rainbow.png b/graphics/battle_anims/backgrounds/rainbow.png deleted file mode 100644 index bd41645b3571cc8bcea41533b053625e25d964e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20960 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 diff --git a/graphics/battle_anims/backgrounds/rainbow_opponent_tile.png b/graphics/battle_anims/backgrounds/rainbow_opponent_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..27377148052c90d4b78c331634c0fa67daa3d0c6 GIT binary patch literal 4030 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 Date: Tue, 18 Nov 2025 23:33:41 +0100 Subject: [PATCH 33/35] Block selecting x items when contrary pokemon are at minimum stages (#8288) --- src/item_use.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/item_use.c b/src/item_use.c index 18fdbea192..b97ac1202b 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1254,7 +1254,8 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) switch (battleUsage) { case EFFECT_ITEM_INCREASE_STAT: - if (gBattleMons[gBattlerInMenuId].statStages[GetItemEffect(itemId)[1]] == MAX_STAT_STAGE) + u32 ability = GetBattlerAbility(gBattlerInMenuId); + if (CompareStat(gBattlerInMenuId, GetItemEffect(itemId)[1], MAX_STAT_STAGE, CMP_EQUAL, ability)) cannotUse = TRUE; break; case EFFECT_ITEM_SET_FOCUS_ENERGY: From 0f4d325467057db3f6bf0021cd985e97e607ff5f Mon Sep 17 00:00:00 2001 From: moostoet <70690976+moostoet@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:34:36 +0100 Subject: [PATCH 34/35] Fix Fur Coat affecting confusion self-damage (#8267) --- include/battle_util.h | 2 +- src/battle_tv.c | 1 + src/battle_util.c | 38 +++++++++++++++++++++++++--------- test/battle/ability/fur_coat.c | 1 - 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index c88f4723dd..c91078db2b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -166,7 +166,7 @@ struct DamageContext u32 randomFactor:1; u32 updateFlags:1; u32 isAnticipation:1; - u32 padding1:1; + u32 isSelfInflicted:1; u32 weather:16; u32 fixedBasePower:8; u32 padding2:8; diff --git a/src/battle_tv.c b/src/battle_tv.c index 6504a3cc43..2fc8fad7b7 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -1267,6 +1267,7 @@ static void TrySetBattleSeminarShow(void) ctx.isCrit = FALSE; ctx.randomFactor = FALSE; ctx.updateFlags = FALSE; + ctx.isSelfInflicted = FALSE; ctx.fixedBasePower = powerOverride; gBattleStruct->moveDamage[gBattlerTarget] = CalculateMoveDamage(&ctx); dmgByMove[i] = gBattleStruct->moveDamage[gBattlerTarget]; diff --git a/src/battle_util.c b/src/battle_util.c index d4fb0d38a6..f98b83d9a6 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2029,6 +2029,7 @@ static enum MoveCanceler CancelerObedience(void) ctx.isCrit = FALSE; ctx.randomFactor = FALSE; ctx.updateFlags = TRUE; + ctx.isSelfInflicted = TRUE; ctx.fixedBasePower = 40; gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); gBattlescriptCurrInstr = BattleScript_IgnoresAndHitsItself; @@ -2181,6 +2182,7 @@ static enum MoveCanceler CancelerConfused(void) ctx.isCrit = FALSE; ctx.randomFactor = FALSE; ctx.updateFlags = TRUE; + ctx.isSelfInflicted = TRUE; ctx.fixedBasePower = 40; gBattleStruct->moveDamage[gBattlerAttacker] = CalculateMoveDamage(&ctx); gProtectStructs[gBattlerAttacker].confusionSelfDmg = TRUE; @@ -8499,6 +8501,24 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) return uq4_12_multiply_by_int_half_down(modifier, basePower); } +static inline uq4_12_t ApplyOffensiveBadgeBoost(uq4_12_t modifier, u32 battler, u32 move) +{ + if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_ATTACK, battler) && IsBattleMovePhysical(move)) + modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPATK, battler) && IsBattleMoveSpecial(move)) + modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + return modifier; +} + +static inline uq4_12_t ApplyDefensiveBadgeBoost(uq4_12_t modifier, u32 battler, u32 move) +{ + if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_DEFENSE, battler) && IsBattleMovePhysical(move)) + modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPDEF, battler) && IsBattleMoveSpecial(move)) + modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + return modifier; +} + static inline u32 CalcAttackStat(struct DamageContext *ctx) { u8 atkStage; @@ -8570,6 +8590,9 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) // apply attack stat modifiers modifier = UQ_4_12(1.0); + if (ctx->isSelfInflicted) + return uq4_12_multiply_by_int_half_down(ApplyOffensiveBadgeBoost(modifier, battlerAtk, move), atkStat); + // attacker's abilities switch (ctx->abilityAtk) { @@ -8764,11 +8787,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) break; } - // The offensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the corresponding flags set (eg. Badges) - if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_ATTACK, battlerAtk) && IsBattleMovePhysical(move)) - modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); - if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPATK, battlerAtk) && IsBattleMoveSpecial(move)) - modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + modifier = ApplyOffensiveBadgeBoost(modifier, battlerAtk, move); return uq4_12_multiply_by_int_half_down(modifier, atkStat); } @@ -8853,6 +8872,9 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) // apply defense stat modifiers modifier = UQ_4_12(1.0); + if (ctx->isSelfInflicted) + return uq4_12_multiply_by_int_half_down(ApplyDefensiveBadgeBoost(modifier, battlerDef, move), defStat); + // target's abilities switch (ctx->abilityDef) { @@ -8942,11 +8964,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SNOW) && usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); - // The defensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the corresponding flags set (eg. Badges) - if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_DEFENSE, battlerDef) && IsBattleMovePhysical(move)) - modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); - if (ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPDEF, battlerDef) && IsBattleMoveSpecial(move)) - modifier = uq4_12_multiply_half_down(modifier, GetBadgeBoostModifier()); + modifier = ApplyDefensiveBadgeBoost(modifier, battlerDef, move); return uq4_12_multiply_by_int_half_down(modifier, defStat); } diff --git a/test/battle/ability/fur_coat.c b/test/battle/ability/fur_coat.c index 84b8549e42..2ad6a3d5a2 100644 --- a/test/battle/ability/fur_coat.c +++ b/test/battle/ability/fur_coat.c @@ -26,7 +26,6 @@ SINGLE_BATTLE_TEST("Fur Coat doubles Defense", s16 damage) SINGLE_BATTLE_TEST("Fur Coat has no effect on self-inflicted confusion damage", s16 damage) { - KNOWN_FAILING; u32 ability; PARAMETRIZE { ability = ABILITY_FUR_COAT; } PARAMETRIZE { ability = ABILITY_RATTLED; } From 39ffda4245318e7d8c81f7d20e17164c7011ecbc Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:14:59 +0100 Subject: [PATCH 35/35] Fixes End Turn Speed Order (#8289) --- src/battle_end_turn.c | 14 ++------------ test/battle/end_turn_effects.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index d423659be9..62a8f67006 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -121,19 +121,9 @@ static bool32 HandleEndTurnOrder(u32 battler) gBattleTurnCounter++; gBattleStruct->endTurnEventsCounter++; - u32 i, j; - for (i = 0; i < gBattlersCount; i++) - { + for (u32 i = 0; i < gBattlersCount; i++) gBattlerByTurnOrder[i] = i; - } - for (i = 0; i < gBattlersCount - 1; i++) - { - for (j = i + 1; j < gBattlersCount; j++) - { - if (GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) - SwapTurnOrder(i, j); - } - } + SortBattlersBySpeed(gBattlerByTurnOrder, FALSE); return effect; } diff --git a/test/battle/end_turn_effects.c b/test/battle/end_turn_effects.c index 51aa1e79bf..01c844f9b5 100644 --- a/test/battle/end_turn_effects.c +++ b/test/battle/end_turn_effects.c @@ -29,3 +29,27 @@ DOUBLE_BATTLE_TEST("End Turn Effects: First Event Block is executed correctly") } } +DOUBLE_BATTLE_TEST("End Turn Effects: Effects are applied by Speed Order") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT) { MaxHP(200); HP(100); Speed(3); } + PLAYER(SPECIES_RILLABOOM) { MaxHP(200); HP(100); Speed(1); Ability(ABILITY_GRASSY_SURGE); } + OPPONENT(SPECIES_MEWTWO) { MaxHP(200); HP(100); Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(200); HP(100); Speed(4); } + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_FAKE_OUT, target: playerLeft); + MOVE(playerRight, MOVE_FAKE_OUT, target: opponentRight); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, opponentLeft); + HP_BAR(playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, playerRight); + HP_BAR(opponentRight); + + HP_BAR(opponentRight); + HP_BAR(playerLeft); + HP_BAR(opponentLeft); + HP_BAR(playerRight); + } +}