From c1852434bbd5cfb26e6f0ca7063216930fea9317 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 30 Aug 2020 19:37:38 -0600 Subject: [PATCH 001/283] add rock climb --- data/field_effect_scripts.s | 11 + data/scripts/field_move_scripts.inc | 26 ++ graphics/field_effects/palettes/big_dust.pal | 19 ++ .../field_effects/pics/rock_climb_blob.png | Bin 0 -> 383 bytes .../field_effects/pics/rock_climb_dust.png | Bin 0 -> 558 bytes include/constants/event_object_movement.h | 5 + include/constants/field_effects.h | 5 + include/constants/metatile_behaviors.h | 2 +- include/event_scripts.h | 1 + include/field_effect.h | 1 + include/metatile_behavior.h | 1 + spritesheet_rules.mk | 6 + .../field_effect_object_template_pointers.h | 4 + src/data/field_effects/field_effect_objects.h | 45 +++ .../movement_action_func_tables.h | 45 +++ .../object_events/object_event_graphics.h | 3 + src/data/party_menu.h | 5 +- src/event_object_movement.c | 73 +++-- src/field_control_avatar.c | 3 + src/field_effect.c | 265 ++++++++++++++++++ src/field_effect_helpers.c | 20 ++ src/metatile_behavior.c | 10 +- src/party_menu.c | 22 ++ 23 files changed, 553 insertions(+), 19 deletions(-) create mode 100644 graphics/field_effects/palettes/big_dust.pal create mode 100644 graphics/field_effects/pics/rock_climb_blob.png create mode 100644 graphics/field_effects/pics/rock_climb_dust.png diff --git a/data/field_effect_scripts.s b/data/field_effect_scripts.s index c57f19a040..3a2e9f14ee 100644 --- a/data/field_effect_scripts.s +++ b/data/field_effect_scripts.s @@ -72,6 +72,8 @@ gFieldEffectScriptPointers:: @ 82DB9D4 .4byte gFieldEffectScript_RayquazaSpotlight @ FLDEFF_RAYQUAZA_SPOTLIGHT .4byte gFieldEffectScript_DestroyDeoxysRock @ FLDEFF_DESTROY_DEOXYS_ROCK .4byte gFieldEffectScript_MoveDeoxysRock @ FLDEFF_MOVE_DEOXYS_ROCK + .4byte gFieldEffectScript_UseRockClimb @ FLDEFF_USE_ROCK_CLIMB + .4byte gFieldEffectScript_RockClimbDust @ FLDEFF_ROCK_CLIMB_DUST gFieldEffectScript_ExclamationMarkIcon1:: @ 82DBAE0 field_eff_callnative FldEff_ExclamationMarkIcon @@ -343,3 +345,12 @@ gFieldEffectScript_DestroyDeoxysRock:: @ 82DBCF9 gFieldEffectScript_MoveDeoxysRock:: @ 82DBCFF field_eff_callnative FldEff_MoveDeoxysRock field_eff_end + +gFieldEffectScript_UseRockClimb:: @ 82DBC3F + field_eff_callnative FldEff_UseRockClimb + field_eff_end + +gFieldEffectScript_RockClimbDust:: @ 82DBB28 + field_eff_loadfadedpal_callnative gSpritePalette_BigDust, FldEff_RockClimbDust + field_eff_end + diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index 2d689348b0..d04304abc9 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -301,3 +301,29 @@ EventScript_FailSweetScent:: @ 8290CAE Text_FailSweetScent: @ 8290CB7 .string "Looks like there's nothing here…$" + + +EventScript_UseRockClimb:: + lockall + checkpartymove MOVE_ROCK_CLIMB + compare VAR_RESULT, PARTY_SIZE + goto_if_eq EventScript_CantRockClimb + bufferpartymonnick 0, VAR_RESULT + setfieldeffectargument 0, VAR_RESULT + msgbox Text_WantToRockClimb, MSGBOX_YESNO + compare VAR_RESULT, NO + goto_if_eq EventScript_EndRockClimb + msgbox Text_MonUsedRockClimb, MSGBOX_DEFAULT + dofieldeffect FLDEFF_USE_ROCK_CLIMB + goto EventScript_EndRockClimb +EventScript_CantRockClimb:: @ 8290A84 + msgbox Text_CantRockClimb, MSGBOX_DEFAULT +EventScript_EndRockClimb:: @ 8290A8C + releaseall + end +Text_WantToRockClimb: + .string "The cliff is steep.\nWould you like to use Rock Climb?$" +Text_MonUsedRockClimb: + .string "{STR_VAR_1} used Rock Climb!$" +Text_CantRockClimb: + .string "The cliff is steep.\nA Pokémon may be able to climb it.$" diff --git a/graphics/field_effects/palettes/big_dust.pal b/graphics/field_effects/palettes/big_dust.pal new file mode 100644 index 0000000000..34beaf0371 --- /dev/null +++ b/graphics/field_effects/palettes/big_dust.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +98 172 238 +198 181 156 +165 140 115 +181 165 140 +148 123 99 +206 198 173 +189 173 148 +82 74 57 +222 180 148 +140 123 82 +173 156 123 +238 213 180 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/field_effects/pics/rock_climb_blob.png b/graphics/field_effects/pics/rock_climb_blob.png new file mode 100644 index 0000000000000000000000000000000000000000..19a9a7cea9b64d8b91262792826091934322e1cf GIT binary patch literal 383 zcmV-_0f7FAP)5Fk0;=I(RNb4rv_|6*FjK|%lj{{R30FCfkm00009 za7bBm000&x000&x0ZCFM@Bjb+^+`lQR5*?8Q#*FUFbvb=Ri~3ydx=+G-AlBhvPnp! zlfJ$VnObh301*16^k09gfa7=kN0FcaJX+-D*ZIXOmiDN!x%IXS9L^`dD+d2GsFQ)c zukKFKE`F&TA(ugI(Qn|Co+>B@11V%Eg9FoHWD+x2)iS>b#2RJYT%wU7Gr-DB7!x!T zXrM=n7Xc#_I|mw66O2eaCw8jc4lUPj1t8%F3^9RCteApk4HbwPz%~uLIB*ZkrKqDJ zY9Lc^J&h^oBeV{0ATEIw@8M(sVPYU;#C1|8mN1Yb9A7D0gr3khj6H?A{kXefjvwkx d{Ydy+eE}yq7eUcLbl?C0002ovPDHLkV1g59m4pBQ literal 0 HcmV?d00001 diff --git a/graphics/field_effects/pics/rock_climb_dust.png b/graphics/field_effects/pics/rock_climb_dust.png new file mode 100644 index 0000000000000000000000000000000000000000..541c6ba9b8b3f3dba8f8546fe42f643169103d96 GIT binary patch literal 558 zcmV+}0@3}6P)=jL9sbPN{d@04`5?qC0JaozJOq5XKm{X z`p@jeM9pC`9Jd)V-^@S%#u$y4%uEZSayg+qBckKmF5j}drwTxH`<)%9hZ|b<`K|+( z33yK_vQ}rVd{6nZ>rZs|QEO_WO|PSkC@7CQV3z9uYMMw5ad0c7&o(w%Giz)-2fyxs zed&+@+fdGKApqMJh`bY!9{`6m@L5cNy=HGdxi5(?6(F(zM3e5^M3q{~RPenE%Fw|W z&s_chYz*?&+X$efb!+F+?2B(%V211n6IGID(mv>o76AH^hJXY1E&(p^J@}Ijcti*2 zf+R7Pu(bG!LqLOrg+J|pCv-4b`MqXn~xIssJ!|uBhZJsx-0h zlKzp}3PH8gZ=*&CAg37!Ovr)AwYhDLk`2X{2jsK5TXz}N5q@=LF$wL|Hq!&#*T~n6Z1+oDC%k~ wpx;7Wj}>ILUya0KB%o8SCKM|$R?g)30(n1Mi4fg(6#xJL07*qoM6N<$g5})wKL7v# literal 0 HcmV?d00001 diff --git a/include/constants/event_object_movement.h b/include/constants/event_object_movement.h index 6a4405b653..8012ac88d1 100755 --- a/include/constants/event_object_movement.h +++ b/include/constants/event_object_movement.h @@ -241,6 +241,11 @@ #define MOVEMENT_ACTION_FIGURE_8 0x9B #define MOVEMENT_ACTION_FLY_UP 0x9C #define MOVEMENT_ACTION_FLY_DOWN 0x9D +//fast diagonal movement +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT 0x9E +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT 0x9F +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT 0xA0 +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT 0xA1 #define MOVEMENT_ACTION_STEP_END 0xFE diff --git a/include/constants/field_effects.h b/include/constants/field_effects.h index dc1085f7ca..f94e19cf02 100644 --- a/include/constants/field_effects.h +++ b/include/constants/field_effects.h @@ -68,6 +68,8 @@ #define FLDEFF_RAYQUAZA_SPOTLIGHT 64 #define FLDEFF_DESTROY_DEOXYS_ROCK 65 #define FLDEFF_MOVE_DEOXYS_ROCK 66 +#define FLDEFF_USE_ROCK_CLIMB 67 +#define FLDEFF_ROCK_CLIMB_DUST 68 #define FLDEFFOBJ_SHADOW_S 0 #define FLDEFFOBJ_SHADOW_M 1 @@ -106,6 +108,8 @@ #define FLDEFFOBJ_BUBBLES 34 #define FLDEFFOBJ_SMALL_SPARKLE 35 #define FLDEFFOBJ_RAYQUAZA 36 +#define FLDEFFOBJ_ROCK_CLIMB_BLOB 37 +#define FLDEFFOBJ_ROCK_CLIMB_DUST 38 #define FLDEFF_PAL_TAG_CUT_GRASS 0x1000 #define FLDEFF_PAL_TAG_SECRET_POWER_TREE 0x1003 @@ -119,5 +123,6 @@ #define FLDEFF_PAL_TAG_SMALL_SPARKLE 0x100F #define FLDEFF_PAL_TAG_HOF_MONITOR 0x1010 #define FLDEFF_PAL_TAG_UNKNOWN 0x1011 +#define FLDEFF_PAL_TAG_DUST_CLOUD 0x1012 #endif // GUARD_FIELD_EFFECT_CONSTANTS_H diff --git a/include/constants/metatile_behaviors.h b/include/constants/metatile_behaviors.h index 94cb0ffcaa..cc4bd7fee5 100755 --- a/include/constants/metatile_behaviors.h +++ b/include/constants/metatile_behaviors.h @@ -240,6 +240,6 @@ #define MB_UNUSED_EC 0xEC #define MB_UNUSED_ED 0xED #define MB_UNUSED_EE 0xEE -#define MB_UNUSED_EF 0xEF +#define MB_ROCK_CLIMB 0xEF #endif // GUARD_METATILE_BEHAVIORS diff --git a/include/event_scripts.h b/include/event_scripts.h index 8515597244..82d47490e9 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -541,6 +541,7 @@ extern const u8 EventScript_UseWaterfall[]; extern const u8 EventScript_CannotUseWaterfall[]; extern const u8 EventScript_UseDive[]; extern const u8 EventScript_UseDiveUnderwater[]; +extern const u8 EventScript_UseRockClimb[]; extern const u8 EventScript_FallDownHole[]; extern const u8 EventScript_FieldPoison[]; extern const u8 EventScript_EggHatch[]; diff --git a/include/field_effect.h b/include/field_effect.h index 731fb9c59f..78e2643071 100644 --- a/include/field_effect.h +++ b/include/field_effect.h @@ -46,5 +46,6 @@ void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b); void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId); u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority); void StartEscapeRopeFieldEffect(void); +bool8 IsRockClimbActive(void); #endif // GUARD_FIELD_EFFECTS_H diff --git a/include/metatile_behavior.h b/include/metatile_behavior.h index b5dae6de09..9222bf7c7e 100644 --- a/include/metatile_behavior.h +++ b/include/metatile_behavior.h @@ -145,5 +145,6 @@ bool8 MetatileBehavior_IsQuestionnaire(u8); bool8 MetatileBehavior_IsLongGrass_Duplicate(u8); bool8 MetatileBehavior_IsLongGrassSouthEdge(u8); bool8 MetatileBehavior_IsTrainerHillTimer(u8); +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior); #endif // GUARD_METATILE_BEHAVIOR diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index ae79719602..020a160c2d 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -606,6 +606,9 @@ $(FLDEFFGFXDIR)/deep_sand_footprints.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/ground_impact_dust.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 1 +$(FLDEFFGFXDIR)/rock_climb_dust.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/ash_puff.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 @@ -630,6 +633,9 @@ $(FLDEFFGFXDIR)/short_grass.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/surf_blob.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 +$(FLDEFFGFXDIR)/rock_climb_blob.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/tall_grass.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 diff --git a/src/data/field_effects/field_effect_object_template_pointers.h b/src/data/field_effects/field_effect_object_template_pointers.h index 41d6271bf2..06166747ce 100755 --- a/src/data/field_effects/field_effect_object_template_pointers.h +++ b/src/data/field_effects/field_effect_object_template_pointers.h @@ -35,6 +35,8 @@ const struct SpriteTemplate gFieldEffectObjectTemplate_AshLaunch; const struct SpriteTemplate gFieldEffectObjectTemplate_Bubbles; const struct SpriteTemplate gFieldEffectObjectTemplate_SmallSparkle; const struct SpriteTemplate gFieldEffectObjectTemplate_Rayquaza; +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob; +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust; const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_SHADOW_S] = &gFieldEffectObjectTemplate_ShadowSmall, @@ -74,4 +76,6 @@ const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_BUBBLES] = &gFieldEffectObjectTemplate_Bubbles, [FLDEFFOBJ_SMALL_SPARKLE] = &gFieldEffectObjectTemplate_SmallSparkle, [FLDEFFOBJ_RAYQUAZA] = &gFieldEffectObjectTemplate_Rayquaza, + [FLDEFFOBJ_ROCK_CLIMB_BLOB] = &gFieldEffectObjectTemplate_RockClimbBlob, + [FLDEFFOBJ_ROCK_CLIMB_DUST] = &gFieldEffectObjectTemplate_RockClimbDust, }; diff --git a/src/data/field_effects/field_effect_objects.h b/src/data/field_effects/field_effect_objects.h index 1626b9f323..5877c288ff 100755 --- a/src/data/field_effects/field_effect_objects.h +++ b/src/data/field_effects/field_effect_objects.h @@ -1287,3 +1287,48 @@ const struct SpriteTemplate gFieldEffectObjectTemplate_Rayquaza = { }; static const struct SpritePalette sSpritePalette_Unused = {gObjectEventPalette2, FLDEFF_PAL_TAG_UNKNOWN}; + +static const struct SpriteFrameImage sPicTable_RockClimbBlob[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 2), +}; + +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob = { + .tileTag = 0xFFFF, + .paletteTag = 0xFFFF, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_SurfBlob, + .images = sPicTable_RockClimbBlob, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateSurfBlobFieldEffect, +}; + + +static const union AnimCmd sAnim_RockClimbDust[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(2, 12), + ANIMCMD_END, +}; +static const union AnimCmd *const sAnimTable_RockClimbDust[] = +{ + sAnim_RockClimbDust, +}; +static const struct SpriteFrameImage sPicTable_RockClimbDust[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 2), +}; +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust = { + .tileTag = 0xFFFF, + .paletteTag = FLDEFF_PAL_TAG_DUST_CLOUD, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_RockClimbDust, + .images = sPicTable_RockClimbDust, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateJumpImpactEffect, +}; + +const struct SpritePalette gSpritePalette_BigDust = {gFieldEffectPal_DustCloud, FLDEFF_PAL_TAG_DUST_CLOUD}; diff --git a/src/data/object_events/movement_action_func_tables.h b/src/data/object_events/movement_action_func_tables.h index 8cf7d1699f..5f2d7cb9e0 100755 --- a/src/data/object_events/movement_action_func_tables.h +++ b/src/data/object_events/movement_action_func_tables.h @@ -261,6 +261,13 @@ u8 MovementAction_FlyUp_Step1(struct ObjectEvent *, struct Sprite *); u8 MovementAction_Fly_Finish(struct ObjectEvent *, struct Sprite *); u8 MovementAction_FlyDown_Step0(struct ObjectEvent *, struct Sprite *); u8 MovementAction_FlyDown_Step1(struct ObjectEvent *, struct Sprite *); +//fast diagonal +u8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *, struct Sprite *); + u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FaceUp[])(struct ObjectEvent *, struct Sprite *); @@ -420,6 +427,12 @@ u8 (*const gMovementActionFuncs_DestroyExtraTaskIfAtTop[])(struct ObjectEvent *, u8 (*const gMovementActionFuncs_Figure8[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FlyUp[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FlyDown[])(struct ObjectEvent *, struct Sprite *); +//fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *); + u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) = { [MOVEMENT_ACTION_FACE_DOWN] = gMovementActionFuncs_FaceDown, @@ -580,6 +593,12 @@ u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) [MOVEMENT_ACTION_FIGURE_8] = gMovementActionFuncs_Figure8, [MOVEMENT_ACTION_FLY_UP] = gMovementActionFuncs_FlyUp, [MOVEMENT_ACTION_FLY_DOWN] = gMovementActionFuncs_FlyDown, + //fast diagonal + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT] = gMovementActionFuncs_WalkFastDiagonalUpLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT] = gMovementActionFuncs_WalkFastDiagonalUpRight, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT] = gMovementActionFuncs_WalkFastDiagonalDownLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT] = gMovementActionFuncs_WalkFastDiagonalDownRight, + }; u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *) = { @@ -1511,3 +1530,29 @@ u8 (*const gMovementActionFuncs_DestroyExtraTaskIfAtTop[])(struct ObjectEvent *, MovementAction_DestroyExtraTaskIfAtTop_Step0, MovementAction_Finish, }; + +// fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + diff --git a/src/data/object_events/object_event_graphics.h b/src/data/object_events/object_event_graphics.h index 50fc6715c7..ac2190ea57 100755 --- a/src/data/object_events/object_event_graphics.h +++ b/src/data/object_events/object_event_graphics.h @@ -286,6 +286,8 @@ const u32 gObjectEventPic_LansatBerryTree[] = INCBIN_U32("graphics/object_events const u32 gObjectEventPic_DurinBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/durin.4bpp"); const u32 gObjectEventPic_TamatoBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/tamato.4bpp"); const u32 gFieldEffectObjectPic_SurfBlob[] = INCBIN_U32("graphics/field_effects/pics/surf_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbBlob[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbDust[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_dust.4bpp"); const u32 gObjectEventPic_QuintyPlump[] = INCBIN_U32("graphics/object_events/pics/people/quinty_plump.4bpp"); const u16 gObjectEventPalette12[] = INCBIN_U16("graphics/object_events/palettes/12.gbapal"); const u16 gObjectEventPalette13[] = INCBIN_U16("graphics/object_events/palettes/13.gbapal"); @@ -325,6 +327,7 @@ const u32 gFieldEffectObjectPic_MountainDisguise[] = INCBIN_U32("graphics/field_ const u32 gFieldEffectObjectPic_SandDisguisePlaceholder[] = INCBIN_U32("graphics/field_effects/pics/sand_disguise_placeholder.4bpp"); const u32 gFieldEffectObjectPic_HotSpringsWater[] = INCBIN_U32("graphics/field_effects/pics/hot_springs_water.4bpp"); const u16 gFieldEffectPal_Ash[] = INCBIN_U16("graphics/field_effects/palettes/ash.gbapal"); +const u16 gFieldEffectPal_DustCloud[] = INCBIN_U16("graphics/field_effects/palettes/big_dust.gbapal"); const u32 gFieldEffectObjectPic_AshPuff[] = INCBIN_U32("graphics/field_effects/pics/ash_puff.4bpp"); const u32 gFieldEffectObjectPic_AshLaunch[] = INCBIN_U32("graphics/field_effects/pics/ash_launch.4bpp"); const u32 gFieldEffectObjectPic_Bubbles[] = INCBIN_U32("graphics/field_effects/pics/bubbles.4bpp"); diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 3c3a3e1ce3..64e128af74 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -717,6 +717,7 @@ enum FIELD_MOVE_MILK_DRINK, FIELD_MOVE_SOFT_BOILED, FIELD_MOVE_SWEET_SCENT, + FIELD_MOVE_ROCK_CLIMB, }; // What a weird choice of table termination; @@ -761,6 +762,7 @@ struct [MENU_FIELD_MOVES + FIELD_MOVE_MILK_DRINK] = {gMoveNames[MOVE_MILK_DRINK], CursorCb_FieldMove}, [MENU_FIELD_MOVES + FIELD_MOVE_SOFT_BOILED] = {gMoveNames[MOVE_SOFT_BOILED], CursorCb_FieldMove}, [MENU_FIELD_MOVES + FIELD_MOVE_SWEET_SCENT] = {gMoveNames[MOVE_SWEET_SCENT], CursorCb_FieldMove}, + [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_CLIMB] = {gMoveNames[MOVE_ROCK_CLIMB], CursorCb_FieldMove}, }; static const u8 sPartyMenuAction_SummarySwitchCancel[] = {MENU_SUMMARY, MENU_SWITCH, MENU_CANCEL1}; @@ -835,7 +837,7 @@ static const u8 sPartyMenuActionCounts[] = static const u16 sFieldMoves[] = { MOVE_CUT, MOVE_FLASH, MOVE_ROCK_SMASH, MOVE_STRENGTH, MOVE_SURF, MOVE_FLY, MOVE_DIVE, MOVE_WATERFALL, MOVE_TELEPORT, - MOVE_DIG, MOVE_SECRET_POWER, MOVE_MILK_DRINK, MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, FIELD_MOVE_TERMINATOR + MOVE_DIG, MOVE_SECRET_POWER, MOVE_MILK_DRINK, MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, MOVE_ROCK_CLIMB, FIELD_MOVE_TERMINATOR }; struct @@ -858,6 +860,7 @@ struct [FIELD_MOVE_MILK_DRINK] = {SetUpFieldMove_SoftBoiled, PARTY_MSG_NOT_ENOUGH_HP}, [FIELD_MOVE_SOFT_BOILED] = {SetUpFieldMove_SoftBoiled, PARTY_MSG_NOT_ENOUGH_HP}, [FIELD_MOVE_SWEET_SCENT] = {SetUpFieldMove_SweetScent, PARTY_MSG_CANT_USE_HERE}, + [FIELD_MOVE_ROCK_CLIMB] = {SetUpFieldMove_RockClimb, PARTY_MSG_CANT_USE_HERE}, }; static const u8 *const sUnionRoomTradeMessages[] = diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 72de880c85..684b2cf1ed 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -681,10 +681,10 @@ const u8 gFaceDirectionAnimNums[] = { [DIR_NORTH] = 1, [DIR_WEST] = 2, [DIR_EAST] = 3, - [DIR_SOUTHWEST] = 0, - [DIR_SOUTHEAST] = 0, - [DIR_NORTHWEST] = 1, - [DIR_NORTHEAST] = 1, + [DIR_SOUTHWEST] = 2, + [DIR_SOUTHEAST] = 3, + [DIR_NORTHWEST] = 2, + [DIR_NORTHEAST] = 3, }; const u8 gMoveDirectionAnimNums[] = { [DIR_NONE] = 4, @@ -692,10 +692,10 @@ const u8 gMoveDirectionAnimNums[] = { [DIR_NORTH] = 5, [DIR_WEST] = 6, [DIR_EAST] = 7, - [DIR_SOUTHWEST] = 4, - [DIR_SOUTHEAST] = 4, - [DIR_NORTHWEST] = 5, - [DIR_NORTHEAST] = 5, + [DIR_SOUTHWEST] = 6, + [DIR_SOUTHEAST] = 7, + [DIR_NORTHWEST] = 6, + [DIR_NORTHEAST] = 7, }; const u8 gMoveDirectionFastAnimNums[] = { [DIR_NONE] = 8, @@ -703,10 +703,10 @@ const u8 gMoveDirectionFastAnimNums[] = { [DIR_NORTH] = 9, [DIR_WEST] = 10, [DIR_EAST] = 11, - [DIR_SOUTHWEST] = 8, - [DIR_SOUTHEAST] = 8, - [DIR_NORTHWEST] = 9, - [DIR_NORTHEAST] = 9, + [DIR_SOUTHWEST] = 10, + [DIR_SOUTHEAST] = 11, + [DIR_NORTHWEST] = 10, + [DIR_NORTHEAST] = 11, }; const u8 gMoveDirectionFasterAnimNums[] = { [DIR_NONE] = 12, @@ -736,10 +736,10 @@ const u8 gJumpSpecialDirectionAnimNums[] = { // used for jumping onto surf mon [DIR_NORTH] = 21, [DIR_WEST] = 22, [DIR_EAST] = 23, - [DIR_SOUTHWEST] = 20, - [DIR_SOUTHEAST] = 20, - [DIR_NORTHWEST] = 21, - [DIR_NORTHEAST] = 21, + [DIR_SOUTHWEST] = 22, + [DIR_SOUTHEAST] = 23, + [DIR_NORTHWEST] = 22, + [DIR_NORTHEAST] = 23, }; const u8 gAcroWheelieDirectionAnimNums[] = { [DIR_NONE] = 20, @@ -969,6 +969,10 @@ const u8 gJumpSpecialMovementActions[] = { MOVEMENT_ACTION_JUMP_SPECIAL_UP, MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, }; const u8 gWalkInPlaceSlowMovementActions[] = { MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, @@ -9006,3 +9010,40 @@ u8 MovementAction_Fly_Finish(struct ObjectEvent *objectEvent, struct Sprite *spr { return TRUE; } + +// fast diagonal +bool8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + do_go_anim(objectEvent, sprite, DIR_NORTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + do_go_anim(objectEvent, sprite, DIR_NORTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + do_go_anim(objectEvent, sprite, DIR_SOUTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + do_go_anim(objectEvent, sprite, DIR_SOUTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(objectEvent, sprite)) + { + sprite->data[2] = 2; + return TRUE; + } + return FALSE; +} + + diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index fab14c5776..73c9fa9bda 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -9,6 +9,7 @@ #include "event_scripts.h" #include "fieldmap.h" #include "field_control_avatar.h" +#include "field_effect.h" #include "field_player_avatar.h" #include "field_poison.h" #include "field_screen_effect.h" @@ -409,6 +410,8 @@ static const u8 *GetInteractedMetatileScript(struct MapPosition *position, u8 me return EventScript_Questionnaire; if (MetatileBehavior_IsTrainerHillTimer(metatileBehavior) == TRUE) return EventScript_TrainerHillTimer; + if (MetatileBehavior_IsRockClimbable(metatileBehavior) == TRUE && !IsRockClimbActive()) + return EventScript_UseRockClimb; height = position->height; if (height == MapGridGetZCoordAt(position->x, position->y)) diff --git a/src/field_effect.c b/src/field_effect.c index b64902c0ec..c7ffa23f4a 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -231,6 +231,18 @@ static void SpriteCB_DeoxysRockFragment(struct Sprite* sprite); static void Task_MoveDeoxysRock(u8 taskId); +static void Task_UseRockClimb(u8); +static bool8 RockClimb_Init(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_FieldMovePose(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ShowMon(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent); +//static bool8 RockClimb_RideUp(struct Task *, struct ObjectEvent *); +//static bool8 RockClimb_RideDown(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ContinueRideOrEnd(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent); // Static RAM declarations static u8 sActiveList[32]; @@ -3880,3 +3892,256 @@ static void Task_MoveDeoxysRock(u8 taskId) } } +// ROCK CLIMB +enum RockClimbState +{ + STATE_ROCK_CLIMB_INIT, + STATE_ROCK_CLIMB_POSE, + STATE_ROCK_CLIMB_SHOW_MON, + STATE_ROCK_CLIMB_JUMP_ON, + STATE_ROCK_CLIMB_WAIT_JUMP, + STATE_ROCK_CLIMB_RIDE, + STATE_ROCK_CLIMB_CONTINUE_RIDE, + STATE_ROCK_CLIMB_STOP_INIT, + STATE_ROCK_CLIMB_WAIT_STOP +}; + +#define tState data[0] +#define tDestX data[1] +#define tDestY data[2] +#define tMonId data[15] + +static u8 CreateRockClimbBlob(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_BLOB], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x96); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.paletteNum = 0; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = -1; + sprite->data[6] = -1; + sprite->data[7] = -1; + } + + return spriteId; +} + +bool8 (*const sRockClimbFieldEffectFuncs[])(struct Task *, struct ObjectEvent *) = +{ + [STATE_ROCK_CLIMB_INIT] = RockClimb_Init, + [STATE_ROCK_CLIMB_POSE] = RockClimb_FieldMovePose, + [STATE_ROCK_CLIMB_SHOW_MON] = RockClimb_ShowMon, + [STATE_ROCK_CLIMB_JUMP_ON] = RockClimb_JumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_WAIT_JUMP] = RockClimb_WaitJumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_RIDE] = RockClimb_Ride, + [STATE_ROCK_CLIMB_CONTINUE_RIDE] = RockClimb_ContinueRideOrEnd, + [STATE_ROCK_CLIMB_STOP_INIT] = RockClimb_StopRockClimbInit, + [STATE_ROCK_CLIMB_WAIT_STOP] = RockClimb_WaitStopRockClimb +}; + +bool8 FldEff_UseRockClimb(void) +{ + u8 taskId; + taskId = CreateTask(Task_UseRockClimb, 0xff); + gTasks[taskId].tMonId = gFieldEffectArguments[0]; + Task_UseRockClimb(taskId); + return FALSE; +} + +static void Task_UseRockClimb(u8 taskId) +{ + while (sRockClimbFieldEffectFuncs[gTasks[taskId].tState](&gTasks[taskId], &gObjectEvents[gPlayerAvatar.objectEventId])); +} + +static bool8 RockClimb_Init(struct Task *task, struct ObjectEvent *objectEvent) +{ + ScriptContext2_Enable(); + FreezeObjectEvents(); + gPlayerAvatar.preventStep = TRUE; + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].movementDirection, &task->tDestX, &task->tDestY); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_FieldMovePose(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventIsMovementOverridden(objectEvent) || ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetPlayerAvatarFieldMove(); + ObjectEventSetHeldMovement(objectEvent, MOVEMENT_ACTION_START_ANIM_IN_DIRECTION); + task->tState++; + } + return FALSE; +} + +static bool8 RockClimb_ShowMon(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventCheckHeldMovementStatus(objectEvent)) + { + gFieldEffectArguments[0] = task->tMonId | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->tState++; + return TRUE; + } + return FALSE; +} + +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_SURFING)); + ObjectEventClearHeldMovementIfFinished(objectEvent); + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(objectEvent->movementDirection)); + gFieldEffectArguments[0] = task->tDestX; + gFieldEffectArguments[1] = task->tDestY; + gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; + objectEvent->fieldEffectSpriteId = CreateRockClimbBlob(); + task->tState++; + } + + return FALSE; +} + +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetSurfBobState(objectEvent->fieldEffectSpriteId, 1); + switch (objectEvent->facingDirection) + { + case DIR_EAST: + //check southeast then northeast + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHEAST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHEAST; + break; + case DIR_WEST: + //check northwest then southwest + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHWEST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHWEST; + break; + } + + task->tState++; + } + + return FALSE; +} + +struct RockClimbRide +{ + u8 action; + s8 dx; + s8 dy; + u8 jumpDir; +}; +static const struct RockClimbRide sRockClimbMovement[] = +{ + [DIR_NONE] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, 0, DIR_NONE}, + [DIR_SOUTH] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, -1, DIR_SOUTH}, + [DIR_NORTH] = {MOVEMENT_ACTION_WALK_FAST_UP, 0, 1, DIR_NORTH}, + [DIR_WEST] = {MOVEMENT_ACTION_WALK_FAST_LEFT, 1, 1, DIR_WEST}, + [DIR_EAST] = {MOVEMENT_ACTION_WALK_FAST_RIGHT, -1, -1, DIR_EAST}, + [DIR_SOUTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT, 1, -1, DIR_WEST}, + [DIR_SOUTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT, -1, -1, DIR_EAST}, + [DIR_NORTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT, 1, 1, DIR_WEST}, + [DIR_NORTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT, -1, 1, DIR_EAST}, +}; + +static void RockClimbDust(struct ObjectEvent *objectEvent, u8 direction) +{ + s8 dx = sRockClimbMovement[direction].dx; + s8 dy = sRockClimbMovement[direction].dy; + + gFieldEffectArguments[0] = objectEvent->currentCoords.x + dx; + gFieldEffectArguments[1] = objectEvent->currentCoords.y + dy; + gFieldEffectArguments[2] = objectEvent->previousElevation; + gFieldEffectArguments[3] = gSprites[objectEvent->spriteId].oam.priority; + FieldEffectStart(FLDEFF_ROCK_CLIMB_DUST); +} + +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent) +{ + ObjectEventSetHeldMovement(objectEvent, sRockClimbMovement[objectEvent->movementDirection].action); + PlaySE(SE_M_ROCK_THROW); + RockClimbDust(objectEvent, objectEvent->movementDirection); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(objectEvent->movementDirection, &task->tDestX, &task->tDestY); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX, task->tDestY))) + { + task->tState = STATE_ROCK_CLIMB_RIDE; + return TRUE; + } + + ScriptContext2_Enable(); + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; + task->tState++; + return FALSE; +} + +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventIsMovementOverridden(objectEvent)) + { + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + } + + RockClimbDust(objectEvent, DIR_NONE); //dust on final spot + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(sRockClimbMovement[objectEvent->movementDirection].jumpDir)); + SetSurfBobState(objectEvent->fieldEffectSpriteId, 0); + task->tState++; + return TRUE; +} + +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_NORMAL)); + ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->facingDirection)); + gPlayerAvatar.preventStep = FALSE; + ScriptContext2_Disable(); + DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); + FieldEffectActiveListRemove(FLDEFF_USE_ROCK_CLIMB); + DestroyTask(FindTaskIdByFunc(Task_UseRockClimb)); + } + + return FALSE; +} + +bool8 IsRockClimbActive(void) +{ + if (FieldEffectActiveListContains(FLDEFF_USE_ROCK_CLIMB)) + return TRUE; + else + return FALSE; +} + + +#undef tState +#undef tDestX +#undef tDestY +#undef tMonId + diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index 886e023d1c..29f4272c86 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -1057,10 +1057,12 @@ static void CreateBobbingEffect(struct ObjectEvent *objectEvent, struct Sprite * { sprite->pos2.y += sprite->data[3]; } + if ((sprite->data[4] & 0x0F) == 0) { sprite->data[3] = -sprite->data[3]; } + if (bobState != 2) { if (GetSurfBobWhileFishingState(sprite) == 0) @@ -1120,6 +1122,24 @@ u32 FldEff_Dust(void) return 0; } +u32 FldEff_RockClimbDust(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_DUST], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = FLDEFF_ROCK_CLIMB_DUST; + } + return 0; +} + u32 FldEff_SandPile(void) { u8 objectEventId; diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c index 435ad72336..151a7a29ec 100644 --- a/src/metatile_behavior.c +++ b/src/metatile_behavior.c @@ -249,7 +249,7 @@ static const u8 sTileBitAttributes[] = [MB_UNUSED_EC] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE), [MB_UNUSED_ED] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE), [MB_UNUSED_EE] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE), - [MB_UNUSED_EF] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + [MB_ROCK_CLIMB] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE), }; bool8 MetatileBehavior_IsATile(u8 metatileBehavior) @@ -1488,3 +1488,11 @@ bool8 MetatileBehavior_IsTrainerHillTimer(u8 metatileBehavior) else return FALSE; } + +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior) +{ + if (metatileBehavior == MB_ROCK_CLIMB) + return TRUE; + else + return FALSE; +} diff --git a/src/party_menu.c b/src/party_menu.c index 7514cf545e..2fedc54f8e 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -405,6 +405,7 @@ static bool8 SetUpFieldMove_Surf(void); static bool8 SetUpFieldMove_Fly(void); static bool8 SetUpFieldMove_Waterfall(void); static bool8 SetUpFieldMove_Dive(void); +static bool8 SetUpFieldMove_RockClimb(void); // static const data #include "data/pokemon/tutor_learnsets.h" @@ -6353,3 +6354,24 @@ void IsLastMonThatKnowsSurf(void) gSpecialVar_Result = TRUE; } } + +static void FieldCallback_RockClimb(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + FieldEffectStart(FLDEFF_USE_ROCK_CLIMB); +} + +static bool8 SetUpFieldMove_RockClimb(void) +{ + s16 x, y; + + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(x, y))) + { + gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu; + gPostMenuFieldCallback = FieldCallback_RockClimb; + return TRUE; + } + + return FALSE; +} From 7d1a1abe51950796d9433999ca1e8d8646b7a792 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Mon, 31 Aug 2020 12:12:32 +0200 Subject: [PATCH 002/283] Update Rock Climb script Small fixes and make it more consistent with other field move scripts. --- data/scripts/field_move_scripts.inc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index d04304abc9..5d1cb31fcb 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -302,7 +302,6 @@ EventScript_FailSweetScent:: @ 8290CAE Text_FailSweetScent: @ 8290CB7 .string "Looks like there's nothing here…$" - EventScript_UseRockClimb:: lockall checkpartymove MOVE_ROCK_CLIMB @@ -314,16 +313,25 @@ EventScript_UseRockClimb:: compare VAR_RESULT, NO goto_if_eq EventScript_EndRockClimb msgbox Text_MonUsedRockClimb, MSGBOX_DEFAULT + closemessage dofieldeffect FLDEFF_USE_ROCK_CLIMB + waitstate goto EventScript_EndRockClimb -EventScript_CantRockClimb:: @ 8290A84 + +EventScript_CantRockClimb:: msgbox Text_CantRockClimb, MSGBOX_DEFAULT -EventScript_EndRockClimb:: @ 8290A8C + +EventScript_EndRockClimb:: releaseall end + Text_WantToRockClimb: - .string "The cliff is steep.\nWould you like to use Rock Climb?$" + .string "The cliff is steep.\n" + .string "Would you like to use Rock Climb?$" + Text_MonUsedRockClimb: .string "{STR_VAR_1} used Rock Climb!$" + Text_CantRockClimb: - .string "The cliff is steep.\nA Pokémon may be able to climb it.$" + .string "The cliff is steep.\n" + .string "A Pokémon may be able to climb it.$" From 50d20131ff32cf557e8a4addf8c2bbfa6fcab23f Mon Sep 17 00:00:00 2001 From: Evan Date: Tue, 1 Sep 2020 16:13:34 -0600 Subject: [PATCH 003/283] fix single climbable tile (thx skeli) --- src/field_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field_effect.c b/src/field_effect.c index c7ffa23f4a..1ecbeb482f 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4033,7 +4033,7 @@ static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectE break; } - task->tState++; + task->tState = STATE_ROCK_CLIMB_CONTINUE_RIDE; } return FALSE; From 529709b5ec6d0448d07c5514e21466ceef2ecb6b Mon Sep 17 00:00:00 2001 From: Evan Date: Mon, 14 Sep 2020 20:08:08 -0600 Subject: [PATCH 004/283] fix diagonal surf blob facing --- src/field_effect_helpers.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index 29f4272c86..ae0e1c04f0 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -1013,10 +1013,10 @@ static void SynchroniseSurfAnim(struct ObjectEvent *objectEvent, struct Sprite * [DIR_NORTH] = 1, [DIR_WEST] = 2, [DIR_EAST] = 3, - [DIR_SOUTHWEST] = 0, - [DIR_SOUTHEAST] = 0, - [DIR_NORTHWEST] = 1, - [DIR_NORTHEAST] = 1, + [DIR_SOUTHWEST] = 2, + [DIR_SOUTHEAST] = 3, + [DIR_NORTHWEST] = 2, + [DIR_NORTHEAST] = 3, }; if (GetSurfBobWhileFlyingOutState(sprite) == 0) From 8f5bef1ec578192c58239748b837fb56b8d8a260 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 25 Oct 2020 09:46:28 -0600 Subject: [PATCH 005/283] follower attaches to riding player --- include/constants/global.h | 2 ++ src/field_effect.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/constants/global.h b/include/constants/global.h index 55830ae8b2..2f256e7bbc 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -117,4 +117,6 @@ #define DIR_NORTHWEST 7 #define DIR_NORTHEAST 8 +#define FOLLOW_ME_IMPLEMENTED FALSE + #endif // GUARD_CONSTANTS_GLOBAL_H diff --git a/src/field_effect.c b/src/field_effect.c index 1ecbeb482f..f524d90583 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -245,6 +245,10 @@ static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent * static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent); // Static RAM declarations +#if FOLLOW_ME_IMPLEMENTED +static void TryAttachFollowerToPlayer(void); +#endif + static u8 sActiveList[32]; // External declarations @@ -1882,6 +1886,10 @@ static bool8 WaterfallFieldEffect_ContinueRideOrEnd(struct Task *task, struct Ob { if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) return FALSE; + + #if FOLLOW_ME_IMPLEMENTED + TryAttachFollowerToPlayer(); + #endif if (MetatileBehavior_IsWaterfall(objectEvent->currentMetatileBehavior)) { @@ -4085,6 +4093,10 @@ static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent * if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) return FALSE; + #if FOLLOW_ME_IMPLEMENTED + TryAttachFollowerToPlayer(); + #endif + PlayerGetDestCoords(&task->tDestX, &task->tDestY); MoveCoords(objectEvent->movementDirection, &task->tDestX, &task->tDestY); if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX, task->tDestY))) @@ -4140,6 +4152,19 @@ bool8 IsRockClimbActive(void) } +#if FOLLOW_ME_IMPLEMENTED +static void TryAttachFollowerToPlayer(void) +{ + if (gFollowerState.inProgress) + { + //Keep the follow close by while its hidden to prevent it from going too far out of view + struct ObjectEvent* player = &gObjectEvents[gPlayerAvatar.eventObjectId]; + struct ObjectEvent* follower = &gObjectEvents[GetFollowerMapObjId()]; + MoveObjectEventToMapCoords(follower, player->currentCoords.x, player->currentCoords.y); + } +} +#endif + #undef tState #undef tDestX #undef tDestY From 8c556c727405be16a7c74e2af41d93e3bea450fb Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 25 Oct 2020 09:50:16 -0600 Subject: [PATCH 006/283] fix follower check --- src/field_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field_effect.c b/src/field_effect.c index f524d90583..70075d2496 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4155,7 +4155,7 @@ bool8 IsRockClimbActive(void) #if FOLLOW_ME_IMPLEMENTED static void TryAttachFollowerToPlayer(void) { - if (gFollowerState.inProgress) + if (PlayerHasFollower()) { //Keep the follow close by while its hidden to prevent it from going too far out of view struct ObjectEvent* player = &gObjectEvents[gPlayerAvatar.eventObjectId]; From c66b03e0832be9ef0ad2521a28f07f251018eb82 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 25 Oct 2020 09:52:17 -0600 Subject: [PATCH 007/283] fix player avatar element --- src/field_effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field_effect.c b/src/field_effect.c index 70075d2496..93ac5dbab0 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4158,7 +4158,7 @@ static void TryAttachFollowerToPlayer(void) if (PlayerHasFollower()) { //Keep the follow close by while its hidden to prevent it from going too far out of view - struct ObjectEvent* player = &gObjectEvents[gPlayerAvatar.eventObjectId]; + struct ObjectEvent* player = &gObjectEvents[gPlayerAvatar.objectEventId]; struct ObjectEvent* follower = &gObjectEvents[GetFollowerMapObjId()]; MoveObjectEventToMapCoords(follower, player->currentCoords.x, player->currentCoords.y); } From 15f7a6ecbb88c6f1c8e6940844ff95d06688fdcd Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 3 Dec 2020 14:35:04 -0500 Subject: [PATCH 008/283] fix rock climb retaining bike flags --- src/field_effect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/field_effect.c b/src/field_effect.c index 734c103ca6..00c456dfe5 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -3972,6 +3972,7 @@ static bool8 RockClimb_Init(struct Task *task, struct ObjectEvent *objectEvent) ScriptContext2_Enable(); FreezeObjectEvents(); gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_SURFING); PlayerGetDestCoords(&task->tDestX, &task->tDestY); MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].movementDirection, &task->tDestX, &task->tDestY); task->tState++; @@ -4107,6 +4108,7 @@ static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent * ScriptContext2_Enable(); gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5; gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; task->tState++; return FALSE; From df145ecb24ac7ae65699d66d46b87dee335a07cb Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 7 Feb 2021 11:44:40 -0700 Subject: [PATCH 009/283] fix rock climb not unfreezing objects. Thx Sph. Ice --- src/field_effect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field_effect.c b/src/field_effect.c index a1858ba572..1b9fe6347e 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4143,6 +4143,7 @@ static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent * ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_NORMAL)); ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->facingDirection)); gPlayerAvatar.preventStep = FALSE; + UnfreezeObjectEvents(); ScriptContext2_Disable(); DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); FieldEffectActiveListRemove(FLDEFF_USE_ROCK_CLIMB); From af36b25817e45824edef3f3609b82a86de6cd230 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 14 Jun 2021 11:34:08 -0600 Subject: [PATCH 010/283] trigger ground effects on rock climb dismount --- src/field_effect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field_effect.c b/src/field_effect.c index 8285bf3dfc..bd036aa3cb 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4140,6 +4140,7 @@ static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent * ScriptContext2_Disable(); DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); FieldEffectActiveListRemove(FLDEFF_USE_ROCK_CLIMB); + objectEvent->triggerGroundEffectsOnMove = TRUE; // e.g. if dismount on grass DestroyTask(FindTaskIdByFunc(Task_UseRockClimb)); } From df46fe1700ca1ae1e33b44f01786ee9e3653322e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 14 Jun 2021 12:47:18 -0600 Subject: [PATCH 011/283] rename relevant functions --- include/constants/moves.h | 4 ++++ src/data/party_menu.h | 8 +++++++- src/event_object_movement.c | 10 +++++----- src/field_effect.c | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/constants/moves.h b/include/constants/moves.h index 85c02e3da5..51a9b3c27c 100644 --- a/include/constants/moves.h +++ b/include/constants/moves.h @@ -1,6 +1,10 @@ #ifndef GUARD_CONSTANTS_MOVES_H #define GUARD_CONSTANTS_MOVES_H +#ifndef BATTLE_ENGINE + #define MOVE_ROCK_CLIMB 1 +#endif + #define MOVE_NONE 0 #define MOVE_POUND 1 #define MOVE_KARATE_CHOP 2 diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 7852b9decc..9696502ceb 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -762,7 +762,9 @@ struct [MENU_FIELD_MOVES + FIELD_MOVE_MILK_DRINK] = {gMoveNames[MOVE_MILK_DRINK], CursorCb_FieldMove}, [MENU_FIELD_MOVES + FIELD_MOVE_SOFT_BOILED] = {gMoveNames[MOVE_SOFT_BOILED], CursorCb_FieldMove}, [MENU_FIELD_MOVES + FIELD_MOVE_SWEET_SCENT] = {gMoveNames[MOVE_SWEET_SCENT], CursorCb_FieldMove}, + #ifdef BATTLE_ENGINE [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_CLIMB] = {gMoveNames[MOVE_ROCK_CLIMB], CursorCb_FieldMove}, + #endif }; static const u8 sPartyMenuAction_SummarySwitchCancel[] = {MENU_SUMMARY, MENU_SWITCH, MENU_CANCEL1}; @@ -837,7 +839,11 @@ static const u8 sPartyMenuActionCounts[] = static const u16 sFieldMoves[] = { MOVE_CUT, MOVE_FLASH, MOVE_ROCK_SMASH, MOVE_STRENGTH, MOVE_SURF, MOVE_FLY, MOVE_DIVE, MOVE_WATERFALL, MOVE_TELEPORT, - MOVE_DIG, MOVE_SECRET_POWER, MOVE_MILK_DRINK, MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, MOVE_ROCK_CLIMB, FIELD_MOVE_TERMINATOR + MOVE_DIG, MOVE_SECRET_POWER, MOVE_MILK_DRINK, MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, + #ifdef BATTLE_ENGINE + MOVE_ROCK_CLIMB, + #endif + FIELD_MOVE_TERMINATOR }; struct diff --git a/src/event_object_movement.c b/src/event_object_movement.c index e52cdc5146..e54bf8d52f 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -9025,31 +9025,31 @@ u8 MovementAction_Fly_Finish(struct ObjectEvent *objectEvent, struct Sprite *spr // fast diagonal bool8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - do_go_anim(objectEvent, sprite, DIR_NORTHWEST, 1); + InitMovementNormal(objectEvent, sprite, DIR_NORTHWEST, 1); return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); } bool8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - do_go_anim(objectEvent, sprite, DIR_NORTHEAST, 1); + InitMovementNormal(objectEvent, sprite, DIR_NORTHEAST, 1); return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); } bool8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - do_go_anim(objectEvent, sprite, DIR_SOUTHWEST, 1); + InitMovementNormal(objectEvent, sprite, DIR_SOUTHWEST, 1); return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); } bool8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - do_go_anim(objectEvent, sprite, DIR_SOUTHEAST, 1); + InitMovementNormal(objectEvent, sprite, DIR_SOUTHEAST, 1); return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); } bool8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - if (npc_obj_ministep_stop_on_arrival(objectEvent, sprite)) + if (UpdateMovementNormal(objectEvent, sprite)) { sprite->data[2] = 2; return TRUE; diff --git a/src/field_effect.c b/src/field_effect.c index bd036aa3cb..a2129f1cee 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4023,7 +4023,7 @@ static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectE { if (ObjectEventClearHeldMovementIfFinished(objectEvent)) { - SetSurfBobState(objectEvent->fieldEffectSpriteId, 1); + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_PLAYER_AND_MON); switch (objectEvent->facingDirection) { case DIR_EAST: @@ -4124,7 +4124,7 @@ static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent * RockClimbDust(objectEvent, DIR_NONE); //dust on final spot ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(sRockClimbMovement[objectEvent->movementDirection].jumpDir)); - SetSurfBobState(objectEvent->fieldEffectSpriteId, 0); + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_NONE); task->tState++; return TRUE; } From a626b4be1987b0952694cfd9ba5815fedfe79a87 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 20 Dec 2021 13:04:04 -0500 Subject: [PATCH 012/283] fix end rock climb --- src/field_effect.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/field_effect.c b/src/field_effect.c index e5ee0b34df..009f4a8c2b 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -4106,7 +4106,6 @@ static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent * ScriptContext2_Enable(); gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; - gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5; gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; task->tState++; return FALSE; From 8cf7de166ceceb1f99764c54632d51446fe9ff50 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 4 Aug 2024 12:32:26 -0400 Subject: [PATCH 013/283] use gMovesInfo for rock climb given expansion's changes --- src/data/party_menu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 555f91f793..2518fc669d 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -691,7 +691,7 @@ struct [MENU_FIELD_MOVES + FIELD_MOVE_SOFT_BOILED] = {gMoveNames[MOVE_SOFT_BOILED], CursorCb_FieldMove}, [MENU_FIELD_MOVES + FIELD_MOVE_SWEET_SCENT] = {gMoveNames[MOVE_SWEET_SCENT], CursorCb_FieldMove}, #ifdef BATTLE_ENGINE - [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_CLIMB] = {gMoveNames[MOVE_ROCK_CLIMB], CursorCb_FieldMove}, + [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_CLIMB] = {gMovesInfo[MOVE_ROCK_CLIMB].name, CursorCb_FieldMove}, #endif }; From 720b2daecc2054e6e9b8d370dc7fbaf182c1a794 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 18:25:27 -0300 Subject: [PATCH 014/283] Improve Pyramid location documentaion --- asm/macros/battle_frontier/battle_pyramid.inc | 4 ++-- data/scripts/field_poison.inc | 6 +++--- data/scripts/obtain_item.inc | 4 ++-- include/battle_pyramid.h | 9 ++++++++- include/constants/battle_pyramid.h | 6 +++++- src/battle_pyramid.c | 16 ++++++++-------- src/field_poison.c | 2 +- src/frontier_pass.c | 6 +++--- src/item_use.c | 2 +- src/party_menu.c | 2 +- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/asm/macros/battle_frontier/battle_pyramid.inc b/asm/macros/battle_frontier/battle_pyramid.inc index bb5069f18a..42141d9937 100644 --- a/asm/macros/battle_frontier/battle_pyramid.inc +++ b/asm/macros/battle_frontier/battle_pyramid.inc @@ -69,8 +69,8 @@ .endm @ VAR_RESULT is 1 if player is on a Pyramid floor, 2 if on the Pyramid peak, 0 otherwise - .macro pyramid_inchallenge - setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_IS_IN + .macro pyramid_getlocation + setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_CURRENT_LOCATION special CallBattlePyramidFunction .endm diff --git a/data/scripts/field_poison.inc b/data/scripts/field_poison.inc index ddda34ebaa..1d89bcfdfd 100644 --- a/data/scripts/field_poison.inc +++ b/data/scripts/field_poison.inc @@ -29,9 +29,9 @@ EventScript_FrontierFieldWhiteOut:: waitbuttonpress pike_inchallenge goto_if_eq VAR_RESULT, TRUE, BattleFrontier_BattlePike_EventScript_Retire - pyramid_inchallenge - goto_if_eq VAR_RESULT, 1, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost @ On Pyramid floor - goto_if_eq VAR_RESULT, 2, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost @ On Pyramid peak + pyramid_getlocation + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_FLOOR, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_TOP, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost trainerhill_inchallenge goto_if_eq VAR_RESULT, TRUE, TrainerHill_1F_EventScript_Lost special Script_FadeOutMapMusic diff --git a/data/scripts/obtain_item.inc b/data/scripts/obtain_item.inc index e982858e7b..6831a75b6e 100644 --- a/data/scripts/obtain_item.inc +++ b/data/scripts/obtain_item.inc @@ -118,8 +118,8 @@ EventScript_PickUpItem:: waitfanfare waitmessage bufferitemnameplural STR_VAR_2, VAR_0x8004, VAR_0x8005 - pyramid_inchallenge - goto_if_eq VAR_RESULT, TRUE, EventScript_PutBattlePyramidItemInBag + pyramid_getlocation + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_FLOOR, EventScript_PutBattlePyramidItemInBag msgbox gText_PutItemInPocket, MSGBOX_DEFAULT return diff --git a/include/battle_pyramid.h b/include/battle_pyramid.h index 62320358b6..8b35e9967c 100644 --- a/include/battle_pyramid.h +++ b/include/battle_pyramid.h @@ -1,13 +1,15 @@ #ifndef GUARD_BATTLE_PYRAMID_H #define GUARD_BATTLE_PYRAMID_H +#include "constants/battle_pyramid.h" + void CallBattlePyramidFunction(void); u16 LocalIdToPyramidTrainerId(u8 localId); bool8 GetBattlePyramidTrainerFlag(u8 eventId); void MarkApproachingPyramidTrainersAsBattled(void); void GenerateBattlePyramidWildMon(void); u8 GetPyramidRunMultiplier(void); -u8 InBattlePyramid(void); +u8 CurrentBattlePyramidLocation(void); bool8 InBattlePyramid_(void); void PausePyramidChallenge(void); void SoftResetInBattlePyramid(void); @@ -21,4 +23,9 @@ void LoadBattlePyramidFloorObjectEventScripts(void); u8 GetNumBattlePyramidObjectEvents(void); u16 GetBattlePyramidPickupItemId(void); +static inline bool8 InBattlePyramid() +{ + return (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE); +} + #endif // GUARD_BATTLE_PYRAMID_H diff --git a/include/constants/battle_pyramid.h b/include/constants/battle_pyramid.h index ac80a2d7d3..08fa695cf2 100644 --- a/include/constants/battle_pyramid.h +++ b/include/constants/battle_pyramid.h @@ -43,7 +43,7 @@ #define BATTLE_PYRAMID_FUNC_SET_TRAINERS 9 #define BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT 10 #define BATTLE_PYRAMID_FUNC_UPDATE_STREAK 11 // unused -#define BATTLE_PYRAMID_FUNC_IS_IN 12 +#define BATTLE_PYRAMID_FUNC_CURRENT_LOCATION 12 #define BATTLE_PYRAMID_FUNC_UPDATE_LIGHT 13 #define BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS 14 #define BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE 15 @@ -62,4 +62,8 @@ #define PYRAMID_LIGHT_SET_RADIUS 0 #define PYRAMID_LIGHT_INCR_RADIUS 1 +#define PYRAMID_LOCATION_NONE 0 // Not in the Pyramid +#define PYRAMID_LOCATION_FLOOR 1 +#define PYRAMID_LOCATION_TOP 2 + #endif // GUARD_CONSTANTS_BATTLE_PYRAMID_H diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index b4bb3cacca..b463e85357 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -79,7 +79,7 @@ static void HidePyramidItem(void); static void SetPyramidFacilityTrainers(void); static void ShowPostBattleHintText(void); static void UpdatePyramidWinStreak(void); -static void GetInBattlePyramid(void); +static void GetCurrentBattlePyramidLocation(void); static void UpdatePyramidLightRadius(void); static void ClearPyramidPartyHeldItems(void); static void SetPyramidFloorPalette(void); @@ -798,7 +798,7 @@ static void (* const sBattlePyramidFunctions[])(void) = [BATTLE_PYRAMID_FUNC_SET_TRAINERS] = SetPyramidFacilityTrainers, [BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT] = ShowPostBattleHintText, [BATTLE_PYRAMID_FUNC_UPDATE_STREAK] = UpdatePyramidWinStreak, - [BATTLE_PYRAMID_FUNC_IS_IN] = GetInBattlePyramid, + [BATTLE_PYRAMID_FUNC_CURRENT_LOCATION] = GetCurrentBattlePyramidLocation, [BATTLE_PYRAMID_FUNC_UPDATE_LIGHT] = UpdatePyramidLightRadius, [BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS] = ClearPyramidPartyHeldItems, [BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE] = SetPyramidFloorPalette, @@ -1113,9 +1113,9 @@ static void UpdatePyramidWinStreak(void) gSaveBlock2Ptr->frontier.pyramidRecordStreaks[lvlMode] = gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode]; } -static void GetInBattlePyramid(void) +static void GetCurrentBattlePyramidLocation(void) { - gSpecialVar_Result = InBattlePyramid(); + gSpecialVar_Result = CurrentBattlePyramidLocation(); } static void UpdatePyramidLightRadius(void) @@ -1419,14 +1419,14 @@ u8 GetPyramidRunMultiplier(void) return sPyramidFloorTemplates[id].runMultiplier; } -u8 InBattlePyramid(void) +u8 CurrentBattlePyramidLocation(void) { if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR) - return 1; + return PYRAMID_LOCATION_FLOOR; else if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP) - return 2; + return PYRAMID_LOCATION_TOP; else - return FALSE; + return PYRAMID_LOCATION_NONE; } bool8 InBattlePyramid_(void) diff --git a/src/field_poison.c b/src/field_poison.c index d952b4b640..e0b08b8716 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -92,7 +92,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) #ifdef BUGFIX if (InBattlePyramid() || InBattlePike() || InTrainerHillChallenge()) #else - if (InBattlePyramid() | InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif gSpecialVar_Result = FLDPSN_FRONTIER_WHITEOUT; else diff --git a/src/frontier_pass.c b/src/frontier_pass.c index a351d81ce9..960684c9ea 100644 --- a/src/frontier_pass.c +++ b/src/frontier_pass.c @@ -917,12 +917,12 @@ static void CB2_ReturnFromRecord(void) sPassData->cursorX = sSavedPassData.cursorX; sPassData->cursorY = sSavedPassData.cursorY; memset(&sSavedPassData, 0, sizeof(sSavedPassData)); - switch (InBattlePyramid()) + switch (CurrentBattlePyramidLocation()) { - case 1: + case PYRAMID_LOCATION_FLOOR: PlayBGM(MUS_B_PYRAMID); break; - case 2: + case PYRAMID_LOCATION_TOP: PlayBGM(MUS_B_PYRAMID_TOP); break; default: diff --git a/src/item_use.c b/src/item_use.c index 322eaf76c0..181698ac30 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // !InBattlePyramid() doesn't match DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); diff --git a/src/party_menu.c b/src/party_menu.c index cbd469713a..f6dd6a264c 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5358,7 +5358,7 @@ void CB2_PartyMenuFromStartMenu(void) // As opposted to by selecting Give in the party menu, which is handled by CursorCb_Give void CB2_ChooseMonToGiveItem(void) { - MainCallback callback = (InBattlePyramid() == FALSE) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; + MainCallback callback = (!InBattlePyramid()) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback); gPartyMenu.bagItem = gSpecialVar_ItemId; } From 29ef1cf9ad37a684ba7e379b5865840d326e4257 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 21:00:55 -0300 Subject: [PATCH 015/283] Stick to the new name --- include/battle_pyramid.h | 5 ----- src/battle_pyramid.c | 4 ++-- src/battle_script_commands.c | 2 +- src/battle_setup.c | 24 ++++++++++++------------ src/battle_util.c | 4 ++-- src/event_object_movement.c | 4 ++-- src/field_poison.c | 2 +- src/item.c | 8 ++++---- src/item_menu.c | 4 ++-- src/item_use.c | 26 +++++++++++++------------- src/map_name_popup.c | 2 +- src/party_menu.c | 6 +++--- src/pokemon.c | 4 ++-- src/start_menu.c | 10 +++++----- src/trainer_see.c | 2 +- src/wild_encounter.c | 2 +- 16 files changed, 52 insertions(+), 57 deletions(-) diff --git a/include/battle_pyramid.h b/include/battle_pyramid.h index 8b35e9967c..990a2eca52 100644 --- a/include/battle_pyramid.h +++ b/include/battle_pyramid.h @@ -23,9 +23,4 @@ void LoadBattlePyramidFloorObjectEventScripts(void); u8 GetNumBattlePyramidObjectEvents(void); u16 GetBattlePyramidPickupItemId(void); -static inline bool8 InBattlePyramid() -{ - return (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE); -} - #endif // GUARD_BATTLE_PYRAMID_H diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index b463e85357..f4352a62b8 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -1437,7 +1437,7 @@ bool8 InBattlePyramid_(void) void PausePyramidChallenge(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { RestorePyramidPlayerParty(); gSaveBlock2Ptr->frontier.challengeStatus = CHALLENGE_STATUS_PAUSED; @@ -1448,7 +1448,7 @@ void PausePyramidChallenge(void) void SoftResetInBattlePyramid(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) DoSoftReset(); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1891ea9285..db92de3c81 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9615,7 +9615,7 @@ static void Cmd_pickup(void) { } - else if (InBattlePyramid()) + else if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { for (i = 0; i < PARTY_SIZE; i++) { diff --git a/src/battle_setup.c b/src/battle_setup.c index ba5cdef0dc..18119a5255 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -405,7 +405,7 @@ static void DoStandardWildBattle(void) StopPlayerAvatar(); gMain.savedCallback = CB2_EndWildBattle; gBattleTypeFlags = 0; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; @@ -465,7 +465,7 @@ static void DoTrainerBattle(void) static void DoBattlePyramidTrainerHillBattle(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID), 0); else CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_TRAINER_HILL), 0); @@ -603,7 +603,7 @@ static void CB2_EndWildBattle(void) CpuFill16(0, (void *)(BG_PLTT), BG_PLTT_SIZE); ResetOamRange(0, 128); - if (IsPlayerDefeated(gBattleOutcome) == TRUE && !InBattlePyramid() && !InBattlePike()) + if (IsPlayerDefeated(gBattleOutcome) == TRUE && CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE && !InBattlePike()) { SetMainCallback2(CB2_WhiteOut); } @@ -621,7 +621,7 @@ static void CB2_EndScriptedWildBattle(void) if (IsPlayerDefeated(gBattleOutcome) == TRUE) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); else SetMainCallback2(CB2_WhiteOut); @@ -794,14 +794,14 @@ static u8 GetWildBattleTransition(void) if (enemyLevel < playerLevel) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return B_TRANSITION_BLUR; else return sBattleTransitionTable_Wild[transitionType][0]; } else { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return B_TRANSITION_GRID_SQUARES; else return sBattleTransitionTable_Wild[transitionType][1]; @@ -1233,7 +1233,7 @@ u8 GetTrainerBattleMode(void) bool8 GetTrainerFlag(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return GetBattlePyramidTrainerFlag(gSelectedObjectEvent); else if (InTrainerHill()) return GetHillTrainerFlag(gSelectedObjectEvent); @@ -1275,7 +1275,7 @@ void BattleSetup_StartTrainerBattle(void) else gBattleTypeFlags = (BATTLE_TYPE_TRAINER); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; @@ -1315,7 +1315,7 @@ void BattleSetup_StartTrainerBattle(void) gWhichTrainerToFaceAfterBattle = 0; gMain.savedCallback = CB2_EndTrainerBattle; - if (InBattlePyramid() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InTrainerHillChallenge()) DoBattlePyramidTrainerHillBattle(); else DoTrainerBattle(); @@ -1331,7 +1331,7 @@ static void CB2_EndTrainerBattle(void) } else if (IsPlayerDefeated(gBattleOutcome) == TRUE) { - if (InBattlePyramid() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InTrainerHillChallenge()) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); else SetMainCallback2(CB2_WhiteOut); @@ -1339,7 +1339,7 @@ static void CB2_EndTrainerBattle(void) else { SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); - if (!InBattlePyramid() && !InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE && !InTrainerHillChallenge()) { RegisterTrainerInMatchCall(); SetBattledTrainersFlags(); @@ -1376,7 +1376,7 @@ void BattleSetup_StartRematchBattle(void) void ShowTrainerIntroSpeech(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (gNoOfApproachingTrainers == 0 || gNoOfApproachingTrainers == 1) CopyPyramidTrainerSpeechBefore(LocalIdToPyramidTrainerId(gSpecialVar_LastTalked)); diff --git a/src/battle_util.c b/src/battle_util.c index 6e201a2956..b2247b3923 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -426,7 +426,7 @@ bool8 TryRunFromBattle(u8 battler) } else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { gBattleStruct->runTries++; pyramidMultiplier = GetPyramidRunMultiplier(); @@ -453,7 +453,7 @@ bool8 TryRunFromBattle(u8 battler) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { pyramidMultiplier = GetPyramidRunMultiplier(); speedVar = (gBattleMons[battler].speed * pyramidMultiplier) / (gBattleMons[BATTLE_OPPOSITE(battler)].speed) + (gBattleStruct->runTries * 30); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index b3ffb76193..64fa3ef55a 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1327,7 +1327,7 @@ u8 Unref_TryInitLocalObjectEvent(u8 localId) if (gMapHeader.events != NULL) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) objectEventCount = GetNumBattlePyramidObjectEvents(); else if (InTrainerHill()) objectEventCount = HILL_TRAINERS_PER_FLOOR; @@ -1643,7 +1643,7 @@ void TrySpawnObjectEvents(s16 cameraX, s16 cameraY) s16 top = gSaveBlock1Ptr->pos.y; s16 bottom = gSaveBlock1Ptr->pos.y + MAP_OFFSET_H + 2; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) objectCount = GetNumBattlePyramidObjectEvents(); else if (InTrainerHill()) objectCount = HILL_TRAINERS_PER_FLOOR; diff --git a/src/field_poison.c b/src/field_poison.c index e0b08b8716..4548933533 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -90,7 +90,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) { // Battle facilities have their own white out script to handle the challenge loss #ifdef BUGFIX - if (InBattlePyramid() || InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InTrainerHillChallenge()) #else if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif diff --git a/src/item.c b/src/item.c index b67cf5f218..37428e87df 100644 --- a/src/item.c +++ b/src/item.c @@ -133,7 +133,7 @@ bool8 CheckBagHasItem(u16 itemId, u16 count) if (ItemId_GetPocket(itemId) == 0) return FALSE; - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) return CheckPyramidBagHasItem(itemId, count); pocket = ItemId_GetPocket(itemId) - 1; // Check for item slots that contain the item @@ -181,7 +181,7 @@ bool8 CheckBagHasSpace(u16 itemId, u16 count) if (ItemId_GetPocket(itemId) == POCKET_NONE) return FALSE; - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return CheckPyramidBagHasSpace(itemId, count); } @@ -243,7 +243,7 @@ bool8 AddBagItem(u16 itemId, u16 count) return FALSE; // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return AddPyramidBagItem(itemId, count); } @@ -351,7 +351,7 @@ bool8 RemoveBagItem(u16 itemId, u16 count) return FALSE; // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return RemovePyramidBagItem(itemId, count); } diff --git a/src/item_menu.c b/src/item_menu.c index f0abfcf62a..e0a7fd0e48 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -565,7 +565,7 @@ void CB2_BagMenuFromStartMenu(void) void CB2_BagMenuFromBattle(void) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) GoToBagMenu(ITEMMENULOCATION_BATTLE, POCKETS_COUNT, CB2_SetUpReshowBattleScreenAfterMenu2); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_BATTLE, CB2_SetUpReshowBattleScreenAfterMenu2); @@ -2036,7 +2036,7 @@ bool8 UseRegisteredKeyItemOnField(void) { u8 taskId; - if (InUnionRoom() == TRUE || InBattlePyramid() || InBattlePike() || InMultiPartnerRoom() == TRUE) + if (InUnionRoom() == TRUE || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InMultiPartnerRoom() == TRUE) return FALSE; HideMapNamePopUpWindow(); ChangeBgY_ScreenOff(0, 0, BG_COORD_SET); diff --git a/src/item_use.c b/src/item_use.c index 181698ac30..dd017ee170 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -102,7 +102,7 @@ static void SetUpItemUseCallback(u8 taskId) type = gTasks[taskId].tEnigmaBerryType - 1; else type = ItemId_GetType(gSpecialVar_ItemId) - 1; - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { gBagMenu->newScreenCallback = sItemUseCallbacks[type]; Task_FadeAndCloseBagMenu(taskId); @@ -144,7 +144,7 @@ static void DisplayCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyIte StringExpandPlaceholders(gStringVar4, str); if (!isUsingRegisteredKeyItemOnField) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_DadsAdvice, Task_CloseBattlePyramidBagMessage); @@ -826,7 +826,7 @@ static void RemoveUsedItem(void) RemoveBagItem(gSpecialVar_ItemId, 1); CopyItemName(gSpecialVar_ItemId, gStringVar2); StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { UpdatePocketItemList(ItemId_GetPocket(gSpecialVar_ItemId)); UpdatePocketListPosition(ItemId_GetPocket(gSpecialVar_ItemId)); @@ -842,7 +842,7 @@ void ItemUseOutOfBattle_Repel(u8 taskId) { if (VarGet(VAR_REPEL_STEP_COUNT) == 0) gTasks[taskId].func = Task_StartUseRepel; - else if (!InBattlePyramid()) + else if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gText_RepelEffectsLingered, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_RepelEffectsLingered, Task_CloseBattlePyramidBagMessage); @@ -866,7 +866,7 @@ static void Task_UseRepel(u8 taskId) { VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); RemoveUsedItem(); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); @@ -878,7 +878,7 @@ static void Task_UsedBlackWhiteFlute(u8 taskId) if(++gTasks[taskId].data[8] > 7) { PlaySE(SE_GLASS_FLUTE); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); @@ -951,12 +951,12 @@ void ItemUseInBattle_PokeBall(u8 taskId) if (IsPlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon? { RemoveBagItem(gSpecialVar_ItemId, 1); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) Task_FadeAndCloseBagMenu(taskId); else CloseBattlePyramidBag(taskId); } - else if (!InBattlePyramid()) + else if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { DisplayItemMessage(taskId, FONT_NORMAL, gText_BoxFull, CloseItemMessage); } @@ -970,7 +970,7 @@ static void Task_CloseStatIncreaseMessage(u8 taskId) { if (JOY_NEW(A_BUTTON | B_BUTTON)) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) Task_FadeAndCloseBagMenu(taskId); else CloseBattlePyramidBag(taskId); @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // !InBattlePyramid() doesn't match + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE doesn't match DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); @@ -997,7 +997,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId) if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gText_WontHaveEffect, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_WontHaveEffect, Task_CloseBattlePyramidBagMessage); @@ -1011,7 +1011,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId) static void ItemUseInBattle_ShowPartyMenu(u8 taskId) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { gBagMenu->newScreenCallback = ChooseMonForInBattleItem; Task_FadeAndCloseBagMenu(taskId); @@ -1049,7 +1049,7 @@ void ItemUseInBattle_Escape(u8 taskId) if((gBattleTypeFlags & BATTLE_TYPE_TRAINER) == FALSE) { RemoveUsedItem(); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, Task_FadeAndCloseBagMenu); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, CloseBattlePyramidBag); diff --git a/src/map_name_popup.c b/src/map_name_popup.c index d004b18d56..150459762a 100644 --- a/src/map_name_popup.c +++ b/src/map_name_popup.c @@ -336,7 +336,7 @@ static void ShowMapNamePopUpWindow(void) u8 x; const u8 *mapDisplayHeaderSource; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP) { diff --git a/src/party_menu.c b/src/party_menu.c index f6dd6a264c..43f3529ea4 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -3092,7 +3092,7 @@ static void CursorCb_Give(u8 taskId) static void CB2_SelectBagItemToGive(void) { - if (InBattlePyramid() == FALSE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE == FALSE) GoToBagMenu(ITEMMENULOCATION_PARTY, POCKETS_COUNT, CB2_GiveHoldItem); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_PARTY, CB2_GiveHoldItem); @@ -4275,7 +4275,7 @@ void CB2_ShowPartyMenuForItemUse(void) static void CB2_ReturnToBagMenu(void) { - if (InBattlePyramid() == FALSE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE == FALSE) GoToBagMenu(ITEMMENULOCATION_LAST, POCKETS_COUNT, NULL); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_PREV, gPyramidBagMenuState.exitCallback); @@ -5358,7 +5358,7 @@ void CB2_PartyMenuFromStartMenu(void) // As opposted to by selecting Give in the party menu, which is handled by CursorCb_Give void CB2_ChooseMonToGiveItem(void) { - MainCallback callback = (!InBattlePyramid()) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; + MainCallback callback = (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback); gPartyMenu.bagItem = gSpecialVar_ItemId; } diff --git a/src/pokemon.c b/src/pokemon.c index e98182b0ae..8ec0c1a32c 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5840,7 +5840,7 @@ s32 GetBattlerMultiplayerId(u16 id) u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return GetTrainerEncounterMusicIdInBattlePyramid(trainerOpponentId); else if (InTrainerHillChallenge()) return GetTrainerEncounterMusicIdInTrainerHill(trainerOpponentId); @@ -6970,7 +6970,7 @@ static bool8 ShouldSkipFriendshipChange(void) { if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) return TRUE; - if (!gMain.inBattle && (InBattlePike() || InBattlePyramid())) + if (!gMain.inBattle && (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)) return TRUE; return FALSE; } diff --git a/src/start_menu.c b/src/start_menu.c index 0910fad84d..13a46c51c6 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -293,7 +293,7 @@ static void BuildStartMenuActions(void) { BuildBattlePikeStartMenu(); } - else if (InBattlePyramid()) + else if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { BuildBattlePyramidStartMenu(); } @@ -439,7 +439,7 @@ static void RemoveExtraStartMenuWindows(void) CopyWindowToVram(sSafariBallsWindowId, COPYWIN_GFX); RemoveWindow(sSafariBallsWindowId); } - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { ClearStdWindowAndFrameToTransparent(sBattlePyramidFloorWindowId, FALSE); RemoveWindow(sBattlePyramidFloorWindowId); @@ -499,7 +499,7 @@ static bool32 InitStartMenuStep(void) case 3: if (GetSafariZoneFlag()) ShowSafariBallsWindow(); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) ShowPyramidFloorWindow(); sInitStartMenuData[0]++; break; @@ -720,7 +720,7 @@ static bool8 StartMenuPlayerNameCallback(void) static bool8 StartMenuSaveCallback(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) RemoveExtraStartMenuWindows(); gMenuCallback = SaveStartCallback; // Display save menu @@ -981,7 +981,7 @@ static u8 SaveConfirmSaveCallback(void) RemoveStartMenuWindow(); ShowSaveInfoWindow(); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { ShowSaveMessage(gText_BattlePyramidConfirmRest, SaveYesNoCallback); } diff --git a/src/trainer_see.c b/src/trainer_see.c index 212cbbdec3..a87ed496bc 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -256,7 +256,7 @@ static u8 CheckTrainer(u8 objectEventId) else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (GetBattlePyramidTrainerFlag(objectEventId)) return 0; diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 11d01f04ea..211729dc4e 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -851,7 +851,7 @@ bool8 UpdateRepelCounter(void) { u16 steps; - if (InBattlePike() || InBattlePyramid()) + if (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return FALSE; if (InUnionRoom() == TRUE) return FALSE; From 2a656ff1a54e13c3155e821ad2072f69bc0ef32e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 27 Dec 2024 12:40:25 -0300 Subject: [PATCH 016/283] Applied review changes --- src/field_poison.c | 2 +- src/item_use.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field_poison.c b/src/field_poison.c index 4548933533..1b8ae94094 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -90,7 +90,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) { // Battle facilities have their own white out script to handle the challenge loss #ifdef BUGFIX - if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() || InBattlePike() || InTrainerHillChallenge()) #else if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif diff --git a/src/item_use.c b/src/item_use.c index dd017ee170..29cf7ee5cc 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE doesn't match + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); From 7612e386419ef913bda5a62a5c8f234190542bb0 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 26 Jan 2025 20:52:50 -0500 Subject: [PATCH 017/283] fix: improved FadeScreenHardware during fade-in --- src/palette.c | 41 +++++++++++++++++++++++++++++------------ src/scrcmd.c | 2 ++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/palette.c b/src/palette.c index 303e6ced42..59fbdcfab4 100644 --- a/src/palette.c +++ b/src/palette.c @@ -2,8 +2,10 @@ #include "palette.h" #include "util.h" #include "decompress.h" +#include "field_weather.h" #include "gpu_regs.h" #include "task.h" +#include "constants/field_weather.h" #include "constants/rgb.h" enum @@ -967,25 +969,41 @@ static void UpdateBlendRegisters(void) { SetGpuReg(REG_OFFSET_BLDCNT, (u16)gPaletteFade_blendCnt); SetGpuReg(REG_OFFSET_BLDY, gPaletteFade.y); - // If fade-out, also adjust BLDALPHA and DISPCNT - if (!gPaletteFade.yDec /*&& gPaletteFade.mode == HARDWARE_FADE*/) { + // if TGT2 enabled, also adjust BLDALPHA and DISPCNT + if (((u16)gPaletteFade_blendCnt) & BLDCNT_TGT2_ALL) { u16 bldAlpha = GetGpuReg(REG_OFFSET_BLDALPHA); u8 tgt1 = BLDALPHA_TGT1(bldAlpha); u8 tgt2 = BLDALPHA_TGT2(bldAlpha); - u8 bldFade; + u8 mode = (gPaletteFade_blendCnt & BLDCNT_EFFECT_EFF_MASK) == BLDCNT_EFFECT_LIGHTEN ? FADE_FROM_WHITE : FADE_FROM_BLACK; + if (!gPaletteFade.yDec) + mode++; - switch (gPaletteFade_blendCnt & BLDCNT_EFFECT_EFF_MASK) + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); + + switch (mode) { - // FADE_TO_BLACK - case BLDCNT_EFFECT_DARKEN: - bldFade = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); + case FADE_FROM_BLACK: + // increment each target until reaching weather's values + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND( + min(++tgt1, gWeatherPtr->currBlendEVA), + min(++tgt2, gWeatherPtr->currBlendEVB) + ) + ); + break; + case FADE_TO_BLACK: + bldAlpha = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); SetGpuReg( REG_OFFSET_BLDALPHA, - BLDALPHA_BLEND(min(tgt1, bldFade), min(tgt2, bldFade)) + BLDALPHA_BLEND(min(tgt1, bldAlpha), min(tgt2, bldAlpha)) ); break; - // FADE_TO_WHITE - case BLDCNT_EFFECT_LIGHTEN: + // Not handled; blend sprites will pop in, + // but the effect coming from white looks okay + // case FADE_FROM_WHITE: + // break; + case FADE_TO_WHITE: SetGpuReg( REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(min(++tgt1, 31), min(++tgt2, 31)) @@ -996,8 +1014,7 @@ static void UpdateBlendRegisters(void) SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); break; } - } else - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); + } if (gPaletteFade.hardwareFadeFinishing) { diff --git a/src/scrcmd.c b/src/scrcmd.c index edca8dbbbe..b6f15b2fbe 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -663,6 +663,8 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx) switch (mode) { case FADE_FROM_BLACK: + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + break; case FADE_FROM_WHITE: // Restore last weather blend before fading in, // since BLDALPHA was modified by fade-out From 0eabbf7a3f3d74baf15c08844466f7621a842c06 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 2 Mar 2025 18:10:22 -0300 Subject: [PATCH 018/283] Simplified Multi Battle bugfix, removing duplicate code --- src/battle_script_commands.c | 45 +++++++++--------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f1a03b7af7..8b82bd9185 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7337,38 +7337,6 @@ static void Cmd_forcerandomswitch(void) } else { - #ifdef BUGFIX - if (TryDoForceSwitchOut()) - { - do - { - do - { - i = Random() % monsCount; - i += firstMonId; - } - while (i == battler2PartyId || i == battler1PartyId); - } while (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE - || GetMonData(&party[i], MON_DATA_IS_EGG) == TRUE - || GetMonData(&party[i], MON_DATA_HP) == 0); //should be one while loop, but that doesn't match. - *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = i; - - if (!IsMultiBattle()) - SwitchPartyOrder(gBattlerTarget); - - if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) - || (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI) - || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) - || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)) - { - SwitchPartyOrderLinkMulti(gBattlerTarget, i, 0); - SwitchPartyOrderLinkMulti(BATTLE_PARTNER(gBattlerTarget), i, 1); - } - - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - SwitchPartyOrderInGameMulti(gBattlerTarget, i); - } - #else if (TryDoForceSwitchOut()) { do @@ -7382,7 +7350,14 @@ static void Cmd_forcerandomswitch(void) } while (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE || GetMonData(&party[i], MON_DATA_IS_EGG) == TRUE || GetMonData(&party[i], MON_DATA_HP) == 0); //should be one while loop, but that doesn't match. - } + // Bug: If the opponent uses forced switchout moves in a Multi Battle, the player side party + // might get the order messed up where the mons appear in the wrong slots of the party screen. + // This causes a hardlock when all mons on the player side are knocked out and the player + // can't select their mon that's on the partner side of the party screen. + // To fix this, the below code is moved inside the 'if (TryDoForceSwitchOut())' block by moving the brace further down. + #ifndef BUGFIX + } + #endif *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = i; if (!IsMultiBattle()) @@ -7399,7 +7374,9 @@ static void Cmd_forcerandomswitch(void) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) SwitchPartyOrderInGameMulti(gBattlerTarget, i); - #endif + #ifdef BUGFIX + } + #endif } } else From 73e891a88a61dfdf3ed11d5c91cad80e5349d519 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 8 Mar 2025 02:15:32 -0500 Subject: [PATCH 019/283] fix: rainy castform is no longer a Ninja Boy on return-to-field --- src/event_object_movement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 513931c035..633167f4e2 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2772,13 +2772,13 @@ const struct ObjectEventGraphicsInfo *GetObjectEventGraphicsInfo(u16 graphicsId) if (graphicsId >= OBJ_EVENT_GFX_VARS && graphicsId <= OBJ_EVENT_GFX_VAR_F) graphicsId = VarGetObjectEventGraphicsId(graphicsId - OBJ_EVENT_GFX_VARS); - if (graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) - graphicsId -= SPECIES_SHINY_TAG; // graphicsId may contain mon form info if (graphicsId > OBJ_EVENT_GFX_SPECIES_MASK) { form = graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS; graphicsId = graphicsId & OBJ_EVENT_GFX_SPECIES_MASK; } + if (graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) + graphicsId -= SPECIES_SHINY_TAG; if (graphicsId == OBJ_EVENT_GFX_BARD) { return gMauvilleOldManGraphicsInfoPointers[GetCurrentMauvilleOldMan()]; From 56bd65eb9d3dfbd0d7fc19ec7f08b45bb0affe03 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 27 Apr 2025 22:28:26 -0400 Subject: [PATCH 020/283] Fix other missing instances of MAX_LINK_PLAYERS --- src/battle_bg.c | 2 +- src/battle_controllers.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/battle_bg.c b/src/battle_bg.c index c32f5ec623..cc9f4a15ee 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -1024,7 +1024,7 @@ void InitLinkBattleVsScreen(u8 taskId) case 0: if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { name = gLinkPlayers[i].name; linkPlayer = &gLinkPlayers[i]; diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 02276a7e14..4b19e62e5a 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -260,7 +260,7 @@ static void InitSinglePlayerBtlControllers(void) { u8 multiplayerId; - for (multiplayerId = gRecordedBattleMultiplayerId, i = 0; i < MAX_BATTLERS_COUNT; i++) + for (multiplayerId = gRecordedBattleMultiplayerId, i = 0; i < MAX_LINK_PLAYERS; i++) { switch (gLinkPlayers[i].id) { @@ -502,7 +502,7 @@ static void InitLinkBtlControllers(void) if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) gBattleMainFunc = BeginBattleIntro; - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { switch (gLinkPlayers[i].id) { From 2cc013ff3e3e89d380fe434795a62ece1fc62dbc Mon Sep 17 00:00:00 2001 From: Catnip-Consumer Date: Mon, 28 Apr 2025 14:36:19 +0300 Subject: [PATCH 021/283] Apply fixes to preproc for Windows compatibility --- tools/preproc/asm_file.cpp | 8 ++++---- tools/preproc/preproc.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index a82354cb5f..69b412b24e 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -679,7 +679,7 @@ void AsmFile::RaiseWarning(const char* format, ...) int AsmFile::SkipWhitespaceAndEol() { int newlines = 0; - while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\n') + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') { if (m_buffer[m_pos] == '\n') newlines++; @@ -702,14 +702,14 @@ int AsmFile::FindLastLineNumber(std::string& filename) if (pos < 0) RaiseError("line indicator for header file not found before `enum`"); - + pos++; while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t') pos++; if (!IsAsciiDigit(m_buffer[pos])) RaiseError("malformatted line indicator found before `enum`, expected line number"); - + unsigned n = 0; int digit = 0; while ((digit = ConvertDigit(m_buffer[pos++], 10)) != -1) @@ -744,7 +744,7 @@ int AsmFile::FindLastLineNumber(std::string& filename) filename += c; } - + return n + linebreaks - 1; } diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 20c2de51b6..ac9496d701 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -26,6 +26,11 @@ #include "c_file.h" #include "charmap.h" +#ifdef _WIN32 +#include +#include +#endif + static void UsageAndExit(const char *program); Charmap* g_charmap; @@ -179,6 +184,11 @@ int main(int argc, char **argv) g_charmap = new Charmap(charmap); +#ifdef _WIN32 + // On Windows, piping from stdout can break newlines. Treat stdout as binary stream to avoid this. + _setmode(_fileno(stdout), _O_BINARY); +#endif + const char* extension = GetFileExtension(source); if (!extension) From 50d81616cd3db3d2b7534ed936b0d3541e5a08cb Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 10 Jun 2025 13:05:03 -0400 Subject: [PATCH 022/283] Relax MAPSEC region map data requirements --- .../region_map/region_map_sections.json.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/data/region_map/region_map_sections.json.txt b/src/data/region_map/region_map_sections.json.txt index b73f992d6d..c3435d2d67 100644 --- a/src/data/region_map/region_map_sections.json.txt +++ b/src/data/region_map/region_map_sections.json.txt @@ -19,9 +19,23 @@ static const u8 sMapName_{{ cleanString(map_section.name) }}_Clone[] = _("{{ map const struct RegionMapLocation gRegionMapEntries[] = { ## for map_section in map_sections -{% if existsIn(map_section, "x") and existsIn(map_section, "y") and existsIn(map_section, "width") and existsIn(map_section, "height") and existsIn(map_section, "name") %} - [{{ map_section.id }}] = { {{ map_section.x }}, {{ map_section.y }}, {{ map_section.width }}, {{ map_section.height }}, sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %} }, + [{{ map_section.id }}] = { +{% if existsIn(map_section, "x") %} + .x = {{ map_section.x }}, {% endif %} +{% if existsIn(map_section, "y") %} + .y = {{ map_section.y }}, +{% endif %} +{% if existsIn(map_section, "width") %} + .width = {{ map_section.width }}, +{% endif %} +{% if existsIn(map_section, "height") %} + .height = {{ map_section.height }}, +{% endif %} +{% if existsIn(map_section, "name") %} + .name = sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %}, +{% endif %} + }, ## endfor }; From 84972342d64e984ec728ec41a901aedd1c779aa0 Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 18 Jun 2025 21:51:46 +0200 Subject: [PATCH 023/283] Add 'Macro' key to trainerproc --- tools/trainerproc/main.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 478f35dd3d..98ca8884fd 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -149,6 +149,9 @@ struct Trainer struct String pool_prune; int pool_prune_line; + + struct String macro; + int macro_line; }; static bool is_empty_string(struct String s) @@ -1280,14 +1283,21 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct trainer->pool_prune_line = value.location.line; trainer->pool_prune = token_string(&value); } + else if (is_literal_token(&key, "Macro")) + { + if (trainer->macro_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Macro'"); + trainer->macro_line = value.location.line; + trainer->macro = token_string(&value); + } else { any_error = !set_show_parse_error(p, key.location, "expected one of 'Name', 'Class', 'Pic', 'Gender', 'Music', 'Items', 'Battle Type', 'Difficulty', 'Party Size', 'Pool Rules', 'Pool Pick Functions', 'Pool Prune' or 'AI'"); } } - if (!trainer->pic_line) + if (!trainer->pic_line && !trainer->macro_line) any_error = !set_show_parse_error(p, p->location, "expected 'Pic' before Pokemon"); - if (!trainer->name_line) + if (!trainer->name_line && !trainer->macro_line) any_error = !set_show_parse_error(p, p->location, "expected 'Name' before Pokemon"); if (!match_empty_line(p)) { @@ -1853,6 +1863,14 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, ",\n"); } + if (trainer->macro_line) + { + fprintf(f, "#line %d\n", trainer->macro_line); + fprintf(f, " "); + fprint_string(f, trainer->macro); + fprintf(f, "\n"); + } + if (trainer->party_size_line) { fprintf(f, "#line %d\n", trainer->party_size_line); @@ -1867,6 +1885,7 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, " .party = (const struct TrainerMon[])\n"); fprintf(f, " {\n"); } + for (int j = 0; j < trainer->pokemon_n; j++) { struct Pokemon *pokemon = &trainer->pokemon[j]; From 07fd8a28fbd5b23a6828846e4606fc3ecd54c3d9 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:01:04 -0400 Subject: [PATCH 024/283] fix: hide followers when player enters Battle Pike curtains --- data/scripts/battle_pike.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/data/scripts/battle_pike.inc b/data/scripts/battle_pike.inc index 3393f808d3..9262dc46e8 100644 --- a/data/scripts/battle_pike.inc +++ b/data/scripts/battle_pike.inc @@ -86,6 +86,7 @@ BattleFrontier_BattlePikeThreePathRoom_EventScript_RightRoomWarp:: end BattleFrontier_BattlePikeThreePathRoom_EventScript_RoomWarp:: + clearflag FLAG_SAFE_FOLLOWER_MOVEMENT pike_get PIKE_DATA_WIN_STREAK addvar VAR_RESULT, 1 pike_set PIKE_DATA_WIN_STREAK, VAR_RESULT From 1f2fe7396b68d82da356b93fca10cc5736d3159c Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 3 May 2025 21:44:52 -0400 Subject: [PATCH 025/283] feat: added abnormal weather follower message Includes support for follower matching != species --- include/constants/flags.h | 1 + include/follower_helper.h | 4 +++- src/event_object_movement.c | 7 ++++++- src/follower_helper.c | 12 ++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/constants/flags.h b/include/constants/flags.h index b7388d6bd0..4863c0980a 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1397,6 +1397,7 @@ #define FLAG_SYS_USE_FLASH (SYSTEM_FLAGS + 0x28) #define FLAG_SYS_USE_STRENGTH (SYSTEM_FLAGS + 0x29) +// Sets abnormal weather on maps that check for it #define FLAG_SYS_WEATHER_CTRL (SYSTEM_FLAGS + 0x2A) #define FLAG_SYS_CYCLING_ROAD (SYSTEM_FLAGS + 0x2B) #define FLAG_SYS_SAFARI_MODE (SYSTEM_FLAGS + 0x2C) diff --git a/include/follower_helper.h b/include/follower_helper.h index 4d316ba1a3..e5787de5c7 100644 --- a/include/follower_helper.h +++ b/include/follower_helper.h @@ -62,7 +62,8 @@ struct FollowerMsgInfoExtended { #define MATCH_U16(type, value1, value2) {type, {.split = {.hw = value1, .b = value2}}} #define MATCH_U8(type, v1, v2, v3) {type, {.bytes = {v1, v2, v3}}} -#define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species) +#define MATCH_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 0) +#define MATCH_NOT_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 1) #define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0) // Checks that follower has *neither* of the two types #define MATCH_NOT_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, TYPE_NONE | 1) @@ -107,6 +108,7 @@ enum { COND_MSG_LEAVES, COND_MSG_ICE, COND_MSG_BURN, + COND_MSG_ABNORMAL_WEATHER, COND_MSG_COUNT, }; diff --git a/src/event_object_movement.c b/src/event_object_movement.c index e0bc0619ae..630e3dffb3 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2125,7 +2125,12 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u switch (cond->type) { case MSG_COND_SPECIES: - return (cond->data.raw == species); + multi = cond->data.split.hw; + // if byte nonzero, invert; check != species! + if (cond->data.split.b) + return (cond->data.split.hw != species); + else + return (cond->data.split.hw == species); case MSG_COND_TYPE: multi = (SpeciesHasType(species, cond->data.bytes[0]) || SpeciesHasType(species, cond->data.bytes[1])); diff --git a/src/follower_helper.c b/src/follower_helper.c index be52877c5f..3df1cfa0a9 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -65,6 +65,7 @@ static const u8 sCondMsg40[] = _("{STR_VAR_1} is gnawing at the ice."); static const u8 sCondMsg41[] = _("{STR_VAR_1} is touching the ice."); static const u8* const sIceTexts[] = {sCondMsg26, sCondMsg40, sCondMsg41, NULL}; static const u8 sCondMsg42[] = _("{STR_VAR_1}'s burn looks painful!"); +static const u8 sCondMsg50[] = _("{STR_VAR_1} is disturbed by the\nabnormal weather!"); // See the struct definition in follower_helper.h for more info const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT] = { @@ -276,6 +277,17 @@ const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT .emotion = FOLLOWER_EMOTION_SAD, .conditions = {MATCH_STATUS(STATUS1_BURN)}, }, + [COND_MSG_ABNORMAL_WEATHER] = + { + .text = sCondMsg50, + .emotion = FOLLOWER_EMOTION_SURPRISE, + .conditions = { + MATCH_MUSIC(MUS_ABNORMAL_WEATHER), + MATCH_NOT_SPECIES(SPECIES_KYOGRE), + MATCH_NOT_SPECIES(SPECIES_GROUDON), + MATCH_NOT_SPECIES(SPECIES_RAYQUAZA), + } + }, }; // Pool of "unconditional" follower messages From 143500a1f95bf5951c001ec88db8b9d3f55d43e7 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 20 May 2025 23:08:48 -0400 Subject: [PATCH 026/283] fix: capitalization in follower splash message --- src/follower_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/follower_helper.c b/src/follower_helper.c index 3df1cfa0a9..db24895a38 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -35,7 +35,7 @@ static const u8 sCondMsg16[] = _("{STR_VAR_1} doesn't want to get off\nthe boat static const u8* const sBoatTexts[] = {sCondMsg14, sCondMsg15, sCondMsg16, NULL}; static const u8 sCondMsg17[] = _("{STR_VAR_1} is listening to the\nsound of the machines."); static const u8* const sMachineTexts[] = {sCondMsg13, sCondMsg17, NULL}; -static const u8 sCondMsg18[] = _("Waah! your POKéMON suddenly splashed\nwater!"); +static const u8 sCondMsg18[] = _("Waah! Your POKéMON suddenly splashed\nwater!"); static const u8 sCondMsg19[] = _("Your POKéMON is blowing sand in the\nair!"); static const u8 sCondMsg20[] = _("{STR_VAR_1} is playing around,\nplucking bits of grass."); static const u8 sCondMsg21[] = _("Your POKéMON is happily looking at\nyour footprints!"); From 200ef41fce5071a2032ef34e4ba64b71368cfccd Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Fri, 30 May 2025 01:32:48 -0400 Subject: [PATCH 027/283] fix: mapjson missing cstdint --- tools/mapjson/json11.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/mapjson/json11.cpp b/tools/mapjson/json11.cpp index 3ac5f392a0..50c2209c57 100644 --- a/tools/mapjson/json11.cpp +++ b/tools/mapjson/json11.cpp @@ -20,6 +20,7 @@ #include "json11.h" #include #include +#include #include #include #include From cab7f8b24b0dfaa26de8d63938cc3c9737d127a6 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:52:45 -0400 Subject: [PATCH 028/283] fix: removed sweet scent field effect dependence on gPaletteDecompressionBuffer --- src/fldeff_sweetscent.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/fldeff_sweetscent.c b/src/fldeff_sweetscent.c index dd979c77a8..c7da9ddb68 100644 --- a/src/fldeff_sweetscent.c +++ b/src/fldeff_sweetscent.c @@ -6,6 +6,7 @@ #include "field_screen_effect.h" #include "field_weather.h" #include "fldeff.h" +#include "malloc.h" #include "mirage_tower.h" #include "palette.h" #include "party_menu.h" @@ -50,13 +51,19 @@ bool8 FldEff_SweetScent(void) static void StartSweetScentFieldEffect(void) { u8 taskId; + u32 palettes = ~(1 << (gSprites[GetPlayerAvatarSpriteId()].oam.paletteNum + 16) | (1 << 13) | (1 << 14) | (1 << 15)); + u32 *buffer = Alloc(PLTT_SIZE); PlaySE(SE_M_SWEET_SCENT); - CpuFastCopy(gPlttBufferUnfaded, gPaletteDecompressionBuffer, PLTT_SIZE); - CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); - BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarSpriteId()].oam.paletteNum + 16)), 4, 0, 8, RGB_RED); + if (buffer) { + CpuFastCopy(gPlttBufferUnfaded, buffer, PLTT_SIZE); + CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); + } + BeginNormalPaletteFade(palettes, 4, 0, 8, RGB_RED); taskId = CreateTask(TrySweetScentEncounter, 0); gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = (u32) buffer >> 16; + gTasks[taskId].data[2] = (u32) buffer; FieldEffectActiveListRemove(FLDEFF_SWEET_SCENT); } @@ -71,6 +78,8 @@ static void TrySweetScentEncounter(u8 taskId) gTasks[taskId].data[0] = 0; if (SweetScentWildEncounter() == TRUE) { + u32 *buffer = (u32*)(((u16)gTasks[taskId].data[1] << 16) | (u16)gTasks[taskId].data[2]); + TRY_FREE_AND_SET_NULL(buffer); DestroyTask(taskId); } else @@ -91,7 +100,11 @@ static void FailSweetScentEncounter(u8 taskId) { if (!gPaletteFade.active) { - CpuFastCopy(gPaletteDecompressionBuffer, gPlttBufferUnfaded, PLTT_SIZE); + u32 *buffer = (u32*)(((u16)gTasks[taskId].data[1] << 16) | (u16)gTasks[taskId].data[2]); + if (buffer) { + CpuFastCopy(buffer, gPlttBufferUnfaded, PLTT_SIZE); + Free(buffer); + } SetWeatherPalStateIdle(); ScriptContext_SetupScript(EventScript_FailSweetScent); DestroyTask(taskId); From 1cc2c7f2a02c350c0d724ab661ea0b78d108df51 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:57:04 -0400 Subject: [PATCH 029/283] fix: destroy shadows during battle transition intro --- src/battle_transition.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/battle_transition.c b/src/battle_transition.c index 0d66dfbf01..dbee25968f 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -1068,6 +1068,9 @@ static void Task_BattleTransition(u8 taskId) static bool8 Transition_StartIntro(struct Task *task) { SetWeatherScreenFadeOut(); + // cause all shadow sprites to destroy themselves, + // freeing up sprite slots for the transition + gWeatherPtr->noShadows = TRUE; CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); if (sTasks_Intro[task->tTransitionId] != NULL) { From f6efe480fa4363eacf59538e6e68ec34fa6f6a1d Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:41:16 -0400 Subject: [PATCH 030/283] fix: ignore trainerRange on OW templates when trainerType nonzero --- src/event_object_movement.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index f63624e135..be4c5abfd8 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1738,7 +1738,7 @@ static u16 PackGraphicsId(const struct ObjectEventTemplate *template) { if (template->script && template->script[0] == 0x7d) { form = T1_READ_16(&template->script[2]); form = (form >> 10) & 0x1F; - } else if (template->trainerRange_berryTreeId) { + } else if (template->trainerRange_berryTreeId && !template->trainerType) { form = template->trainerRange_berryTreeId & 0x1F; } graphicsId |= form << OBJ_EVENT_GFX_SPECIES_BITS; From 9ca6562874d92d7dd9562fc10e5026d9ef64b7d4 Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 25 Jun 2025 18:04:12 +0200 Subject: [PATCH 031/283] Cleanup of merrp merge --- tools/mapjson/json11.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/mapjson/json11.cpp b/tools/mapjson/json11.cpp index 74f9272313..fcacdbeb39 100644 --- a/tools/mapjson/json11.cpp +++ b/tools/mapjson/json11.cpp @@ -20,7 +20,6 @@ #include "json11.h" #include #include -#include #include #include #include From 64a6e8817cb143c4f6d81d7ba6bfb6486b156a81 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 25 Jun 2025 18:54:13 +0200 Subject: [PATCH 032/283] Fix sGpuRegBuffer potential alignment issues (#2157) --- src/gpu_regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpu_regs.c b/src/gpu_regs.c index 3bcc4fd931..d645c1442d 100644 --- a/src/gpu_regs.c +++ b/src/gpu_regs.c @@ -8,7 +8,7 @@ #define EMPTY_SLOT 0xFF -static u8 sGpuRegBuffer[GPU_REG_BUF_SIZE]; +static ALIGNED(2) u8 sGpuRegBuffer[GPU_REG_BUF_SIZE]; // sGpuRegBuffer is read as u16 so it needs to be properly aligned static u8 sGpuRegWaitingList[GPU_REG_BUF_SIZE]; static volatile bool8 sGpuRegBufferLocked; static volatile bool8 sShouldSyncRegIE; From 9df5ab16e8a11f289747dcf41abd4a8e8b6d42e0 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 25 Jun 2025 20:41:23 +0200 Subject: [PATCH 033/283] Ensure sMonMarkings_Gfx alignment (#2158) --- src/mon_markings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mon_markings.c b/src/mon_markings.c index d7a61c27e7..1de8e413fd 100644 --- a/src/mon_markings.c +++ b/src/mon_markings.c @@ -23,7 +23,7 @@ static void SpriteCB_Cursor(struct Sprite *); static struct Sprite *CreateMarkingComboSprite(u16, u16, const u16 *, u16); static const u16 sMonMarkings_Pal[] = INCBIN_U16("graphics/interface/mon_markings.gbapal"); -static const u8 sMonMarkings_Gfx[] = INCBIN_U8("graphics/interface/mon_markings.4bpp"); +static const ALIGNED(4) u8 sMonMarkings_Gfx[] = INCBIN_U8("graphics/interface/mon_markings.4bpp"); // Alignment needed for dma copy static const struct OamData sOamData_MenuWindow = { From 44c30698951d66788029ad41a2e3254ff3ffb023 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 26 Jun 2025 16:22:09 -0400 Subject: [PATCH 034/283] Add explicit defaults for MAPSEC data --- src/data/region_map/region_map_sections.json | 708 +++--------------- .../region_map/region_map_sections.json.txt | 10 + 2 files changed, 128 insertions(+), 590 deletions(-) diff --git a/src/data/region_map/region_map_sections.json b/src/data/region_map/region_map_sections.json index fa7eb5efa4..49426128b8 100644 --- a/src/data/region_map/region_map_sections.json +++ b/src/data/region_map/region_map_sections.json @@ -675,11 +675,7 @@ }, { "id": "MAPSEC_INSIDE_OF_TRUCK", - "name": "INSIDE OF TRUCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "INSIDE OF TRUCK" }, { "id": "MAPSEC_SKY_PILLAR", @@ -691,897 +687,453 @@ }, { "id": "MAPSEC_SECRET_BASE", - "name": "SECRET BASE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SECRET BASE" }, { "id": "MAPSEC_DYNAMIC", - "name": "", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "" }, { "id": "MAPSEC_PALLET_TOWN", - "name": "PALLET TOWN", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PALLET TOWN" }, { "id": "MAPSEC_VIRIDIAN_CITY", - "name": "VIRIDIAN CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIRIDIAN CITY" }, { "id": "MAPSEC_PEWTER_CITY", - "name": "PEWTER CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PEWTER CITY" }, { "id": "MAPSEC_CERULEAN_CITY", - "name": "CERULEAN CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CERULEAN CITY" }, { "id": "MAPSEC_LAVENDER_TOWN", - "name": "LAVENDER TOWN", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LAVENDER TOWN" }, { "id": "MAPSEC_VERMILION_CITY", - "name": "VERMILION CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VERMILION CITY" }, { "id": "MAPSEC_CELADON_CITY", - "name": "CELADON CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CELADON CITY" }, { "id": "MAPSEC_FUCHSIA_CITY", - "name": "FUCHSIA CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FUCHSIA CITY" }, { "id": "MAPSEC_CINNABAR_ISLAND", - "name": "CINNABAR ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CINNABAR ISLAND" }, { "id": "MAPSEC_INDIGO_PLATEAU", - "name": "INDIGO PLATEAU", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "INDIGO PLATEAU" }, { "id": "MAPSEC_SAFFRON_CITY", - "name": "SAFFRON CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SAFFRON CITY" }, { "id": "MAPSEC_ROUTE_4_POKECENTER", "name": "ROUTE 4", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROUTE_10_POKECENTER", "name": "ROUTE 10", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROUTE_1", - "name": "ROUTE 1", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 1" }, { "id": "MAPSEC_ROUTE_2", - "name": "ROUTE 2", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 2" }, { "id": "MAPSEC_ROUTE_3", - "name": "ROUTE 3", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 3" }, { "id": "MAPSEC_ROUTE_4", - "name": "ROUTE 4", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 4" }, { "id": "MAPSEC_ROUTE_5", - "name": "ROUTE 5", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 5" }, { "id": "MAPSEC_ROUTE_6", - "name": "ROUTE 6", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 6" }, { "id": "MAPSEC_ROUTE_7", - "name": "ROUTE 7", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 7" }, { "id": "MAPSEC_ROUTE_8", - "name": "ROUTE 8", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 8" }, { "id": "MAPSEC_ROUTE_9", - "name": "ROUTE 9", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 9" }, { "id": "MAPSEC_ROUTE_10", - "name": "ROUTE 10", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 10" }, { "id": "MAPSEC_ROUTE_11", - "name": "ROUTE 11", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 11" }, { "id": "MAPSEC_ROUTE_12", - "name": "ROUTE 12", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 12" }, { "id": "MAPSEC_ROUTE_13", - "name": "ROUTE 13", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 13" }, { "id": "MAPSEC_ROUTE_14", - "name": "ROUTE 14", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 14" }, { "id": "MAPSEC_ROUTE_15", - "name": "ROUTE 15", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 15" }, { "id": "MAPSEC_ROUTE_16", - "name": "ROUTE 16", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 16" }, { "id": "MAPSEC_ROUTE_17", - "name": "ROUTE 17", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 17" }, { "id": "MAPSEC_ROUTE_18", - "name": "ROUTE 18", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 18" }, { "id": "MAPSEC_ROUTE_19", - "name": "ROUTE 19", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 19" }, { "id": "MAPSEC_ROUTE_20", - "name": "ROUTE 20", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 20" }, { "id": "MAPSEC_ROUTE_21", - "name": "ROUTE 21", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 21" }, { "id": "MAPSEC_ROUTE_22", - "name": "ROUTE 22", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 22" }, { "id": "MAPSEC_ROUTE_23", - "name": "ROUTE 23", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 23" }, { "id": "MAPSEC_ROUTE_24", - "name": "ROUTE 24", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 24" }, { "id": "MAPSEC_ROUTE_25", - "name": "ROUTE 25", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 25" }, { "id": "MAPSEC_VIRIDIAN_FOREST", - "name": "VIRIDIAN FOREST", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIRIDIAN FOREST" }, { "id": "MAPSEC_MT_MOON", - "name": "MT. MOON", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MT. MOON" }, { "id": "MAPSEC_S_S_ANNE", - "name": "S.S. ANNE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "S.S. ANNE" }, { "id": "MAPSEC_UNDERGROUND_PATH", - "name": "UNDERGROUND PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "UNDERGROUND PATH" }, { "id": "MAPSEC_UNDERGROUND_PATH_2", "name": "UNDERGROUND PATH", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_DIGLETTS_CAVE", - "name": "DIGLETT'S CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DIGLETT'S CAVE" }, { "id": "MAPSEC_KANTO_VICTORY_ROAD", "name": "VICTORY ROAD", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROCKET_HIDEOUT", - "name": "ROCKET HIDEOUT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCKET HIDEOUT" }, { "id": "MAPSEC_SILPH_CO", - "name": "SILPH CO.", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SILPH CO." }, { "id": "MAPSEC_POKEMON_MANSION", - "name": "POKéMON MANSION", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON MANSION" }, { "id": "MAPSEC_KANTO_SAFARI_ZONE", "name": "SAFARI ZONE", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_POKEMON_LEAGUE", - "name": "POKéMON LEAGUE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON LEAGUE" }, { "id": "MAPSEC_ROCK_TUNNEL", - "name": "ROCK TUNNEL", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCK TUNNEL" }, { "id": "MAPSEC_SEAFOAM_ISLANDS", - "name": "SEAFOAM ISLANDS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEAFOAM ISLANDS" }, { "id": "MAPSEC_POKEMON_TOWER", - "name": "POKéMON TOWER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON TOWER" }, { "id": "MAPSEC_CERULEAN_CAVE", - "name": "CERULEAN CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CERULEAN CAVE" }, { "id": "MAPSEC_POWER_PLANT", - "name": "POWER PLANT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POWER PLANT" }, { "id": "MAPSEC_ONE_ISLAND", - "name": "ONE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ONE ISLAND" }, { "id": "MAPSEC_TWO_ISLAND", - "name": "TWO ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TWO ISLAND" }, { "id": "MAPSEC_THREE_ISLAND", - "name": "THREE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLAND" }, { "id": "MAPSEC_FOUR_ISLAND", - "name": "FOUR ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FOUR ISLAND" }, { "id": "MAPSEC_FIVE_ISLAND", - "name": "FIVE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FIVE ISLAND" }, { "id": "MAPSEC_SEVEN_ISLAND", - "name": "SEVEN ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVEN ISLAND" }, { "id": "MAPSEC_SIX_ISLAND", - "name": "SIX ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SIX ISLAND" }, { "id": "MAPSEC_KINDLE_ROAD", - "name": "KINDLE ROAD", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "KINDLE ROAD" }, { "id": "MAPSEC_TREASURE_BEACH", - "name": "TREASURE BEACH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TREASURE BEACH" }, { "id": "MAPSEC_CAPE_BRINK", - "name": "CAPE BRINK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CAPE BRINK" }, { "id": "MAPSEC_BOND_BRIDGE", - "name": "BOND BRIDGE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BOND BRIDGE" }, { "id": "MAPSEC_THREE_ISLE_PORT", - "name": "THREE ISLE PORT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLE PORT" }, { "id": "MAPSEC_SEVII_ISLE_6", - "name": "SEVII ISLE 6", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 6" }, { "id": "MAPSEC_SEVII_ISLE_7", - "name": "SEVII ISLE 7", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 7" }, { "id": "MAPSEC_SEVII_ISLE_8", - "name": "SEVII ISLE 8", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 8" }, { "id": "MAPSEC_SEVII_ISLE_9", - "name": "SEVII ISLE 9", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 9" }, { "id": "MAPSEC_RESORT_GORGEOUS", - "name": "RESORT GORGEOUS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RESORT GORGEOUS" }, { "id": "MAPSEC_WATER_LABYRINTH", - "name": "WATER LABYRINTH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WATER LABYRINTH" }, { "id": "MAPSEC_FIVE_ISLE_MEADOW", - "name": "FIVE ISLE MEADOW", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FIVE ISLE MEADOW" }, { "id": "MAPSEC_MEMORIAL_PILLAR", - "name": "MEMORIAL PILLAR", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MEMORIAL PILLAR" }, { "id": "MAPSEC_OUTCAST_ISLAND", - "name": "OUTCAST ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "OUTCAST ISLAND" }, { "id": "MAPSEC_GREEN_PATH", - "name": "GREEN PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "GREEN PATH" }, { "id": "MAPSEC_WATER_PATH", - "name": "WATER PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WATER PATH" }, { "id": "MAPSEC_RUIN_VALLEY", - "name": "RUIN VALLEY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RUIN VALLEY" }, { "id": "MAPSEC_TRAINER_TOWER", - "name": "TRAINER TOWER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TRAINER TOWER" }, { "id": "MAPSEC_CANYON_ENTRANCE", - "name": "CANYON ENTRANCE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CANYON ENTRANCE" }, { "id": "MAPSEC_SEVAULT_CANYON", - "name": "SEVAULT CANYON", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVAULT CANYON" }, { "id": "MAPSEC_TANOBY_RUINS", - "name": "TANOBY RUINS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY RUINS" }, { "id": "MAPSEC_SEVII_ISLE_22", - "name": "SEVII ISLE 22", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 22" }, { "id": "MAPSEC_SEVII_ISLE_23", - "name": "SEVII ISLE 23", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 23" }, { "id": "MAPSEC_SEVII_ISLE_24", - "name": "SEVII ISLE 24", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 24" }, { "id": "MAPSEC_NAVEL_ROCK_FRLG", - "name": "NAVEL ROCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "NAVEL ROCK" }, { "id": "MAPSEC_MT_EMBER", - "name": "MT. EMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MT. EMBER" }, { "id": "MAPSEC_BERRY_FOREST", - "name": "BERRY FOREST", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BERRY FOREST" }, { "id": "MAPSEC_ICEFALL_CAVE", - "name": "ICEFALL CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ICEFALL CAVE" }, { "id": "MAPSEC_ROCKET_WAREHOUSE", - "name": "ROCKET WAREHOUSE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCKET WAREHOUSE" }, { "id": "MAPSEC_TRAINER_TOWER_2", "name": "TRAINER TOWER", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_DOTTED_HOLE", - "name": "DOTTED HOLE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DOTTED HOLE" }, { "id": "MAPSEC_LOST_CAVE", - "name": "LOST CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LOST CAVE" }, { "id": "MAPSEC_PATTERN_BUSH", - "name": "PATTERN BUSH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PATTERN BUSH" }, { "id": "MAPSEC_ALTERING_CAVE_FRLG", - "name": "ALTERING CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ALTERING CAVE" }, { "id": "MAPSEC_TANOBY_CHAMBERS", - "name": "TANOBY CHAMBERS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY CHAMBERS" }, { "id": "MAPSEC_THREE_ISLE_PATH", - "name": "THREE ISLE PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLE PATH" }, { "id": "MAPSEC_TANOBY_KEY", - "name": "TANOBY KEY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY KEY" }, { "id": "MAPSEC_BIRTH_ISLAND_FRLG", - "name": "BIRTH ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BIRTH ISLAND" }, { "id": "MAPSEC_MONEAN_CHAMBER", - "name": "MONEAN CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MONEAN CHAMBER" }, { "id": "MAPSEC_LIPTOO_CHAMBER", - "name": "LIPTOO CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LIPTOO CHAMBER" }, { "id": "MAPSEC_WEEPTH_CHAMBER", - "name": "WEEPTH CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WEEPTH CHAMBER" }, { "id": "MAPSEC_DILFORD_CHAMBER", - "name": "DILFORD CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DILFORD CHAMBER" }, { "id": "MAPSEC_SCUFIB_CHAMBER", - "name": "SCUFIB CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SCUFIB CHAMBER" }, { "id": "MAPSEC_RIXY_CHAMBER", - "name": "RIXY CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RIXY CHAMBER" }, { "id": "MAPSEC_VIAPOIS_CHAMBER", - "name": "VIAPOIS CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIAPOIS CHAMBER" }, { "id": "MAPSEC_EMBER_SPA", - "name": "EMBER SPA", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "EMBER SPA" }, { "id": "MAPSEC_SPECIAL_AREA", - "name": "SPECIAL AREA", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SPECIAL AREA" }, { "id": "MAPSEC_AQUA_HIDEOUT", @@ -1609,19 +1161,11 @@ }, { "id": "MAPSEC_BIRTH_ISLAND", - "name": "BIRTH ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BIRTH ISLAND" }, { "id": "MAPSEC_FARAWAY_ISLAND", - "name": "FARAWAY ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FARAWAY ISLAND" }, { "id": "MAPSEC_ARTISAN_CAVE", @@ -1633,27 +1177,15 @@ }, { "id": "MAPSEC_MARINE_CAVE", - "name": "MARINE CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MARINE CAVE" }, { "id": "MAPSEC_UNDERWATER_MARINE_CAVE", - "name": "UNDERWATER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "UNDERWATER" }, { "id": "MAPSEC_TERRA_CAVE", - "name": "TERRA CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TERRA CAVE" }, { "id": "MAPSEC_UNDERWATER_105", @@ -1697,11 +1229,7 @@ }, { "id": "MAPSEC_NAVEL_ROCK", - "name": "NAVEL ROCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "NAVEL ROCK" }, { "id": "MAPSEC_TRAINER_HILL", diff --git a/src/data/region_map/region_map_sections.json.txt b/src/data/region_map/region_map_sections.json.txt index c3435d2d67..0da2d31794 100644 --- a/src/data/region_map/region_map_sections.json.txt +++ b/src/data/region_map/region_map_sections.json.txt @@ -22,18 +22,28 @@ const struct RegionMapLocation gRegionMapEntries[] = { [{{ map_section.id }}] = { {% if existsIn(map_section, "x") %} .x = {{ map_section.x }}, +{% else %} + .x = 0, {% endif %} {% if existsIn(map_section, "y") %} .y = {{ map_section.y }}, +{% else %} + .y = 0, {% endif %} {% if existsIn(map_section, "width") %} .width = {{ map_section.width }}, +{% else %} + .width = 1, {% endif %} {% if existsIn(map_section, "height") %} .height = {{ map_section.height }}, +{% else %} + .height = 1, {% endif %} {% if existsIn(map_section, "name") %} .name = sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %}, +{% else %} + .name = (const u8[])_(""), {% endif %} }, ## endfor From bdb09890306455561c96ac71d0b38bfbec437114 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 2 Jul 2025 10:57:56 +0200 Subject: [PATCH 035/283] Remove remove_terrain.log (#7268) Co-authored-by: Hedara --- remove_terrain.log | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 remove_terrain.log diff --git a/remove_terrain.log b/remove_terrain.log deleted file mode 100644 index e69de29bb2..0000000000 From 734a15478c499bcd5d2236ec5e92635a12867c1d Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Wed, 2 Jul 2025 17:25:03 +0200 Subject: [PATCH 036/283] Clean up for Moveend --- src/battle_script_commands.c | 386 +++++++++++++-------------- tools/compresSmol/compresSmol | Bin 0 -> 100384 bytes tools/compresSmol/compresSmolTilemap | Bin 0 -> 104416 bytes 3 files changed, 193 insertions(+), 193 deletions(-) create mode 100755 tools/compresSmol/compresSmol create mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 386d636e77..10c81993e8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6568,6 +6568,24 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.moveendState++; break; + case MOVEEND_SYMBIOSIS: + for (i = 0; i < gBattlersCount; i++) + { + if ((gSpecialStatuses[i].berryReduced + || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) + && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) + { + BestowItem(BATTLE_PARTNER(i), i); + gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; + gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); + gBattlerAttacker = i; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; + effect = TRUE; + } + } + gBattleScripting.moveendState++; + break; case MOVEEND_FIRST_MOVE_BLOCK: if ((gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT @@ -6640,12 +6658,6 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // King's rock - // These effects will occur at each hit in a multi-strike move - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible if (gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE) && gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)) @@ -6683,6 +6695,12 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_KINGSROCK: // King's rock + // These effects will occur at each hit in a multi-strike move + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) + effect = TRUE; + gBattleScripting.moveendState++; + break; case MOVEEND_SUBSTITUTE: for (i = 0; i < gBattlersCount; i++) { @@ -6819,6 +6837,37 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_DEFROST: + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; + effect = TRUE; + } + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && MoveThawsUser(originallyUsedMove) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; + effect = TRUE; + } + gBattleScripting.moveendState++; + break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. { u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); @@ -6942,37 +6991,6 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - case MOVEEND_DEFROST: - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; - effect = TRUE; - } - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && MoveThawsUser(originallyUsedMove) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; - effect = TRUE; - } - gBattleScripting.moveendState++; - break; case MOVEEND_SECOND_MOVE_BLOCK: if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) { @@ -7083,6 +7101,57 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_RED_CARD: + { + u32 redCardBattlers = 0, i; + for (i = 0; i < gBattlersCount; i++) + { + if (i == gBattlerAttacker) + continue; + if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) + redCardBattlers |= (1u << i); + } + if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) + { + // Since we check if battler was damaged, we don't need to check move result. + // In fact, doing so actually prevents multi-target moves from activating red card properly + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + // Search for fastest hit pokemon with a red card + // Attacker is the one to be switched out, battler is one with red card + if (redCardBattlers & (1u << battler) + && IsBattlerAlive(battler) + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) + && IsBattlerTurnDamaged(battler) + && CanBattlerSwitch(gBattlerAttacker) + && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) + { + effect = TRUE; + gLastUsedItem = gBattleMons[battler].item; + SaveBattlerTarget(battler); // save battler with red card + SaveBattlerAttacker(gBattlerAttacker); + gBattleScripting.battler = battler; + gEffectBattler = gBattlerAttacker; + BattleScriptPushCursor(); + if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE + || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG + || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) + gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; + else + gBattlescriptCurrInstr = BattleScript_RedCardActivates; + break; // Only fastest red card activates + } + } + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_BUTTON: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -7130,6 +7199,61 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_LIFEORB_SHELLBELL: + if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) + effect = TRUE; + gBattleScripting.moveendState++; + break; + case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out + { + // Because sorting the battlers by speed takes lots of cycles, + // we check if EE can be activated and cound how many. + u32 numEmergencyExitBattlers = 0; + u32 emergencyExitBattlers = 0; + + for (i = 0; i < gBattlersCount; i++) + { + if (EmergencyExitCanBeTriggered(i)) + { + emergencyExitBattlers |= 1u << i; + numEmergencyExitBattlers++; + } + } + + if (numEmergencyExitBattlers == 0) + { + gBattleScripting.moveendState++; + break; + } + + u8 battlers[4] = {0, 1, 2, 3}; + if (numEmergencyExitBattlers > 1) + SortBattlersBySpeed(battlers, FALSE); + + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + + if (!(emergencyExitBattlers & 1u << battler)) + continue; + + effect = TRUE; + gBattleScripting.battler = battler; + BattleScriptPushCursor(); + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler)) + gBattlescriptCurrInstr = BattleScript_EmergencyExit; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; + + break; // Only the fastest Emergency Exit / Wimp Out activates + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_PACK: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -7184,80 +7308,25 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_WHITE_HERB: - for (i = 0; i < gBattlersCount; i++) + case MOVEEND_HIT_ESCAPE: + if (moveEffect == EFFECT_HIT_ESCAPE + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !NoAliveMonsForBattlerSide(gBattlerTarget)) { - if (!IsBattlerAlive(i)) - continue; - - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB - && RestoreWhiteHerbStats(i)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; - effect = TRUE; - break; - } + effect = TRUE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EffectHitEscape; } - if (!effect) - gBattleScripting.moveendState++; + gBattleScripting.moveendState++; break; - case MOVEEND_RED_CARD: - { - u32 redCardBattlers = 0, i; - for (i = 0; i < gBattlersCount; i++) - { - if (i == gBattlerAttacker) - continue; - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) - redCardBattlers |= (1u << i); - } - if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) - { - // Since we check if battler was damaged, we don't need to check move result. - // In fact, doing so actually prevents multi-target moves from activating red card properly - u8 battlers[4] = {0, 1, 2, 3}; - SortBattlersBySpeed(battlers, FALSE); - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - // Search for fastest hit pokemon with a red card - // Attacker is the one to be switched out, battler is one with red card - if (redCardBattlers & (1u << battler) - && IsBattlerAlive(battler) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattlerTurnDamaged(battler) - && CanBattlerSwitch(gBattlerAttacker) - && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) - { - effect = TRUE; - gLastUsedItem = gBattleMons[battler].item; - SaveBattlerTarget(battler); // save battler with red card - SaveBattlerAttacker(gBattlerAttacker); - gBattleScripting.battler = battler; - gEffectBattler = gBattlerAttacker; - BattleScriptPushCursor(); - if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE - || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG - || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) - gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; - else - gBattlescriptCurrInstr = BattleScript_RedCardActivates; - break; // Only fastest red card activates - } - } - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + case MOVEEND_OPPORTUNIST: + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) + effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers else gBattleScripting.moveendState++; break; - case MOVEEND_LIFEORB_SHELLBELL: - if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_PICKPOCKET: if (IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item @@ -7294,75 +7363,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out - { - // Because sorting the battlers by speed takes lots of cycles, - // we check if EE can be activated and cound how many. - u32 numEmergencyExitBattlers = 0; - u32 emergencyExitBattlers = 0; - - for (i = 0; i < gBattlersCount; i++) - { - if (EmergencyExitCanBeTriggered(i)) - { - emergencyExitBattlers |= 1u << i; - numEmergencyExitBattlers++; - } - } - - if (numEmergencyExitBattlers == 0) - { - gBattleScripting.moveendState++; - break; - } - - u8 battlers[4] = {0, 1, 2, 3}; - if (numEmergencyExitBattlers > 1) - SortBattlersBySpeed(battlers, FALSE); - - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - - if (!(emergencyExitBattlers & 1u << battler)) - continue; - - effect = TRUE; - gBattleScripting.battler = battler; - BattleScriptPushCursor(); - - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler)) - gBattlescriptCurrInstr = BattleScript_EmergencyExit; - else - gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; - - break; // Only the fastest Emergency Exit / Wimp Out activates - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; - else - gBattleScripting.moveendState++; - break; - case MOVEEND_HIT_ESCAPE: - if (moveEffect == EFFECT_HIT_ESCAPE - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && !NoAliveMonsForBattlerSide(gBattlerTarget)) - { - effect = TRUE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_EffectHitEscape; - } - gBattleScripting.moveendState++; - break; - case MOVEEND_OPPORTUNIST: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers - else - gBattleScripting.moveendState++; - break; case MOVEEND_REMOVE_TERRAIN: if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases && IsBattlerTurnDamaged(gBattlerTarget)) @@ -7381,32 +7381,23 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_SYMBIOSIS: + case MOVEEND_WHITE_HERB: for (i = 0; i < gBattlersCount; i++) { - if ((gSpecialStatuses[i].berryReduced - || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) - && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) + if (!IsBattlerAlive(i)) + continue; + + if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB + && RestoreWhiteHerbStats(i)) { - BestowItem(BATTLE_PARTNER(i), i); - gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; - gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); - gBattlerAttacker = i; BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; + gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; effect = TRUE; + break; } } - gBattleScripting.moveendState++; - break; - case MOVEEND_SAME_MOVE_TURNS: - if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] - || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; - else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) - gBattleStruct->sameMoveTurns[gBattlerAttacker]++; - gBattleScripting.moveendState++; + if (!effect) + gBattleScripting.moveendState++; break; case MOVEEND_CHANGED_ITEMS: for (i = 0; i < gBattlersCount; i++) @@ -7419,6 +7410,15 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_SAME_MOVE_TURNS: + if (gCurrentMove != gLastResultingMoves[gBattlerAttacker] + || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT + || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + gBattleStruct->sameMoveTurns[gBattlerAttacker] = 0; + else if (gCurrentMove == gLastResultingMoves[gBattlerAttacker] && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) + gBattleStruct->sameMoveTurns[gBattlerAttacker]++; + gBattleScripting.moveendState++; + break; case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) gBattleStruct->moveTarget[gBattlerAttacker] = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol new file mode 100755 index 0000000000000000000000000000000000000000..c518f8381b4a471181752509730a92c1967e738b GIT binary patch literal 100384 zcmeFadwf*I`9HoJ0z^emP}HcXsa@NoA|?o$6wxdsa27Wj1(bRVh(u5>DcKcNF45i9 zoF3PvEw;8_ZE3ZwT5V|+!3&yj3usj?UQnt8s&Ebw!5hX4C)aAN{0S%uDSqFa%`M=Ll zMPJu2A9?)c%im0&jrkyQ1Iu-#FBLD-@To9GXO%8jdy=ZJYxuaPKNY6vybR^Y&;RtN z#l?5IuCKfP+pFtKg^DWG&LULCZXI>WIA2!1uZgsz^8G%)#E;MfW$Ab-pRoP#pXgb> z^0Yvr8Re4ziYs!9TU%)Hud`R2A?zShO?(loe`aL_MDRQ&OUGOz`B_O z2T8e7lqEiC_wRkRjlN5>nD#^b=dk|!?iK+tQ$Pry20~dH}rg`8~XcngJ)$o=?lA|XJj}1IH{X@ zS9OEu%x?HFzZ>`k-N^H0-K4MTrhgyk2LH}(=-Ji{p7Xll|8w2&XKXk4Z|;U3>g#;` z@A{kB4g7*``tg_D^b5#8B>n;2r0?yf-hJTDcYG)Ka`k*(uL<6PdYPWD?Sp)sz8rY^ z`cCmJx{MTL=IeVAC48gClP|fLGXQ^v?`U6Dg-ZC1P7k2p316o1*X#5z5Hh_43(`U}8u8T~Z6{)WFRfon_R^Kpr*5n(f)~Jmbd5lPd6v6c-l{x_)Ba)JdRV*3=m{h9-@P6c-ax1F@mOCHTDW54%Ve> zQ2FGE(+`P4)l-5RssTN@e2_Hnl8gWQ78IXfGj+xd)iqOR)kUgj%#2jetf>GyrcXx| zH%zO#h2hw-{}oxq=c*ReOr19Q`e@A|8vq{6tedQ;9y4_?8hS%T)ud^vUByK#T6Zft zdwQxz2G>rEOc_!gh6IdIohi&3qN-A?>aH@4^*%gO&h5{io;3bQ8HPMbJsa>exN zWZ}V$IgcG3t%IywGN!sy%PI(r?t@6MMbtFOl>m{C1x zVr0^kRGDvQSMj;kq3N~LFo32_#^{+et)l9ZF@vgyNUGF3CX$w<5n7T!$$!AE!9p3@ zN^p_oOF`=NnKw|FG1!Vz0$L4gan{6Hw^mP`F*U-L+&E`Wb?xL?bu(v7oHjLbYxONf zC?P%iA5_bBkC{1S_N=Lq$rRSZiB0if^i5qYDyp6|y*5&(#V$S6W`5gH>m;cM_fJM* z{-c4b!Dq~tafRW27+oPvJsi+ra%{Nv|6S1bI8-w@_Q)j70rR4uV)wMFhZkSqEn^7G9Sr4YV=zpLc2U9tw z^&y&c9#s9zS(7VLBBz!0w@MJ0dgvh{<9RZ)Z)!AyQKjkmY37a40{`EpCukG&%FG#1 zkI_kyQ26@dii(O`L^sWv8J%%Mjjwj*Y+v=b8M8SDTt2xjI(@RQHX5nJ2!*PebaVBj zDK}TwOq@E6shj|P(^+0w9*0_ zG0tzB%;Fe=4C*FFBvyN?uSQ0)513GR(phJ56?q<`)6-8kPC_M&6*GO3N*^_1MD@7? zi+rQPq2VK{2Mrulnt2>JL_Lom50JqF&mH6&F@Ah-c&NH~;JE`eoX#6m?8)m?YS4M! zsP{RA9<>fu>3Ay6Jf1rkwoDdQ!rAh#C)VP8>WTGmmi){1^+uQtA4pH%5t4VL?OHz+UN-z8)L~r=N{60gTv7-0D`lUSA-+o^%oEItkwCa1e9_2%c0`1UX znO-`d{sQY~TuC3}E7EDvlc&N(aFlOo8osyh3)pzXSC9Y0+kXYi?r7gA4S(x~zXAV| zzAJS6$CBUMH%Z4g{q1I0zP)_2bo>^{@9CSTjb6`^`!f%6n`K(=)=q} z$CHkZPXBT}=~%L)e|esCELqaOd`~*-PW=iz>Fk@-ugH^5no_?KPkO5FnOEjXPx;K4 zZhF#>WP<)xdD1Z;(!cSZbO>(xH^GyBOgh!)o8n0~Jn6NbbdJT;Z;mIuZz>UCy(iu4 z=Vhy z__dz&l#ia->pkhGdf+#E(ogfGw|de~_oO?X^n6eHUQhaWJn8M8^fNr^K0Qt;Yv1*x z=XlZsp7dN#`k9{eJWu-fJn8wK^zVDp3q0usp7bJ5dZ8!1#FMVK6ePFIlTM#Q>Sub= z2c{AcR(aCT@uZLUq;tMW{U&(Qi&KdRr+CuO^`zH&(mBtjesetOLsE$d>pkfup7j5H z{9g|IF9-gY1OLl`|9?5~sd3s@X6(Zp)9$(M9KX*@G)1yH)|;_aIV***jv+50x#P@# z;;(Uf8J-xQ!aTRN1HUs@Fiz9bT`%!x8K+6aZcZEt;B!AI88)%g2eA+oTi~$CGp!Br%C9RNqiRLGzHxviQmLH zmkMsa#II+ZCZU@v@v9i8Dd_qnemUbb0o}a^kZ|T`#%cPwtr8#3I88oxy~KaWI88mb zN#cVT=MuzSEb$*OPLt1FB=IvCr>W;QO8jKTY2vx{5j{?$OlX~MZ>690s8nr?29#CI`Hlg-VS_;$u=s=2ume}{3JXs%D<8yTl*=I-6k z_P@k~E6xWPOt`%JbZdOpxNKL!pn`FtQBgU5LvJ%GeY>qDmy zMcSUz6+Mnf*y?aTLyxun$=MGQbxxMf`3gxw!pC@Mi}5iGtb0+9^B$9$(v>X8RI&;= z?igu>H0UYDha%o+CWlpjin1HgS~EE}kne1Mf^FLAtY>JK2gYX_lEbz>0!o}oKtQ0Y z^A%8D7oZq{E+i0e&T(!a7@j6LKam3Q!2KXNQ|4?Uz7%B?(Bwk`9ZjGg5b*~f)?xn; ze2UXcW3O@s=zbLCxD#0iTzGuN9&7fjG5(ud~}LwA!ZaJ;@pP; z!_1OQ3xqXE7B^WEl-3dmGBHOgp4Z?kc#5T#uP4x^$K`o5pJxlUINH*Yo*C^*n*kLlsOJpU)9I6>Bp@Rg#W&Y02_Dg7gs(MZzM82gnf;7UJ2R zLkYDNV2qi`1a+)wB}j5xi!dD_$bEsHk(+smOYfS%a7b)a30*qW&FG{|l+kTl}+8^5+Kf zoOW0TRL%J$<{%}t$8pGmhX@Vu?PgSMwEp=XvO}k1kQ9flLw>RwOF=o;dvw z^yPJ5Zzb!^(ey3;wA*%^Nw`+xNo@nBRao&^6c%ZX2aVon=^*?~ZHp@UxQ6@Xk_NWs= zC9taIWrkuEcVkut)Br7GB%gehY(Pd*dx6h_2W9Op9kv!9WDu6MAaw^FzJm8G~M9Enb%O#=aq>8v^Xk0Tct{98@a&)cNKNNm-G8+E3HNN;C4h+9P9>#zw;ipO8WeHRgLX=7k#bJqmLJXRZMsD_)EAu%&`l3lPQ}RGpF@ zvZ08$6B>7|5Oj}j+Cts5dsNc~2#^*qpn=FK0pmEH;NHS)^z3>{#4~%L$xhV;MA`rY z`BT!y0#k~cq#XZX7R;b6aamD~v8M@I82D5x7K*qVg=$PVrGEw0*&6?PVHadax3g8p z^Vzf;G|*m2gf1ZwBE@LDNHyY=VlsnL?S3w%JXRo3L1B9u2VZ$0$Jw!mT*VXS&9J4D z^PST``^cNt)STH%=w)nr?btv z)u}=`=P1FfhDb&`a$bFgI0gWRvy(`{8V;k*Ftb@_4q;XjhBns?6o&FZ5gM%e6OjTw zq07suav&g1MGGc-dwNdTp6shE{UA~nf;y7c9Ua2tBF!rX#!zfke%pJd9R^aF>;grM zjK{PGqcJI4vVdz>u@!*Y!RnQuWkQCQ8x<`T6yYxQIc;qn z9nS_pmT4dTw^RH+#nI%jUvMN0M7OOe51iu7Y~q@$JYH0&)`ch_(jFLr_gce76w~p&%uK@+*3EUom(GowP2Td@4Qja{8*D8#qTmTcw((WKv0a zzD(Tt6T9ftAY=t}1;wB8;Y7$Ev`r(@=^mK|K~JOPdge~x7Mg>yDUrT%$E zkP-hknE`Ss*w501Owe5}2lZ1z4=3bC)Pr=h@Ds;CX@Xp-!x}py7PDRpqf*RnVN8_QI%FoE*042m{KfmI|Dho+fKt5- z%tT*+e&>Uo;4I)^jsV!)@Ff=ob0C;N$E4b}Q)`UV%YD8P#?ryTi&woRrz?C}#ZFHlO@3&|m)-=vaqMxsu4 zDqKSBiuK6C2+oHp#OjU=bZ(&*z%b=FLso%kN%$X;j3}l~QJPhRg0dt6wr#W2ar_H! zAQ?KY8Qg{*NqmN6D4hX*!V)84+ZF83HSB#F7M1{E&lXs*bO5WBagBzZDzMSZ05{N2 zv1s2xvF~v9A{0;fPCU5tv~O}WyADv-OZbIzG6Yqiwn2hP=c61Q*NB5IU028JDsMmd z$u|66(KXQ5cCUx}w>8vT8j7M$>V57oaU-NzvRDKDRRi9m00;P7M{Mw6Jx@^GBWo-$Sn&&@-x!FJ&ucRa32sa@Qu|`k!m!{#tq1Au*J5^NQGlWN-zsmA0R>B> zqiRaI@ibzPekw+Anjj!Or`#xC>kgw5D)~S>Anxm^0d6_>3)a*J-Q#`-f8ZN&&u8Rk zlD*2^ufuyZ_}R>?P>`Z1+?a;g-6gzU#~p;m>7?Ap{mTr#g;*=vcq+vy4H5^r`)5TJ^l1L1}yBcx;{C1t4yn9?{XN@vhV%;7bL5$RGxV z2TW_P+5FK(W^;QF)4#^ta3InT2*zmyIUTJ^Z=}kTzWQPNj|1+>f(LZx|hEX6R$CNMaV)M-U^NlS+B#6vp$t#_pzAuj#;|d zv{swO$n{WE5kn?5_&<>eQz_ppY+Ht!7npZIQactbFz|pbs9(lEM&(M@DK^e^E5U>~ zy9Z124|9q)K7%nzb#>ha=-wkhh#70|Fcvn+K6Rs~iH(3S_|%wr4F31N!L+l*x}>n? zK{wl@a*e)*X9gWBIWRJ+VDp27FELJM8wir=_ z5UY(5B?wCpmLV)dXd*;VWmQx;@5=bK$M&eT#`df=V@=uMWS{6q#Z5??i?q3!G}DeX zNR>}gkHNJpft6sQ@pP;aK|_Lnox7NZ#9t zy?8SECMCiCg~ZbRb04E-ON;@3M&DQ~0@Y0eVNC(mFWQl!x^pL@Nk)M-2P`!D-lt-} zU`$Gx)_wBa5@Wz0a1zKU>=ST~0?IBuKM_5jPr+P?Zi}1(b^?*7yDa$T_PRe}i%Z*# zcoiQY{>PcIul$iy9d|3@98z5Jq1>A66H!ACw*YX))4dvcw{3HVv~on2qiPPq@1q11 z<^_J^S4zY)@+M=|eo@+l|d{8MEnh)nXZ-o zhf0M83qxJlGY(QCUz@QO)HJjb+VluBvD--eQyM=FG{p8BvoFVAf3zHJ^)-;Bn;~ml z6WyH8HRkXCMb>O}LYlygd&NjBARg$qt1)*dIZW)1yukLO;fe)e)qap4Mx#~xTRiRG z6}Hwm`&oxgdhDU@?H#NTd?DkGgS0aT1-Cj^97IB-z$rc`G1>-B{o_?|Dj~G5Zd=jz zS2krNsL*smKSJk1s4)-M(v#vo3Rq;u(InqN@x##+?tKD5NgSxOY3BEJ(p?&M5Yl z4g1E?)qCU$eo3yhObg?RB9-U3?+{uXjJvp<^bF!$TLGrIGO;dlA~W-VR|(Qf0?zDY zcA;q^v^KX*EDB?UJTxVe$&Ph9n|HWvHdDd~J|4p-SuW79SE9dug z21_knngIP2LZwFHOt9BjdO}Um>g%3_=L|=qOO2(+ApMB8zcz|~`+vjV>`wgMc_`vi z-w+>!5LH*Ie>M(?$I z1ug75-lgRuEsr7Zc)tPzAv50J05e0K#(TS2xK`Mw$Gblzj~JA@oGXQ>qf9^63(|;A z<6YS78Sh`d*;yXfNgQ1f!jzpJ?{uWd#PJTYMO;J4K80b9cbLPOY7QFj?f&^UaTqJV zPLA^|_^ZSnA{nwT!+#9bf+yrra8p*LD46+9!tXE78Kd>WdwVsIL*}`@@;e60EHBTf7A9I8ob{}oY~ZW|-R%ne_m;?q49dmgczK>h3MPBfNY5UeS^U}R)> zafj8OuKz`v;GTGFPj;*$%lKug{^Y0wu-_1m?db`Rz46NxN38eqlwS9RP4qD@WKJWd zF&!oRZIx;(qwI=S2$ofG@=wCHPg#RXP#^S0B< z{cl@G;;HrI=577Y1k$EEw()Pde{H#cgEbtYvDq4pWf#}FD;q=Bmx+DzOUz08=ymWg zPRn)3E)801O@9j+X*_LMFO?Urh;26-PBcr`M7OO(;UT8oo8{LPZ#=ksR=*rV_d^f% zh6xN+(Tx6hHM%q1zh7bHZ-Xp*7VX@^HD>dH?6%`m@=;b&f)!6}g&+09s{bVV(K3jC zN4o#)vTSd6V817|#RI=jBv670+=xF22H06)yDyf?Fw(>J>7puMF2*^C`_1OoY*?)2 zJ+gxh**^^1ST?m_tc}PC7p{jWMtfGo_eHP6bqw$=Uh5-t*uU8}``BeUn_8hR&NU}( z2-$rCqmzU0=)yth<#PLidxM*Hvf1T+i1vo)?vQ_N%qa_E6&J>GJaHSEb9LBi%51K9 zxQO-?HwCRP==OLuI4)%Ef02?RtNu5}gsqn;VnH|~f<{G?*}OX|*u3M|=6^%wuBz}K zX#ODEIcj4^N4X!nT2&bI6~2%)E*JlE-~lVM3Yxbc=igNB|F<<>1Ooedo;@D1A6k0* z{eIs{Jgf0)JiX3%dSjXK^uFe8IY(^ZpN}mg<1dj_aPrFBHKTGN&hQ$ANINCe~DD^c{f-7;C8(ICJS#?iUCt6A%_MGPCi& zAO07ag&QK1%;qmKhJ*A1Wf^y^l7;=N@b5H#lw~&W$oBRh+yU9c@h3by*I3isVD!!I zp(J^4^!um}Gv5x>7m2&6bK>#KmDE%{2N}z<JE4WLz#bzVV~q0)Av9q9@AG z6Ja(VT-3qNvBm-cizSMVJuzA0u(&Q~_J$R30wuv2(2r);J%uS8Utq*2VeOhUQ(zHoI9?MfM%rzUjb}^r~sqnbw;YlHTRZ<*HZ5RTi&JGpYY3`?5y4sP^#G#B!+=Yf_tbTHxwI{;}4g99-*J+gb)3KP`>HPJd=zE;_!;upj^jn<=kr0Zlt_qjJYh)xo z5+_8LcMFUJ4&-o~o$U7LU$N`GEiA^+0S5r(E8fD#T0Zh&ih4M>?U6ghj*aj{iR_7l z1Nlz-%b*h4EuT$81{NKw$lE#Lj z$i5EbLU15LBSnOYC_-kq@ZUy!G|_t>g4FDyIf&eV|C;=Cl;H!Bxf*fQ-Hgd!K>^ zm7V7d0s-*JMX*45k3On15Qn%z^x)bs5>IN;W5;In!(fOVd&whqdYuMlR3XDxyc_4Q z(sJiEQ$zM7nF*E{w$?8Dq79H)O<}Sr}%Vhq2x{;EY>~2oRK{ zyUs`yP~c;$Oxf4;bfDH7DH@IVGIXP~L$#rJw;T@8_8i-{I^90F*do)oNGbdZ%PKCj zlKrk^Lov%7+)!+#(uD@|Bi-ciJSuRe5i68TUYEwBhUjlIQ;s@ekh~eNeZ%&xIqnw_ zFw8@y^{)FN9yLo<-O$3a#oM*gx8_pM5GKQ8RxO0MeW_n(a`-mP7ed9Yq(0>Orw(HD-=`B0eP(~3~(n?~&9&Z0#5fvgTL z3MH@b!@UW?EQ{|G`5jy2Z{7~s-DvtZAU6w8xnX!{p#p=kodR|&)-Sn!BxW`5;QA`W z75O?N@e+Cyu84Cg6CKeXxslFQdYW?BN0AeF5h>g3Es<|JGE3bEX4MKz>Vv0nA!H66 zksEyzy4AF>L3PvZWH!9N?BG&2`i8fnMjAQlY$DiVy`njD=jYTuu~ksVn>$G=EbY$q z81ctMT7{| z9BF*%qGg0gpwYJnS*h32nLX+WJdh9lf2T$jfj6=T+MN^0hSiw!0t<7VoFx?ZFzw@; zo@EMF->Gfx0*&IL!=N}PjUv$%#om7?D!y5z8q^&XAKnT$&}Sb%x+{uh8pSh*LGfrB zh0zs7y+(1%VNlehQM~?47haee#kq$;@!d3vUw1{3t5NJ-`R%-Dh4rC$aa~swoB65& zI`xT8D25)?sSl=6e77r#MH+zuNEs_{QfW~ewIdYepeJLHHzyFgW{4jif@*7;l(`~#VLnD zaa0;bb5|7OG>Xm5-_DD*x1@M+S639LX%zPz21O!`;^M9-cK%JV^YX)>7@kIv+ZDxP zjlwt#ijHWiA#Xh0g`Kx*6#vB5Ar+v~7YED5^Jx^n>55{wMqwQW#jR-+)m>2>rBRGL z42tv8C<0wkypF{jM{1A5p!hVB;)T1U3ojnjD4JgUc3vz_qxfrA6g3*fyu+ZFo<>pE z6~#Fk#SagI;scWd=jpC`ppm;cqVntUJKhY?D zd>9lH(n{)TfsIpnVz#bltMg#n)++>aP;KQxYAUt=2cSMU$~-YX(KYm7HN=E8_HQVU1{ zHDj%D0yf*MTv#cvdB%MqcKf*G@NaNBFy#i|ixvggF6nqr>wm#`Lw7)+^##z2!uoFFE|cn#4{3`eY*}v4chJ1kr`<5)*ECS%@cioT;+# zo3Qn7)4#=N_!8p}D|jHFvD5Q86iSZiDBdRrtNY*t&m5TK30_NJTFJGTZDl!OwM%bFg{FU_(NHH2%J*|)y$rs zbDB+7VP%$JI*4L91oYs*Yh1rvIBLYhaujJv8IoaS7kaE!W#_^l)~~mneSE6f4^8S1TP`$v2t;K_Y5012k&DvGAG0{@QGGd9NUSlfcy6HQ9E>7 z%5ngL#+AWX@c9bclMVFvhnYkp?Ow2=$@xhRDySSo1u#->nh&>n@|^NI+<9E5Ysm=J(>H*j4(>_c_^#bDNE z-$yz*7MnCBsIJDC))Y?m!4cEM1feBas{*;?;$KTypR`ZJEo>#}`*z+(I+Q`r=Q#r^ z!6}nsJJAzWc!JQNbxcEoDZv^uc^|7l0&#(MpNRCFj%kvkRePc2tvM4YwIk^|W7 zUqZZO!faFyK*6Q6NHeppk*p;}h@uO^NExkwrK2=(t_D5_SuaqE=srFJk^1G-7T838 z<2Z_1f`G`Dtp{iX89qK1wv&`$2n22;c%1 z9V&oE{7wjq@pNBGqZxDk4OL_aApjlSD9m=|KdrcY1?N`baz%aEUQ#dI8`nr4+ldAh zYk;CL;t%u#Bt5h(PLPG!*N{KFxud)KlH>&t$mO-DNcXtYzJyI#B7LH6a|v790V5s# z9Q;1r@OrP5>ms0ABvCpZl#&r(4VgvO#JQQo}Ni3BCYs4lV4Lp;!fO6@J=70CZYcF{f#?#s7VQ65q!6lj-ItzyZtY#zL z19KW!P~IT3haS1ksX}d%!h!u?oz+6Fwcxmx0d2OK;{#*&e(X9m(8(IIaReI<9BicE zBt{>o3TNq4JQ8yOCKu7)rZun8dXN77(`1o1uOT_U2{LRXP9r;Xt6Uz+YD`Pq7;GeB zz)-p}RDgJko{?Y76uwi)z`+_&dNIW}^pL+&T3fFx~zmLBZ7=1lUS3 z;yVms4ivC+6xt&1$G~?zSnZ;y&a`CsIWIrS{3RxeS`S_Toaw1ygJ?gQ8la&}WK|Y^ zVZ@KYP@*>c2MS^^U}H-3jG9nI*MzKpV#*8gxJ2T|$5Ms(sr_#iQVu@cu|w{>e2gRDI}9b3lEZ+ zTvEmglzc*Uv9Ynen1z>6Z5dBDRXHzgWd%z9Y`K>PwuQ6#A5hLe3SI>c3yEs#=Xrji zm5#VG-50=e&+M73Hk74_YRiy=@oJDGUOj{VDVX=64CFNs&*%bo%j&^ zK*yukKnO>*u7!i>QV^0Bus?7BXr^gy*-Iz^qQ30=d@S3NAPNrE7MTzE1lK0ci)&?J z;*djgdsbV}L;HX8$k#~}icskqBQ_834-U7p|50vz97@iIJM(~I)~41TQh#jc>B=IA zu7S#!LK26H%oy<_G5js4&Sto&Bqu|0+pnQal)u_e&~(HMMj?o`_rlv~t77dugA>~D zW$=hqm@S#(!;Sa$eG~A6(>3V)ba}iFcfrWwri+t zKsR70wlcdCTk)@mmE){j3|cd`4Wv%wR16zsYWz>^n~M1Rk*g_Jpp@^g6s~{{8V%bJ z)Du5n1e%-cKXi}KpJ=^mJdHy&c(?DR!cW)?OglKV;)E?JpF*wYH!HD>%A<61SNq9~ zWp9A}w37CdnhFnNKP`NZ?5J2APDU4Lm4!(cdUX-1^szN|6+Eg%&drT1lp$HkaNxiSlCYK1STo_3h(_TM2f66zy?BC z$obVSnPyWK$dX*Z8^>-&_F^_43Iho|_V6CoIAZc?b&H`KISNJw_1pHpvJr< z8U#q$j8Dk1%`Q{2$x6I7<6LDkCh8&1%4|$Y@qkxparr+=ghl2t|-yM#R;#$w7uR0gWobmWRati%yB z#7eBJ2k$&q;$o>@Q;}RmLF!^GjuxU0*)Qivme*K3RRMdAMG*lg(=3(6Q6@H{8Ef-9 zyC0VpbChT+kfH)!(t0e?k6Ku05aKZ(siD&M4mJoc%cjQ1aWWc&Z61RV(Apq`MU}%Q z+7FWLPBm&LU(bIy#aB*m;~McFCx?8Y!uO2$U+^j#`}17FDr*o@g&kip{5i*CHm?Ou zsZQMW7glhPHMoSs#(Cm4)O2Ve-!A34h~6ub=(Pr+p=6}b$%UoX%Pf4$Z0^WzJ1M2F z%YT?<#D9gQo*ev(t-u++*P^?gdl8jun-Pp0D+foY`O7TRHgn9gpt(mP=!F-{tL!D5ah7cPX!LuRZQV9m96T>9%Th0Z=vLJ_@{l&Y&nM|t{)_|GAa92fg&|X zYG=|moU;mA*H%Hgp}Ay%NI4D{?sKjXoN6W6MI8)PSsaBaO~G+Wb17eC`8-*A5Lf+wq1XZ>1bm3gwNbk=;y^4!&E zByu=bl9M;9UH#OB8|n8-K-p&Yp!J^foofLJ#p2HYIwK$H{8vMG5$3=(+$+Ac!yPRm zR8E0Nn&bgax0kNPHm~&>EL@Lyafo|m-u^QWlB~+FEZvFo4thP`r5Ba}hMjgSdY1YUD-TTjU&+?xj#bD^!S8^ zr%YhFo`OIYP>bPmqk-{b5O?qbO0`2~<29*8)bYwmw}?%&6OTwsWf3KB4CzHw7N(oj zdO$5qu(HV&*p%H=COxm_-%tN24HN)nYl_*CSx^0g09tRzno1T@sDW52u@Bv8AtfF* z!F-e7nY}U1Jje^Ha25jFkFJ9(OhD=4CYTCbHVt$ifOFWxQ}3hjm$Rp=pJD*)w0^q& z4Y0@h=2<#TQG z`rmjjh=o-b5t$p=EutgiRQ!Bcw6>Cc$8)UfHJw`Jx$jDQFnh8;I7YaxYe}$v#@z4k zWqVNpG1HjQwu&A?c)J7gzXu}>!f$1t$(NMe-y#mtMg3}>r5x}6nA0=kdv_N&0u*O0 zzHn;!)*qu7g-}-rOSqsFgeP96B6rT09(YhV0Wd7eGmME^9dW+~R-XGodvp>TlX;|L zj-}iQtbSmo|1!RLGe@ru3qQt^Q1_-xs_3Dm&Iz=GJ~e zVOL8>BYr-VF>GGeU6GO=>v8Cg@wTL50b;RpmrIVYG3=QDU#i&Xd zsdx*=W2PR{2>Ud0O~y9;GWwCSO*2NRn~#Qg*iJ$-R7^&7-DdVc#Y({N+OTrmrv`NS zk1%$Wt>#|24>&L*q9@g5Wf+leEk=#=TQ&>_EEiCdAbeAYU+6H8IvVLYIvl3L)HI-$ z!|o|MH&2&(M2CHKSfTUJ)Zyhi+^_R*(D5&I{Che+NQXmp_-CEJ`XNQt$S!b9cQ4e5 z%QVnLUFazl>iGri;40DmSVL9mQa{q+O*$Nh&^u?O&+o~*GG=nYczJ>Ujt@<&FFa@U zACQZy<>1vc{VoO1xE4?)m^jayk85*^pp5i!Ywxjg+|Na$7MXFm?32%O)ZDLnVd``RiFP2pivv9wOn4>Y5agD*le>PAZwmiC(;OpeUz+Jr}XL|>BL!l_8? z&w$eww;<(kUAh5}q~-@t_uS2EN-AI^pPDKDIf~;|tp1)3HSOm`ENFG)n)XxbMp-OO zE_;At^1R#{m(I)u!?|i1tTV}=bSC?jnJ4PZ_1?@@o%z-OQD`X{>5^-8=DU)KtHshe z4LWC~&dE1R_e752!CSnN1P|C>B)!YU@YpFqLvhxe!_ad8w5G8#8J$bp;;u>z_sZmQ zL9fr88u5Vu58||SM%;0t9bVZlqFcO-Js)6|xXK-*RoY89I^i`1Q+eK;z-POAFrRsa zA#FeK`289gPaI4Dj-1U3K>@{8PQLz2&ffDB!B59P`ZNJ=YdZ31{tsS0w!7YHSTLM?&1OH)PVjzjk0q|drF@8+7}wO)#*W6 z)bQ1V*k$1Z}KaQ zY-IpDaODPL`+G%yM~uM?Mver}3s~pj)N?`l)bmQ{8{XcDcX9eSebI89Qt#u=CLhtS zSf6fnzP=0}e|Xk;_Pjt|RZb-jcf2G6qPl?%9_8!*w*_Qn~M^$;6<6a|*d93+x;Yvgzd?eWDr z1&^CkkFq}J#Rh9+n-YwccY_e*urWY`K=nW(50A*8d4r%t1*Qtdt6&NO=l5%2EiG>( zQTBt25MZ^)wQh3MH`a0==$9iwAZI)cTjE!5ldb2#N4i-gF!T_eHMuf+D{Ro^@ctlW3m;{a*oe38^ z_W$9SWe5J|m*5JFyX0V;c26`Ch-+AD$s#`D_zA0yeT}`*y_n3gK9dA1aX+$oyt~=C z&`8|>Tl!P5^yr5TwM&!gg}5?chFh@+TUx-gSkNu!M}cs*rHQfRoGiTbpBIXK<2T|z z20eJS-~jC7rS~BdK0ejxWm0gniMRKygo8Arq4YugjsJlc5Mqu+68#e!Pznu!OSweZ z*=mb7k&E(ZPCf$XTEKv4MDvKXxfOTtCHUPNqroRQ3lvT!5$8OG6Yok3PAqpeBS#?? zKO^@hm4hNn5iR*@PrQD)^tqAvHJDProV|{t9hdhKE>gh5_F~QfVY{AlKqdT$g)O6# z+50IA?Dyt9!;Hi;4`6}NytAh)fVU`L40e$ggAV7tg&+pEK)}lc!9%ORDc;wD$pyue zw`KzscDs}OGzlQMOm(hh0b7!=Jw+U&lXFX8m@O|sb|o%8m{eJattoiCUc!;v0!S zL~oNJAWg)?UfhZ{U>h`}$W!O1mi8N2WAzJCMtP=dPnyZKoU!pPV>p9LgxOw9vqH91 z%OUqq_v_Wr4;vhOZ+Y{qy&AZ9i(OWwHs;gBeFlUaWq6|wGi09r+6W!U;I4e)h0l1! zVF$x}XTx)7fXW~|T%O$bczG$CC0{V1O~PYD>c13S)SRU2dX2`D#g#U*MyV{S(o`wxQ)UfNS^1uN^b6GD%Vmn5*I%!x1lAW&` zp?scBP&v>Sf4p;ej^1qct{&H@UL2`UM;M^;V-`P1H@ve7p||!UbF_!5`-!s4V=< zh|k41g=fNh!laz!~l1q=vFy$a0-v3Cd0Y@;*D8ypfYuopgD?r z{6&f2L;@#}%EFh7_z=>gj+TWseAVTA#o%CZ6Hkrm^A%*urtP@hDu$C4J8MQ*gM&O? zK?PP>x_;KHt^=zut##z$4?qKVR!c_fWYb&rAr z1zGH3#&JCfc(I(i!o3!vrr4{@h>U}iV&ndu&Oj}R$>n>=D@?F#aq$8~G@v1s7tF%b42oz!?MV6gwYWBD?D%O=!vl0w_;BM2w0mZNDfL zD)=zkcP9mqRHYOFIYvdWQDw0S$TH#$?F3!o)7eiV+l@$?ntHl&uGT5~j3uu7Pl|I--owTna$dS$Wu-aC zi+w$uyA|2)*-UGZfk|n_V=L;?j~u6bbU&o05XV?`mh!0P>zG@oavL)R7iAu)y9CEi zAiqlZQ;NmoXIIK4tyx4>LIu&CuGFMbGvZE9tC@yn+}m+~#}R9ZLF(SiL6RAK;@wR< z_T@vD-RBN~M0qqg0IQH9tWYXEtj;$|)Ax&(VQn@*ug#|MTSWW$fi&Y2Ai#nTwhtzxJx=vX#QCy6g-`BhDd5N~ z`3aLR2&7YSp7nrphNOC58IShCVzf+OezMXD5&-SLQ4xaygCDQVIrvf&ldJxn&ZRUL zSP}2f<}2d38H~Of-p#fmI+nL_)xnL17YX{N{S{&uuCE(q;2!##(!rx}{}zsDaIp&- z=UYVBX~A3y8uRg%aO%C*Eo{}6wtuG2gP`bhG|5^1LX>ZNL85JMIkkwT-rr7t=3@@c zSUQ5tWIQkd1x+gwC;+?F?E@yRx0phZRoMFH4Ktm!CM` zPd@IEdIs7&0JSns*X|>DVCd+uU5C6qp6UGh8AHAv!?1)@utJ3VG0nuYV?Bcb`+$5p zDLLXBd~U6uEQEJrWtALp0FLV8)H1j{fc?h@JwNi(qD^`HGSFMnnt|j#LG3X z!Y|uv;>GSgg2J@=1qiztbviEV@SwAqm-^P#J>qVKT2O8Rp!6=GaG$xl*Tz%BZabd- zauruf@DzpdZII*OBH-mx6nC6p#|=*Ui+fM0PgW&8-!e39`Pu=wgX1`$vk9_;E64D} z%cktIT+p``Pn78*hFoA~2b@NA)a6pQnnwGA7{=2Sa}sVVUR$0F;U2P; zrvKFtFF`B(GGu*H>32dfXe<4@4DJI5lYL4n8pdNoHwT_HYfetAK zK8WqVX#QtG%j^TwE*JX&mCy&PconT!dhNNi(+2_nZX@SblQ@$AT%K zbr~#sFo{>qFN2fE_YC85KL+n{$TRUafAWHRi`UtMe;TwR4Y(;BSINb`>=FG)bQ1Vn zl4j{Yr6wRXy?o^-B*;|fPu$W2Qk?K7leX{>+vCDDd+viiFz6;PgSK>HP{_ZY3<}}R zFYJFDl0PSP;!n`}Cb;SSVCd<_8H6|{g(aHY#dPFK$O+1h*41OSxkI=aiU~=8wv3hhpAUhbr*gijY zTlYD4BOfyjzMjI_EL>@A;{cnO+k>C~1*MGy>TA-~xJiLDj>&AECgm>6IA;Gv(Z+!4aPc@+*U3@|?~4IYUa8|DRti4UqmmA1AhIw_ z`&C*lPaIKrQhhHAV03?G-HR1(x|xs#jj09ak#;^oQeZb>_rf_6ILG5%j)fvZToIpX z7QTTyaZgKDKuR~5$w-#JxG4)fZ1%@mjRxHFhYKtB@PlsT6|Y4t3nRh~#+N86lYPo6 zjHS6;^bYQ{=-mFbJp@3rG@mDi%C?9OfLvi&G_mH%K$!*YwB|qNz^TkGDHY>hk)f@z#ZBSZhWFmiZ@D~<@M6l%J z=ZrZ7Xy>K<6fpJNTv_eu!w7)pxfK0@ImFy`x*WtgP@5V*DYeOQ1YoL7{?vOk+I`gh zFk1AOtn-@b0l+8kSX$=nXV4mqg#H2d60HAuLh5rY|CAWZJjOW~OZ(L4z0%Y0*7KD(84MTq0-Xjfuc%ldnI1VYu+wWe1@0-)TZZ#ll|`s+I@ZzwEEz%6SQaPTNs=E z_DYPX!7_`5aT^z^ElE{}O&Q+y1A9x){!>t`%>JylsIs)xi2n_QhcPW-!mP#iO1Q8& zob2}sc@wlty7SO;{>R%xyJFk@R=<0_{`r;p813-Se+2*hJJILeD*8ph@LbJs9({|8 znq(DjQ`c-GqB7sF5Pumi6QeD2uDcQ-kZ2>Gg~Dzr zV$NlA@qQv_6)Y1{b^)z|hX|Tf(qLLRdNdoT-0d_xusS>$HX7zp_hKE6P+|8<%3Y0; zDDf>2zXXK4gMVO*cG{Ph`+M=$SbF)!VT`K*F3?xSJuk~9ylc)`pWNj4Gjp9QZUeFQ zsiXcZem=}cJzxK$S{&5CX5I@pyl_{HTmy?L??Q|-4bfm3>yYPE1pKM5T3g|4eE9~p zrzF|8J7ND$XY}o4SI<-a1gPXRE*8tVbGrwoE;f1EHJE_s`E zG7d1;eb-E8|D6{=oXiUe+xlsLD|fLvoU;ehX2XY-@XpDrMBQH+y2puw1ZhMYsZRF% z=3z2X>{$Af)0{z8A-aZ4%XcniA?@#AA2?1ITa+i)d!dur%;FG%@e~wESl}Tgm@yGV;_>;2-?lBL9Cl zSpJdw|3d!BTgX2d-@W{kAg}zRP{=+%BmY8h7x}N(@-G#1k^fsV@?Uze{6{;>KP)|` z4p`FikJ>``EEYzf2>o81D4%tFsI;Z-JEN1?7gE@9o9D=!wqqM%A#$d|>Fq)1Qq<3r zm+kTW1ZmJ7=K)kDa{g~6=l#IvZsa^DSrp_OS%`8zQ1R}{-;;M~IWG`qh@2;-%pv4F zn?(+i^BID;tDN8Xt#XdfnGE}$D6b(GO@o}j1lArT=R-h}I~y|0d9sUqpTs;r28Ppt z>fPIDTtdG8iqQQD{!qSW>%=z@eye;xB4Y@{AH^LaePj*zJbT><jW!>#J#m@Af25hrz^Z@{dmTE5IqIx+8Hf zEqu8BMn&9E>558Y_{U*m_<9`o$5P3~g|si%H9y+{?D(ET$QZd1YfmHgbJWf`2bV?S z4GOGAUd1N|L#3Y^cg}(YQM&T$=l1BxHxex(ZJwS=T)`CdPc3lZ{$Vgan#JCPGZ&^H zIL{foo|*X7;G6Gi#>8nw>5f|6F$yNtH=@0VuPHyPV|-<@61LOE$QfYASuczS5`G#8 z&UWY}CkFcH9m?gmJMi&7d`KXAihCEh>0wVzBX2N{eSo4^{Na^@X1EFcW%UR0qdRcj zo?7nuInJQ&vaE;Vt-4P0jR3p(;6d-+C>JrClFuNs%)wuR+D z&5o3ByCz3Lgz#}!)jV(Od4Q=L>VX_UZmP+nV3<_oRQlJ+oXwNYXj{o}yaRs(Kguyo z5EX?X*k$Br4gBP0TAa&LEW0E*?FW8$Sh|0rxxm==xIlAx0j!wl$togpjwq5Y7v{CC z#Il4d5aDbM+_TIX$xv-TXaijojj+!s{t5C{yHUq1I84=GB(2wvXh30ndJ)4DtNj9e`k{B^d-Y`<^-L{m zma0v zjrg@lHI|Oa13l`VWD7aqS>`09k>E>O*xbRld2l2|KCxL2JzX9+5wCH51`iib5~FP| zqtR64q$OE}#*G2-J*?(b`-hG}s{r6@z{g-N2Fzs&rrGHoIkkQ`88D^*rZU=3$RDz0 z@Vk)O*ic{eEO#fC=aE@oJzSAFv%SR!ybK*ozd2Rz z4eT8YHfKCRUjV3c%nZP18i(_1>Y}%h^|^k};(qi@7~fQcI>4+I4irJWv$c3@lMYk8 z%w!xo_=3P*BQXz!+?UW(cpr%0GZ-5vaK=n$2jEG+!JA z59qd)RUzwIEO6fEi7+0Qlo$U_BNE(+4$;Pnm*W>M^&^moQ`~ri59=f&emUxe_0Nr* zk(m7Vtdq;-Ss>pi4AU(!7Zwm`lFt>G+&(K}#svPUba$qRZjo7P@1AM;uXnd7tcjWp| z^16Jk3t=f%z*fh{gRQM#Y%As^2*ZfI{DuX(rrkMM?uJ%Y2uXRDBRP{FJMeBGx7O3_^@$()h?%fDoMJaAY?5l@`y^qTr(J)}{jc*8!$_urO63IlurLexqH%^O7S;0XB z;oBK~N9BVc{GVRnCFsT!K_HZ3h|2Kh`GNwV7db@1D@zQyl?C@1^n=EOQi@ZoGW^GN zLivEhcS$So0i%%^ALxLfH8Rh66x++}0YH>U4?L2T0ba#>_Fv>H9m6szD`W!*ZeYC6 zdy7dg@7FkciNyR=Vi6N}Ffq2KiZ746LJK^nvd4fxCCzO1sF{{(Bk>{F31vLqBhi!_ zyo&BL0t>qp0)w4t^fvz#Nxw^P%h!6p%kHpto7Nj`KjOH-38?W>PW3lVN?)WdXo*4_ zR7ihU+Vjdng}5Z4V}2iuXeS5oa@~Z5bo4iwz?awx!u%ZY3UCqIY?=Pvf-XXTQ=}_Y zf774VQXxHEW8vE@IFW1gy%rsg?-vL~Yi`VRxQC)5p3`NAgQ5a2MYjN+6d{it{yu6e z!7XY~JQdR6sL<#;8C`xf`Wju{S9Lk;0Yv_Yi6`Cv#T{*y^3Pm@6(6oyxxDlIb5MVt zg{lwg&l8x4{tTCX8hs^X_s13W?3TjK><65t(F-)Fh^@}98nl(!((fVv>X4N!U7zcI z4a%G&g%>N`XSqPYy7zM(KB>chALOIUwQ|RYdD&p6eGX4EGzw=i$51Q5O7cvS zIe_A3(i+%jw>0nKt0uKvA0rw?g`7(8C3BqQFgG}K37AwD@hgs{PJ3QrmnH)jaV|H| zl;U;xW(gONu*;x!aQ{wR&bEZD$MtcT=jB~Ub?reruyCiB=Q-|xrNr|b#82oFN;=fK zgw{Klbm%Doy79a)uWVe@;tYD zo?AW7dp*xi`WfRBdWr{jMiMu|3LTEpVL3w*wisb&dE&mHkc;`wgy>>c(`R~E1pH+Y zqfoWe8MueCvQRY|`?IY;4BK>6os$@Fb^Ll_`mJF30z#&**|_~xe3{riAKdF)iDx< zsK@{bphnpO0MwZ3g^ZEIVtsns-UYRO_YH(aW5 z$E^-VEma$%M(6kao^$TZWf-#6zMuE=|9d|S=icW$=Q+=L&U2pgoaLT7mW+boR)(E< zNpPO@lfKLQsbl9d3hmV+7NdpLnt&Z{Kqr_J}J~AT;EHQU93Z5gJx2&&_yeng;ZkOg%CWxb9@@d zsh-x2$)fQ&+Mj_mx3zU48pBArZpl43J;X=7pDnFHpkP4r%tIbm$o?Da+@k+JTV#a6 zBRh2fMgM&Yf$+ib(W;gwJZ&43yFpe9BzZdSSIa#T#PWTv3f~KiNa1O582PG-q;-iz z_N&Nl5qZBdke`OuiRboY8gP?`a5L-tnyobc8z3d~$^*tb9io12PcEna!92+DmSnyy zKQF+FQjtcxRD2v}(O^-|U%DViC9l&M5oo!lxC-6D6%h?bJN1AAT2 zn_x@6UTwk9U@ybSM$9%W6;p|T1K8-vm6ROqxtyy+Th|zN+^*=`lbL4@ zI20#j!`;EGhxh6I11b>s_GDPEogJsqVC@5^yr5qsCWE7>=!crsdeaqi`?$U`$YzVuii!XaF#{7+tbBcl3-vDAdNRI;Y<=3z;lg zfY}hN%`ICc`)V@Cs$p|wH8TS=Z#^_i@CWWyWUo2Wts+_3k+#YjXG0#RBG;ND*Qv-) zFOh{@WsY2E|zp0E5rL`KCP^1 zV=oE~GdXM$q^`t-17f1vV!o@u^CRGDViyUp=;pD7i}a+?;;M%d$f$4%i{$m-A zG8u%$U7;(GrnK|!)-i2F7>Ma5 zeAOk%%N@sJw+E;=Qg2tsJ?sqRVQJ1p7D)@V7@GujbfPW^+;aFw3DLF9QYn;r_!E**krfTB58x&>mqvi#*@mQuA@ zqoDg#6S+-AiZ*LRs)if-fr{KfWFyjOvkO&Z+%{XNBICB%Q&eQ!HakK^_EQ-Kx7qjR zM=OTDO5fT0P2=2`BqbseZr~RFImf9I1E8VGQ7c8sOb37baw(dek%h3qCs;0>4{5?@;j?WEDDA z>|4ip43V5Yb;(YM=tM(ulEDTPQV^7xqoPR4p{*BUn;deX9(BScL+HinKbXG5@DmT1 z%>q&QC%nfzRf>p7AzE+-Bl1*44lv6@k1DY&1eElsWt>98Ht4^x1tU=-5>+!%aK>^H zsKq_NSK>Axz}L4c-j|D*>qX;QkNRQkD)IH}(4`_DG(Kh`^t^M!IwT7fnIlB&=-fb& zg-$a^h&I)^p_dW&VQY#|Ly`(14^QU?R!%5*6(jB!7F4kxdglrlg%kJ7x|fP`DEfD< zAY~}$*P(y=R~%6P?jAz_?*4l9@76wu;3)DsvxX z%K?5lfzSpKiOB&*vM0j4Qx7KyT1Dd3a%5I3-i>7BA!m*%9-MhCGT(Cz_24ilVPrCx z(j=-#7WxhLtmSB9yu=%aD5rX46g_@keZ3z@`N6@R{%9L0c1}$^A3+DUMu)2AV$0%2 zF^a^t`2|RWr(z~`tmG*_coMTUJRE7v^+^2?#;}od9e-a0xmxC7asaOzX`y%LfVFM^ zI_&Dwk(kvqpt{aNyXpJuN3xup>q0eYeMhUp9EKE`ZV>fXpx=EyQa`*Zk<%D4tlmgs zcL+5dQ+e%x&j)l)Ur`9jyh_QiV}TU&iD8!F3}QS?j8n>wBSVpKL?3=Ry z|7K$#+tIwt60+o^MspQ`GZ!M7X8za`pTZ z6<#aoZRy*i@W}(|eow*o0&a4F#QG!W!Z4p4*)tdX0YRZM0y7d&UD`H$%@y}~yhm8gaGNmAc)VWh9%4*zIJyih&0SC1kKisDY>>eY8SIup zNCq^$TyVrrge2Ue8C;0918gU&N=^@57@*UOwJe3<6c|8t@dhUXgg$uzC5PvUPK#a} zmLPzOb*j?bcLT>^iV>flEuzDKL0fLQbXbPBcL$bpn6tsKjpr@1|Tz2L7n^5d@KX&vqsg0?N# zobYPPn_N2JYQgbd2niMPx+nEDF8uU804%`|pG-V<4bHD9Hot-MS(h=tj+pV;g^~$5 zJ~NmY7t2ICuwwF$N-N$S*PAvx@wmK9D-~_;r^ruspIH|C%A1Pu*GHaBpW8i-dwV<^ zekw0)yx)vh$YAs^;HP&6=LhHBaPGiSyxC*v@jMj8?D05eY{uu&1@Ai^(wg6AZ_o4XT#tae{`trFTIgIUGEcoG}#DxO~9qmscTd^dL z4R2hbPhkE@p(H^Zk7DZp^%)C0k>zobyewEE*2fbLTaFJ)nY4Jp0BSsu}RLzf6-7CbmB53ge5 zqaR*0%-k<=;v@1g>xQYu;@(RA@9jsN92L?WPbbdb8&tbp5;>o|AfDt6Fs& zUWB(EU*kHO*i)g@Pwc69U?!XM#N<-To-*oy7q2NhVJYNhpG)%>&R z5N+Q_UzyrBpf1Mag+Sa2We_LOp%>VL%`VfYoduh+{d`Cq+d{D<9D2E)_t*mYVJIC; zaC!PJ$kc{x%iK8732lV)5u~`!5sBu9wk`Vg5$76Zb zllv&N7!`)~Z{!c-g|A5s&tGMqNQ;n&iWDcgyc=4<*v?BPTEr>#SOUeq32_>F7b41n ze$8unUu;$h`YECW)56k{D)VF1YS>sjq?WaU)r%Gp)Bu!JtT}@47f;38Jb)<5`x-d5d^`HE>z}MR@Nu|3dXmb@Xl*pyACxr?U$m zz=5T~%LpGem2IaUz>8dt7isz|ffLc1ZsaD|U2-D_FmdX7=w%N|fIc$86NKe%+nWAe zrEDC1X&SVym7xcHVrsuPxYrxp;th63#CoE4(-+oKECh33$TYO=(%ctIapn&EbXTMa zoak{BZc=+gVI)c|h{tktM3(2QWES{ZnFvE`1WQDOU2&Cm099-v^>Q1)u7b8?u!Hk< z0wp*rOvADE<8W#@T7=l&i_IX|1<357H82w#Ft|c{XRwf%hbo1g5ftUO?MW7!p1K2P zmIhxa4Q>{vKVm(ZL}dEV9+eac2op9pxS7>?dMRJwzzQxCq~b-9xl99QL+?h@5GD#> zfmn|AcG`bfX2I7F3sG5fSmR3EP~7#?P}yf7Wwf%zeuhE)bC5Vj`!w~HL-pqu9}wSY zrY9b#eF&981L=UAquo`!1_GDBXdt38*+_Pj$VSpJJYEy|A!6A??6FPc4n!QZi7cK9 zseM{ZgVjnch$`lPuRQyZ9UFc8@;rptxaD~o5eF^Lt$0BwbgHR5Uw3=oQ}lnXz27BR z`a0YDFh%hQ+WQxU(o`Hyd;c_==Fr>wwhYwtbfg^E-cjFY=U?az?&C=^Ii(#wW!m{| zGn(~NxVe`f-);K}M_{(V;(Bqa1T0Ao4EL6G`$K87m@CDkrYD>m0H+o6fbmMOlnbih$yw}oY`s5C<~&idfFSz z!-hG0)kld~t^apU#46;4cx{kG6GFG-8*Xs$^}g@HBZEbM8}1iQ@H5wN7hhJ08E-vE zj3Mp0;YQj9*fSJ$89GIDTOXIoy-b_-=`g*H_T9oncPmc}r=ctsE}dc5 zgPZpJ2{K)JCS*Dsi4Ax}bqB}?vcV44BlS;@1O1`>(-+S}Y&`$89}x%jPajA_0ZM?W z^oYB;S9Z4ySLZd+tK;Dd9q_nL;(5bH0_B?83%SIL{rYly)q|%IOR--BgzP z4@di4jLwCJ2g6WAZ!+}dbksd8FN|=JbOpE5a^bDAdaTn97x-_&%RAHCxeO|rhu4}$ zVqges+SqUv47j<~xC4JCxmKV51!CibSj4wQ)?Wb-=TW$JNQE-$PMTJ9^;1p8uM5G|x z`mT=Z(QO}CmOoO2?bLWTxhsEFRx;l1a9RL$TzfA2g^o&?-yN`C<-(PH;{Xq0CW?Q;hHyLlK&H%FNDlTofbb zg0|{(p?0Dp2EH$yo;C^FFz|jh#s;J_ zQP%ZIf)3(D-$XhSMV*V8XuKc*9xBm6bi%&z9^s zMdH3!F#WuJI9=7gONocs*_$!m?rRl;Zt*^dH~4&H%RWjE1Hn%$<3y+v`#8UD(&mVM z$fN%Aa?)Eq?3iyyC8HRuXveB!kplZ)_DnG+iyDBUAWV0+op0|74R{xfIeyjW#rNyV zI{t+UPkSRv0hS9FgXbhOW@>EZnVV~+3lbpM{}V?zy+dk zHP9h%f(bqzt)V*rrvUF9qZ%2Rx{Y~;{6H3CMv^WICYD+Hyuk(NU}iZ*RUMClKo@wR zpLvRf?~g|(!as&3hWw|Lb}UNhnC4A=-@9qQ9fuvQ8im5<2hq1a@2P};@MUr8yEqZs zj**e0eLUoiIW>AsoJhnXF5g2f!VrGqDoa;U@cE+Df6%^qEFTti zEErvcdGlhpLW@f~3Z40#SMZ>NPhTjtKwjOjn~wG6;iBNC)J?Qf?KrFsJ3oKC*|Gi^ zapWv&{k5Xti}}yKiKBRmf;~m4IA6Wjj{R-AokvdnAh{MW6G|N9h+Yq=9v4+$By}rIWFAgNZIspk>m8;cmp`vw1j={ z7~Pfcxc9NhVJjaseNf!~OyDG7iuj@qdsi|0|LyiJXb$S0N3wj>^sXpa8kj~;Y9d-> z6YUkTEuZixv-UfMzFoRA?JqqI>MG2gM|9u(A~D{rO?@5TD7E5@P3R9c)eKkw zh!)@Qlglj~ft&a9)HRo2wa1eiY6*EN=O$xY*L#k(Nr2+za8ts=xb5n&-wYFQR8ek! zzT@`I5N(m8_;dXF@ipzzekslOT3)229)x%!8i3kkFi$x)b(ht z^xWaz*>@7UmG+%2?Z~O`ZQOf3P_jMQYWyJc+YaQ|{1TAx z$qdTK%;doQevb8hc?93|n@#!sWKgo0{4R=<-)Q8wU{Jzne%`jN7Mve5NZ{B06xD2) z*e&_Unk4sQXy8u(Ue=j3NFkJ^O;p@Q$Ss<${py>1Z4 zGTk1zOJEbF);axgpn)~Khz?PZ0%ogoUkRKf_0_Sy8MbBmy#h&4xebV=xo@?+BdJ^= zsr*<{`9Xw=yUWQdvf?> zkcuiF^r@p6uXq^+45yGyR2lt#xUkyT@?RJO(Z3*T?bfm~UVp>A$_hHfa520U>GG4J- zf_aX}c)4HtaOU-pYu?`nQl%Y}N0?Ze>J!t+sn3wn;wQhZxUEF6jtJwuLpOdwdpLyAa^8?lDACubE#miSIv+ondx*!(s4 z-G$!<{IFD*zZ*aBmoNE)Xmh!|`{hJN5)(TSmDDJ0KdN-EWGgG?TGv_Fna%YsjIsZlpU z;Dz%sI>rRn`wsERB+o;Cse5@n|D>Q!qcAq@vx}u#NCEHipirgo&Bd_M!?u(I89-aP zl9gMUoa1PFfL)te#q!Ye&BA_>67=jieC zF>V9T<|ycx_@Mlf=05g)MO22=E&TjC-b-Y!XMv-EeKu#$fb95jcaBK|D7+JlEhl3b ztzIeKfrk?1^?UH{@kb7)o&}SS+J?EoXbAS$LduAlvde=Hy60~MC8kUW{W%RIAl%^G zSt7uD4RL^)gpYDruAbI+3-F{LUxm%~QWE?$V`m!k5d0*OGm#s;SkP{{Q`s*= z-twb~5rJRJH|qIzRSw>UDoysFGjEiYcI|hR_ms}F1<*q9ZWLNdpiX?Ow`|)#;=l``&^>=y_P${qTuY zLr*GZ{^@mLsd%@e{YFf6VDv7}g$EfI=8Si9UPaEedn{XuNIW`@$D%)$!J(;dVI1&! z=pR#9Bu<|&KYRc>GKr6ugP$o1j&lZ1mXj?U4`T$vxwIc45nC`5%8{+Nv*%m84-*{`c#!~)eN8G+BN8Pbfu!mT z-2ya$A|-q}(1h{m8_5J}l)D#>Rq!Hb-v#XKQB!%SThU{SK7|m`%arB5;aGX&=Mu+5 zoW6Qc3H7F8UMT5o{JRYQ%>IcwEF=jkgD(3V)n#u?P5=Ps-+4OaS1!H5cS2XBfNsaP zYUja=lSkWqhSwq4A@FF&Uf2U{J-ZOG?1DmgWVnxDZ1mJbbRoJn^j)~;#e+&c!O`}J zw}IAz^@Vps-v_%m*sg%@lVa;2YMD+@~YnUl}|1sUaQPgVMR~Sb}R@0(*a$nPBk2b2g?1a$sld0A%@C@MK3SUi50)fhVxKh-LMaj@4JY7cxuAX8Tv5@2)j6F3m(2Of#ny@#$T2cnkDnW84~m0 zGr^}0UWTo?g~Gh>7#l(TcY~;BAB?&SgwjL($)XfEg<>8YF+n{A)P;otb-ADKv_aHg zM6v_&j)|ztJfWK;^>R?3uc+sN`a;SE)X_yjGWXB`arrkQnJW%Py&TjRhOz|p;%Yq1 z$GM0wM1|F*!7s{k-*vR_We#e*=~#dCs(CPh_(bXULeU^GD8V!rHs@e)f-nhiQD1mY z!m|s{F7k+H7oOo!%!4yMCmnEU)`RolLe9y-bB@A;2RJ7WczFonSxO1w*@I`WJFgre z-1d3kbk0JA3lUZeCnPwp+VD9%^c^}+rfg$&w=S2!feojUKsKDVN9l|>Rvv{W@9Dg> zkz*zYPH(|HYPb|6&l0Ka$=oB2u6qHtl;X&aVP(Pk*!d>0zgS7hjU$$&T*P}HXngG~ zEVa9wp@?6|yS^5fA#=Qtiinqe-KX$Q%<(R!67fQweJjLt*4904%rh**K?b3ONwiyA z_ayS)QQ|N${aF_73Rh_VGvX#8^f7Nb&Vlg@pc9yfBp4}$oP`aH`wqHgcSr?sFSiX65?a zMxI$YKDUu+R<_S=B}_o&CKv+W@x1s zxXNmp>nZ}3)g!ezE9w?C)S3Xrvu9s0`z+Vw%UecjgDOs|YpC-3($lgQH8#q7x9L8^ zbf0Ou&obRlmG>eSt+1hSMR`+0CG@YReu)duQW>EmF0I8|A1G|7U+Qma7SHC$#n9iD zCjUsyg=_g)E^Tt= zYf(jWO{K3n&;<6*LR+cFZA)c<{48#2sB_h~)YiIcnqBn`0oT%s+L|hruB54=&hJ{* zR1;viYD5F7scWqD*ZJ!MXm~69XiBDQUVW3lvSCSm&E<$}_6L~E?V2>XdD7`F)tE>K z?R64c@gyU0ymT2ym@e~B(lx_KoHdeCH(xLlXDo9~YODxUpBZR4v$>(pe|ujzk>4e)7{tGHvQrVD9t4`u zXasK!uz|~1IjY*4T@8yxjLF~)mKaNVhRZt$(^V5yG07iT3*^t5Fps5sbd8_i*1}eTT=2#C0AxKrLI*3LMrHF%cfubvd!bq!g zP;ILjQp=2{427a8s6^KofG!5A&N@qWn66rAq`!&!Q}3#)Sng{^Q%^}X(iJx~p;L7g zHnh}Mv9oPJkIK$>aYK^}w5q6Ii&nrKtA>A|{#($Z4a9XQbVWx`c0l_)q~QYpx%gp4 zPn(V();_g!@Wak4?QHz8&r8Gc5!x{PaLR&){eBu3bGU4VPl9ULd7|MZc8#p!wQOw^ zep&d9#xD~;oLH>krB@B-`D$+bc(xLkc(8(@;k7=Ehg9S3IPEC>&cN?z{7%Pj9Db+a zcMN`0@H-Yi3Xq34r{Krsxl{2w9=}uY8;>8hL1`24OU7>^ekbGiE&L|ohgEa!B>Yaq z&!v6{c;#sptIe(t8=f#?yeS3xNE zjl>yU5XvJ6--a+gKzI&>anz`AxCg>$M0g8?@g&005Jtji;3G^z*aM*yBx1=5La9Z# z58;mx1|XcPoS=vB9)uK5I+pU5BkVz#4k0xjjgK}#NWVmw1tBGj3x}UWxC~(_gjJao z4sS*HG{Qy*E#Y|Zjc^>oQV7q5a07%_jPP*?Z~AzAjvT`4N9aVky0B=r1Lf?(nkvs` z?nao7FdfUttq2z)tb%g%AiN8q3p)&|0nbCY2B8!CB{mQr;o}Hh*v;btUO6^Gl_P9L z*otr+!dnpbB76m57dBX}LjL_{pgai6&qO-Nw-wt;Z%4@e${~bWMmW45;W~s)D5DGe zgt@tb`-O85mLn`hxDeq&gidUtUPU;<+YxplT!*k1;Z}s}u!}qa^_Pwp0m>2PA*@2U z5aDu!y$IJ5o*NF^QNJ#{Y;+~+cOiCB<)MBTo{RD#bm7I?bkuKaVL1E=!iA+MAL_Zc z8qWyV)dLUp+}#ikC!v13eh?1djnH)!=%O+7B3zDe?P`<<^}Y5+$OU2RP2uqUsQ1>N z-~de2d--jsPlW4kha6GwjdwtQ5caG`eWTvjVvTb(`0YV>2^;5wfFo=~co#zFLr9OX ze6b{#d|HjSXa0>WbxE1mQe|g)& z;kndHgw+VUwnLxD=MH>1oO~e+fv@hJpbI@*_&DT(u=fe*H}rAgQ=p4*-7}C6!nMzV zAB4Ss2R-O%_w$eo^tAQ0aJZk1{SEL9_&S8IAnbW396p_JT*y{jmdj^rmgP>%gwewj z_@WKrvECewrnyK)J_ zR;;|H5s;tgyv|ybnAB!FKhaf&B#F+#!~|jg+7Z19cuR;^km$U@>PbvmZ7WK2U1!fv zOli|+B&J)>PfW>Abmb=|0ihrw!!509|vb>Mq zTHtRc9Q?Fdt?Nc6CR{KoKQV!Y8;x?8qwUhp@=C|g1=uBky+Hu7UTp;n*V({Io4qJ8 z&*~p3m;yC0HDi>>hp3jz%S(kshyU!DOqg0juBRg|8NYp?IR&)sXM=ko8_;b-ne(hG zMkXc!0;WKZeDM{geXt!T;hq<&TAcL$3F^jAKoR8gU6dqW;y)LIPa530Htv)t4VG;` zU@pjMCJlJBY><1K-IJJSd&y!hT>dDgNeAwJ@NygOr3_J>4I>4+#iM2$H`Y7>fjogW z4*BdJ7Y_dvw!`j&f+MdRtrsLF-C!$7bamPb5>r;|`HAV*4a-l=X&XKxu_wWH8uHFT zxlsSWDKM%XB?Qm-RfA@gP1cKj6=)(++wkj#t=2p3H`s2pdVuo^%Y`z37q}YqP3hkZ z$QX=9WNckv+9^aY*+t2!^EIO?y z-)idAbJHFBwIi2DAass92=@QPhp+Kz|Bk0}~6m77Rb0ed zO?rT#HY2dLqz4$xsJN2x|9-&s0d_ATqU{K~Qkv+p{>-RK(t8DX>^t*_hl{X&!0ra@ zECG=)ZqVNiSdoI|Axr{n9QxO-gb95`9mUsI>ph9-s5Y~jqDdmzC7`huG_Huym_ZuF z)OnaQrSnBn=ku)IcnVLR?<9Yq!>*hcVH*H@4lr~J;v(#Ez z8vBO?3#>glbNm`ng#u}UuRp*rpz*~ zgP&9T$7p$&*H*w*0p`a&%d(pNjIzFqD#IRFlf<3@ zWuWXf0%t9J=KCqTr+_152VGL_zBtlmML$)N*lMvYV7?`BDpuu7fBPZiOM7Gg5%X;w zkT3Nq3pgS8-rr`vEk?d@tCXz}`JykpZdjqT73H?`nC;;1v1pVF^x8qM6?sB(nmwI) zmYb_fW1joq?>@IK9Da-azzphdG4m6C&5Xoy>nu~F_ilOeDGz9fj@5QCvW^-AcE~9p z;ejD<$GG5C!$-$=9H~Tc?M^%`jf}WH{%d-zXU~to%mX4falb^{}?#woPNxoL8o4wj#?&xWOJn zcb-Gqyf42BPhtJMjS5R!Z@MidYl6K_LZQS*lIIZBxTeM(c6(4%^cC!Avr;qdjiw?Bb& zqW>`a_zSJygTliK$bJeLivADjZh}oblj-h2y2OQ%e#!;de1OK)g~Q#rr>?c3PfE95 z1OFJK9#|!|!7G822b=kIw83`L8;!9c^87RC+K<7%7#$qsXRp(3eR|>sy&$n$uMr_2 zuUl|;J|J@t<|hJjZT!wFf0Xrhg<7IerLDCi>tCZT+E^D)fhiC%>n+<$3UC6KW8*K| z)MLOAyox?l_(y|y?X}zH#peT_gUpxmT!%VYi)Z_9nQyP%oG*2}A8Nf3GXJ}>dpF22 zDYUxQsNsSwPtw}iZm`-egsoHcjyfaX{7BozE5qSu$@d(CZ(%#*k7dC3^n>utIfFF@ z-)9cyoA&W8nDMt`?Bhnjv_FT#$FnR4^Bc;ouf?@CuyWN%z5zUJ#eB+F@ayakL!zQS z4pc6S%@My7${%I((XwIG9^>wyrd-G?8GL(C-VEH^>ycL+e_{;^U4*jzr#?|B^5EQH z=vs{XQD-dI4W{vym|vhx`z&T~HDi?R9F#A`YwGMuqz=3d{;OAp!~9&WeLaj`RCk3A z#P|sq&suCJPzMJ42{d0qCOP17G1?4$So<>2jPXyB0lyorWJ{(@py38ERUrgH)p8n4cqNBS(^K|gn0Q&Y}_=1(l)a6QXwWxi_%l$U+SIhecag)Mmp_bjU#$78&t#_^>v z`CA4Kps0_Wt6YP6{2%Jiy@s5kzQQ0mwOXvNKum+#Eg0njy#VN43|_NwZ?6Zv7$1{< zLI}KWy+0hjinbzJFY#!BQcwg=P~g<{0K8e)j{IYaN(Z zeEYc2mN%3cVP0!Ns~h9Nq4MfR{QH>4Er)){az$-cv>l2uHp?|KzRQ(Aiaz3K=xsmd zeESvOqHpNrczreJA+OU56Vuy<*^ZlG(4t;3ZnG z@$3-FZ@oOO8lewxfyPGATL`->{I~N!FQ#s(yS>199K7;tllGH=bFhAAp)EDO%!|d? zw-wW$w?77-5VQ|UE6@5f@IQE@3M)!Ga3$oJ2YEaMw(NIf(0X9rW+bk&+I~p;Gq_>F z(o4JC1DfB5{n>|SdmU&Zky+uH?eiCp(!}WDeZBv5&zEgWTL4Vh&1xHK?j@AA&Qh&jz{d&}7 z;Jh+QzhvJkbG~?tv0$$DWMa zCoK9?cI{THzTK{Eu<@QqlM#c^aT3CxS@c~Nt=l3&_6agPW+}pFEjrfAHe2-vb?tr~ zT_Dno{UI@Lv+8%-wYO|K<^oA@$`l!S4I`hk=>M{5y;i-?W{x~+wN<}e*TOa(6KbE> z^}BJ8r0Ful;dfYnX5A^Njgp{`EVq)}DyzOWNBhdEugTH&+w@=OXus9jPZGyfpTl=4pdTWmM(nx((j<$A`-USMy^}DjQSI6jU zvb7HrPhFd>^*Qvv=4h`t|7m$?nzs8Gl79C%eO#HVcuMX2Y0U0sjrU}}r#9fx#CTQ0jP0(+T)}I=$y>qnQJzo3GIQ_%%+QY{X z{>Cx-7vr^G9IL-RUh6$pe_=ecJoy)_nB5i~FXDe}(brhDtyX=fRlCQg<5lDxHhq<- z`GkqUI$gh7aH(|e+-EHM6XUgQR{eK^%Rf$_8oe`KyU(s)KSBFa|GRz1cbcE&5x!_7BVRmOZ-mzD<8xw*>WbanFu|_+u>g`ZKU#BpxH_*NgOzi1b^S{t?S# zI%f9uKk1f#*{9)ti1cC0gjwL~&Efjq5!$a3^bbd9YexWZ&xmXQSY0W2LO2#huxqVW z{RO+W*Lt;TnI$svG5KUV(;sg8TmvLjV{Vxqn!Rr|%a^e0laU!S1g zo2tEg!u?i8oTT56h)Mc`h&Wk)Bvt$9Wc`^`?Vri|LsPT|C+nN1XxE=I8~NOEs{Z>a zTKH7`x2f9WDf%x`wGUHH1sp=qVGTqHPI$ng-*3}iu;|#m@C&QH)uyep>Kkp^S{v^v zH!m=GGwNKuOV@sC)7JaPyhKCvFjaNGzRtm%#*7E>T-~F6NJSI6k$js)f6tCjAnCj9 z+LIQ&$F99*seRL~eFoBY%a80+aUano=+<{qBD#exTg;&|dd94I_>aCt{lvrn5B~LY z;|{L1DwI#({Qtiq0j0Xyr|{u;8PCHK20n9MotF`Rf_fI?1V*^{PwuH=I9g$1`-8Y} zFtG@^2a1}00rt->UloKi@dOBUc{^HwSM*dJjR^7K2y&I-xB)2|9@SXDqu|3(_9izqQVPR zxLActRd}5WZ&l%MRJdM++f?|x3jd+Py(%1bk|wTWRd|XDr>U?+g%_%Du?m-}@H!RV zs>0u>aJ>q*sqlFf{zHX(RXA*t%3p=2sBoGJOH_EF3Ky$zsS2-C;jJqCjSAPRaGMIB zSK&WYxL1Y4PFDG=@DvqJQ=yE-UMI1E!gxYIR9JYHD+Rq#s>?k!&7J0UWu#|JP0zv( z{{vnY#M-rg;Z%o#7p84AtAgM@%TAI;cF!lQS3#*EyX}O3uj2UAr^kHgz#>Ugo`~QxaH|m zgilJAaKp~!StY#RE8${a2X3nrJWb)BDWkQU75q{KpRC|dD)_YuzCgiKZIXU(41A@6 zpQ{LPeUsPU6nwdYJ0)1#tKh2?oNH;k+U=75eW%K2jN`<$Rl#3TaD&e`6x@;`@wnc@ zYpgEme3&Yqjq*-c@NX%?T$A9{tl(=;lh12qpgpbNd8ZGAp8>;8`S&U~=dO9xEBH}x z;d%LGfN_q*cdeHI&c*UNakzvpSNMkUU98~mDmdpmdA+OP&${I^=OcOL!CJ@DH!tAi zGhZ>7Ezz|$1z)b0+@b(z^7Yg2`;FA@dQ_z8s{sRimc@bVU3VshZyYc$D48;F< zeBK9qdZUeE@gj=+DBu?KYO(hGNdZ4T(k~h*xR3ZK@YDYX3E}z$uLrSt`6zii;J*tU z@+9E57DzDd1uwkQBjAmn%jaLq0K@qBbRJUp-ET<5%M||S3f{{}Ib0{nKpT&apM1JX zC7@ctxk2G1?AUfGf5WBVD-?cuPy)DS%Ii)A?~(4i#yt|ez7TMEZ~mW)ijF6TC4f8O z?W{Enk4jWO1pe;?e2mtk6rAhmyfVO7Jo+n#fd3V6%D<~nrZ?Kb8K#Rp}ebN%FFdY=Bxcg;$1HT?KnsL za!mt#EO+KRrQnsiX~jd}UnAh?FW!`d-%<4M9|Herz$YmjbMXEU_}myrd1`M+Y_VR3 z+e{eVc=b{OIPsk?OZ=TGlPd*2;J=XouFLZJyTXrcFH_KPgg##&@x&fC+|E|;g;^5L zJ)gWT0-X8w7s=<7WT5fDD#BZzl>qLk;`M}r$F`#n6udiz&KMLnUU{Frp z^$>1NjEtL%G_wT0@e~a&Q*>I(BrH!w-Jsy<{Sv^rd0vkzc#kSqlLTw0Kv41OWwC(6 ze|t+Ja_x-Q&lFsnC7+dAXd8#1^Q6M>QtiE4Cey}Xx{LMO`?>@e-O?-tU#H-P{&3xb za_jnz#OK~EUiS&Oyf^>1qCy3I)$YWe43 z81)+hob5WcfBeM2SNt3JJMw1<#A&CwYS8rza%w#QG?1X9~E4ng9RXz`saBxd)QhvqRv2sPMby zNIdR0KE=+@J7IyZ?CGy76t#Uz*i5Z;NcU|6o>wI;v5yM3dj&qq8`DpXaY;FJtMWP&3vK~d52m0NaPkvt2UZGv z_$R-U$lQO$>lK%jzfq3@h<_o#g&wMYVXKO8qrnp1e~AQ${i?XV9&p-KrZJH`t{4K|2{_9e>lfXl;4bBFAUknAq2RIp&j&-$w?OgY)%(OD;O78N zeq5@3ZBzL+DR}I7=RO7R%9n`f{>1hA5cJPYj?d3^fHU9N_Rg=X5WetvN%tW|-#R%y zojF6m7XeN>v3CB)fV&h;bMPlY2kk=XErxaCdS1a}?fD)7H&c-JR&?A#57)?N?#<+t zDd6(n{Qo+I-~DF^{r3<9|3ns z(18Dc9RmJ>q91Fo5>sTpv3i>ZcsxDK7jW>|BeQ+nBEugmI(aY2XJef57~pKDU8{S(#ST+*Fa4PC7FWpHMd0sc7=YP?{5%Cf|DZeh(RbuejKq zh2vuC8kYKfD(4I4xP9O*y9TFWENQB!^@*c3D(VB?MWu_}#lnVbDpUY=1? zF{k)~IX(lUuA-(st+JuE$`DO+e(jQmsB8>Q0^lT2T#UrCXCiYWxsacMqqsdFPLv%S z0#b$(89;YVx({W{L>XoAd=)Lrz2!3ncVfhlF*gBq4U+cifpg zqF|PPnFoQt$%Lo`S{^NtszW1bMh0>!ZD=mRVJcqJ$rmOX8QF8H8=7zuOyp=76QUvf z@;N@QDo%uSCP?Fqm#>Ak(jJ4h8yeG8vv@@Tk7N++nHW}lkR_FD&QxDCWfjhwsPZ3T z%1E-QIHjT1kimui$^+&X6}QsSx+5?W#Y5McI|rhjhvRv`2y3pWB2Y0H+r*;MgGgzz zTk0DtDlaQ(@_)Yt=bF^`o6EmvL}sK*36Uu1qoFiIwFZ+n@ZHlSzOW6lE~4d+Q8)Kg zYU=EYWs102sSRC?R$C;8ET$^Kc{cgYEcFoyGunD$g^^*RUicrSd` zC>KgK>!_x=2FePyr%V_#qv#pw1_4u}Gm{yZly;B=587t46k<%fLg@`#d{7e1OIqrT z_}2VLC>Z5-PivINQVFdR`WXyAj?%$+HYPMagoZ)!f0x{NT8VP@b+D8(=%3G*Z& z)i=7+<%vQp+@P{iDT?c9s0tfusT3I|rEurSlyh(@O|4%ZAQr{0HYr)Gs+*d2x!Wx> zs2a#XF3;l`kZnywCR6K;K1p^-QMPNqV@+{!6g5{K!6UK&n{#>eTNHg@Ce$PpIJWJ$ zq55p}bI=DKNd+jjeOUGN6?=Rov-8V}eV(G(ny={MS@~t&Ld`d$^n!x?Qr`t7C3A}B z`sU^rlotEoiXCyYmF}QBy`{behSk>?X!3${cRG*wXHyQnJQHH{+nFhzQ0Ulv( z-i%UjLE-%QKAZ%XHdS$!>zh|!Q(qG(!ij)Q4J&4}z#;OMAF!n^EshWmxHEjROYp(b z^?Q{cqT=1T${SU^Mr^-qbjBGJ@!SjN1ahUfT+;y0c(AKnY%Ty&9BRKr)c=C(p#+#I zd1i$!YFQkY@2Qow4bA@Ir7`@|zlZ!NIUH$60vHNp*EIWh)>JIEzY11CWtpYKv=~+9 zuc(WgC-o#IKllF$mxX0u!4KR7V)VYUwzzy2OrB~P=7Oc+97f?pAB19Ij6e>at}ugb z)o7oGI+QEMSf&_5nz_DNxSNJC2F`UX28)O2!^^_tpbdy7Rfu+ME-ne7E5tBOw)$8* zDxs>67-&bC^glJBBKw28cQJ*aJs4OB?*%x+5r?SxS}=%|*yj41#smIZnjywnb9_b( z2n#vD2*^5wnL#rM_(eZ8xNA|p2>KJ%CutmCQ8GGH;$+-m*x13>YHZ|>|tN3nX($FQz=X;I?^bA4K!zpk>bacDA%&A4P{ z&qSwc5MsY%a#g=JN7$&3udmaRospYXI5H}2j(Tgxps22PgKdqK?G4 z)Uff37A=Y&u~aL%D6PrAIL+rr-apQ`Jh;hI)JjDz-kz~y5z%&gpg<+C^q!L+7!zv9Ph{rWS z2Q@&0T8v@Ql%X)DTMlsoOV!08xUE^j4@I*^6TmP84#@>@OnFXkY%`1&T3JI;(t&4= z7sEIR*F_vI{l7hmN8ZB99E$54Q@Z+Pbukckw$u@0l4jsM&ft3I1dK^VVj2fLJZZG5 zYRi|_nOu>yT&)Qcy;X}N8cHWbHl;(TzF3Es;y<$CzRWYC*MnS4qeqTvs+#39BA`G@ z@C^qVvw-8n)3#`19@r*mKr1ivRaRf-+0%;U@NlN60^FYWP8|CKLaZ> z{^UViLj{+D$Uui6YT$AO3L5oep25s;0Sd&E?qjm8Nj$W#r$ zum|ShN*t4q{0=g$lf^bkpD3OWh{1G>^_?}RW@@wFf7y~^bm?$K*)h$*b5%{#08ET8 z;i*O1e#CYfd=K5=4@v!foRE>8n&#uzHhka7scD|oQn$$8bObUMGX&E(!HFf9i&%LW z&NW9n*2vh^>|z|y;~ZcT@%<34JI9emZ9`>6t)H4RKzh*0!(T*{I(kU9eyBMyROwJN zLr}vb5p4YVn8jiaB~I6BsE0DuLwPcTh91iBXGI1)MLdT;+9fLUeHbE&Qzx^c^o%Z6 zj!WJDg*7XTMiwF2e*mCwU43?YVtSMR#f`YlXD91%ij`Vft@A&l-vxZ4Y9t_3h zNk-FmrM&0Qo@tuSJTehwQ9|*B(%7&ps$sctm3rvDTk5fQE}TMt6J~g^#MT7Qy|$s= zFQ&>t&OKGy=+cG*%t@Ku^9<#l&#T90WvYC$@p+p%$iJ`ximPfT)jOX27_s#+-LW6trl+56UjJ<$S z!#Z~^xIgSE5-kniHwsiNLKtY0VYP7wc|}aQ23BZk5s;V=Jp*6pO2cZF zzo}6Zh}9L%)mmEBih2;0VW3IIU?9iujtzM5A+E_^TfqeCuCX>iiWugn1^mnLU(Bqg zH8qG8)HHv!Z!y0G=ButkTH^^sD>1XXywcwoz&1cQIEqm$3!Q;&fs&%HqN%9@MIc4v zo>a*KG7#)m)YVjiS_3l1zcj&(%o)y#xUS8Z=?Kp4M<$y#eZgL+SLkf zq&LppFhb+p4I_Uey;1(4N?)J|8s~Tzp>gg9)8o~nNd89pn*k$>DqawoGq?E}1OyKQ{e4h)KlHD5h~Pj`JKz zCzfC1*$DrIw0x(>NN=2*lXQsbzeHN*WTcP02d~n1Nj88XFC$;$c_iW~A|t(VZosDNj!5h_MHBRnZ4 zz43n8s(hKyXy*n2Bc1VlD$ocs_&45zTC36<V~=_Cs--G#Kq5Zrr(XpnB{u%wSZsv z6v%hx`Oan?OXB3tZdrIaZMIcp98%x?B#*u-v>V zm4DuK9iIVaz$g7o(~~&zuiBw!=Vu6M{DkD&u#cI*6s8PSA4&%8{Pm_2aOM z=Sru(?)q=1L$CBxVWrwxjLO)p!$*$s+wqXFbAO=C!9`a-aPyfJj+|& ziN~F@bii?`k7k^;deGTT$E@5RIA_Y_8_pke&XkE~O_@A3HuJ2RrRSe@{-CpGOgsBr zDR(Z)5}vgCH=g_h2^ltj=l5X-}(oK8!bQ6DVH*lWlrrx}6 z@c&*n{d-k6a0YZ!FXdeU{yKlo=_da@-So?&-QWo{yM%vcH}U^Od{=zR0iB6h6 z?e>}}wNr15PO7P$K7HEs>Jbx=itHEE)J&K;v!tZt+#ANvm^=X(OrJdU#_)tu(UOu0 zlg3Z4iB2CsIXWXep>ouCd{vg!RMm{1F=O(LQ!B3=F=`M{C6tmus`Ruvl&>9sOIPJ9 zhnAqow^dnEqw1&xz=1X4X)|grudkhY%e0ATG;1kSl}w%nbPmR^^1KOCYR6A!;d7-h z07S<}S$6bQSrjLK8;Yu)Qq)j`x@s%V6(UZYQhnPk1T*?S0#h-{^h)qO~6Fv0o1(RpgOar-z z3s_=&%?)6_sWlVEM<-0`M3$k7EbRC1(8NIk6%5DhoqHAhS(2u94HTE@g~cqV8ui5u|o6^nFf(amDNC@3mz${sdQTV9SDVCNl5|P{BLBz z1h6a!eB~`{99a0g8MU=H-&i>Xh^bLH3gL;9r~mJ2C@F@xnK*eyy}LWUOAn^I2%P?( zwrWt_<0nsHECsmdmfBlxnRZ*P2Ou#6ARmSq-bY3@?)_cT0I zGbmF_N%nQ%Ak4Zsu!Ve?e?1Y-L8zB}_lEt;w8K1yoZ}i)VZqn$xyA`UE8*Ur zS|_aV&&lAQ_Isr5__-Gns>hS>=tt@JYA1edC%r5kZmv=K7s-;goe5`!D_&!S^I7AH zKO-H9=XzKC*{=AFuK06Y@#7qPSo>+N__SUL;)-3JPD<;8jK3fqiDz0LWPGVBKCQPh z{#;jlS`TIXd9L`h-pY7#dFC@t(TClr-c*X;6_1Y2d;+d`sLGj7zAGN8e&$o)if7&F zPmwF0eUttayW)vc`cvwPPxn33LazA3)0y$qUGZS_%%|EFkI|6%jCI9>aWkKBuK1%e zu^!JPS3JjT`cv{@yEO37rNq4aK$&f;!kwNuW-eueX&el72jI_5Z)M`#58+j zJ3gl_W|$_2y+*<>Fica!ZkF)h8K#M0&y(<<8K!Ar&z10R8Ky~LH%a&x4AYdb8zlS_ zhN;%s^%DLO!!#Z2aT30lVVZFiiuyS;FTsOq0N#C*d;~ zrYT_0mGCJH(*&@aBzywHRQ>G+3HN1~D!*MX;lmlGs&9{za1O&%@$G5}@4EzHs`hqB z!k;rtmEJCv@HU32%G(7J-pnvncsn5BcNwPYZhIuWj$x|o_ReqE{#6VYFuYO1iy5Yh zZm*H>3k*{=x0@yWcZR>u@H`3snPIBv_FM`7mSL*qc9VpE!7xp2yFtP~VVEkqT`%Du zF-+Cm9w*^@8Kz2ZS0jw)fArCf4Z2ZL=(l#EvAT&j-PoaG9syGA2$reAn=ae-jP)^4)d9BNx*1kH->R*L@D?$r z6qZKJiG{^gWgo|C2&Gt0wnvZD%_wjP9}Oh{aHb-KQ{`ksV~FszfI|5H5^`1)=69gw4(nppdz>`< z*}^8!S~njke3VZkimo%CEu1TXNMR9U^7T}tu)bt_$$OP0AL&M}` z>2@Lm8xTQ%3W-3707=vAltL4u7 zS0ncc767IE*5iBwyNqEPhC(T5nB|xg$x(-c*CKe{D?M^?p*0z0+7?*rzEWV{#k1|7 z;LK0ILf`b0*xk~}%dFW5>EvFBLq@vkRorc!p{(;(=E)UgmPAq$3#%RW+)6JlLE8tqiSZ&bLRc^Y zQ0Q{-U!-sx-$HFE-Mkw*j1VUlAaNon&5m$*+bss~0jk!uOb7Au5QrF-2qyE$`vy@a z^(&Oha`PyeMw7RCesiu8OCF95j4eJbeUGZc-$CvTAs?J1V0TzOyUcO|v+NTLTCKjw zVm*z3ee4JTUBci?ES4I4&K^WCo$OX%JsDx;Tdlc#f|z5o9Ofs)CjrEYGdnV!D7<-a zug96`dI#oA>!Y&(3(&_|hr=ySiam=sHy~oanciu1clLf zw`YoMRT+m09!cuBx{+l5wpQ!GFV#@L@3JhycdGZjY{&;60m>x`id1ous!poDLS>Zd z*uQOy(zMtE&nDg_*8o?pmxaoTE=Rknxt-O#jpn2a?f$pY5S~$hq>A6--Tospr9k>9 zilnRCi`;GN(`8?9%1&qgo0uQ-Ic2+Ux+!@&#!2rlFiy7Z>YUUENuTUO(rP4GH+_Mx zT70D|IG%v16Qv{cFtOcZRU?z#57eUc9EeC;Bk5!ej((5$b{6o$V?lI+OoT8N6Q``+byWn+dhwd8P-a2u>2 zvLOzRJD_HhFsB0(`)c95C2c?NP%t(G#Gdmxh<(H7DCmY6I|WG-nKT?pVPjdx_SvNX zXuXOgtF_DYTvpft;4lC@ngDly))m0jpexb!3)(xXjBl*7@QT*Z60*GP_ow)FHBmJ% zX$igU7ZBI6A~x#JpP`}@D(aYY5|Vz*r0GloXwr6h5kUW%p!Xxz+QYBUCH=0#d}}6B zMSk-M-smW#c32i^u!PycU^JyO-4Z(uwS5n@MWCKk>nUo`slSL)MeSuCM7FhUCrT%~ zEY0cs!=1>poO#A0PuN&WEgNwj>xy?sn->e$Fi?R2M5?tPmKS7X#Q4~1k=G5@N{0(t zNK4Gu`PT6DeCv$sag?q7gtX}DG`?*wS{7<&MFFswBv?Nq=&o90UoV~B8T4gn$O%9? z3-%x~e7K`4`jG;gcA$Mrk!;nF4Ai}XCJEBt15UvCxbEpqTH?mpkC z%;zC~$@i4;T0m*|l2f9iZsBKRcOkR&I@43L3alg?0u;29tPy-OeT58(@iHl5z;34g zIMcdb5<45YCz0`f$I3CdX3_+h6ak;2jIXfmPu65q(xj*EF0lGLwG>-pK4dL4LXa_F z9V>WN6zbWLH<0*`1kiA5PJ#6?92mr?*g8>4cE~D<%J|DqCpkEW!#zSop^-jTSPd?+mi>z{ ziNXdcvw^I}coG1;o+unEfka`k)Rib4$3mV>DhG6P`T>xw*eNrPfe`b&3eOFpKx-E# z2w2$3Gl_W$m}k9{XC@IWk{a5WxRb9ys!@|O#sgxO zu+ItD?k)2U%xoqi6H#KOjRNFhLDk-j`Gs6G&&i~?$uWaz4ojhj9d3F+h+)(1LWl}7 z%ylP|g8YDj+{l?L(xzxF+{2c#ZnRt&2xAVSPH_*(Pz*43(t%ws2tD95O?eZDy)^Ai z$>cB?z<}ixgNYqz-^OHg&Kh#WJKG@1PI3wex1j*|PjMRyOe$%Xa{R(9m<3yEv!Xg} zM>C`_;Hg$TEbOiY)tImjgLZEF9QbR55@`nu*u)7Juxa8{L%lmC60(Fy2p6OA!qo_q zi%AS}wf&`dN??I-&V(-ygRcT^fnI15M-e35o`~T@7g)b8V9^a$@3kZ{8krS0$5SS5 zK(UhM%98DzoD`_Gh1Q>J0E2}48=h@{sykcjpFq_fxaTW8p7N{9uNpH-zvq*^Kx?9I zDub8!(Lq_#9B=OtJyo1NlJ58`wPXXEc+XOn`r&ou*O%8|rua-ZZ-a<|$*HF}UC_T0 zhTk(a1#|uqx7ypu`JM))uXv)fK@y?$yKD(chO8!J zq7KuDCy6f;I;ZDPL3C-2l@eMy(!pp|HA}0K&8$=!00gzf4O9k_>$JoK(F$I-7H?I3 znr~l$m>2SZ44pcJYtp-T@CX}^r z=htF>&EeOB_^Ols<$6uY_OP+`dfnKp$3NOxJ-V`_xnw2u8v2*pkJ*I-a$jVb0`d2p zP93D@oqUw-jUI!gp0|*ROFf6RZ`ArX06EVR=ZXARNdEIK<0E)LH+JeRpI)lB?Cqg@ zm+NZ}MDqaP4-No-`$mOVx;*h~72`k>V%s z17BIe4-so$j99|`;Sz;+`Dl!m_$LJzDrbs|T*vT)W;6}M?HoP1TTA>x`tEDp*b_Fs zuWL@jjOX|PT7K9#x zkxiZiLsC-g7pys~j2^nNj8F&@e^`}R6*0D0mk|SrHV3pdb*v`Z(=wTy8a(JDj1~>= zS#oyuhVoj(9PSSXS40Pd*X{)?t#kE2U6b*)_FP`M@mBCaoiV6fk2iZGWzExVbhi>Z zD6gBh`}N@K5G!jB98|upM_zfIktZefvYpd+bnIY|sdve4J+-ijR5q*q`hY<6`?{$Y z=mYe8eeGA#V|DK;R9mcj-_pxkWAA|&Cle&tf7KLM0+r1H`P@@CxcQa z(s}Bw)m3bpR3cfbtwoo!fm(7IGNF+loPtIc;XU2RWt-4QzciAzFN}+$DQ6p)o$~bq z>xY{a1*$0wWZ7&Sr9lOvX$h2aF`zhH_V4Imk*5$FvI0hLx-5X5DCK9#`WGW*`KuQr z<4dYhF7}#0K-F5}C!(+^na{d6Y=W%58>eWc9N?hT?t!|`vt+JkS4=-d!7wpj^5>pD-w+r}XetELiD}LTN5k*>( z&PwgMqwC5IjA#(|GU%RK@;t^a=+)Q*{v?d7v0nT8h@r;d(UO;=ZIURP7PKT6#I)y* z00_VRA>OUuvrafdKVx(8eBOCJ;XMC=C&w}ML6JrjMU4~tY%hu_!eyHJi4pT+ z5l#`~MOnKI!)G?}1Ged;*oj_G$x2G-o;fFYWyIG(rx(52JhBF z47K#uM4^s2e$;ZW5%JYiP|TDlbCwnHZng5+mQ>F$Dxe#uL2_5nUf%)9UzCPu%_UAy z-W=qujR=R$3tq^T0z0gb;5-@y%{vL0T4iDe>Mz-CO_VyI1xwymnZm7__uJbkZMGsZ zY#s*%<(89)!+8(B4>7Y=z+qArIoBErAQzg8^q#*u9@#iDh@}ffB)uX@O43=M{+m>! zM`4g^N*mnMWQ;8py)9(?|?FP%PCm!GdYhrU_`hF7Oi_SKPJa zE*bs69KxM_o|f#?>R)PCpE)!zEa8etSt_?wPtEj_2E}1xIVD60KuWDp=Tms);61@){o z@8QWlqP7^p_|I1}3Rd~35n*W$rD*@OR|R*DUeuO45X zQ)g5|V-<5zzD5_0tAfs3qL(d>{fj*TkYb%-anUM12IxX=<+JXBG>EpPgu6?djaiJ^ z!wSk<@W7N7-KfSS?Wv+xxCdjHWka;+g1fDc&=#@H9X-{&y&(R&&)N=3*$L!L>r3I( z)ucEYmv4<@nfDGb(ZiM%gBd)PNX2`I?|jMUi#=a*VfH67;P08_Z>J7}bu2;#>&GN0 zguxHdh4!QT`V?P``7;B%oWL+VADlYV4sMy#N2HixIsbPM- zb+|CU9$W(rtL+TpTed<=YyfK7b4RfQ>I@x(ALe3>_0 zC{p%i6w~}rOaVu5_6V-h*J2jjhY95hy=-V8_6p~Tfn1?SDddi=%fbztd4=``7$RwV z2wDBeD)IeY@$sdY?$*0Tma-=ZdVOE^(@?)X82O>Z+fRYv9e86%Zim7}os16S%QT@$ z`c$mix?Z*spd}X#4QPq=7$)YJ(IB_asNPR%o0T$tehJEzaL}%7yQph&bsbB6w^GO0 zm@yhd19n|yk@lRg+F0JQC6HM8JgW0(mCN<`Vy|~EhE3k?#opNK=sVyu0{GC?XJFX1 z_;h0gaRIy1491KBnA87~Sg9pnM6klFjBv)BRzzoBL zf__WeVdN8`?&C;>&XDIKZ`&f+7b-nEty7wP8afyH4D{bTbUMWf7$UFG`g0#8%)owN zrCMQ`5QM(UCt2=C7D-)k05Fsunu?7k?@U3GeJY~U1*~fr^SnDoXH0(pwtn@tVz6s4 z@Ev-6TUY=u*IF35ZexM+2D3Lk^=@&Kb({hM; zsE%jFm6?Nvhs+^9JTT~n!xCHrUqOz|YQSH0=%LiDIYUg}DaPWKZGk#CJDH?k1i7mv zh@zgF4e@a-Cyt`Vgh~ZF7U&m2Q_&I^A`5&%so~zRImR=@%sZuJo4+v)1vqPo=fH@K z0d$-zOQ2&GZ0I;BOMb^Je*;TqjXBM>A=VI{h7Y6qDZRnX_P`M z9lS4sT-TDl(Klqi;`Ejx(RCpTy4t3N$hiPv4FRcXqctHwo90nGiGxhAOkges^6h89 z4QcrVGy>U8N>EglFB8)eUz??j+DK*1b8499016N)6;5d{11dXcY9Ej)Lcrv^!>@M3 zM+?%>T=l?6ux9}@m^JM``0ns`Vizv46#Tn~&z%k~_^_j0^l|8-K!_%gCV^_bWq!9x zxU^0^p;I@jZqp65?N9ckNS8E$%GS7}6#fikdX?SGKv9P-2IGO%eFb*gepL@dWGVHI z3w#iIJK&+=A@t#KySbd-m<+ff$0^g(P!mgLceG8er$<#NnGjA%Tm7JFl|9@ zAe^f7Rwh>70Vm6fA(Xo<8++@IR;41|1|;P;oj(afIM0g$zP^=-<~xpyc&08dP7Egy6p!1Mc$F#l;Z(v2*Q5&`K8;+4)v`u2(p|9FxeB z9HqYvJy2D4AUa7eYm0qIg-wrO>lL)DiBNmguEoa+8-!+952R2lwYa;Rx>zY8MIfg` z*=>Ki=@=AH4gom!gbNGyU*w`Gg=4jQKc;+zK^okmCEmdRuQIkk!95LYyq)}Ebv-C& zl%84E65B}Wv$Ioe(F9x>1E(1lPuU@cxtp+HAT+A$&9+nz#nRq~_g zQLt>FAp-;JQOT)n71#7N26)j$kH&XUJkFvRQ|*)eMm=qa^63jZQh*Dt9*my+Sz+b(byckz`Y zU&^5%D$Slof-(@Q%63FAhchy^S%<~DhRlS1L2ICwC!A$hwIpC2iIzxlQ)MIw4%GEh z=vi6I0JzxS^x$4LbP@~~XvjxqsZNH7KHrE3F32xwKNG&lHb+o0h7$GwC5OdYvQ9nMvuIbb59LAd36L+9K=wFDkg;2CNS_6L_lLYvrRn zHw+Z(kh7(c;5T8zf^S?)+(>^ZH^aa;^xRN(?>hTlG|06%fZ7JQe`*E35;- zV<{8rT(kyTAJe&J6u=-T(E4Dh0P;m7PBp5OWf3%v)BG;xev(8mXOtp$DRRr2iR3aG+b7Yq~SpVL30FmR08TM z+&D&aokSr;I+2($amOpFq==Ao;zlQN9TKa8A8QF)nhCDqvguzCJ2G`K+z?=nEpRJR zE?%u0k%@sv5r~*KgJouos|xPW64wi;cB@XH_#m>dl-Vlo73E8cV6_yI zgz5yoFk?c+vGNHHq=kw>-z_kK1I}8<&4=Lf0x)U0vCKLJx!~GRK6AKi_E-VLR3^4N zejg49PE@d|IZ;`kuTp&ia)}#6I^=yslIo>E)HQWoj3A~iB^caBa}(Che1%-{RaCHf z{zCLBSQ^!6KInq+#U)Xj7t6WM=m3qSkJM6g z^hbJYGgNf7p8M|C5NgZtrTpC_An8O?r=AGViP^vxeCQoU{7k-E4}r@-IJ>ojK8xgh zCW}7S&cZ~GAHL6(H<)iHp-@_X1O*3waTpzg=iR*$`OH8`vo#8oTt2kkE9Voe`77D5 zW%dJ*)O_CMJpbuDpXwBz>V)g@%o2-!8#u$wODQ7YvajbBc{>Q$nfc1K6sz=#gY$p2 z;#=~=lf;#;FVjvW$ednSqr-aKFfMk9a14#ajeNnT1dEwKb|WYddW zm4v;o5`M&(phTY;D4UoJ5ltS8v!)T|=wC`2&fd`Z}0J%|K1JA}I8hvR`#roMyt zVIc<&K9{;y7T_$5m={FM8~s(mFVIDp0ig3}2?LbEg3ChmH^woh(LK6WxmfqE(O*zN z+Ar11*67;s#d@kAP}yLmma|REFemn|8)8(P3TG=+V}O(?e1}zq^pUBFr{+*nX<;&m z^1n_*LfE(kt32;l8MWA^atriyhmOvEmekP zKTjjQ%l=u4ghMuF|57yO4CKu6Xr_PW9MnI$S>ulccj;wIv_zbwPQJIu#c63m%mL4} zfi2*?0jF79csN~GC|Nf=A7 zc$HA$S&11r3GDiqL-QIMpe zox92*pWx4ImJrx8hKX{Nzsk%l#Eu}$lp?=}n!bCWP}N4T`V57mq`eZ`4nlg%7GITj zNyPhUdCGTT$x5RaXwjo_m~W_=caL|Uag{&5@6tIM=8JfX*I4t$#`xY#XMbUg%pEZy z?;g71V5g9BePdKhdGmLx7wX;dZmu z;WB+z(GnjGEgIvShpz$^F!}t}EsN1N@dI8AWc`iI9CF|7uHenr<)SkNcbKM-`*Uc-@ti{p(L*X4c zr|k%?S2s({kr(=7yDCf_qjY=h!Z7ky7^|?(0oNe*NA2wyTwGQ5<@CQ*7)J;fwOenr zV5G#C>KQ7?rn)9`Qf_>^cjikK=2(AQ9_*(^s2cI10WV@T9%Y8YHvtO4i2QQxcWoi< zC(FZSug2aHH#F2Xe>k`_J0!woFg4aeTtiBhi@^iTYUj|`h#AVd}*7Qjf`0xa!UU{3(FMgSPnI0zFifJZN)zUQZu zr{*~tRuVuKu>t|!&-xQ|D`qWb!6JevAiRFuDgZ6ie|c(R0eAdG&)1FD1qfBsAk^Q{ z1aWO)Kh@U{2^^#m7(g%qaL`F~>0$K)^Ej?&r@D|&>ctmhmP6;-*K@X$rO9nr`Q7)j zLMI@F?SI4IZS74_XdX`5G*31aUT5CKO@uu!?JHuTpD-kM;0iaGR%xMU z0%7m63`6wCdRzoTFx>KS4s==TWI%-U1684DL2<1xuy$*-M86;5g6_NM96*3AK>k?w z5_VBCMDimOMC9=p4b9O4v2wu+Objk(oz|PkOfN+~L01_^Re9~OaXm!l$bfX!@n{F& zs+A3O(A};FYxD{i<#a?Di<<*ALU7vQH3?F zPdSmqw|Tk#4b(X_{MK`eRBJFU!G9G1l8@YeI6x}~`^sg7ssiRwzeaCUh4EHJa0}(D z?)|jFygs+WyvkpR38pS$4h@v2W^wg*&)X3%=tcWqTTtCzVYCEWD5Vl`3t*w|k;U4A zb#H9uhPS=34=Rjz%HP;r?)|*NSW^MF91Lr1!RVeoaS=D>VX?KvOSc_P%%0uWP_n!2 zb?S$}!x%{F;!vxLz`A06?4NE`OS*KY-OZMa9_(ujw7mlQ8>^%Xj5pJoJbEEwj>IVF zMehlQ-fBGvp>aTOIgk_KI`A&>b}TMgS=ZD9;&!nwT(&m$WqH|a+JiSTi9V=$yl_6l z-^yKD;Fur(lMac%Nps|R#!5_QXDr*LUEiV=tt!O>6o;ns; zwJ~dUX=kk3r7eD^mp1y}yR@;dXjiS$iduG6XlJhP;H(w-Zsx+o{Oc=5E=DRnai34$ zUYS@I{T^~kdWGq0s)UQWcdM@noP)ksxwcBf&IZz$NnJy?qKAxEq{hCG?V-FlT%1bu zc;#EK{*zqBEjHx*RzQSAPgVP%;KJnsSJe*`Pw8=Nlki4Q(c|qtE%7>mq^{miu6x_k z0V9$c-D7`b0N7Q;9XF3f3~Z0&R*63wc%+e=}F7)Zx7Z%4BJ8Y0~7tBhhL&i3lzMnz_^sOk{S*|^{7^JPxD)-@U zCw$?Nor;>4w!efZN99^#BwomG$rJIyK1^QBBwV&Yu~iAj z8w_+hvS5z$8w8mdupdPp#Sa+oKA}yy(OM3NFn7*g$) zVt>=%V~_!36zYX#cFd+j%XshQ!+|(zvJO1Y8P8d#46dO*5Wf|a%Jv{e_MlTrnsI)Q z8%t7yThI%7%f~)zpumNr4eQ&oWZScCAovMa9w65rkc*yp2%Da0c@AV|kq=IZ1J4m> zccF0E^69TQ`0Tc(3O*FAgKq=~R$hQ&tp^oryTGwmRDI`lQJ)_LA3UgF$NCPS5tM_d z&+Dr1>Vt}Ps&CoCgWH#j`c6KmV79(+e5uz;NrfEiAYAr-^rT4Y)DTje%z-dD*wsq{)?8#lVysQ*X?>49lp1^?vH`Vt z1_G>GY+wDJ;#Y0K49J$jCrKuOat$&@%07&Jtf0KdCZz`VP*4VEpeQ^}10D;Xgfs!w7TcykH7QWd$Pa`*pRbyvqe(iNGytG(A*d|#fuGD7xmkEGvj`TGwqYRo z1*W2#eLf(o_Ne(^?O!12F!P+Io7elXNpX-Y9YiQ*u^~MY{4hG5*0r>kuGDwK#z&FV z#hCIjIr*?Md$Id!_KPn29490BaoguOtpf-V^C+~k&}rrG z#rqyH>!37ktqQKj>E&?CH$EtW+P$LykIIkn&4^UqrMj^TMv0c_1+5mEkE6F>=CCf6 zF2WmCF}T)tti=9PGgn zrBD7mcQJS0H%Mka{-QkK*r1{4K=a3jD3dAMh(z_(5?i62MQPB#nGAMCg89 zPgwY9ec;4xgoBs6RvRTkU3kIplTLV{^IUI*g{()y>`H$r_R#oxqNaFrz04mpvhZFywkh^Sm9ZRlL?C?8Fywj; zYdY9}tZa<{;*074p%sb6TA~(-b=qu#p(#>Sr`50d747h39U0Zvp=+LJc4>TK4*M z?XO@%>{!rKXjBBcxtNVQ`Jogv0Jn0NMj6(7wfKBaZEh9|VTa5}>^U5UnY~>PuAn&- zE^AejprVI44BL|K_6##~pGV$m>>pYPpRRw1+3)#E?6AhVEzS1|GDC2QJ^|-T*2}Et zg`zP$pkFi`v};Gbv`M3&PXLI`Bw{cu?vkrVz(k>)x-mTPxfbYIIA2&8;s(YKAZ0}prI!%+9_flAz-Gl312mgwFMIF$qJZ_kh677t#I6mRu22__!O^9vpofF>lt zX9hM=unxf|pO{H)6dZsZ`@JLo()5108WM=i#2P3@QSIK(;~%D7KO7Es&D9Ll&=Map$SjFe@>YZ)0| zQqPkbzoU{}>`^=QL)07PFh`k`Q>&X9k*_6>q@|*^SLhvVCZ(5kLqs<>2ptDNH&ZlZ zcLqpE`$H&%RO;o^pKQoYsnEp5dS9<4{>UjP*{oLV0j2;x%k}iD!1lftdZ%|u1%YSn zcsM=b%mk-?2s;4h4gX4_iI)V~#3{yNAe_qWUuDd$hL9K=Hb#!Kg-zVX_^ zD5M6^sMFrUP_Zua!vTW&>{VD}qsW|ztOd-9zktfljFR1NoyhD+kPX;=d%9Do9)b1;Y6_u|W~pFqRozRG;COo!7GeniL#*%#$zs4#BLIPqz~HBUNo z8km7ku&2l_Qu@UkB+y0M5DyJR`K|c2~8jF@5Ngj%+4RaUX`OyvDOO@**vY-{q z&$4tJqgczDa8AQU6jm`|XHp5u9HAgA>pJF9M<^uxIKu8D6yN-X*ya`T1O;HqwhEp{ zf*GK4HPM?V1+J-9Bd4e6*B~twk>n-FH z*zXfWs^>_Mgs2i@=QxElJ=OCrNr8m4e#qmr(g<|$yMjYUX-91a$y%omZv~G{n6Ln4Mn8>hCSoL{( zpkP>k1~oAI*yn)|bxqEm{4Wt{zb=vwO_J^UJDj9eyTUoE{$xy4DPvx>#?1US&>@cRjAWO3r5V1eYgJ z%zzuA#ab~9&Onjx~7ojMZ>G$?4?oNqmdY^bLI^+3mh4sP5W0DKWg$W$QE|8x-a z+Ybf30Dy|EVg{}^Q4d~;ns6elrgaEef;I0$w(uo*fSCwtm68vf2j6Jg8=tk^` zHb?nUx1V*xh`~_c$?Gwg#YS-(fb9pPexOA&Sy z&N0v!M}-g{!V{XPq9DRL!a#RSHJ(uO#{kn&L4E=8{GR3{%`B`epKH5di|W>;y(V5Ajoj!?7Uvz z``gBYc0fz4MzgR2{#p856gCW@LvgXd`M8?^1ACbs z{IV*zA`HjDrMUb7vJ~gJR*7#`&QHs!=FOxHch#-7t_I?|iTf%nh!NN^Tw_X~_u=+8 zXrq+f7*Q~YtmA<^xegV{v1a>s)FmZP3%0UHaV`|%oU0yGhpl}`re=*pw7#HjU^^Ud zXUJ6J^lSP)0G@ZAeUlVM5o?ju#lpPBmD|S65;^aDH19WXopzomwRCC%{ApO*4r<9$ zAseu<8OMS9*j!4>Qatt?4&)*Ju(oHK{y(IzPkYcs-#uL+r}SfJah>V={BJwb*FgAN z==%%F{vXiSH~WSReXq-O&LQaQlUlxwzUHx{?un!{*3)7yn@5qV3!7Z(7W%`v>EX>$ zU{Q5$5(}iK>*nQwNN|&0X3wb8dBY+T5EC&5guUA%#?6R<)(~HsuM|^oS_L@Yyd0Cko4g|=xEUj32JS{Y6K5&+ z`DWim2o=)a5&m#+JDi2H`^sKARQRd2Z?0^2!@P)deQu}?7*OyCedC*b1|R@E?0d2H z3$`Qt5!g%#y2G#t?=BYGV&Xu@QeQd7%Ko-@nqm){y~?3VwcY3NM`pZ--Q)c#420}> ze-p&SjU=w|zL(A&lFu3MIPvzt-W%F6;{1HyGh~AA#{Mv|=>}jrYCY**EdnDK{%}$gfJ5=a3JZSKtpr z9#;~`eL6wsMuMmy(WwdGFD)4ak$DvW94kHa6xx`Nh|K)Ekew8pFB#e%hyHI|0FxKu z?eaifg)uzez4u1sfq7iSyc$j2g_YkjESOOZcd@i?PDfV^fy-eJ^yuigh?x_{F%dZ<&7AZdvy97(0(TXbUz1XuJ5-Bt?mFv~LEm(}qcfpeS==Uw#89ffgedTqP zWxn!gTS+s>ru2U}3k!fp?EWwoqQamFZg7E%`{Cw{yvD{H?!dSJ4nFg6Y|w!UzLV|~ z?8mqOb76Eab{nGN{;rB$uP`TR8O%6Nd+y@$y0VLhMYor<8+$YL%etZ~9N*!Kx94a- zOV^(oejtt;CVti&-_etY+JCnAur+R);yx`P8*lHWJS-4+c9bW2$hybPn2b3xL&b*ANv%mV(smj{xd^9cXzn-UD3cz37+i?G@fHaZUzxEe zhQ`iR>0%kCt`026_7X}t1Lul|E9Pz;9s=sHr-x7CbNT&EDtNyiMk7Bw*`xKj|516p z|4H?rfJ5X8^;oYSmU`^P!%eO1eEiMJA*68uagu9IZDJvumS0#!zn}o6eJoZ!I6DOM z7!xquNUd-nz=sDHSXilmQ2CJP!(Sf$;6PprKYPnp7{leT*Y@UU_bnBh_jULhTRzR< z&L4OGVH3G;2)-gi0^0JHMyTI7*G^8}8T)8=OAkyo7+vv=`=J3WHU`Bx%5WLN^qqpg zHT!>{x@*%=S#^l6t`Ko7pv$3{p40-|MuB7sjnRcgFR;m2i-7BN8cza+3iwitmtyM= zo7v=PauRPM7ORX6FEKX{@CE9^+U#Xo&{t^nM|E_Qi(g2z5487y zJn_;{?1)wmF2?e_z-~kXV5+Q-ZN(;=V^P2i@XoxSxl&+=Rt6B3l|E^v)~C{A{q#}P zjb^HjsboXYBV(K`GhZ5aJfT+hF=yVU~gu?#I*<@O%i*41bINO~xRc zaO&Q;ezIcA!>RE3?6Ow-RuSZj>&KzhYD^*2To z7;9U$^=+|pj7r}WHewAe#(iY{kr8gF zSzwM?W39j!s=2O(>|@Ye@XL;u{HRo1br%6Wt4?rSV!!umG%YJ_IDWGG@9z18Ly)sC zhESffEd8)^C<%NE+bKeyn_T9E)w@fvzrTtqD27aiUf7)xs4{B{oOMj3Rbz91Wj@z1 zLv;v_MUEmKH-(a@C5}XIV5J|Yl=fKn{EXTq`ttM3QfC&6F)K@^7_>N}V+}zvd};7@ zRXI#ErEn4*<&7jTKC;NG2S3x2loNE7PNvUXcn_Or!o~+}edN4pV;~$K?&nP)(PGR5 z$A;15#?ffcMZ*Iz{OSZ861?^1vwI;Jc)}PrhOAG^yNsR=V{)tY!6WDaI7qP^MTLHY z^%^3u4q6>4o5G6$J{6B}r{7l4lFtyodzO;iN~f2-!p{0-wuSVuICre!04ZMUQ2_F^ zqHvOWIk@f7dqt0pa^VfDQT!^fiijnoTLGJf1Q;Dl*=zWXltJLvRS_ItClRd;53>iH z>($EM*OI)i!afRP#VRBW433wm-Qf8#p49g`@Xw<}Pw`K#!#@uQWE%IVFd&=k{F3SqMn+YmxpAD-d{A!m}1IJFls&IC8|ZU-)F?D;9_ z0N28nkv#FKKw_h;P;C<7&b0m^dBB)$A=ijH^s52pTZ*&qIG$__$J+nL(KC4>6w}Xe ze;vg7*}{eEGh8_9RdUo)9A^JG_7?s9U^IyAeCq}vz(aB{P-I)nl?a1f!Fq6QXvu## ztjCVcio-!*JNA-`?J#tqw~!dsNPuGxo8=iA$B^AZ33)oJLZ|nCOg)F;>FA51ucU7i z8Z!!fiv9f&`fN;y46Fy0fRbNf7KKb1?=)=-7r(z;1VmB6Z3lz>wGyn|@k89}+IvPhj zA!NSNjW*DRgt#{c!;HRU*gFTT zaH-Ns8Tl;n%QEeQ$sL^{mnQAwAugC%sl2P%P|Pw1H&oWAo$1YK^1oNoT4o&2MnK5G z2hW0;#-oPVud-8)<4L<2dHY1nJN)(@Fc{_`-FV;r1g{QBRo!x*Mi-Udh)O$EBUK9` zb}r>rv3ezIT#Tu*7n{Y*(gLQ$}5A0~iDqXc7@>Texi~Fb^q5@ znft%!`UQ??&lzYB83m&-w~%lmxYq+)^OZf5ZBGhk7)}Q(Ir7o4#q*k`%11nZ!M(Hq zVn;Z1v9SAds97$wWqus}{Bi6+EaK|MnVPBE>vrW)ovzeWyWu-vM#yAwc{(17dJz5N#=i#r~9PP?FhXC=@42UZ_gE+zgvGaj%r$u!J z#Ic=0yn&S;cIwj|KwNZCryiLB@t*Xdt5bjJfVk-pAXY&KQhYHt0|I-)$XXK|5T_pk z#Qhl%wVgqn>45mibkpMChE!xgoY5J?m!_h{Zw>*%n*p&yI)Jor8uF3@;`&2?cNgS6Ol|F<{f>I{haok6_lfOz&0Ao4OG z?(7UA>43QP5FpmhNYmod&LBoQAkIDnhzBzue4RlY=YVLt@7rlHA_HQjbbyPT8}C=- zeDV+={234rDi9*};9O6g_a_HLEkIDifKL$a$Gz>*3$?y$uy<+pVt&Ezy*SzvJ1t%6 z!at^`sZ$Q1+~%}GI~J>8MgUq0be=JLL~kFH8iJciKTf*=xJ$AKs~ozq$ilV|-I%`< z595)I5=b@U5iyb;Xos)|&vfj;TUKD_ySP?wgRYbsa$tFKD>8ayAtt$nMa?9^MNI6} z3Bj)oLp)goAXUNr*deBS-_shu`Z4fHJPiO;cFs$nP-+woUoJ;PDi^nl^XlRxf0j`< zQY#44NL3?bt%?hL6_wPP!AuhCh>3kdA%8@z(yIz}?>eny2g3cg2@KF z;xSh}n(?rz1k|*ie_%hSs^RcSG9E~=93J%Gz-!#FNGPf$B0Z7OoF76ol$jkV44LkNwdhj|-whrt;3;;32d!bS z@7T}U0+5oo4*1@p<2(jsTJq^BRdH&ON0f13BEM4!gyfen|FspUm`O=AQ-0>b8C)Y7 zAc{tcKXs`krX59Zr2OtB9e_LU;YJx=6bI7=Zl%fwP>uy~=X;a&cch}$0)RreF_Nln zfWt^KCgle&H+{$|?{085h{c*{*#8BkPz6ijeh@4Q)t8&Yv3gz^#nX=`HvbC(9xdTH zmVKpuhI1loGan(I9E;5kCa6wsxWTbzaK<>nB~`B;^7Ea!QlGR>*eznDCL!6%Lp+2* z&nZdNp%^D5#kQg+s_`ZlpF2M{`iPDQ93#?GkFW~lAZ$=?4Z6k(E)r0rP9^+PiwFm4 zO(dyeT2cV3{qqTzM0lbBPjivLa*~KMlOB+y`NasL3uOPB$}An_WDYo)YmoF3xrpxL zD-mc|L}`IV^f!+t%O#l+$+GnDPrMT$4-1%tb7Ekz~{o_kvlp1%1ekdffIlRTsyQFo2l9f5&_G`Asv(!ya(hxfAn4p4{5=s^~@PI?zaH~*k`IO&%z z*r+A8XhIwaVCy2Z1xqO6yB?%gQB-FdGW@Ks?_&CV9Yu}Dc~&|zHLMlsCsP9?l#ZmT z;2te;6owL|;bs)XV8FtZ$Qd=EimVA6uVTtmzX5P7?m`EG!r^Jw7DkjMAK?cr(Ta%= zlo&^9nu}y48cAW_lp}GJWSNF4(I?E17OjvnN@!c>G7+ocRq&#w?ruQui>8oD5iC4N zdTM@%6)52j(Z$BbcVZTvPqC#fXs)(i+Q16b1Y*kX@32nNxdSuT^Pmy|5VZU2+;SDQ(yju9oV<9l&$(ZfsQd$|WEy!NZ|!`nP zm-wo%6#trNIo7T_fNNH_0oMtiiejTwjsJ~)QY9Tl}703*A0CO750kSL}j!wZLXN^I&h?$lNj8gg)_u3x;C4=&k6EA`20TX}TC<7!B;8H{RW3-AQ0+y%DS3 zcQ;BVr87SLj?~mqXPn7O+&bf3N@q+qfSr}vn56d_`?cE(k(x_J>ZB~*DM)qMFEx_nRu-#NX1B5^EPzftS0!76hdfJ zem2p3oMg9t98+}NN-wU^mDAgpCj4RNkS84cKubJzxa!Xd%&W9Pa1~a3Me!e*8U!|z zc_ZD4CmB{BO-xlY>PH&NzyYlDzbGSX)T)N$&!aW{>x?fCTk zS8-vEmiReLJ=ypdUyPkkt7F^#iE05ybVd-CeZWObr9QH=+D^%=k1G8!!HN&kAEjT@ z`eR8i)I$AH2{4!bcvKhq<3HG^Ml1Bky-FrX4;(4&6ZWJ2sFMC;{qczz-RO_M0@HuH z{)i1i4Zw`IyWkZ|B3N_(<7XI>&UzFM8cqf6GV>Y2Cx7V*V`gN>KG|PO%C!oP$^yMe zhf)MSu-IDj5qe(AjrHMR3$1kJ;0U*Th0D!#+(-k-Jq(Xt_yNXhb3SKWYsTB{?bxex zH_m=dQ-bvx?7o=<=T9Xz)#2b4hN&!7zdM~32)~6>i{_yL*6ph$YA4_zY9ph3uS*oM zLDXJGZNjzp<;Hc@5Selk#nFHG>q_?tOl3)S5(hV{B#y$gq~JKEn66ey9#;}aGn39! zNzEL54!|{hN74x@$t`;3IZ5reB8$1G!BwisN%}}7jdLZ{J4q{5QplB5?Ib-TNtG*H ztNMP9l~nC|wW_avk+Hlcv(FsWuLsRA;;r%5b5yl??b%;v`6HA5dKd>`EhgB` zvd@^M0tL*JNM@X7DO-VMUSl;hT$g&G)^0%(Tqnjuj3CHiKoUDn3UC$=`yCv6zEdxJ zT+bs5yLr^!5x?@QSg#}cAoB#aEG7Yt`7o}r(h@(Qr3Cx-A!J5zNf6Hw`?OqL@Dxss z#5FfQ*e@c5X{*4WdTgF_1s?iafy@i0=-$Y5`hFPs|v;NFOLi;Gl3Pm{_QHqUPJaZ@$6 zM1N}k07Wz76B3?0f$4e@9%4YvgUgKy#&3Y!!3LCShs?$qBkCCCq?^kon#m`nrD8o8)8$5A%z-3=$0z1 zLw7Kw=nYac`%PZ!_H`NJfnNf^*IEi_Ke!&eFb<`8AJtZxO=sJW!8z=rsryy&D`roz zpW?{a!G2o&j4Y$SK&PoPp;CiCtcM)2Rm;Fl)JXV)8pBb!{Q1!=}l!I;&?_gCNmg_VPmEJwn)PUf-|r2 z#oI!5{T|RaBNiS7>Fm3Oe%RlsC4R^7pMU_){~P=5U*j!Pzp~ry%aMilSlaC%1IHOL z%J1Mz?9On4O)91oBZ#Q;I7!yNx6h){ z)07>t8)eWc-c(MIv~KY&BX<#|<(l%b_9(D}8h_dPI#$=VE8SmNeBAy9`_4AOCtIF= z2N%ARsJ1kvapL_wX?^EY_xN;|Z+4ge0-dOSP0>2;CXNmnkM_UzWuiTZh6J$h!l+6s zsW^orxBe(K^{6K3r_pP(y6IQ3PnB+(RZ8swG{i-ABAW54*tMvx+r%EISTR`JGr&(t zVKtx=zvHB!2FTUB0RuB4`c>`{<%qQFF>0)rCNpJ;JqHRUpKm$OJMG*>&U3JO zrl$cV`0W#&)O@GZlg_h`^Q?5zPj#MGI?r#M^odURD<^!K6F%2@UgSKf_7a2hQ^*=Q##X_neX0zb9v9^wgZO&Q&eE zxObxN`W5a{M99XgDb866?r|;RxZ?Kmg5|s!0=zw<#j@uxL?h7NrOJIlD& z{%OWu1$_h2&QCyMJ2W&N{;cwSb0CB147=}-m@LtpeyB|%?w>C&UhO_2h=CY37xCaj z*ql#{IQX!p75u!rU)yw(I4gT8?@&%%1@(Ej>}@T65`e<@hh2|(my~0#Jbum*zvTGF z<{qO9`(ZP4zw+J7d*JssGe04D7BDujW}<#VGL3TEpECNBGxglJ1!w|k(h*2+bR&)3 zeQlLpV|d6|nAU0h0cLn=(4}a`jLW16&*jZ7PYuiI+=M54#8ydf$*)FIe^J+}v5zth zcrradU}Isrd+xsR5!c%DVlp~$tEwVOM#%01a$M+Livqd zDCrZOL=uSliX^gcslg9-64$sBH#&)DIEmzpOiA)DOCBkSxb!EJ(&(h@nn-N8FBiX` zbQJgZ;z$xaVDCx%LB9ZVG8&4#<{XCZz2;3-sn}iAE$*wrq*|3)B;dJ^QmD&Iwac;F zI?L|Z(GIWdp4fYC!d`%ERpuhLpvs(2lM`N35S9DQnfWYx2j(+3Gi3A!ZogkH|Jo19Y}tT%Jyof@>)EDk7q3EWIX1t$ z+t7+O98hhL@%kY0q^iHhMbz4T+yI>((5F)=8%W&K{KR8lXxIj8C~;B4*BQ+AB4m`` z$=G0>id1_IAZ79&t@3X~P0l#7M}EVa4oI#1{a|~g7?KUhB6}_Fdmdr=1-9&%$6ep7 zec5A383gPYScrhM7q_sa%o%|;{3<{LOR`YK|7-7E;G-(ezwxt|1L2kpiWY&| zMWZHwn1lcc7fr}*7ZOMT6&2kC2qchRk&K%=2 z0SK(!2yZU$-e#QbTDuX|E`}Z>FrhXtC^y8_0yCziQ!u3kJnaJA1d-8)+;EKBfEk%a=|&Rkwk{k;xVB5+)CA5XiIX7WydU8~9PE`A zI5FJW2Ol|iEbNS8kyIy9&ytxI{&G&d@o`b-uC>1eQ5qj-tz&7&`~iZBWbne4cJ={< zEsg90ieN`f-i?c;z9KKM-nSi`>00~fWe}X(_UmE*{JONoU>2zz`7q*{CQgBXmFb8W zM&LyD-RN8pJ$Shjs4&|d>|l=N(lO(@-jT?ZpX=7Ig(%UBr2 z)hbZ7Q>_qFs=46%her%pKLQgR+_${1u3H68eZ3{CSWe7GGWRJEvXx;+9eT)-g~7Xs zj|OB=_crE}@7Ut-9$mNb0wkgGV0f53IhpqKBP`bAtRLzmTt-BL0hN`K#lowTxl~?V ze1}(_^h&UJk$>qmPI@tYGnQyf@N!A7R*P4giuLJ52;TB|t;MTRdHq#-6js6!;>D3Ry;eytic&Kc};2H?l34Owmw8^%&k$RB-i{L~!$(#I!tNCrwV)q+MnJ!u4ZM1B; z(y$nLG{yrCBMgNDZ6RoM7-mzXd4j$=a{b5S%+J5Y;*uRk z0#Lyif-JW(B9twl;j#~jDEY_%?9p17jh$Rh`-trIBL>P=u&W_t@_h49M1%>rRycR9 zhEtUMsjGPn+9@m(#{XQv^l<5eEClW1q7cgg$22;EdvO9-?1RwS?kDN26I)jXN`kxR?GFMJWRz9KyvH=APBs9Ik^qKL~(xUypZ z@|-|=HkVgWfE8tS);$+8zNAr9iS{p;GjytJ*8!^7A;JKm-=m_WTttt|OhFP+Md^sX zGLM9YhQNRVFIF+XaXblV@i=8g=wh&%B(GE>q6SW~P3ZSD1}aVrKHkk71s)etKUllQ zxD<9P_!5koJtTaEF#sD+L#$7iG1cIB8*%Ahj zmUyrj1yw|Uks?&!Lu>y&5=KDg%9Jdm7zKe{da(%bay73%#Gnsp%KIPZfpUHUlU+|N z${j#IOUnHeh>n?ZGZDB4xUi!91 zBeq3fDZ2!YpMrlS^P7UjVrQ4aB_dgbsDucjIbCv_6f?q{9uYI^w{UJJbURyYKq#c4 z>yU`0@d@j0#IPS?{`>cx0FJUqa0Dy{M36#?@Q6Sc*@N^^`4uufD$GBA1R4dG?O{xr zffjGnE~GqtQZ=T~b?8oc{I2Pqh#{B7`*`^ox(LBS=Eo9#WWy)4nE%#`FuOxH%dkqN zQA$hbMnIYP&5X2(;qO+Em*Gk|Cd`vfA7o){HbITeDsh7whH~g0T%P~|27J(cu#o(q z;oE_4*j#X^HzsK1=?!R^sgN&^99tpWxRpcZDpy$Pj(ok41n^lkeO*F zg~gFM?%2WgKY7^`@-vU>0uzGC3UmEmcyKZpZ8bcbZF|E)p2k%VGa5D$43F3=gksoP zU*LKq9p`VQ7vTIYEYaX;i^${e<`ZF$0dpqu=*BK#b6@N0EY<4=o{6jnK~#B8I^tI& z{(&dN=Ydy^R(!?WFL?C_tEtA)5abCqCze3Qcmg=|0wt8E4|s6AMLB~6A51J3zPT`I z1)AjtOuUPP`j7Fjj4jN*;-)ANizZ+(PtSLt9f?3)3{TVUX1vfflzT|IJZGA4o-R$7 z+hgcvFc(Y^E+4`?csBx%qQP!TtVR4_&S4xgGeQi6_hV!g%sB!>_3?5ToSTUG$4!ar z5l#$dVFW25A|h?%3m#Y^cx*9e|*w_=kM57)p5A9plhWA{OM!)9PaBE#-OSmUG^bS?C2 zPV6Qggb{XfdG#id^cX^AY3f`XO9~&hG$*#9=#0ye5-df9jcZUzSm#Vz4A>nj*l~hW zAxwG2D{KUa6f2vz%vx8T>{Qe zD}p@Oi6ak$M$8*Qul2xKoh7pRmOQ^I`ESMpbD{aINjwfjL0-2&vj>rmN1!b*@@S9p zTbz%qeX;|GvtN2AyXo*b zKl!)^i8>o#X#k0MyvUac4b4#!f#GRS#}QT=ieyfqwd105mWnsIwPA!+*dm*lAfT)H zb=pM8W)0sLhNH0*Cy=vo;)FxW+$kZ>E*9C)BJaSU&eeP=qHu+TAS zxK)dkrkZ9s?-1CO=mtvT7YHVf+dEFRu1#WME4%448)jQSGai9IdK%tVk9J*H6!<$E z7#UX{|L|iD)8rm8oKOdgn6OzY$G{aWvaw@Lh1eW+mnXPEW&k-yquDC?9r{T2dB&Fy zU~Em%0I|Wv`*WCf%LYk1%$_jAI8tv>_64M<5I{U4uoD!;V6H$8<_gx2kgLJ5qYP{H z9~80JVSP0Rz4!y*OG)*$pCX|x6xc$7-p+w9Y0hbyRzM*=Tc&sdFXXnQuWS0dZQI|S z*)M?x9vcK``uRN8@H1RD=*r#Z`uR3b=4*8?iyCyTJs%1W?Kq$w7J!c#gyX%iB7B3$ zE+sM$&HzH3Ao^Di=GU@cI_L=w{T={$>t|p#?Q<|xCrt0#v2^C`x=yYo44Q(%nWz}% zXCOo&xSst5?*nzMzllTV=6WFq2G8Y%mclS-GR1w8DXu{%%A!ut zp%C<-tfidil&3fOEm!j;VyF~0eu;o$OC1-nlJOxPWp0g2;Du&7q9_pJiX$?QS@&W9 zjOve$dokjT6cfClFzv>Ar2Y3ZE6|%Tdtpoi&PCYEag$&nj)+h5B>x3x;+`DL1DC$w z3Ht4})DAmnxXsqoYz$62>5!6GOGl#5Bs z5@jj|JgRzIrgIhpQ(5Tn9Mqh|lFR~ud8_Qw0E7YOK{<^GmL8`(Sx<~1JiGV-&tb~5 z-Rjw)JiB3ZGC4gGvrT!vBs|xkeVRBMmCvKfN8I}(wAd0R^=pNVI!`1Hl_7erRh}tU z&n)Fxt~^ItJ*ieP<{agzSv?b!=S1ach6ixP z9FkHnISu-<@NX8nrNuP1iV0u6b2S{xG$=JRauXl1@E00{_`s0wUJUBk1gPgl>=aP- zLJ4BDrxqh1G}omxCw7?e_NsVb=fqmG{g`5t?FfM>f%(XNG|GI`e=};kSB&$v(E<>Z zN`~mOA4O@<62>Hk=3@NM6;l7g@K3U_=*OtrU}$fuH<9k;fhiOX%Mur{gD)1WL~`OI zr6}-r5jN#*ds}evDMAgPG@Vo!9J4OFW$2CBkt^((fc#ml%h;*n0o*jFGRNl;a!XAmBQq0g~1Wek~Y~b8U0!4+5cnr z(ECkq+X5r5v)bo(xY62SpZ^H<`PUk@hKgwy0l^a#!MXIUS%^s{5$cHb#(`@V?}ssX zr6iTo2ez?|Fm0)x;!H#p{rz@fFT-JC)MX}xcF_7oGmRaQLz(z8ew2s(iR@J{OfdBV zY6W*NXi##4CxE3#tAHx>wi+Fd5`*TQp*hOUk#7G&D)b~`qUSwIh?@~2^dA2;0h>jm z#(n7G{_P{`{%v`90FDNjp^gUFDuzwiYtCMu)Z|5c3C6=Yq|oMDGkfzte69QsP0y$YmI(hNHQZN;t=>?^!Svl&QC@cfE{d!li#gr1$?Q1IGe7RY zajoJm`+sxwwq3CL6tUTUzp+ph=%6tMNeMpxhvf5{xCM>|ir##_O?Z*d_n*z`0iREl zw0rdm(k{a19zhJj=fg->Nd2pC8Zh;6q>3!iV9I9CsjMISx2hu*_X6dNjRN|tE z;lv!w!FnYG<5(L!nUpQALW|lXvj21hb&pjf71?5~aZ%=*p5VMAMXvleVe4Do3ft{T zmI`a70cUn_L=sjx)epwGw6NihDDa28ncIt8vpz0#&FaK*e+-pEIFR<~`fZPefgSfb zcwPA~V(jT^x&b+4pM%39v4aAmk>@-w9PwuU%XLj1IEdWkZd~ICyIpH{3vRR2)Y|h1 zLH*PM2hMK>;Ts_QJS{NhLKOt%*<&}-6VLL%O{&MlYDG~UwW?xd7_)AK^q#dVcYJtJ zQLqTQ(~JI7K#uWGECLeV*a2fZR~_$d7#&&%=CP1xc`HvaZh99{ zG5EulgKe-p+OistxEtQX>6s^aZ2NW%nAezr;?1JeLe`T!w&yJvc4_lGIO7H;v&O5! zZhtp-^tAjK?Am~xk~nSQaiC^Jt`^fA1z@4V#9CQAYw5XwDHq~_Is<&oA{Rh0$%`wp z?G=4CS309?8MCkleh@F^m?;pY@Jj70(sMcN}2>3(btwPeTGQ9=K10 z=I{bo(IQDIA~He~MU@NU9oT_k2}dA;vddw{m0FDqFA5_{XDy4d83<&XZIIL#sKf<} z9DZq`*DP6)3@+~JX`FEycq;4$>DcrU5_?QSM}%S=)8HCPRAZA(HQL@nuiwH}M9VDH zw3CsO&_s@Rz^Je&z|4ZOSTiefkHs*G_QnTiBF14PY1pSpQ5c53fgJEf(cpfdSh0&k}l9stMRx{`m2x?56ity3GVf~ss=*=7Wm)d8s5jBIm z_$Ut0YZWG@fW4iHy_HIbu3q$HEH!Qr=yt7zVycCnLQP>m5brZsn3!ZVO=14=rZ&0r zBrSQg)eP9Sa&YF+l^)}41i}ldZAY;;a4`lr?{GyJmrII`e{+chXQG3(X_ZC$g-JaV zK&;}%4nB;NT+Q>5F0_A6OvD8! zb0Fklzk4K?ve>aakb`}P@4K4WlSZghHrYxYv8Y&4$4TnA3voXLjUGwHXoRGlBMB+J zD3n<=tjMLH3o>wB7#7>0askX>F2r1Yj)$+IwkUsq9+2+`jUhh(oVR_O>u_@149f0F z7309qxsMMj4n=)*^z}VRTylpH;ZcFR!}x1D630BWBVW2s<(>^!*aMU?py`7})Wi}j z90d{~U0x|xCNzUf&}MLrz+rNrxH<5zJgqMo*Mfo7$aL66v&VIf4}p0mJq}#wkpt5K zcQri+J}3-U4#TZHANrSggO|8DE`+9-2VK1Zb@CPn+l77!%#hQ~J1kH&hm7$zBG_~48r zZ{VsdUOs^hI>jO(pm#N&Dfm54+^UcVW#J%{gQ_I&_$oKX`#8)I1q0@RxI?gDq<43L z;7kDKLHj1%*e&i)>nlUJJ7ai(8yUi{D#@CmUobo~gp866kr;NKUzG&(g3l1~{0x^k zl?CS+jDW-gb2XE#qV&gcLT-c`zzV=v4ebLJkR8Y$Y5eAA#11mx269mYn}ec(7xSF` zKXXgR%&5rnwjdBJ(%8?t(nCY;c;pR0w+T!k@I(Teb`^8;$g|?2)gs4)#3HKMtWi&d zt6gh9068Iy7g;!(e1om%Mn@{i#DO7arcvAchZ#xrmVx}anonhQ1U|%A=fDMQH&_9+ zUc{62jg`{p$OBp$APw?FeHXR-ILn)iLlVM28HyHdWFWjat}FmJ>YGI1CbpzPCa@h; z#57y9zF$Wbp}xt|d9uD~Pura*YI=D9ce7wcu50+ksBlA?aTAnNJ|B0JYR1xAKuD2jFA23|v_Lz_O(ErN&fM}+nSu@Zx!FfLmSmk$GsBn*DV%5S6T zhj26sig0-El&>Owhvof{<-N=D-fej|BJXIQkW*Z+lTX}m^ORel++4cMSUcRF{KR=d zkzMq69esTMU<>!tvd0zJp~}GwdNm zBmyzth4QjTCY;Dw{yqFg#Ylhf2J{l+^PkIvBv2%hVj@N&S>`(eV{Nodl`+eSi6O;V z5a`W}gTIiN1Ta!$KbKvoyUd_nNsL5LVm$FnEax1FOc~7+5EaahfFp5k`*3Cy8E&K- z%o+*hNq-@Q?~{j~MK82hkC=?Y6g)n~{HJl%nLvWmja|+EB2?kRxp|ED9>#XY#b$`L z^~`wB5S7~(IH5Xm?vFea7N z4DrWEh(B0D;LKr`W!?mY_*o=G4njoM%aJmmTnbnrl#fCxy^Z|s3C`S(@v3pgIM$O~ zVilQsV3MD2L4$+nr9Z$xKj4tnCBM# z_hllXm>bs5BM>?mF8ykF*3+~#u>)u||42{EgKD}*f>^$Bs_g&qt8RUu~Bn~nzngNvd0%QJ@-_zmNarvq_t=H_H1 zaxIeOoW-j3vahBrV%4y5v6`6xbavhN2_wO?Q+ak-Jxi4*D?8FwS>tTTxyrN6>e;S5 z&rqK0t)3f|=V0aOv3f32o*%;E$P9Ip9MfkcN_vu)#pbBz=#6tkJ(-xgbgc~wfw?uY zk!)=)i=kj<4u36Bt%1P-KG9_{EegCS0xoB0zW|GF9!t20PYO-GTE{!R>t{1$NvvF^1N6og>F5)TfR(Y_l2;DebAYM-0&>Po&zgfmXu%7mLEkvJuU zC~amG)W~YQGkhytvVID~6DOO-Mj&I;ke)&(-UpEJ#0wHH5pivt@Q3{$BR61YBp}&H z&twCuiTytW2fueZB0h;y@bXcyri%f&f)2K(XJNi$iD1xGtBXX^Am$(8WAZ%p)R5T3 zjP=StS)91qbs|=K0E;VmlREBUuRjY@GbdYVC+&7-`&tSdyf`p_d3NT)Jk5{!hnaJj zwQ;PJG7PW^$0Hw)jQdMG@*bP%2niso9IDgyRZmi?!& zl&Z~|1wEvi$WzKwv{}`bkHsmGC8C|K7!W7iudC5ADHhj z{KN;WSwIT?gzvCZB?+G-1`8C>BTIQ?AY`%eq#{cRpu|TmqX`Ymp#RJkj7YVJRL)3& zg4IM&iFbh4;MFg{*EXxXuNFSnipKRY>W9ATuWf~|aj{4TjgN^4J`Zkbr$?^UL$r?I z7Lv>uZ}kvuD!8SK9)GxkG*qYzq~Qr}VdWTspU~q$AwgC4jd!nvQ24=NNp;CM$HISS z3sfd^ei!_A_;Q(tR#ql5nM60rfA{snfA@X2{C9H*DV z21X{mF`YsdfoUES1JZJXKrr*;3^$Y$wZw<-)cE;?x;~UefPy>ow2R>xoIK$Ba9Xf5 z+GzehmMm@+qez_Da0%kzE00lKYkA5KzJ#@gha(N!zZgg3V+-7x)qz;L8Ie61h4J zi+-0SW?9Uu96|*Put1<74%Mvf!fmd2&*D4Wa=N>OXvXKYapX@tp1?qK8JL>8ma-qt zX6bB^&K~LPla3)Bie64QVkN>zyrLPLhq(hRCtH@7Vhljr<@#7~mk5y{LLjJ{FE|mv z`1Dnj9Ga(FXpb~SBP`~r3N!cnzXucJK=M|cEBrB;`wAP zphW<4VB-9Y%OL6`PGAz}c1bL!0t+?R1kv>>^)((qCbTGG&S;p7$qo!WdtT$3h2jlM zy#V}%yI>-%Har^qcF`yZq`QqzN5TS+RS<8%OicGQ)F|Ca%KaPQ953QNR4jn_v!EXI zK}_cUk+s0#$JIdLY57wZQlP3xuWr7>Yq|7dMVMZ!4SLOyUhGs&uMXvvBE2?RyjZb} zb%OA^QVhCqnR~q$b7=xN-4o17@MP}xkKk5|i*Ue|E%e^^go>C87%}JWe}Szvbzu?zosu-t7eg8xDA=RWKQ-3aK8O>#sZNp%q1`* zBGk@=i*}H{u7_>wMO%o0djjc+SR{rv7H4cGiCQr48o&yz-Q;JGu!BZowjcji&+ZO% za~Pa{)^I}2Vco$949N*r?^?EPUAsEE42_ z*M`w6%;eb#P-t!5-T5ixDo@LgAUJ*q3mhj(vpJzVfO1kynBpVfjl&*Y&Cj!Calr)^ z3`*)F{gFnTK#s}~OD`x7FfkTcULc|u1@guEf;i((n6Bme0th!^Y57qG63${`2!k2k zd=E3kNEsr{>1LXOL6L~@OJLyAhiG!hj7Scf+Au+hnBKr#j}U)Gp$N=^2j*sBD?2Vt z@j|d=euYzdk&cyjE!EcNs~kVKct|-+;dWr&bbGNUFuTL`h-Z&$_^kHjf!TZD=jp<~ ztZw`(?sN^G-Q^lSAMPwJB5vsLJf`X&d+Uv256lAF3|91Z&tv2%JTA}JPRRO39fv<* z*XZ9k4=L89sOBNoq}+8p#o?I5Lfe5N@_<*Y0d7)@r7q6CB-;mehkO7*Gf2?Xy(Vcx zpP)03j86e|(;w?G@G6)=oZyFE^Z*tM&HN>9Z!&ft2a01^EvD3s(X;uEC8Qr2Ze)Vf z`{kfMo-!WUPV{7>8(<7#d~k`O#%u_?}>P~RKa;SF>|sPO~uwlD34n0V$olqqNng_(aX#2G&r7q}xV^8=47XPa7! zibhpvgFmLfVPvHoz)Fg>%qeb16RxpHWQhUM4&8+<2r3q>db#Z2saZ{lC>754@#o`g zG7ZP*kN7#G%k{)qe1cVnOdeE5v*G~7ZR|>5Az}9_M7tCiM-n#@K#(GAfIO=(@M>XT zyEttU^VdWo;~T$KQ4xVKA)^A@S(OtC1K2Y1Z&Gt)VKNRqTF5xatZ`2?4q>7IHjw3b zZ_xSEA{%a7%t2)>U~MaMqoT7hCun@-LPbXo^AzhRdiA$nV2`v9OW!BkKNjD{^v@?9 zHT-wYPZyyC|CjMooXFC5$xkcezcoKyq@sQkemXxI=h*q_V@%T-_YaHZC)D@!?DM>V zLkpmzWE8gel<44HT@)Lq?-DWtlcGm(q+c zCMF^p3wd%%Hx{G`LGWA=Weu%g(EzTTS5yl{%bOD%I#?`$gYDVl%Ey!rPd+miA=9Gw z6|IfUN3>Qq+duY#&)VgT)BLlrQkI7k#$h9YSQ#kfi)gq~zKMqa>`>X8n+=~$mF-yQ z8dw7F&xFuK+s9ynvE0ODZTDA($2JEU`xtXYgp)^@0# z5~pw+M*nDdY)?ii-C_2W+uqgLTV9SFb9L%K^dqj}&XIgCz$(w&kqJfENYQ*X*$Y=1 zV?&5V{ZV`etp%%}JKWH1++5j@?^)eqVLuK-dD|1bz|BG5D4~mR&`08N;$j366>42k z04rB$4;=t)4QmBY{z4!JUvk`=yei@&@LV9kZucCxmK2wjEiY}T^qVPyl>W0Ub$6D(bV+5IPm|7+NxoF`HO-f1 zzNY#nnXf6nboDwp(>K|C&G1bzU#I$}ny*uQ8RqL`U#9t*?n_NE-;tb|-sCi2s+r*A zR9~u@;^Y)xs+nYZrZ3e@Gd;tXY9^XK)t73fnm)ysY9^aL*_Udjo1X4VGt*6<25Y@4POGX} zR_05Yn7*X8R=%fN-qS4alPvG)miNi>U8JJr)YM*HTvxM{O&X03-;wt1)*8Ik{+ya> zv>vwio}SCm1RCnt7@|+sIe3ThL&HfFLK4k{i^)-K27XTbrsJpMHw{0|iD%-6V+%DJ z!Q=3oiXRRZ)o`SfM$D7(;{yM5{BSLYHVHor`?WOuVBpbG@#CC0E#nFJorNDa7hs9K z2FtN_CVnuHYgkaPaV~Q_ekb5J4!;xeqoClT`y~8E;&%pqC*gNGexvX^4ZqR&!RD%s z!S7W3un0ms1wTx`Yh&@lVg}8vewxkhaOwjF#tj-gWazMX7iqx-2&4haZyW8HJ`^vF zcyIjTNH`1cC0`v0j{#9$hr19&x#`G}@B|RWA3hRpgWC)@3&i;iTn~uz3tKqc0rwEx zS`g_hdpO($cRJic5UT+0Gayza+zBAkGDkRkCtSM|@j$G2xG5mcOt|aeE`eJN;&i~> z1NUS-9L@rf7QuZGZaLg7Al3~75f8-L3il?se}|g@qCGbVYeC?C1$PsO*9cp~2oTQ= z!^<;pJK$~w5kG<33?kCLl?Wp4hPw&wA7Sqv0b-_LKHv?|BLVXjNpvx9RZjZAT~8NN zhFPFf8{CC(yWp0?bz?qo4cuC|t#I4n4h0>vury*H+!CxMD+V1qu~;twbWBMMhd+he zHX$6Y1RaahKp(_wgv&iA?QoxgTaq3QuSWb!;2ALn~IB>;da3_ zfTuG9hZUe6YNvxfaJy&Vm}}HW?b%2NF7EdUZ-LvMgY@Bc=OW*zr_Ma&6HMJ&gnXi& z5{f}*z&qfU!|jIK4L9Ljlpo=`;BKIM9_kC>vlfAVsMod&!r>CQofm?Ra8nk8j%XCc zaA&Y_TnzkhYvC?~+X#0x+%~uy;I_kUgIjV5@DdL94Y*x!yWytz!eJ*HR|%{&a2w&a z!)=AT6K*@)eQ;As!{HAIUyAg=U$x7^;lpTz?aOi51o*4H9R6@?FGD`SU%Xc}3H;T* z67+zZawF1Z`1tsf+ap7KYrwF z*N|0ljoLY*rjMJHNYNzXE{5BdfSsEJWXC5o*{>WNA6GaeJ3dax%QXOZ!vF8|pB105 z!JZvIa-AbP-reNPjnA@|4UTsMf|#@7;|hidoD6EaqPS4xcHpfaPl0$e^E?B7iTD+w zUB8AhIOm~KfcJX)toV`F5$`%@c6?HkUJ&0lVCCTWBtU>4A%H)7h~`GzW%$iFbR>Kw zT<2uON6;pHo%1@!^(?KB@#(-l5;7x$06ZiN7kcFamL?z)wivKlz}Oe@VYphrHUU;7 zAQILL*gn8AEwGJ%-3j?H)&jc^unr519t}}>AM`^BOc{j-N=F0M>IHuZS z3Y;?}7x5P&9`myS^3A!zjE^b}I%dVYH;`WI^xXKArU3=<9X9)~2gj!XB?yNkB;oRg zxPfOA@LYwf<{rhnb2{)Kbkl%!`UYpvaUCefvRA_GIx|`(4`7Xe9R_R{-nGI=T_NqD zb5?xP20c4IW!-@6_>883WQku4j?VxDxk89Y7EpJ^i0%e1%4#>u@@F*IXx;aP4+YX4 zpMorXV+20n^b;q_)rEKGAAu8*ng*^Lut5(Bo+t#I3;5%(vZ;b~aF3ZTXm}lI7^K%Fgw77Nly!eq#4(4?g@;Wj%J^{_PUv_<>6z|S=ffJFe=>jbD)i)5X8+Gw60Z2C}ZI?ZO#{WkK$^;^vSG>ypbRJ=Rqiu~HF z`DI4kMi2ES)M4n$Hc>!@%A2El01cZ@e z1Y+h}m;piA*C(RQ?8^y<@4`FdZeY5qpSGjbsUCU`I(GG{`ai@g&W*}@@)q^iO6aM7 z#k+GZlo&x1(LYCJrB&va*sti5wLG%F9)UFK|D|Nn5a5fcZ>E`nFo%$T?wEBRghKUo z{Y;4?x$k<&8{z@Jbm-c93jTB1OI(e>RfvP3pThgs<}1s7Yd`EE`#<37Mjbx}8apR^ zZ8?RE`zd8y?~W)U2$o+ zccaQNW$OpPxdrL|57T{w>2^A;4VkptIv9Kg+FeARp3OcBd@1@Y`+UijqRX;hBG?k| zo*lb9vahnwjs(aRbsC3+6TRUu55xUWa4kmkg}{}8WpLvnZ7oJ0n+;8-B1Rp{AHqEK zP)R*QVgqH1{`W!Pp9b1UnUh8Jbb})(``=FZeSoyNBjP_P2X&7zOrS6v2KB{57{`S} z0lU`%%LQyRVC5FrBEXzQ;V`O5Jd9gOe1M?`5D#IE#0MCLi{fGbb`xN6fIUEn&_zVO z7RI~nx0+SSxLXm9W7aH&!$VjnU|Rv3CLj{_4qyggxeAsA_Yh!-b1_aL?CAVzzhCIQ z5Kj?>6S_X4&A=GA9XL2vkT?n`+eM!>JEFS^*$zF*?(M6gu@7kmo<%Q&!`q2RjFar` z7%0u-K#66#6aIUU4#hto!nOdm6EJ9p;vwuAz&Zh|Q?M+!>443c7Y?7#ws{o>>nN+z z1H^d9D`kJH&2hXP>}OR4gucQ2tp<))K0XpY3-8Wzfg`@vW-=Z7hmG*h_+dEwBK>E| zG&Z2PW*ENxWH2&UKCr$f_vgCV&z^m$CTf!?fA~ zn*dlD0Vqq4zNj$L7tOZzMT}=4-ZI2%=qp}nBwn61UJAmx!I<|U-YtwL>SlJlyJoP^ zhVzC%%up@P8)DBAFK8|Zwi#(D; zWijkA%-fS_1V`ung7_|*qlU7&_oyqy3BMTPkQNKVvLy& zUDk04)6MT+?_Up`uOMB@80QPf4I){~TL}1l2;+o(?1xPEA%qch7J9#s579AUjvQ|k zJI-OUy}RPvA#UJ141AlACLGOK%QTCvNeaGu27G%9OAB2S?YzlZ5MOMc zYf$m_(yCY)&45x)XdJI&Ew)4Z`H{*a$v^CMDp&>Roe;jEt1w)u8 z55m3-9yQx4VT%Flw!o;v(oQ!4cDi~97H2zp2O;0{hYcvc-f^8XsBak1G|;ha_{4-Y z6E#P!Z7|GH(DY<|)1bcjqa)#Qr0HdV4jqsHBG@+!2#-3fF|gyD{c) zUWhPJx(odh^3G~gz}Us%xVCR)FQSXA2F?q?-{XMaIUG1+##=K0--IxCUJd&i`TJie z7t#&d=TOH6y_DT47nN{-Zz)R|`v&5>k%o|k+?9yBG5hsJ@IMUyh1Wn&gg9~D1OL3C zgSFy>0rr&|wq)2>u1<)zudGcNW?xx8$K_bLXh6bH`^u8+1c!ZPu_G{G@QzteA;PR@ zW<5LWxmnL=@5%*XSi=Z~|1#f-Gygv-w5&@%%1OzI9S|-Be7_SxaTCWd>uf@Cb zE?MTDHoOx1rC=lOm{JGE<>HP;oEr?)9vb^ZPoYQXYF{7QUxYI$9a$`s@@^7nePsyQG0th{1Wp$-pqG&Jlu=M$oI^z$@d84snE># zz~1?$9C`;~$}Mt;V~0b4-2~W4EX&vR&&Bq?_1ObLGEwK<2wbaw6%HS9qFgsZSPI@b zTDfcvSKq=udx*nFX;jdw_d!j$k(Lt*-(m1a8sGDgR!m>Zw(&B;7VUQ0)S9-j5K8u-dF=fUGTov%R)73J%9%#QJ$&2cj8t#=`{O(UWIp^h%YyEdQYKo>=RbK8qe)?)rfB3#nF;qb$x z|M|W17sFS%P+uLlehpt$0_OzeuLk&?<{m!oA(1^7TeV0RPa}3+& zU?}Is2nF|q@o-yh`a!$)l}*P9WX%ptv(jf|@uUypwEZ@{c@U1%)-fA;pZzZVaGZ#} znz3)qv(31}rZ>fDPuuj*2Wqd|^o?=a0o%fsIPELDeq^BSHs=hy->463jni%&pnp72 zJ2F5A(&!&gVUC4+6y-Q0hwizsItJ)F03WD7k)Zu^kp5xkP}(qt-wQsJ&x`hv|`hOrF* zK5Wx>57ch5>u(O!KC$cj25OxS9kS}Bfms6S@Ja+S9Qs2pZR4N^^>!CA3>yXD*}6yj zh@}86&$K1pV$tADgvz&_+UG#+wEfIE8SfF=53@NhOp*&SWZq9a z6^Nd->CZd0o9+5;C+0Eu&hniGAGofuaBsEgIKI0>(axzVT8PAgMD2F@R#=uk5$l_eyMvMLx0JOmyJcwhZlvUEi3Y9d_t9e~+8YT6ZLdwy_MJe~`@g5RPldG6AIi`k7^xq~(3(%uU(e8P97V`; zqx64dXd6fCTc&F7jMn!})i#gO_e|Bco~#>FHREKxW2*MMALw0EwI{~voyf!~diPXq z->EC!o}#^fI>Q9dV74Ah(qEjS-8+uSZyx`a?WGLum5HwmL@3tEl_>OHhyGiK_Krgl z=a05)2LE}8Ahlb92E1k)eYgkjt$59*w~y8ywCmePYrk^npN-PKbm&_~YwtVtrqS9H zy1st2_T~UR2*{w(H;mTS$3JDeWwdtn@dVv-y#D+s?cL+`j#1j(BlM3(X@5F_@V}p+ ze>qCK{Y3q(QCNhbzdDMUIQ4c`%s!ib$fo@h!osfYwCj8A+Wih4n`8DkbWB?zSlk$d znxJ1L@~wF8>=$kNv!k?KcKtUZm%kfLHhOoI_6Mha?P%>Q{V&cvqqLib=x>hF{t>U^ z{SPkvFL)pRq+VQ60BF*ZPT_h7k{$j^EEIVdtlLSPWzQje?`}J+4R5Z+AB8w zAG-FQ?G@VrUHibHzo6R!`q_Aw4JUjn+D-MD(RPD&$M_G6_)m!VI~e~7+ta%CvP1v9 zZu{6d1@HaD58Fo1MXn$iKO3ao5vPANNNXDe!2N@!0)Xs0lkf$1IEvuJoUHz;Q~S(* zm1>#!((}|d8x)-;yZ*aD+D#7qe+Fs4cK#1i{HLzpJV;wRP`_K^nw%nVJ!o5lcyBuN zTgGX7o%*lGX@Ai5pN`WG>-rbT+WiCcYsP7h4A5^Fr`!d-{B&^Q$xTd&go_-L7wSprhkE>E=a94Qhw5 zSCRS!bI-+p2_yXf^`}i4VvCjg|2jSXZ!5o)7_h5iPLz-N{pXnPy)oafs&81-@E)STirmYs!vp^}R1apw~WE-)6og^#A<-_KQ^k zW0IcYmVkWao~PX9%3Z14b;`Y2xpyn~Vdd^p?kmcDPr08dcfeRpJSQsmbmdM_ZoYEQ zQ|@x*u2k+i<=(8^yOsN}a(5~B73IFC+|QId;1rd1bC0-d8@?tMD6D_^B%Vb_IW4!A&{#rGmd61D|G> z>F!r>GoNJ&J`}?oKFl|t%?j>JmfxJm=JPS&edW`R2F-Fcu94xyoHkxhSMaVMOSqVy z#_Mba&$>#&#auI9?^p0&t8~qBodAJC{I!iTyqF)xYo>z#PK9T^^5ME?hJRDR&GO!% z;C2kI_;AjL4{cuzUlIeqP?zv06x>t;Zc^|=3U2ZPlvsf$ZoI@xTR)!*An1ud4QeqT z6;1o4f-hEZGoKGD_|*zd+cux~6uep$)GY6D110|36oB?uJ{|>kr^@d(>1cN=ct;G} zjt)T3fd)D}%F%KZ{00Rmliu1N6uj*N37`#&57&ni&mk4QMuN5JgCu;#BnhCMh|g99 zU!WMAb{zBRi{DNdOy2~p?KD+T6*viS8+y4|`JO7^Cq?>66L$gN$047!Z%YXIfKMR| zJ;%w{9{-yV{uG37Z;;@-l<#i^o*qHP#~u~FMClX476>1%*C3wG1eyP_Dryqo%um}j z5>T$-=K?+!J1*Qx&u}aFwJLo3pCy3vD}4T-;Kdu{H|H(+3_^qIt6T;Bz#9Nhz)p_x z82Qb0_kH1cM8Jn>#hYY$oG0Uxg?zDGo$KWH`Kn!9D&P`k{U1=_OIApzSTly#oq&^W z#fv1I>xTKft-`0&%Wtmb;Sd1d_O#V;D95?gR_^b?ft#q^^0aqUurxNht+$rOh z2`Vp%xP4SFJ!P-JGfZs+~3psHV*Wob*gl{Qo@# zFIRB4f?FsqKd0alczzBc6p0UvXnV;JI z(o4*>;I))+d%R|jf6Rz0M0oQn>NYDp2{R=uQ+e@RHR9KrB_K<|w<>t;WfH)(etf=A z@M1-WItkVmVgMuZsXA(|>E#np@J59{SAw;B1zdetoUJN+!gCVXq5QrCocxe=f+U!j zPlMkKR5an5f{#_5^?$d*lQLZ57xTRcFbbw9;%}cOLz{AA zGT_AD>6LJ<_vUk{g4Y(vZ?1LcbDe^hd@R2?m&4~c$UWj|R~2%)1Z#uAc;wFx#h=9r zJ`3=^_=Nk1h^PB%8Sq{e{ssk)<>%k_gQue(_)Go3hhf0WbX%9m1REv!v;x3Mx7I-t zVCo^4nQ)$tif6lwrZt=JnDCngeig{#>>%8Z&eLrH;&rdWqp5lvtGo{bPPq}=KgOLT z^BF6zk^pD9vJ~H{>euEdc<0p;F~o~_N)(=0KD)c`ege2?7Y!0%>Q{G*@G6kS*`dOVjj@3LUHJ`y-a$NF@scoRyPE`fUwqDe zm3_f~2l#MUeHvrr?KXwK@k*KCQ!3q|Xm`|?V)c!aRC~;tAp@qV@Hryqxg^)$cr@JgNa_xir;(DKcqyiSTCZsQYL?@K+T6lzrd67(TmrD0#6+Uae1l*xZcMLWMi}s@E0JTIsSpu#;EY6jH zGe4~{a^NO~r}Zrvm}@xr8~{AQQojR?hQK(!TO} ziy2<&EnMHl=jndJpM083w^5brY#Cfzpx_+}UZmjl3ZC`81aOTEpEm_uzFYr0p-8Y? zom(W7>lFE%132rqB&L74RE00Dkm1Ds9lYKOxLbmH{J*y!_)djCR_=YN;IaHX`i#Em z+1d~M4gnvAbrCj^AFfT|^KZaeE=|cRb3Aosl5Fp-s=d2KX#A@xt*GXqDfJVV@^}e+ zOR*vx0qj6j{{Q7?4_m3(`#5bOQ2|RE=4Xb&C6Th>s7GHW@ZFo%KYEH zZ2s)I3k2aou9ULsr8wy$x71%6%|tmeQ7$r(nJ2t+YAOL*kmj?HCqu?ufb%>m%jDrA z(a`0V8d60vNsyXCy2>PrQ&VLE%X(%YGgkz$BwG=QKDoN4t_p_;T>%0%RQv0r*{(ny zEAsN9K{Mq^J|YQZb0H6-i3abPND9gZs;i<$QcFd}lA9JFy>Cx(v+A-dSJWuV16d3U zmoCVgKW9OzZ(>D#UFpOW&3Bc`akNBb%e*{X$;?e!8d55(sn5p=R^I4| zR`nJfX;T-J*VN(cn#f@`mVhSli+gib+9aSxlle|?#|l7j70<_-#dEDh_AD7zWM!6A zv;~uWW`R?Mz*|;!j4>n8CgaGeN|OeVe@9I(N^TtWLmsXAHm$1vT1(9UY0t%hLdXbf zj&h}UXiFAjrPI`g>e|w!m*v-${ip#FuA;2I_)@c|X%^81{AeikV6EQh&G05g1z*X! zh?YNw-BKr$Q|FhiVvgC1^v@x`dbk*Dv4r=VeL$F{zKfck~N)eKsKLR zQaPFn#hO(tZ>AaKa<->QmJTQ_#YA9fbXGJyqf!nM;n%j=bQLhBU0HurQgo&D zEzQ3ThDeo9sg(z539b_S9VMOFzLhPc$LnNf&+ znCSN9d3^cvvy1Y4p4|DGFZY7E*+t$Q%~w!3Z&r4pZ(e@>g1m*kh1s(T^L*$aQ@l6&TIN+9nDS4}r0P&wN4=8bCRU)E zQap{+Sa{w7f2P!OD{7$8_EvH8tOY=fV-;u&`oGX;DFRNCc}6!$Dx zeM`z#06mWVTw0z5;gCJc>r0(DNqH`>s1}12nJHh|#54#Fa9w3tbq`PvZC|C7IO{*9ip8XAN?bJeK69m%B9$u+mwY~dd0ovaAL?+0 zzuZ^GV{D7(EbYm6tecpWR25OM$dtaRaUwG^j$<=R_gPb%h(kxK%Bt$i{Jr_=o2G+& z7x^OR_<9SMq>_D5#42$0vicey&cR()S;iWlQc*94nwM8eX|b$VrHfEsZ%aWic3`QK zrD&FdxxfCvT5yswMx)3{&0Df$N#7nM{eNyH(sIwASXZ`uqR+Qt^=coqhWZ+|bN}VO zl^nUJ_BD(E9OcW5a8Jz&bXxr}&rw-EHDyUdMddOvQiE0-Ye~@16;@ZEswyj%@LcB7 zI=_!bwg_WPN@pI06reRp4UR7*Fm+j3rN30xr3JH+NI;6d=Ubaq7(2tNJ?7VyR+W7# zZ8WCFiTNAbvKVO!NVUuh^{t|`Qk;KWY_VdoK`pJlJVG~|6%0)%O^&e5AunWGKVv%! z{gh}!bc@LDJwoYIhJCFB>(%5;k*Fk%*^eIM$X;eL^%&H$bfITKE`YBm`Mgjw=0Wk| z(ZR6|G|Hn&oQjh6JU%)P(xp$WLKWki8&82Rm1dlynPwU0|F0nx(iSrBSk%!NidL_x zih-m~m3(QAn0pSYd-IyboFM4lbA$*@PKwZFmBlNoEPBnvOsx)v*JaBit%4ej;Ok>y z8HnZ>1q}`NTUmrrf__-ugu!kwqU(*}3#G-_r8Sd_0IcQeub! zj`&omdk)}Ir%2%`P2wD%M=~UFE-cFN<;~6YDgCV<9YJPZiDPLFw}=yqIG!7=SED#YMSMb*`D8%{Cy9h`xIx;TsW3Eno8E&G;d0>uebh-ZvUIl`=q8o zr~d|jOziKYSwbpltiVj6f5`?<-E3|{ zmDQ*j(Ia@l1Gy5t8*SC1hl2sQ_jFj#`aY^!*+WplTFCj)KFVELv$V9bj6BkVPRPwS zpKX!3OI00U&C%>JecFJQ3-d)EeUVu^)}eG?Tot27(nQjeVv6E@)+HvMqhc)eyO^P6 zou)^IRJqi}qy3i}MSlaD^-)Q4qxj7JQ1nYZ2SwkJwI5@UCH3`D?w%xj`neTLFcoXz z)!qW1+KEyXi!1n{Dzd7I0$yl!3t@02?_2Pw5%#x`O?kj7bg^SldwZ}w+DUzEBk9XB zmKw2)eeGffRl&!QlRoMf28vYE;Ku=AU1{CrLR;z4S|{Rq5UI2E)Lu*zjAV)4CJa>z zQ57mieKCzCjE})nRn1B@6i}8gX)%NF>dRi%dnj$uJ7spwW_`3)Ie$)%cF96~I~#q3 z2w!7Whh!=%t;>t_BIrqYlTHsd5ybw+9cJ3mI!vo*gWb|{^^bS<{5d`CgfNtU)5Oy` zGG@{A%c^5)4E31Q%wI0h8pgmXCRF?@; zHPEF_mcp{IMrNf?^OIFYPE#uKxz(#sJRg_mRH3GFaxkYOEH~e19#$6Un^Kl$JY_?f z-zRZ7W?fk0heZO*PAqDFRCJs3L288u^1+1>(vZ`K^nw5Xq4`ot5lDrelQMk>s&6}0 zA4$PFZPvR3F~>D>fxcCqS4?SiY+6-BwTO|Krc8~9 zn`2UkFxZ!e$5zTuX)vWY9I8z#aQ3EQpza&2M+BrL0E;*PqB zm=`OntJOrn^3wWpZQ`=atASLy{yOP{VIi-r>ha-&UtL*cDI=)2+Dbn$!e}tjU$z?m zg^6}zU5%KPoLE-wTTWZ3uY4KenqNS=6ei-;OUr8gSd#^vNo5psOlM+^mc-~Qt*a|V z5s1-zCst+w35e{LR#hwowi+aie-lM+WXjObG|a$PRh3oy&Gni8p^NPX;>-lKOja}Z zOPFp}41RNemI7@G&(L($^7crq*!`qjZObmfEmP$|LJTQ-*nwFTI7Fh z{CD9KkDp>Q%{NfD5EG1E1n U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Wed, 2 Jul 2025 17:25:34 +0200 Subject: [PATCH 037/283] remove leftover --- tools/compresSmol/compresSmol | Bin 100384 -> 0 bytes tools/compresSmol/compresSmolTilemap | Bin 104416 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tools/compresSmol/compresSmol delete mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol deleted file mode 100755 index c518f8381b4a471181752509730a92c1967e738b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100384 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 U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Thu, 3 Jul 2025 13:19:18 -0400 Subject: [PATCH 038/283] Fix redirection abilities triggering on self (#7276) Co-authored-by: ghoulslash --- src/battle_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index e4d43d7766..8adee1946f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7469,7 +7469,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_LIGHTNING_ROD); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); @@ -7483,7 +7483,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_STORM_DRAIN); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); From 31fc32ada8e511200e83252d2c8ac98b21514a07 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:16:40 -0400 Subject: [PATCH 039/283] Prevent AI Recursion (#7279) Co-authored-by: ghoulslash --- src/battle_ai_main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 18c140c2d2..1b8520fa5d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2047,7 +2047,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_COPYCAT: case EFFECT_MIRROR_MOVE: - return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + else + ADJUST_SCORE(-10); + break; case EFFECT_FLOWER_SHIELD: if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && !(isDoubleBattle && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) @@ -2312,7 +2316,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NATURE_POWER: - return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + predictedMove = GetNaturePowerMove(battlerAtk); + if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + break; case EFFECT_TAUNT: if (gDisableStructs[battlerDef].tauntTimer > 0 || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) @@ -2492,7 +2499,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (AI_IsSlower(battlerAtk, battlerDef, move)) ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail - else + else if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); } else @@ -3852,7 +3859,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_MIRROR_MOVE: - if (predictedMove != MOVE_NONE) + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckViability(battlerAtk, battlerDef, predictedMove, score); break; case EFFECT_ATTACK_UP: @@ -4116,7 +4123,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_MIMIC: if (AI_IsFaster(battlerAtk, battlerDef, move)) { - if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF) + if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF + && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); } break; From f74a23f44d1ccdf7f911608d6a9452dbd2bb8630 Mon Sep 17 00:00:00 2001 From: bassforte123 <130828119+bassforte123@users.noreply.github.com> Date: Fri, 4 Jul 2025 05:04:29 -0400 Subject: [PATCH 040/283] Typo fixes (#7280) --- test/battle/ability/liquid_ooze.c | 2 +- test/battle/status1/poison.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index 0e5a0c6cf7..fa8ca8e3b2 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -138,7 +138,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder" } } -SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+") +SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+)") { s16 damage; GIVEN { diff --git a/test/battle/status1/poison.c b/test/battle/status1/poison.c index 0a749ea96d..97b8782590 100644 --- a/test/battle/status1/poison.c +++ b/test/battle/status1/poison.c @@ -27,7 +27,6 @@ SINGLE_BATTLE_TEST("Poison can't bad poison a poison or steel type") GIVEN { ASSUME(GetMoveEffect(MOVE_POISON_GAS) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_GAS) == MOVE_EFFECT_POISON); - ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_GAS) == MOVE_EFFECT_POISON); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { From b3f52166dfaa2ce06ec20dd499aefc241acad6f1 Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 4 Jul 2025 05:06:36 -0400 Subject: [PATCH 041/283] Changing P_ONLY_OBTAINABLE_SHINIES to truly be Only Obtainable Shinies (#7275) --- include/config/pokemon.h | 2 +- src/pokemon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config/pokemon.h b/include/config/pokemon.h index 92b0f3bd64..fdee4e8ad2 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -58,7 +58,7 @@ #define P_CAN_FORGET_HIDDEN_MOVE FALSE // If TRUE, Pokémon can forget any move, even if it is a Hidden Move. #define P_ASK_MOVE_CONFIRMATION FALSE // If FALSE, when a player decides not to learn a Move, the game does not ask the player for confirmation. #define P_EGG_CYCLE_LENGTH GEN_LATEST // Since Gen 8, egg cycles take half as many steps as before. Previous Gens have some varied step counts around 255. -#define P_ONLY_OBTAINABLE_SHINIES FALSE // If TRUE, Pokémon encountered in the Battle Pyramid won't be shiny. +#define P_ONLY_OBTAINABLE_SHINIES FALSE // If TRUE, Pokémon encountered in the Battle Pyramid or while catching is disabled won't be shiny. #define P_NO_SHINIES_WITHOUT_POKEBALLS FALSE // If TRUE, Pokémon encountered when the player is out of Poké Balls won't be shiny #define P_SHOW_DYNAMIC_TYPES FALSE // If TRUE, all moves with dynamic type changes will be reflected as their current type in battle/summary screens instead of just select ones like in vanilla. diff --git a/src/pokemon.c b/src/pokemon.c index 12f2860435..1ed82d39c4 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -1081,7 +1081,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, { isShiny = TRUE; } - else if (P_ONLY_OBTAINABLE_SHINIES && InBattlePyramid()) + else if (P_ONLY_OBTAINABLE_SHINIES && (InBattlePyramid() || (B_FLAG_NO_CATCHING != 0 && FlagGet(B_FLAG_NO_CATCHING)))) { isShiny = FALSE; } From beb576f4c5b9dcac3d8ff1e4eb9e7bfe20837162 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 4 Jul 2025 11:11:21 +0200 Subject: [PATCH 042/283] Set BP of Gyro Ball for attackers with 0 speed to 1 (#7270) Co-authored-by: Hedara --- src/battle_util.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 8adee1946f..4f0ffcf962 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8183,10 +8183,20 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower = sSpeedDiffPowerTable[speed]; break; case EFFECT_GYRO_BALL: - basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / GetBattlerTotalSpeedStat(battlerAtk)) + 1; - if (basePower > 150) - basePower = 150; - break; + { + u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk); + if (attackerSpeed == 0) + { + basePower = 1; + } + else + { + basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / attackerSpeed) + 1; + if (basePower > 150) + basePower = 150; + } + break; + } case EFFECT_ECHOED_VOICE: // gBattleStruct->sameMoveTurns incremented in ppreduce if (gBattleStruct->sameMoveTurns[battlerAtk] != 0) From 5cfab59209b695c3eb3f0bc5f77adbd745b190f0 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 4 Jul 2025 18:11:32 +0200 Subject: [PATCH 043/283] Fix OOB in Cmd_selectfirstvalidtarget (#7269) --- src/battle_script_commands.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 10c81993e8..25edc5d759 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14530,6 +14530,8 @@ static void Cmd_selectfirstvalidtarget(void) if (IsBattlerAlive(gBattlerTarget)) break; } + if (gBattlerTarget >= gBattlersCount) + gBattlerTarget = 0; gBattlescriptCurrInstr = cmd->nextInstr; } From e8abfbce496a97f225938131017ec03c77ff4e2d Mon Sep 17 00:00:00 2001 From: Nephrite Date: Fri, 4 Jul 2025 18:07:53 +0100 Subject: [PATCH 044/283] Untangled TMs and HMs from item ids (#7173) --- include/constants/items.h | 3 - include/item.h | 124 ++++++++++++++++++++++++++++------- include/metaprogram.h | 24 ++++++- include/pokemon.h | 3 +- src/apprentice.c | 8 +-- src/battle_dome.c | 7 +- src/battle_script_commands.c | 2 +- src/battle_util.c | 2 +- src/data/items.h | 108 ------------------------------ src/daycare.c | 4 +- src/debug.c | 5 +- src/evolution_scene.c | 4 +- src/field_specials.c | 3 +- src/item.c | 25 ++++++- src/item_icon.c | 12 ++-- src/item_menu.c | 8 +-- src/item_use.c | 2 +- src/party_menu.c | 20 +----- src/pokedex_plus_hgss.c | 16 ++--- src/pokemon.c | 26 +++----- src/pokemon_summary_screen.c | 2 +- 21 files changed, 200 insertions(+), 208 deletions(-) diff --git a/include/constants/items.h b/include/constants/items.h index 0abfc31a44..58f453414f 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -1027,9 +1027,6 @@ #define MAIL_NONE 0xFF #define ITEM_TO_MULCH(itemId)(((itemId) - ITEM_GROWTH_MULCH) + 1) -#define NUM_TECHNICAL_MACHINES 100 -#define NUM_HIDDEN_MACHINES 8 - #define MAX_BAG_ITEM_CAPACITY 999 #define MAX_PC_ITEM_CAPACITY 999 #define MAX_PYRAMID_BAG_ITEM_CAPACITY 99 // Values higher than 255 require free SaveBlock2 space. diff --git a/include/item.h b/include/item.h index 7fcdb37fe3..b14d9bdf14 100644 --- a/include/item.h +++ b/include/item.h @@ -3,8 +3,44 @@ #include "constants/item.h" #include "constants/items.h" +#include "constants/moves.h" #include "constants/tms_hms.h" +/* Expands to: + * enum + * { + * ITEM_TM_FOCUS_PUNCH = ITEM_TM01, + * ... + * ITEM_HM_CUT = ITM_HM01, + * ... + * }; */ +#define ENUM_TM(n, id) CAT(ITEM_TM_, id) = CAT(ITEM_TM, n), +#define ENUM_HM(n, id) CAT(ITEM_HM_, id) = CAT(ITEM_HM, n), +#define TO_TMHM_NUMS(a, ...) (__VA_ARGS__) +enum TMHMItemId +{ + RECURSIVELY(R_ZIP(ENUM_TM, TO_TMHM_NUMS NUMBERS_256, (FOREACH_TM(APPEND_COMMA)))) + RECURSIVELY(R_ZIP(ENUM_HM, TO_TMHM_NUMS NUMBERS_256, (FOREACH_HM(APPEND_COMMA)))) +}; + +#undef ENUM_TM +#undef ENUM_HM +#undef TO_TMHM_NUMS + +/* Each of these TM_HM enums corresponds an index in the list of TMs + HMs item ids in + * gTMHMItemMoveIds. The index for an item can be retrieved with GetItemTMHMIndex below. + */ +#define UNPACK_TM_HM_ENUM(_tmHm) CAT(ENUM_TM_HM_, _tmHm), +enum TMHMIndex +{ + FOREACH_TMHM(UNPACK_TM_HM_ENUM) + NUM_ALL_MACHINES, + NUM_TECHNICAL_MACHINES = (0 FOREACH_TM(PLUS_ONE)), + NUM_HIDDEN_MACHINES = (0 FOREACH_HM(PLUS_ONE)), +}; + +#undef UNPACK_TM_HM_ENUM + typedef void (*ItemUseFunc)(u8); struct Item @@ -20,8 +56,8 @@ struct Item u8 holdEffectParam; u8 importance:2; u8 notConsumed:1; - u8 padding:5; - enum Pocket pocket:8; + enum Pocket pocket:5; + u8 padding; u8 type; u8 battleUsage; u8 flingPower; @@ -29,14 +65,75 @@ struct Item const u16 *iconPalette; }; -struct __attribute__((packed, aligned(2))) BagPocket +struct ALIGNED(2) BagPocket { struct ItemSlot *itemSlots; u16 capacity; }; +struct TmHmIndexKey +{ + enum TMHMItemId itemId:16; + u16 moveId; +}; + extern const struct Item gItemsInfo[]; extern struct BagPocket gBagPockets[]; +extern const struct TmHmIndexKey gTMHMItemMoveIds[]; + +#define UNPACK_ITEM_TO_TM_INDEX(_tm) case CAT(ITEM_TM_, _tm): return CAT(ENUM_TM_HM_, _tm) + 1; +#define UNPACK_ITEM_TO_HM_INDEX(_hm) case CAT(ITEM_HM_, _hm): return CAT(ENUM_TM_HM_, _hm) + 1; +#define UNPACK_ITEM_TO_TM_MOVE_ID(_tm) case CAT(ITEM_TM_, _tm): return CAT(MOVE_, _tm); +#define UNPACK_ITEM_TO_HM_MOVE_ID(_hm) case CAT(ITEM_HM_, _hm): return CAT(MOVE_, _hm); + +static inline enum TMHMIndex GetItemTMHMIndex(u16 item) +{ + switch (item) + { + /* Expands to: + * case ITEM_TM_FOCUS_PUNCH: + * return 1; + * case ITEM_TM_DRAGON_CLAW: + * return 2; + * etc */ + FOREACH_TM(UNPACK_ITEM_TO_TM_INDEX) + FOREACH_HM(UNPACK_ITEM_TO_HM_INDEX) + default: + return 0; + } +} + +static inline u16 GetItemTMHMMoveId(u16 item) +{ + switch (item) + { + /* Expands to: + * case ITEM_TM_FOCUS_PUNCH: + * return MOVE_FOCUS_PUNCH; + * case ITEM_TM_DRAGON_CLAW: + * return MOVE_DRAGON_CLAW; + * etc */ + FOREACH_TM(UNPACK_ITEM_TO_TM_MOVE_ID) + FOREACH_HM(UNPACK_ITEM_TO_HM_MOVE_ID) + default: + return MOVE_NONE; + } +} + +#undef UNPACK_ITEM_TO_TM_INDEX +#undef UNPACK_ITEM_TO_HM_INDEX +#undef UNPACK_ITEM_TO_TM_MOVE_ID +#undef UNPACK_ITEM_TO_HM_MOVE_ID + +static inline enum TMHMItemId GetTMHMItemId(enum TMHMIndex index) +{ + return gTMHMItemMoveIds[index].itemId; +} + +static inline u16 GetTMHMMoveId(enum TMHMIndex index) +{ + return gTMHMItemMoveIds[index].moveId; +} u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos); u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos); @@ -85,25 +182,4 @@ u32 GetItemStatus1Mask(u16 itemId); u32 GetItemStatus2Mask(u16 itemId); u32 GetItemSellPrice(u32 itemId); -/* Expands to: - * enum - * { - * ITEM_TM_FOCUS_PUNCH, - * ... - * ITEM_HM_CUT, - * ... - * }; */ -#define ENUM_TM(id) CAT(ITEM_TM_, id), -#define ENUM_HM(id) CAT(ITEM_HM_, id), -enum -{ - ENUM_TM_START_ = ITEM_TM01 - 1, - FOREACH_TM(ENUM_TM) - - ENUM_HM_START_ = ITEM_HM01 - 1, - FOREACH_HM(ENUM_HM) -}; -#undef ENUM_TM -#undef ENUM_HM - #endif // GUARD_ITEM_H diff --git a/include/metaprogram.h b/include/metaprogram.h index e12822946a..47fa99af72 100644 --- a/include/metaprogram.h +++ b/include/metaprogram.h @@ -26,8 +26,9 @@ #define STR(...) STR_(__VA_ARGS__) #define STR_(...) #__VA_ARGS__ -/* You'll never guess what this one does */ +/* You'll never guess what these do */ #define APPEND_SEMICOLON(a) a; +#define APPEND_COMMA(a) a, /* Converts a string to a compound literal, essentially making it a pointer to const u8 */ #define COMPOUND_STRING(str) (const u8[]) _(str) @@ -98,6 +99,21 @@ #define R_FOR_EACH_WITH_(macro, args, a, ...) INVOKE_WITH(macro, args, a) __VA_OPT__(R_FOR_EACH_WITH_P PARENS (macro, args, __VA_ARGS__)) #define R_FOR_EACH_WITH_P() R_FOR_EACH_WITH_ +/* Expands to 'macro(a, b)' for each 'a' in 'as' and 'b' in 'bs'. + * Uses the shorter of 'as' and 'bs'. (Credit to MGriffin) */ +#define R_ZIP(macro, as, bs) CAT(R_ZIP_, CAT(R_ZIP_NONEMPTY(as), R_ZIP_NONEMPTY(bs)))(macro, FIRST as, FIRST bs, (EXCEPT_1 as), (EXCEPT_1 bs)) +#define R_ZIP_00(macro, a, b, as, bs) +#define R_ZIP_01(macro, a, b, as, bs) +#define R_ZIP_10(macro, a, b, as, bs) +#define R_ZIP_11(macro, a, b, as, bs) macro(a, b) R_ZIP_P PARENS (macro, as, bs) +#define R_ZIP_P() R_ZIP + +#define R_ZIP_NONEMPTY(as) R_ZIP_NONEMPTY_ as +#define R_ZIP_NONEMPTY_(...) FIRST(__VA_OPT__(1,) 0) + +/* Just a lot of numbers (with leading zeroes - remove with REMOVE_LEADING_ZEROES) */ +#define NUMBERS_256 (00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255) + /* Picks the xth VA_ARG if it exists, otherwise returns a default value */ #define DEFAULT(_default, ...) FIRST(__VA_OPT__(__VA_ARGS__, ) _default) #define DEFAULT_2(_default, ...) DEFAULT(_default __VA_OPT__(, SECOND(__VA_ARGS__))) @@ -171,4 +187,10 @@ Input must be of the form (upper << lower) where upper can be up to 3, lower up /* Finds the required digits to display the number (maximum 4) */ #define MAX_DIGITS(_num) 1 + !!(_num / 10) + !!(_num / 100) + !!(_num / 1000) +/* Converts a number with leading zeroes to a normal int (base 10 and up to three digits only!) */ +#define REMOVE_LEADING_ZEROES(_num) (((0x##_num / 256) * 100) + ((0x##_num / 16) * 10) + (0x##_num % 16)) + +/* Useful for counting arguments */ +#define PLUS_ONE(...) + 1 + #endif diff --git a/include/pokemon.h b/include/pokemon.h index 3b4cc0715b..f6c242606f 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -824,7 +824,8 @@ void CreateTask_PlayMapChosenOrBattleBGM(u16 songId); const u16 *GetMonFrontSpritePal(struct Pokemon *mon); const u16 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality); const u16 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFemale); -bool8 IsMoveHM(u16 move); +bool32 IsMoveHM(u16 move); +bool32 CannotForgetMove(u16 move); bool8 IsMonSpriteNotFlipped(u16 species); s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor); s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor); diff --git a/src/apprentice.c b/src/apprentice.c index 4b0403b281..585b4eed43 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -353,14 +353,12 @@ static u16 GetRandomAlternateMove(u8 monId) // NOTE: Below is an infinite loop if a species which cannot learn TMs is assigned to an Apprentice do { - id = Random() % (NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES); - shouldUseMove = CanLearnTeachableMove(species, ItemIdToBattleMoveId(ITEM_TM01 + id)); + id = (Random() % NUM_ALL_MACHINES) + 1; + move = GetTMHMMoveId(id); + shouldUseMove = CanLearnTeachableMove(species, move); } while (!shouldUseMove); - move = ItemIdToBattleMoveId(ITEM_TM01 + id); - shouldUseMove = TRUE; - if (numLearnsetMoves <= MAX_MON_MOVES) j = 0; else diff --git a/src/battle_dome.c b/src/battle_dome.c index ff7fe4b8b0..68bd6af252 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -27,6 +27,7 @@ #include "sound.h" #include "pokemon_icon.h" #include "data.h" +#include "item.h" #include "international_string_util.h" #include "trainer_pokemon_sprites.h" #include "scanline_effect.h" @@ -3976,12 +3977,12 @@ static bool32 IsDomeLuckyMove(u32 move) static bool32 IsDomePopularMove(u32 move) { u8 i; - for (i = 0; i < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; i++) + for (i = 0; i < NUM_ALL_MACHINES; i++) { - if (ItemIdToBattleMoveId(ITEM_TM01 + i) == move) + if (GetTMHMMoveId(i + 1) == move) return TRUE; } - if (i == NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES) + if (i == NUM_ALL_MACHINES) return FALSE; // Filter in TMs/HMs if (GetMovePower(move) >= 90) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4372b09291..e49d824d75 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8497,7 +8497,7 @@ static void Cmd_yesnoboxlearnmove(void) else { u16 move = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MOVE1 + movePosition); - if (IsMoveHM(move)) + if (CannotForgetMove(move)) { PrepareStringBattle(STRINGID_HMMOVESCANTBEFORGOTTEN, B_POSITION_PLAYER_LEFT); gBattleScripting.learnMoveState = 6; diff --git a/src/battle_util.c b/src/battle_util.c index 31caab95a0..76786d1f44 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10445,7 +10445,7 @@ enum DamageCategory GetCategoryBasedOnStats(u32 battler) static u32 GetFlingPowerFromItemId(u32 itemId) { - if (itemId >= ITEM_TM01 && itemId <= ITEM_HM08) + if (gItemsInfo[itemId].pocket == POCKET_TM_HM) { u32 power = GetMovePower(ItemIdToBattleMoveId(itemId)); if (power > 1) diff --git a/src/data/items.h b/src/data/items.h index 187b4bc399..d1d7ae3125 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -10454,7 +10454,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FOCUS_PUNCH, }, [ITEM_TM_DRAGON_CLAW] = @@ -10469,7 +10468,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DRAGON_CLAW, }, [ITEM_TM_WATER_PULSE] = @@ -10484,7 +10482,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_WATER_PULSE, }, [ITEM_TM_CALM_MIND] = @@ -10499,7 +10496,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_CALM_MIND, }, [ITEM_TM_ROAR] = @@ -10514,7 +10510,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROAR, }, [ITEM_TM_TOXIC] = @@ -10529,7 +10524,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TOXIC, }, [ITEM_TM_HAIL] = @@ -10551,7 +10545,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HAIL, }, [ITEM_TM_BULK_UP] = @@ -10566,7 +10559,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BULK_UP, }, [ITEM_TM_BULLET_SEED] = @@ -10581,7 +10573,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BULLET_SEED, }, [ITEM_TM_HIDDEN_POWER] = @@ -10596,7 +10587,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HIDDEN_POWER, }, [ITEM_TM_SUNNY_DAY] = @@ -10611,7 +10601,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SUNNY_DAY, }, [ITEM_TM_TAUNT] = @@ -10626,7 +10615,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TAUNT, }, [ITEM_TM_ICE_BEAM] = @@ -10645,7 +10633,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ICE_BEAM, }, [ITEM_TM_BLIZZARD] = @@ -10666,7 +10653,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BLIZZARD, }, [ITEM_TM_HYPER_BEAM] = @@ -10681,7 +10667,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_HYPER_BEAM, }, [ITEM_TM_LIGHT_SCREEN] = @@ -10696,7 +10681,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_LIGHT_SCREEN, }, [ITEM_TM_PROTECT] = @@ -10711,7 +10695,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_PROTECT, }, [ITEM_TM_RAIN_DANCE] = @@ -10726,7 +10709,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_RAIN_DANCE, }, [ITEM_TM_GIGA_DRAIN] = @@ -10741,7 +10723,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_GIGA_DRAIN, }, [ITEM_TM_SAFEGUARD] = @@ -10756,7 +10737,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SAFEGUARD, }, [ITEM_TM_FRUSTRATION] = @@ -10771,7 +10751,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FRUSTRATION, }, [ITEM_TM_SOLAR_BEAM] = @@ -10786,7 +10765,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SOLAR_BEAM, }, [ITEM_TM_IRON_TAIL] = @@ -10801,7 +10779,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_IRON_TAIL, }, [ITEM_TM_THUNDERBOLT] = @@ -10816,7 +10793,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THUNDERBOLT, }, [ITEM_TM_THUNDER] = @@ -10831,7 +10807,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THUNDER, }, [ITEM_TM_EARTHQUAKE] = @@ -10846,7 +10821,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_EARTHQUAKE, }, [ITEM_TM_RETURN] = @@ -10861,7 +10835,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_RETURN, }, [ITEM_TM_DIG] = @@ -10876,7 +10849,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DIG, }, [ITEM_TM_PSYCHIC] = @@ -10891,7 +10863,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_PSYCHIC, }, [ITEM_TM_SHADOW_BALL] = @@ -10906,7 +10877,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SHADOW_BALL, }, [ITEM_TM_BRICK_BREAK] = @@ -10921,7 +10891,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_BRICK_BREAK, }, [ITEM_TM_DOUBLE_TEAM] = @@ -10936,7 +10905,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DOUBLE_TEAM, }, [ITEM_TM_REFLECT] = @@ -10951,7 +10919,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_REFLECT, }, [ITEM_TM_SHOCK_WAVE] = @@ -10966,7 +10933,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SHOCK_WAVE, }, [ITEM_TM_FLAMETHROWER] = @@ -10981,7 +10947,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLAMETHROWER, }, [ITEM_TM_SLUDGE_BOMB] = @@ -10996,7 +10961,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SLUDGE_BOMB, }, [ITEM_TM_SANDSTORM] = @@ -11011,7 +10975,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SANDSTORM, }, [ITEM_TM_FIRE_BLAST] = @@ -11026,7 +10989,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FIRE_BLAST, }, [ITEM_TM_ROCK_TOMB] = @@ -11041,7 +11003,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROCK_TOMB, }, [ITEM_TM_AERIAL_ACE] = @@ -11056,7 +11017,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_AERIAL_ACE, }, [ITEM_TM_TORMENT] = @@ -11071,7 +11031,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_TORMENT, }, [ITEM_TM_FACADE] = @@ -11086,7 +11045,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FACADE, }, [ITEM_TM_SECRET_POWER] = @@ -11101,7 +11059,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SECRET_POWER, }, [ITEM_TM_REST] = @@ -11116,7 +11073,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_REST, }, [ITEM_TM_ATTRACT] = @@ -11131,7 +11087,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ATTRACT, }, [ITEM_TM_THIEF] = @@ -11146,7 +11101,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_THIEF, }, [ITEM_TM_STEEL_WING] = @@ -11161,7 +11115,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_STEEL_WING, }, [ITEM_TM_SKILL_SWAP] = @@ -11176,7 +11129,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SKILL_SWAP, }, [ITEM_TM_SNATCH] = @@ -11191,7 +11143,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SNATCH, }, [ITEM_TM_OVERHEAT] = @@ -11206,7 +11157,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_OVERHEAT, }, [ITEM_TM51] = @@ -11218,7 +11168,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM52] = @@ -11230,7 +11179,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM53] = @@ -11242,7 +11190,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM54] = @@ -11254,7 +11201,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM55] = @@ -11266,7 +11212,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM56] = @@ -11278,7 +11223,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM57] = @@ -11290,7 +11234,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM58] = @@ -11302,7 +11245,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM59] = @@ -11314,7 +11256,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM60] = @@ -11326,7 +11267,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM61] = @@ -11338,7 +11278,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM62] = @@ -11350,7 +11289,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM63] = @@ -11362,7 +11300,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM64] = @@ -11374,7 +11311,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM65] = @@ -11386,7 +11322,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM66] = @@ -11398,7 +11333,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM67] = @@ -11410,7 +11344,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM68] = @@ -11422,7 +11355,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM69] = @@ -11434,7 +11366,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM70] = @@ -11446,7 +11377,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM71] = @@ -11458,7 +11388,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM72] = @@ -11470,7 +11399,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM73] = @@ -11482,7 +11410,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM74] = @@ -11494,7 +11421,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM75] = @@ -11506,7 +11432,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM76] = @@ -11518,7 +11443,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM77] = @@ -11530,7 +11454,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM78] = @@ -11542,7 +11465,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM79] = @@ -11554,7 +11476,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM80] = @@ -11566,7 +11487,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM81] = @@ -11578,7 +11498,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM82] = @@ -11590,7 +11509,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM83] = @@ -11602,7 +11520,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM84] = @@ -11614,7 +11531,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM85] = @@ -11626,7 +11542,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM86] = @@ -11638,7 +11553,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM87] = @@ -11650,7 +11564,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM88] = @@ -11662,7 +11575,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM89] = @@ -11674,7 +11586,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM90] = @@ -11686,7 +11597,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM91] = @@ -11698,7 +11608,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM92] = @@ -11710,7 +11619,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM93] = @@ -11722,7 +11630,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM94] = @@ -11734,7 +11641,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM95] = @@ -11746,7 +11652,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM96] = @@ -11758,7 +11663,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM97] = @@ -11770,7 +11674,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM98] = @@ -11782,7 +11685,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM99] = @@ -11794,7 +11696,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_TM100] = @@ -11806,7 +11707,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_NONE, // Todo }, [ITEM_HM_CUT] = @@ -11821,7 +11721,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_CUT, }, [ITEM_HM_FLY] = @@ -11836,7 +11735,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLY, }, [ITEM_HM_SURF] = @@ -11851,7 +11749,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_SURF, }, [ITEM_HM_STRENGTH] = @@ -11866,7 +11763,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_STRENGTH, }, [ITEM_HM_FLASH] = @@ -11881,7 +11777,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_FLASH, }, [ITEM_HM_ROCK_SMASH] = @@ -11896,7 +11791,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_ROCK_SMASH, }, [ITEM_HM_WATERFALL] = @@ -11911,7 +11805,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_WATERFALL, }, [ITEM_HM_DIVE] = @@ -11926,7 +11819,6 @@ const struct Item gItemsInfo[] = .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, - .secondaryId = MOVE_DIVE, }, diff --git a/src/daycare.c b/src/daycare.c index e2f6f8f070..fdb98d6630 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -895,9 +895,9 @@ static void BuildEggMoveset(struct Pokemon *egg, struct BoxPokemon *father, stru { if (sHatchedEggFatherMoves[i] != MOVE_NONE) { - for (j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++) + for (j = 0; j < NUM_ALL_MACHINES; j++) { - u16 moveId = ItemIdToBattleMoveId(ITEM_TM01 + j); + u16 moveId = GetTMHMMoveId(j + 1); if (sHatchedEggFatherMoves[i] == moveId && CanLearnTeachableMove(GetMonData(egg, MON_DATA_SPECIES_OR_EGG), moveId)) { if (GiveMoveToMon(egg, sHatchedEggFatherMoves[i]) == MON_HAS_MAX_MOVES) diff --git a/src/debug.c b/src/debug.c index e46c5c5062..3f970ae7fc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -3236,10 +3236,11 @@ static void DebugAction_PCBag_Fill_PocketPokeBalls(u8 taskId) static void DebugAction_PCBag_Fill_PocketTMHM(u8 taskId) { - u16 itemId; + u16 index, itemId; - for (itemId = ITEM_TM01; itemId <= ITEM_HM08; itemId++) + for (index = 0; index < NUM_ALL_MACHINES; index++) { + itemId = GetTMHMItemId(index + 1); if (CheckBagHasSpace(itemId, 1) && ItemIdToBattleMoveId(itemId) != MOVE_NONE) AddBagItem(itemId, 1); } diff --git a/src/evolution_scene.c b/src/evolution_scene.c index c746414958..1f9d2af8fa 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -992,7 +992,7 @@ static void Task_EvolutionScene(u8 taskId) { // Selected move to forget u16 move = GetMonData(mon, var + MON_DATA_MOVE1); - if (IsMoveHM(move)) + if (CannotForgetMove(move)) { // Can't forget HMs BattleStringExpandPlaceholdersToDisplayedString(gBattleStringsTable[STRINGID_HMMOVESCANTBEFORGOTTEN]); @@ -1376,7 +1376,7 @@ static void Task_TradeEvolutionScene(u8 taskId) { // Selected move to forget u16 move = GetMonData(mon, var + MON_DATA_MOVE1); - if (IsMoveHM(move)) + if (CannotForgetMove(move)) { // Can't forget HMs BattleStringExpandPlaceholdersToDisplayedString(gBattleStringsTable[STRINGID_HMMOVESCANTBEFORGOTTEN]); diff --git a/src/field_specials.c b/src/field_specials.c index 0ac0d9fa68..927326e399 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -19,6 +19,7 @@ #include "field_weather.h" #include "graphics.h" #include "international_string_util.h" +#include "item.h" #include "item_icon.h" #include "link.h" #include "load_save.h" @@ -1671,7 +1672,7 @@ u16 GetMysteryGiftCardStat(void) bool8 BufferTMHMMoveName(void) { - if (gSpecialVar_0x8004 >= ITEM_TM01 && gSpecialVar_0x8004 <= ITEM_HM08) + if (gItemsInfo[gSpecialVar_0x8004].pocket == POCKET_TM_HM) { StringCopy(gStringVar2, GetMoveName(ItemIdToBattleMoveId(gSpecialVar_0x8004))); return TRUE; diff --git a/src/item.c b/src/item.c index fb470866bc..f0f9071c5a 100644 --- a/src/item.c +++ b/src/item.c @@ -31,6 +31,27 @@ EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; #include "data/pokemon/item_effects.h" #include "data/items.h" +#define UNPACK_TM_ITEM_ID(_tm) [CAT(ENUM_TM_HM_, _tm) + 1] = { CAT(ITEM_TM_, _tm), CAT(MOVE_, _tm) }, +#define UNPACK_HM_ITEM_ID(_hm) [CAT(ENUM_TM_HM_, _hm) + 1] = { CAT(ITEM_HM_, _hm), CAT(MOVE_, _hm) }, + +const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = +{ + [0] = { ITEM_NONE, MOVE_NONE }, // Failsafe + FOREACH_TM(UNPACK_TM_ITEM_ID) + FOREACH_HM(UNPACK_HM_ITEM_ID) + /* + * Expands to the following: + * + * [1] = { ITEM_TM_FOCUS_PUNCH, MOVE_FOCUS_PUNCH }, + * [2] = { ITEM_TM_DRAGON_CLAW, MOVE_DRAGON_CLAW }, + * [3] = { ITEM_TM_WATER_PULSE, MOVE_WATER_PULSE }, + * etc etc + */ +}; + +#undef UNPACK_TM_ITEM_ID +#undef UNPACK_HM_ITEM_ID + static inline u16 GetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos) { return pocket->itemSlots[pocketPos].itemId; @@ -592,7 +613,9 @@ void SortBerriesOrTMHMs(enum Pocket pocketId) { if (GetBagItemQuantity(pocketId, j) == 0 || GetBagItemId(pocketId, j) == ITEM_NONE) continue; - if (GetBagItemId(pocketId, i) <= GetBagItemId(pocketId, j)) + if (pocketId == POCKET_BERRIES && GetBagItemId(pocketId, i) <= GetBagItemId(pocketId, j)) // To do + continue; + if (pocketId == POCKET_TM_HM && GetItemTMHMIndex(GetBagItemId(pocketId, i)) <= GetItemTMHMIndex(GetBagItemId(pocketId, j))) continue; } SwapItemSlots(pocketId, i, j); diff --git a/src/item_icon.c b/src/item_icon.c index a218ebaf8e..8d4ff3223d 100644 --- a/src/item_icon.c +++ b/src/item_icon.c @@ -166,11 +166,11 @@ const void *GetItemIconPic(u16 itemId) return gItemIcon_ReturnToFieldArrow; // Use last icon, the "return to field" arrow if (itemId >= ITEMS_COUNT) return gItemsInfo[0].iconPic; - if (itemId >= ITEM_TM01 && itemId < ITEM_HM01 + NUM_HIDDEN_MACHINES) + if (gItemsInfo[itemId].pocket == POCKET_TM_HM) { - if (itemId < ITEM_TM01 + NUM_TECHNICAL_MACHINES) - return gItemIcon_TM; - return gItemIcon_HM; + if (GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) + return gItemIcon_HM; + return gItemIcon_TM; } return gItemsInfo[itemId].iconPic; @@ -182,8 +182,8 @@ const u16 *GetItemIconPalette(u16 itemId) return gItemIconPalette_ReturnToFieldArrow; if (itemId >= ITEMS_COUNT) return gItemsInfo[0].iconPalette; - if (itemId >= ITEM_TM01 && itemId < ITEM_HM01 + NUM_HIDDEN_MACHINES) - return gTypesInfo[GetMoveType(gItemsInfo[itemId].secondaryId)].paletteTMHM; + if (gItemsInfo[itemId].pocket == POCKET_TM_HM) + return gTypesInfo[GetMoveType(GetItemTMHMMoveId(itemId))].paletteTMHM; return gItemsInfo[itemId].iconPalette; } diff --git a/src/item_menu.c b/src/item_menu.c index aa241b7c75..647b99eb2d 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -916,16 +916,16 @@ static void GetItemNameFromPocket(u8 *dest, u16 itemId) case POCKET_TM_HM: end = StringCopy(gStringVar2, GetMoveName(ItemIdToBattleMoveId(itemId))); PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 61); - if (itemId >= ITEM_HM01) + if (GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) { // Get HM number - ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_HM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 1); + ConvertIntToDecimalStringN(gStringVar1, GetItemTMHMIndex(itemId) - NUM_TECHNICAL_MACHINES, STR_CONV_MODE_LEADING_ZEROS, 1); StringExpandPlaceholders(dest, gText_NumberItem_HM); } else { // Get TM number - ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_TM01 + 1, STR_CONV_MODE_LEADING_ZEROS, 2); + ConvertIntToDecimalStringN(gStringVar1, GetItemTMHMIndex(itemId), STR_CONV_MODE_LEADING_ZEROS, 2); StringExpandPlaceholders(dest, gText_NumberItem_TMBerry); } break; @@ -983,7 +983,7 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) itemQuantity = GetBagItemQuantity(gBagPosition.pocket, itemIndex); // Draw HM icon - if (itemId >= ITEM_HM01 && itemId <= ITEM_HM08) + if (gBagPosition.pocket == POCKET_TM_HM && GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) BlitBitmapToWindow(windowId, gBagMenuHMIcon_Gfx, 8, y - 1, 16, 16); if (gBagPosition.pocket != POCKET_KEY_ITEMS && GetItemImportance(itemId) == FALSE) diff --git a/src/item_use.c b/src/item_use.c index ad0fb47565..9df366e595 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -884,7 +884,7 @@ void ItemUseOutOfBattle_DynamaxCandy(u8 taskId) void ItemUseOutOfBattle_TMHM(u8 taskId) { - if (gSpecialVar_ItemId >= ITEM_HM01) + if (GetItemTMHMIndex(gSpecialVar_ItemId) > NUM_TECHNICAL_MACHINES) DisplayItemMessage(taskId, FONT_NORMAL, sText_BootedUpHM, BootUpSoundTMHM); // HM else DisplayItemMessage(taskId, FONT_NORMAL, sText_BootedUpTM, BootUpSoundTMHM); // TM diff --git a/src/party_menu.c b/src/party_menu.c index 0954715a5d..16ea3522d7 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -158,14 +158,6 @@ enum { #define MENU_DIR_RIGHT 2 #define MENU_DIR_LEFT -2 -#define HM_MOVES_END 0xFFFF - -static const u16 sHMMoves[] = -{ - MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH, - MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END -}; - enum { CAN_LEARN_MOVE, CANNOT_LEARN_MOVE, @@ -1567,14 +1559,8 @@ static bool8 DoesSelectedMonKnowHM(u8 *slotPtr) for (u32 i = 0; i < MAX_MON_MOVES; i++) { - u32 j = 0; - u16 move = GetMonData(&gPlayerParty[*slotPtr], MON_DATA_MOVE1 + i); - - while (sHMMoves[j] != HM_MOVES_END) - { - if (sHMMoves[j++] == move) - return TRUE; - } + if (IsMoveHM(GetMonData(&gPlayerParty[*slotPtr], MON_DATA_MOVE1 + i))) + return TRUE; } return FALSE; } @@ -5355,7 +5341,7 @@ void ItemUseCB_PPUp(u8 taskId, TaskFunc task) u16 ItemIdToBattleMoveId(u16 item) { - return (GetItemPocket(item) == POCKET_TM_HM) ? gItemsInfo[item].secondaryId : MOVE_NONE; + return (GetItemPocket(item) == POCKET_TM_HM) ? GetItemTMHMMoveId(item) : MOVE_NONE; } bool8 MonKnowsMove(struct Pokemon *mon, u16 move) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index d986ce63af..db7ff38ee0 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -290,9 +290,9 @@ static EWRAM_DATA u16 sLastSelectedPokemon = 0; static EWRAM_DATA u8 sPokeBallRotation = 0; static EWRAM_DATA struct PokedexListItem *sPokedexListItem = NULL; //Pokedex Plus HGSS_Ui -#define MOVES_COUNT_TOTAL (EGG_MOVES_ARRAY_COUNT + MAX_LEVEL_UP_MOVES + NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES) +#define MOVES_COUNT_TOTAL (EGG_MOVES_ARRAY_COUNT + MAX_LEVEL_UP_MOVES + NUM_ALL_MACHINES) EWRAM_DATA static u16 sStatsMoves[MOVES_COUNT_TOTAL] = {0}; -EWRAM_DATA static u16 sStatsMovesTMHM_ID[NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES] = {0}; +EWRAM_DATA static u16 sStatsMovesTMHM_ID[NUM_ALL_MACHINES] = {0}; struct SearchOptionText @@ -5054,13 +5054,13 @@ static u16 AddTMTutorMoves(u16 species, u16 movesTotal, u8 *numTMHMMoves, u8 *nu // TM Moves if (HGSS_SORT_TMS_BY_NUM) { - for (i = 0; i < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; i++) + for (i = 0; i < NUM_ALL_MACHINES; i++) { - move = ItemIdToBattleMoveId(ITEM_TM01 + i); + move = GetTMHMMoveId(i + 1); if (move != MOVE_NONE && CanLearnTeachableMove(species, move)) { isTMMove[move] = TRUE; - sStatsMovesTMHM_ID[*numTMHMMoves] = ITEM_TM01 + i; + sStatsMovesTMHM_ID[*numTMHMMoves] = GetTMHMItemId(i + 1); (*numTMHMMoves)++; sStatsMoves[movesTotal] = move; movesTotal++; @@ -5072,12 +5072,12 @@ static u16 AddTMTutorMoves(u16 species, u16 movesTotal, u8 *numTMHMMoves, u8 *nu for (i = 0; teachableLearnset[i] != MOVE_UNAVAILABLE; i++) { move = teachableLearnset[i]; - for (u16 j = 0; j < NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES; j++) + for (u16 j = 0; j < NUM_ALL_MACHINES; j++) { - if (ItemIdToBattleMoveId(ITEM_TM01 + j) == move) + if (GetTMHMMoveId(j + 1) == move) { isTMMove[move] = TRUE; - sStatsMovesTMHM_ID[*numTMHMMoves] = ITEM_TM01 + j; + sStatsMovesTMHM_ID[*numTMHMMoves] = GetTMHMItemId(j + 1); (*numTMHMMoves)++; sStatsMoves[movesTotal] = move; movesTotal++; diff --git a/src/pokemon.c b/src/pokemon.c index 1ed82d39c4..4a3b0bf706 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -871,14 +871,6 @@ static const s8 sFriendshipEventModifiers[][3] = [FRIENDSHIP_EVENT_FAINT_LARGE] = {-5, -5, -10}, }; -#define HM_MOVES_END 0xFFFF - -static const u16 sHMMoves[] = -{ - MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH, - MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END -}; - static const struct SpeciesItem sAlteringCaveWildMonHeldItems[] = { {SPECIES_NONE, ITEM_NONE}, @@ -5947,19 +5939,21 @@ const u16 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFema } } -bool8 IsMoveHM(u16 move) +#define OR_MOVE_IS_HM(_hm) || (move == MOVE_##_hm) + +bool32 IsMoveHM(u16 move) { - int i = 0; + return FALSE FOREACH_HM(OR_MOVE_IS_HM); +} +#undef OR_MOVE_IS_HM + +bool32 CannotForgetMove(u16 move) +{ if (P_CAN_FORGET_HIDDEN_MOVE) return FALSE; - while (sHMMoves[i] != HM_MOVES_END) - { - if (sHMMoves[i++] == move) - return TRUE; - } - return FALSE; + return IsMoveHM(move); } bool8 IsMonSpriteNotFlipped(u16 species) diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 3bf7c0aac4..b63f6d17eb 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -2609,7 +2609,7 @@ static bool8 CanReplaceMove(void) { if (sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES || sMonSummaryScreen->newMove == MOVE_NONE - || IsMoveHM(sMonSummaryScreen->summary.moves[sMonSummaryScreen->firstMoveIndex]) != TRUE) + || !CannotForgetMove(sMonSummaryScreen->summary.moves[sMonSummaryScreen->firstMoveIndex])) return TRUE; else return FALSE; From c6a62758a2c608e329308242344e400dd8a51298 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 5 Jul 2025 07:45:20 -0400 Subject: [PATCH 045/283] Use compound strings in battle debug menu (#7282) --- src/battle_debug.c | 379 +++++++++++++++------------------------------ 1 file changed, 122 insertions(+), 257 deletions(-) diff --git a/src/battle_debug.c b/src/battle_debug.c index b91ca4b5e4..a98b3a12a5 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -263,145 +263,10 @@ enum static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect); // const rom data -static const u8 sText_Moves[] = _("Moves"); static const u8 sText_Ability[] = _("Ability"); static const u8 sText_HeldItem[] = _("Held Item"); static const u8 sText_HoldEffect[] = _("Hold Effect"); -static const u8 sText_PP[] = _("PP"); -static const u8 sText_Types[] = _("Types"); -static const u8 sText_Stats[] = _("Stats"); -static const u8 sText_StatStages[] = _("Stat Stages"); -static const u8 sText_Status1[] = _("Status1"); -static const u8 sText_VolatileStatus[] = _("Volatiles"); -static const u8 sText_Status3[] = _("Status3"); -static const u8 sText_Status4[] = _("Status4"); -static const u8 sText_SideStatus[] = _("Side Status"); -static const u8 sText_AI[] = _("AI"); -static const u8 sText_AIMovePts[] = _("AI Pts/Dmg"); -static const u8 sText_AiKnowledge[] = _("AI Info"); -static const u8 sText_AiParty[] = _("AI Party"); -static const u8 sText_Various[] = _("Various"); -static const u8 sText_CurrHp[] = _("HP Current"); -static const u8 sText_MaxHp[] = _("HP Max"); -static const u8 sText_Attack[] = _("Attack"); -static const u8 sText_Defense[] = _("Defense"); -static const u8 sText_Speed[] = _("Speed"); -static const u8 sText_SpAtk[] = _("Sp. Atk"); -static const u8 sText_SpDef[] = _("Sp. Def"); -static const u8 sText_Sleep[] = _("Sleep"); -static const u8 sText_Poison[] = _("Poison"); -static const u8 sText_Burn[] = _("Burn"); -static const u8 sText_Freeze[] = _("Freeze"); -static const u8 sText_Paralysis[] = _("Paralysis"); -static const u8 sText_ToxicPoison[] = _("Toxic Poison"); -static const u8 sText_ToxicCounter[] = _("Toxic Counter"); -static const u8 sText_Frostbite[] = _("Frostbite"); -static const u8 sText_Confusion[] = _("Confusion"); -static const u8 sText_Flinched[] = _("Flinched"); -static const u8 sText_Uproar[] = _("Uproar"); -static const u8 sText_Torment[] = _("Torment"); -static const u8 sText_Bide[] = _("Bide"); -static const u8 sText_LockConfuse[] = _("Lock Confuse"); -static const u8 sText_MultipleTurns[] = _("Multiple Turns"); -static const u8 sText_Wrapped[] = _("Wrapped"); -static const u8 sText_Powder[] = _("Powder"); -static const u8 sText_Infatuation[] = _("Infatuation"); -static const u8 sText_DefenseCurl[] = _("Defense Curl"); -static const u8 sText_Transformed[] = _("Transformed"); -static const u8 sText_Recharge[] = _("Recharge"); -static const u8 sText_Rage[] = _("Rage"); -static const u8 sText_Substitute[] = _("Substitute"); -static const u8 sText_DestinyBond[] = _("Destiny Bond"); -static const u8 sText_EscapePrevention[] = _("Escape Prevention"); -static const u8 sText_Nightmare[] = _("Nightmare"); -static const u8 sText_Cursed[] = _("Cursed"); -static const u8 sText_Foresight[] = _("Foresight"); -static const u8 sText_DragonCheer[] = _("Dragon Cheer"); -static const u8 sText_FocusEnergy[] = _("Focus Energy"); -static const u8 sText_LeechSeedHealer[] = _("Leech Seed Healer"); -static const u8 sText_LeechSeeded[] = _("Leech Seeded"); -static const u8 sText_AlwaysHits[] = _("Always Hits"); -static const u8 sText_PerishSong[] = _("Perish Song"); -static const u8 sText_OnAir[] = _("On Air"); -static const u8 sText_Underground[] = _("Underground"); -static const u8 sText_Minimized[] = _("Minimized"); -static const u8 sText_ChargedUp[] = _("Charged Up"); -static const u8 sText_Rooted[] = _("Rooted"); -static const u8 sText_Yawn[] = _("Yawn"); -static const u8 sText_ImprisonedOthers[] = _("Imprisoned Others"); -static const u8 sText_Grudge[] = _("Grudge"); -static const u8 sText_GastroAcid[] = _("Gastro Acid"); -static const u8 sText_Embargo[] = _("Embargo"); -static const u8 sText_Underwater[] = _("Underwater"); -static const u8 sText_Trace[] = _("Trace"); -static const u8 sText_SmackedDown[] = _("Smacked Down"); -static const u8 sText_MeFirst[] = _("Me First"); -static const u8 sText_Telekinesis[] = _("Telekinesis"); -static const u8 sText_PhantomForce[] = _("Phantom Force"); -static const u8 sText_MiracleEyed[] = _("Miracle Eyed"); -static const u8 sText_MagnetRise[] = _("Magnet Rise"); -static const u8 sText_HealBlock[] = _("Heal Block"); -static const u8 sText_AquaRing[] = _("Aqua Ring"); -static const u8 sText_LaserFocus[] = _("Laser Focus"); -static const u8 sText_PowerTrick[] = _("Power Trick"); -static const u8 sText_SkyDropped[] = _("Sky Dropped"); -static const u8 sText_Electrified[] = _("Electrified"); -static const u8 sText_InfiniteConfusion[] = _("Infinite Confusion"); -static const u8 sText_SaltCure[] = _("Salt Cure"); -static const u8 sText_SyrupBomb[] = _("Syrup Bomb"); -static const u8 sText_GlaiveRush[] = _("Glaive Rush"); -static const u8 sText_Reflect[] = _("Reflect"); -static const u8 sText_LightScreen[] = _("Light Screen"); -static const u8 sText_StickyWeb[] = _("Sticky Web"); -static const u8 sText_Spikes[] = _("Spikes"); -static const u8 sText_Safeguard[] = _("Safeguard"); -static const u8 sText_FutureAttack[] = _("Future Attack"); -static const u8 sText_Mist[] = _("Mist"); -static const u8 sText_Tailwind[] = _("Tailwind"); -static const u8 sText_AuroraVeil[] = _("Aurora Veil"); -static const u8 sText_LuckyChant[] = _("Lucky Chant"); -static const u8 sText_ToxicSpikes[] = _("Toxic Spikes"); -static const u8 sText_StealthRock[] = _("Stealth Rock"); -static const u8 sText_Steelsurge[] = _("Steelsurge"); -static const u8 sText_DamageNonTypes[] = _("Damage Non-Types"); -static const u8 sText_Rainbow[] = _("Rainbow"); -static const u8 sText_SeaOfFire[] = _("Sea of Fire"); -static const u8 sText_Swamp[] = _("Swamp"); -static const u8 sText_CheckBadMove[] = _("Check Bad Move"); -static const u8 sText_TryToFaint[] = _("Try to Faint"); -static const u8 sText_CheckViability[] = _("Check Viability"); -static const u8 sText_ForceSetupFirstTurn[] = _("Force Setup First Turn"); -static const u8 sText_Risky[] = _("Risky"); -static const u8 sText_TryTo2HKO[] = _("Try to 2HKO"); -static const u8 sText_PreferBatonPass[] = _("Prefer Baton Pass"); -static const u8 sText_DoubleBattle[] = _("Double Battle"); -static const u8 sText_HpAware[] = _("HP Aware"); -static const u8 sText_PowerfulStatus[] = _("Powerful Status"); -static const u8 sText_NegateUnaware[] = _("Negate Unaware"); -static const u8 sText_WillSuicide[] = _("Will Suicide"); -static const u8 sText_PreferStatusMoves[] = _("Prefer Status Moves"); -static const u8 sText_Stall[] = _("Stall"); -static const u8 sText_SmartSwitching[] = _("Smart Switching"); -static const u8 sText_AcePokemon[] = _("Ace Pokémon"); -static const u8 sText_Omniscient[] = _("Omniscient"); -static const u8 sText_SmartMonChoices[] = _("Smart Mon Choices"); -static const u8 sText_Conservative[] = _("Conservative"); -static const u8 sText_SequenceSwitching[] = _("Sequence Switching"); -static const u8 sText_DoubleAcePokemon[] = _("Double Ace Pokémon"); -static const u8 sText_WeighAbilityPrediction[] = _("Weigh Ability Prediction"); -static const u8 sText_PreferHighestDamageMove[] = _("Prefer Highest Damage Move"); -static const u8 sText_PredictSwitch[] = _("Predict Switch"); -static const u8 sText_PredictIncomingMon[] = _("Predict Incoming Mon"); -static const u8 sText_DynamicFunc[] = _("Dynamic Func"); -static const u8 sText_Roaming[] = _("Roaming"); -static const u8 sText_Safari[] = _("Safari"); -static const u8 sText_FirstBattle[] = _("First Battle"); -static const u8 sText_ShowHP[] = _("Show HP"); -static const u8 sText_SubstituteHp[] = _("Substitute HP"); -static const u8 sText_InLove[] = _("In Love"); -static const u8 sText_Unknown[] = _("Unknown"); static const u8 sText_EmptyString[] = _(""); -static const u8 sText_IsSwitching[] = _("Switching to "); static const struct BitfieldInfo sStatus1Bitfield[] = { @@ -487,160 +352,160 @@ static const struct BitfieldInfo sAIBitfield[] = static const struct ListMenuItem sMainListItems[] = { - {sText_Moves, LIST_ITEM_MOVES}, - {sText_Ability, LIST_ITEM_ABILITY}, - {sText_HeldItem, LIST_ITEM_HELD_ITEM}, - {sText_PP, LIST_ITEM_PP}, - {sText_Types, LIST_ITEM_TYPES}, - {sText_Stats, LIST_ITEM_STATS}, - {sText_StatStages, LIST_ITEM_STAT_STAGES}, - {sText_Status1, LIST_ITEM_STATUS1}, - {sText_VolatileStatus, LIST_ITEM_VOLATILE}, - {sText_Status3, LIST_ITEM_STATUS3}, - {sText_Status4, LIST_ITEM_STATUS4}, - {sText_SideStatus, LIST_ITEM_SIDE_STATUS}, - {sText_AI, LIST_ITEM_AI}, - {sText_AIMovePts, LIST_ITEM_AI_MOVES_PTS}, - {sText_AiKnowledge, LIST_ITEM_AI_INFO}, - {sText_AiParty, LIST_ITEM_AI_PARTY}, - {sText_Various, LIST_ITEM_VARIOUS}, + {COMPOUND_STRING("Moves"), LIST_ITEM_MOVES}, + {sText_Ability, LIST_ITEM_ABILITY}, + {sText_HeldItem, LIST_ITEM_HELD_ITEM}, + {COMPOUND_STRING("PP"), LIST_ITEM_PP}, + {COMPOUND_STRING("Types"), LIST_ITEM_TYPES}, + {COMPOUND_STRING("Stats"), LIST_ITEM_STATS}, + {COMPOUND_STRING("Stat Stages"), LIST_ITEM_STAT_STAGES}, + {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, + {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, + {COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3}, + {COMPOUND_STRING("Status4"), LIST_ITEM_STATUS4}, + {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, + {COMPOUND_STRING("AI"), LIST_ITEM_AI}, + {COMPOUND_STRING("AI Pts/Dmg"), LIST_ITEM_AI_MOVES_PTS}, + {COMPOUND_STRING("AI Info"), LIST_ITEM_AI_INFO}, + {COMPOUND_STRING("AI Party"), LIST_ITEM_AI_PARTY}, + {COMPOUND_STRING("Various"), LIST_ITEM_VARIOUS}, }; static const struct ListMenuItem sStatsListItems[] = { - {sText_CurrHp, LIST_STAT_HP_CURRENT}, - {sText_MaxHp, LIST_STAT_HP_MAX}, - {sText_Attack, LIST_STAT_ATTACK}, - {sText_Defense, LIST_STAT_DEFENSE}, - {sText_Speed, LIST_STAT_SPEED}, - {sText_SpAtk, LIST_STAT_SP_ATK}, - {sText_SpDef, LIST_STAT_SP_DEF}, + {COMPOUND_STRING("HP Current"), LIST_STAT_HP_CURRENT}, + {COMPOUND_STRING("HP Max"), LIST_STAT_HP_MAX}, + {COMPOUND_STRING("Attack"), LIST_STAT_ATTACK}, + {COMPOUND_STRING("Defense"), LIST_STAT_DEFENSE}, + {COMPOUND_STRING("Speed"), LIST_STAT_SPEED}, + {COMPOUND_STRING("Sp. Atk"), LIST_STAT_SP_ATK}, + {COMPOUND_STRING("Sp. Def"), LIST_STAT_SP_DEF}, }; static const struct ListMenuItem sStatus1ListItems[] = { - {sText_Sleep, LIST_STATUS1_SLEEP}, - {sText_Poison, LIST_STATUS1_POISON}, - {sText_Burn, LIST_STATUS1_BURN}, - {sText_Freeze, LIST_STATUS1_FREEZE}, - {sText_Paralysis, LIST_STATUS1_PARALYSIS}, - {sText_ToxicPoison, LIST_STATUS1_TOXIC_POISON}, - {sText_ToxicCounter, LIST_STATUS1_TOXIC_COUNTER}, - {sText_Frostbite, LIST_STATUS1_FROSTBITE}, + {COMPOUND_STRING("Sleep"), LIST_STATUS1_SLEEP}, + {COMPOUND_STRING("Poison"), LIST_STATUS1_POISON}, + {COMPOUND_STRING("Burn"), LIST_STATUS1_BURN}, + {COMPOUND_STRING("Freeze"), LIST_STATUS1_FREEZE}, + {COMPOUND_STRING("Paralysis"), LIST_STATUS1_PARALYSIS}, + {COMPOUND_STRING("Toxic Poison"), LIST_STATUS1_TOXIC_POISON}, + {COMPOUND_STRING("Toxic Counter"), LIST_STATUS1_TOXIC_COUNTER}, + {COMPOUND_STRING("Frostbite"), LIST_STATUS1_FROSTBITE}, }; static const struct ListMenuItem sVolatileStatusListItems[] = { - {COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION}, - {COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED}, - {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, - {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, - {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, - {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, - {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, - {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, + {COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION}, + {COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED}, + {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, + {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, + {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, + {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, + {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, + {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, {COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION}, - {COMPOUND_STRING("Cursed"), VOLATILE_CURSED}, - {COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT}, - {COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER}, - {COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY}, - {COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT}, - {COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT}, + {COMPOUND_STRING("Cursed"), VOLATILE_CURSED}, + {COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT}, + {COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER}, + {COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY}, + {COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT}, + {COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT}, }; static const struct ListMenuItem sStatus3ListItems[] = { - {sText_LeechSeedHealer, LIST_STATUS3_LEECH_SEED_HEALER}, - {sText_LeechSeeded, LIST_STATUS3_LEECH_SEEDED}, - {sText_AlwaysHits, LIST_STATUS3_ALWAYS_HITS}, - {sText_PerishSong, LIST_STATUS3_PERISH_SONG}, - {sText_OnAir, LIST_STATUS3_ON_AIR}, - {sText_Underground, LIST_STATUS3_UNDERGROUND}, - {sText_Minimized, LIST_STATUS3_MINIMIZED}, - {sText_ChargedUp, LIST_STATUS3_CHARGED_UP}, - {sText_Rooted, LIST_STATUS3_ROOTED}, - {sText_Yawn, LIST_STATUS3_YAWN}, - {sText_ImprisonedOthers, LIST_STATUS3_IMPRISONED_OTHERS}, - {sText_Grudge, LIST_STATUS3_GRUDGE}, - {sText_GastroAcid, LIST_STATUS3_GASTRO_ACID}, - {sText_Embargo, LIST_STATUS3_EMBARGO}, - {sText_Underwater, LIST_STATUS3_UNDERWATER}, - {sText_SmackedDown, LIST_STATUS3_SMACKED_DOWN}, - {sText_Telekinesis, LIST_STATUS3_TELEKINESIS}, - {sText_MiracleEyed, LIST_STATUS3_MIRACLE_EYED}, - {sText_MagnetRise, LIST_STATUS3_MAGNET_RISE}, - {sText_HealBlock, LIST_STATUS3_HEAL_BLOCK}, - {sText_AquaRing, LIST_STATUS3_AQUA_RING}, - {sText_LaserFocus, LIST_STATUS3_LASER_FOCUS}, - {sText_PowerTrick, LIST_STATUS3_POWER_TRICK}, + {COMPOUND_STRING("Leech Seed Healer"), LIST_STATUS3_LEECH_SEED_HEALER}, + {COMPOUND_STRING("Leech Seeded"), LIST_STATUS3_LEECH_SEEDED}, + {COMPOUND_STRING("Always Hits"), LIST_STATUS3_ALWAYS_HITS}, + {COMPOUND_STRING("Perish Song"), LIST_STATUS3_PERISH_SONG}, + {COMPOUND_STRING("On Air"), LIST_STATUS3_ON_AIR}, + {COMPOUND_STRING("Underground"), LIST_STATUS3_UNDERGROUND}, + {COMPOUND_STRING("Minimized"), LIST_STATUS3_MINIMIZED}, + {COMPOUND_STRING("Charged Up"), LIST_STATUS3_CHARGED_UP}, + {COMPOUND_STRING("Rooted"), LIST_STATUS3_ROOTED}, + {COMPOUND_STRING("Yawn"), LIST_STATUS3_YAWN}, + {COMPOUND_STRING("Imprisoned Others"), LIST_STATUS3_IMPRISONED_OTHERS}, + {COMPOUND_STRING("Grudge"), LIST_STATUS3_GRUDGE}, + {COMPOUND_STRING("Gastro Acid"), LIST_STATUS3_GASTRO_ACID}, + {COMPOUND_STRING("Embargo"), LIST_STATUS3_EMBARGO}, + {COMPOUND_STRING("Underwater"), LIST_STATUS3_UNDERWATER}, + {COMPOUND_STRING("Smacked Down"), LIST_STATUS3_SMACKED_DOWN}, + {COMPOUND_STRING("Telekinesis"), LIST_STATUS3_TELEKINESIS}, + {COMPOUND_STRING("Miracle Eyed"), LIST_STATUS3_MIRACLE_EYED}, + {COMPOUND_STRING("Magnet Rise"), LIST_STATUS3_MAGNET_RISE}, + {COMPOUND_STRING("Heal Block"), LIST_STATUS3_HEAL_BLOCK}, + {COMPOUND_STRING("Aqua Ring"), LIST_STATUS3_AQUA_RING}, + {COMPOUND_STRING("Laser Focus"), LIST_STATUS3_LASER_FOCUS}, + {COMPOUND_STRING("Power Trick"), LIST_STATUS3_POWER_TRICK}, }; static const struct ListMenuItem sStatus4ListItems[] = { - {sText_Electrified, LIST_STATUS4_ELECTRIFIED}, - {sText_SaltCure, LIST_STATUS4_SALT_CURE}, - {sText_SyrupBomb, LIST_STATUS4_SYRUP_BOMB}, - {sText_GlaiveRush, LIST_STATUS4_GLAIVE_RUSH}, + {COMPOUND_STRING("Electrified"), LIST_STATUS4_ELECTRIFIED}, + {COMPOUND_STRING("Salt Cure"), LIST_STATUS4_SALT_CURE}, + {COMPOUND_STRING("Syrup Bomb"), LIST_STATUS4_SYRUP_BOMB}, + {COMPOUND_STRING("Glaive Rush"), LIST_STATUS4_GLAIVE_RUSH}, }; static const struct ListMenuItem sSideStatusListItems[] = { - {sText_Reflect, LIST_SIDE_REFLECT}, - {sText_LightScreen, LIST_SIDE_LIGHTSCREEN}, - {sText_StickyWeb, LIST_SIDE_STICKY_WEB}, - {sText_Spikes, LIST_SIDE_SPIKES}, - {sText_Safeguard, LIST_SIDE_SAFEGUARD}, - {sText_Mist, LIST_SIDE_MIST}, - {sText_Tailwind, LIST_SIDE_TAILWIND}, - {sText_AuroraVeil, LIST_SIDE_AURORA_VEIL}, - {sText_LuckyChant, LIST_SIDE_LUCKY_CHANT}, - {sText_ToxicSpikes, LIST_SIDE_TOXIC_SPIKES}, - {sText_StealthRock, LIST_SIDE_STEALTH_ROCK}, - {sText_Steelsurge, LIST_SIDE_STEELSURGE}, - {sText_DamageNonTypes, LIST_SIDE_DAMAGE_NON_TYPES}, - {sText_Rainbow, LIST_SIDE_RAINBOW}, - {sText_SeaOfFire, LIST_SIDE_SEA_OF_FIRE}, - {sText_Swamp, LIST_SIDE_SWAMP}, + {COMPOUND_STRING("Reflect"), LIST_SIDE_REFLECT}, + {COMPOUND_STRING("Light Screen"), LIST_SIDE_LIGHTSCREEN}, + {COMPOUND_STRING("Sticky Web"), LIST_SIDE_STICKY_WEB}, + {COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES}, + {COMPOUND_STRING("Safeguard"), LIST_SIDE_SAFEGUARD}, + {COMPOUND_STRING("Mist"), LIST_SIDE_MIST}, + {COMPOUND_STRING("Tailwind"), LIST_SIDE_TAILWIND}, + {COMPOUND_STRING("Aurora Veil"), LIST_SIDE_AURORA_VEIL}, + {COMPOUND_STRING("Lucky Chant"), LIST_SIDE_LUCKY_CHANT}, + {COMPOUND_STRING("Toxic Spikes"), LIST_SIDE_TOXIC_SPIKES}, + {COMPOUND_STRING("Stealth Rock"), LIST_SIDE_STEALTH_ROCK}, + {COMPOUND_STRING("Steelsurge"), LIST_SIDE_STEELSURGE}, + {COMPOUND_STRING("Damage Non-Types"), LIST_SIDE_DAMAGE_NON_TYPES}, + {COMPOUND_STRING("Rainbow"), LIST_SIDE_RAINBOW}, + {COMPOUND_STRING("Sea of Fire"), LIST_SIDE_SEA_OF_FIRE}, + {COMPOUND_STRING("Swamp"), LIST_SIDE_SWAMP}, }; static const struct ListMenuItem sAIListItems[] = { - {sText_CheckBadMove, LIST_AI_CHECK_BAD_MOVE}, - {sText_TryToFaint, LIST_AI_TRY_TO_FAINT}, - {sText_CheckViability, LIST_AI_CHECK_VIABILITY}, - {sText_ForceSetupFirstTurn, LIST_AI_FORCE_SETUP_FIRST_TURN}, - {sText_Risky, LIST_AI_RISKY}, - {sText_TryTo2HKO, LIST_AI_TRY_TO_2HKO}, - {sText_PreferBatonPass, LIST_AI_PREFER_BATON_PASS}, - {sText_DoubleBattle, LIST_AI_DOUBLE_BATTLE}, - {sText_HpAware, LIST_AI_HP_AWARE}, - {sText_PowerfulStatus, LIST_AI_POWERFUL_STATUS}, - {sText_NegateUnaware, LIST_AI_NEGATE_UNAWARE}, - {sText_WillSuicide, LIST_AI_WILL_SUICIDE}, - {sText_PreferStatusMoves, LIST_AI_PREFER_STATUS_MOVES}, - {sText_Stall, LIST_AI_STALL}, - {sText_SmartSwitching, LIST_AI_SMART_SWITCHING}, - {sText_AcePokemon, LIST_AI_ACE_POKEMON}, - {sText_Omniscient, LIST_AI_OMNISCIENT}, - {sText_SmartMonChoices, LIST_AI_SMART_MON_CHOICES}, - {sText_Conservative, LIST_AI_CONSERVATIVE}, - {sText_SequenceSwitching, LIST_AI_SEQUENCE_SWITCHING}, - {sText_DoubleAcePokemon, LIST_AI_DOUBLE_ACE_POKEMON}, - {sText_WeighAbilityPrediction, LIST_AI_WEIGH_ABILITY_PREDICTION}, - {sText_PreferHighestDamageMove, LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE}, - {sText_PredictSwitch, LIST_AI_PREDICT_SWITCH}, - {sText_PredictIncomingMon, LIST_AI_PREDICT_INCOMING_MON}, - {sText_DynamicFunc, LIST_AI_DYNAMIC_FUNC}, - {sText_Roaming, LIST_AI_ROAMING}, - {sText_Safari, LIST_AI_SAFARI}, - {sText_FirstBattle, LIST_AI_FIRST_BATTLE}, + {COMPOUND_STRING("Check Bad Move"), LIST_AI_CHECK_BAD_MOVE}, + {COMPOUND_STRING("Try to Faint"), LIST_AI_TRY_TO_FAINT}, + {COMPOUND_STRING("Check Viability"), LIST_AI_CHECK_VIABILITY}, + {COMPOUND_STRING("Force Setup First Turn"), LIST_AI_FORCE_SETUP_FIRST_TURN}, + {COMPOUND_STRING("Risky"), LIST_AI_RISKY}, + {COMPOUND_STRING("Try to 2HKO"), LIST_AI_TRY_TO_2HKO}, + {COMPOUND_STRING("Prefer Baton Pass"), LIST_AI_PREFER_BATON_PASS}, + {COMPOUND_STRING("Double Battle"), LIST_AI_DOUBLE_BATTLE}, + {COMPOUND_STRING("HP Aware"), LIST_AI_HP_AWARE}, + {COMPOUND_STRING("Powerful Status"), LIST_AI_POWERFUL_STATUS}, + {COMPOUND_STRING("Negate Unaware"), LIST_AI_NEGATE_UNAWARE}, + {COMPOUND_STRING("Will Suicide"), LIST_AI_WILL_SUICIDE}, + {COMPOUND_STRING("Prefer Status Moves"), LIST_AI_PREFER_STATUS_MOVES}, + {COMPOUND_STRING("Stall"), LIST_AI_STALL}, + {COMPOUND_STRING("Smart Switching"), LIST_AI_SMART_SWITCHING}, + {COMPOUND_STRING("Ace Pokémon"), LIST_AI_ACE_POKEMON}, + {COMPOUND_STRING("Omniscient"), LIST_AI_OMNISCIENT}, + {COMPOUND_STRING("Smart Mon Choices"), LIST_AI_SMART_MON_CHOICES}, + {COMPOUND_STRING("Conservative"), LIST_AI_CONSERVATIVE}, + {COMPOUND_STRING("Sequence Switching"), LIST_AI_SEQUENCE_SWITCHING}, + {COMPOUND_STRING("Double Ace Pokémon"), LIST_AI_DOUBLE_ACE_POKEMON}, + {COMPOUND_STRING("Weigh Ability Prediction"), LIST_AI_WEIGH_ABILITY_PREDICTION}, + {COMPOUND_STRING("Prefer Highest Damage Move"), LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE}, + {COMPOUND_STRING("Predict Switch"), LIST_AI_PREDICT_SWITCH}, + {COMPOUND_STRING("Predict Incoming Mon"), LIST_AI_PREDICT_INCOMING_MON}, + {COMPOUND_STRING("Dynamic Func"), LIST_AI_DYNAMIC_FUNC}, + {COMPOUND_STRING("Roaming"), LIST_AI_ROAMING}, + {COMPOUND_STRING("Safari"), LIST_AI_SAFARI}, + {COMPOUND_STRING("First Battle"), LIST_AI_FIRST_BATTLE}, }; static const struct ListMenuItem sVariousListItems[] = { - {sText_ShowHP, VARIOUS_SHOW_HP}, - {sText_SubstituteHp, VARIOUS_SUBSTITUTE_HP}, - {sText_InLove, VARIOUS_IN_LOVE}, + {COMPOUND_STRING("Show HP"), VARIOUS_SHOW_HP}, + {COMPOUND_STRING("Substitute HP"), VARIOUS_SUBSTITUTE_HP}, + {COMPOUND_STRING("In Love"), VARIOUS_IN_LOVE}, }; static const struct ListMenuItem sSecondaryListItems[] = @@ -934,7 +799,7 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) { u32 switchMon = GetMonData(&gEnemyParty[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, sText_IsSwitching, 74, 64, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Switching to "), 74, 64, 0, NULL); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, gSpeciesInfo[switchMon].speciesName, 74 + 68, 64, 0, NULL); } From c360900a5b19e63d89f2fa44f927a485e4b68bbf Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 5 Jul 2025 07:46:23 -0400 Subject: [PATCH 046/283] Renaming STATUS1_REFRESH and adding more constants for common STATUS1 checks. (#7284) --- include/constants/battle.h | 5 ++++- src/battle_ai_main.c | 10 +++++----- src/battle_ai_switch_items.c | 5 ++--- src/battle_ai_util.c | 4 ++-- src/battle_script_commands.c | 6 +++--- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 2ebf99ebce..e785498489 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -132,7 +132,10 @@ enum BattlerId #define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON) #define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) -#define STATUS1_REFRESH (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) +#define STATUS1_CAN_MOVE (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) +#define STATUS1_INCAPACITATED (STATUS1_SLEEP | STATUS1_FREEZE) +#define STATUS1_ICY_ANY (STATUS1_FREEZE | STATUS1_FROSTBITE) +#define STATUS1_DAMAGING (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_FROSTBITE) enum VolatileFlags { diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 78693b1950..751402af43 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1059,7 +1059,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // Don't use anything but super effective thawing moves if target is frozen if any other attack available - if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & (STATUS1_FROSTBITE | STATUS1_FREEZE))) + if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY)) { u32 aiMove; for (i = 0; i < MAX_MON_MOVES; i++) @@ -2029,7 +2029,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_FROSTBITE))) + if (!(gBattleMons[battlerDef].status1 & STATUS1_CAN_MOVE)) ADJUST_SCORE(-10); break; case EFFECT_PSYCHO_SHIFT: @@ -2085,7 +2085,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_BIDE: if (!HasDamagingMove(battlerDef) || aiData->hpPercents[battlerAtk] < 30 //Close to death - || gBattleMons[battlerDef].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) //No point in biding if can't take damage + || gBattleMons[battlerDef].status1 & STATUS1_INCAPACITATED) //No point in biding if can't take damage ADJUST_SCORE(-10); break; case EFFECT_HIT_SWITCH_TARGET: @@ -2565,7 +2565,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && GetMoveEffect(aiData->partnerMove) == EFFECT_PLEDGE && move != aiData->partnerMove) // Different pledge moves { - if (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) + if (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_INCAPACITATED) // && gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 != 1) // Will wake up this turn - how would AI know ADJUST_SCORE(-10); // Don't use combo move if your partner will cause failure } @@ -3835,7 +3835,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(10); // check thawing moves - if ((gBattleMons[battlerAtk].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) && MoveThawsUser(move)) + if (gBattleMons[battlerAtk].status1 & STATUS1_ICY_ANY && MoveThawsUser(move)) ADJUST_SCORE(10); // check burn / frostbite diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index dde7434155..550a2f91f7 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -2395,12 +2395,11 @@ static bool32 ShouldUseItem(u32 battler) case EFFECT_ITEM_CURE_STATUS: if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[battler].status1 & STATUS1_SLEEP) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_POISON && (gBattleMons[battler].status1 & STATUS1_POISON - || gBattleMons[battler].status1 & STATUS1_TOXIC_POISON)) + if (itemEffects[3] & ITEM3_POISON && gBattleMons[battler].status1 & STATUS1_PSN_ANY) shouldUse = TRUE; if (itemEffects[3] & ITEM3_BURN && gBattleMons[battler].status1 & STATUS1_BURN) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_FREEZE && (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE)) + if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[battler].status1 & STATUS1_ICY_ANY) shouldUse = TRUE; if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[battler].status1 & STATUS1_PARALYSIS) shouldUse = TRUE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 88b4e3b065..645a34beba 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1870,7 +1870,7 @@ bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) bool32 IsBattlerDamagedByStatus(u32 battler) { - return gBattleMons[battler].status1 & (STATUS1_BURN | STATUS1_FROSTBITE | STATUS1_POISON | STATUS1_TOXIC_POISON) + return gBattleMons[battler].status1 & STATUS1_DAMAGING || gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_NIGHTMARE | STATUS2_CURSED) || gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED) || gStatuses4[battler] & (STATUS4_SALT_CURE) @@ -4809,7 +4809,7 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP) scoreIncrease += GOOD_EFFECT; - else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE)) + else if (gBattleMons[battlerDef].status1 & STATUS1_DAMAGING) scoreIncrease += DECENT_EFFECT; if (IsBattlerPredictedToSwitch(battlerDef)) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e49d824d75..7138ad9803 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14687,7 +14687,7 @@ static void Cmd_curestatuswithmove(void) u32 shouldHeal; if (GetMoveEffect(gCurrentMove) == EFFECT_REFRESH) - shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_REFRESH; + shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_CAN_MOVE; else // Take Heart shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; @@ -15871,9 +15871,9 @@ static void Cmd_handleballthrow(void) * (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2) / (3 * gBattleMons[gBattlerTarget].maxHP); - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) + if (gBattleMons[gBattlerTarget].status1 & STATUS1_INCAPACITATED) odds *= 2; - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) + if (gBattleMons[gBattlerTarget].status1 & STATUS1_CAN_MOVE) odds = (odds * 15) / 10; if (gBattleResults.catchAttempts[ballId] < 255) From 38a3963ec2ecb9eafa068b7b5c9ba3f8bbf0757a Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Sat, 5 Jul 2025 13:47:36 +0100 Subject: [PATCH 047/283] Fix Psych Up message and cleanup and don't allow switching to self in tests (#7277) --- asm/macros/battle_script.inc | 3 +-- data/battle_scripts_1.s | 2 +- src/battle_message.c | 3 ++- src/battle_script_commands.c | 17 ++++++++++++----- test/test_runner_battle.c | 4 ++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 02da5bc775..b23992d332 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1033,9 +1033,8 @@ .4byte \failInstr .endm - .macro copyfoestats unused:req + .macro copyfoestats .byte 0xbd - .4byte \unused .endm .macro rapidspinfree diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bacf15e1c6..a57ce67c25 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4258,7 +4258,7 @@ BattleScript_EffectPsychUp:: attackcanceler attackstring ppreduce - copyfoestats BattleScript_ButItFailed + copyfoestats attackanimation waitanimation printstring STRINGID_PKMNCOPIEDSTATCHANGES diff --git a/src/battle_message.c b/src/battle_message.c index 9082bbef6c..860a3d5ac2 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1202,7 +1202,8 @@ const u16 gGotBurnedStringIds[] = const u16 gGotFrostbiteStringIds[] = { - [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE + [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE, + [B_MSG_STATUSED_BY_ABILITY] = STRINGID_PKMNGOTFROSTBITE }; const u16 gFrostbiteHealedStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7138ad9803..ff4104b19e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -61,6 +61,7 @@ #include "constants/songs.h" #include "constants/trainer_slide.h" #include "constants/trainers.h" +#include "test/battle.h" #include "battle_util.h" #include "constants/pokemon.h" #include "config/battle.h" @@ -2397,7 +2398,7 @@ static inline bool32 TryTeraShellDistortTypeMatchups(u32 battlerDef) // According to Gen5 Weakness berry activation happens after the attackanimation. // It doesn't have any impact on gameplay and is only a visual thing which can be adjusted later. -static inline bool32 TryActivateWeakenessBerry(u32 battlerDef) +static inline bool32 TryActivateWeaknessBerry(u32 battlerDef) { if (gSpecialStatuses[battlerDef].berryReduced && gBattleMons[battlerDef].item != ITEM_NONE) { @@ -2440,7 +2441,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) if (TryTeraShellDistortTypeMatchups(battlerDef)) return TRUE; - if (TryActivateWeakenessBerry(battlerDef)) + if (TryActivateWeaknessBerry(battlerDef)) return TRUE; } } @@ -2450,7 +2451,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) return TRUE; if (TryTeraShellDistortTypeMatchups(gBattlerTarget)) return TRUE; - if (TryActivateWeakenessBerry(gBattlerTarget)) + if (TryActivateWeaknessBerry(gBattlerTarget)) return TRUE; } @@ -7431,6 +7432,11 @@ static void Cmd_getswitchedmondata(void) if (gBattleControllerExecFlags) return; + if (TESTING + && gBattlerPartyIndexes[battler] == gBattleStruct->monToSwitchIntoId[battler] + && gBattleStruct->hpBefore[battler] != 0) // battler is alive + Test_ExitWithResult(TEST_RESULT_ERROR, 0, ":L:%s:%d: battler is trying to switch to themself", __FILE__, __LINE__); + gBattlerPartyIndexes[battler] = gBattleStruct->monToSwitchIntoId[battler]; BtlController_EmitGetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_ALL_BATTLE, 1u << gBattlerPartyIndexes[battler]); @@ -14269,7 +14275,7 @@ static void Cmd_halvehp(void) // Psych Up static void Cmd_copyfoestats(void) { - CMD_ARGS(const u8 *unused); + CMD_ARGS(); s32 i; @@ -14277,8 +14283,9 @@ static void Cmd_copyfoestats(void) { gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i]; } + gBattleScripting.battler = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; // Has an unused jump ptr(possibly for a failed attempt) parameter. + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_rapidspinfree(void) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 20271a588d..51f0ca02dd 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -2016,9 +2016,9 @@ void CloseTurn(u32 sourceLine) { if (!(DATA.actionBattlers & (1 << i))) { - if (IsAITest() && (i & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. + if (IsAITest() && (i & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. SetAiActionToPass(sourceLine, i); - else + else Move(sourceLine, &gBattleMons[i], (struct MoveContext) { move: MOVE_CELEBRATE, explicitMove: TRUE }); } } From 4052ab337c4f25a66ec38b770ce61b5924cc2309 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 5 Jul 2025 08:49:35 -0400 Subject: [PATCH 048/283] Expanding and Refactoring Skill Swap and other ability-changing moves (#7238) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/battle_ai_main.h | 5 +- include/battle_ai_util.h | 9 +- src/battle_ai_main.c | 230 +++++---------- src/battle_ai_util.c | 435 +++++++++++++++++++++++++++- test/battle/ai/ai_check_viability.c | 32 ++ 5 files changed, 534 insertions(+), 177 deletions(-) diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 31d6437b97..6c58063350 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -38,7 +38,10 @@ enum AIScore WEAK_EFFECT = 1, DECENT_EFFECT = 2, GOOD_EFFECT = 3, - BEST_EFFECT = 4 + BEST_EFFECT = 4, + BAD_EFFECT = -1, + AWFUL_EFFECT = -3, + WORST_EFFECT = -5 }; // AI_TryToFaint diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 2144056cd5..991584a534 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -177,6 +177,7 @@ bool32 HasThawingMove(u32 battler); bool32 IsStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsStatLoweringEffect(enum BattleMoveEffects effect); bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect); +bool32 IsSelfStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsSwitchOutEffect(enum BattleMoveEffects effect); bool32 IsChaseEffect(enum BattleMoveEffects effect); bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect); @@ -208,10 +209,14 @@ bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId); // ability logic bool32 IsMoxieTypeAbility(u32 ability); -bool32 ShouldTriggerAbility(u32 battler, u32 ability); +bool32 DoesAbilityRaiseStatsWhenLowered(u32 ability); +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability); +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData); +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData); +s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData *aiData); // partner logic -#define IS_TARGETING_PARTNER(battlerAtk, battlerDef)((battlerAtk) == (battlerDef ^ BIT_FLANK)) +bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef); u32 GetAllyChosenMove(u32 battlerId); bool32 IsValidDoubleBattle(u32 battlerAtk); bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 751402af43..bc3c35db84 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1030,7 +1030,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 abilityDef = aiData->abilities[battlerDef]; s32 atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; SetTypeBeforeUsingMove(move, battlerAtk); @@ -1142,7 +1142,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) RETURN_SCORE_MINUS(20); break; case ABILITY_JUSTIFIED: - if (moveType == TYPE_DARK && !IsBattleMoveStatus(move) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (moveType == TYPE_DARK && !IsBattleMoveStatus(move) && !IsTargetingPartner(battlerAtk, battlerDef)) RETURN_SCORE_MINUS(10); break; case ABILITY_RATTLED: @@ -2312,7 +2312,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // evasion check if (gBattleMons[battlerDef].statStages[STAT_EVASION] == MIN_STAT_STAGE - || ((aiData->abilities[battlerDef] == ABILITY_CONTRARY) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner + || ((aiData->abilities[battlerDef] == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner ADJUST_SCORE(-10); break; case EFFECT_PSYCH_UP: // haze stats check @@ -2361,26 +2361,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || !CanBattlerGetOrLoseItem(battlerAtk, gBattleMons[battlerAtk].item)) // AI knows its own item ADJUST_SCORE(-10); break; - case EFFECT_ROLE_PLAY: - if (aiData->abilities[battlerAtk] == aiData->abilities[battlerDef] - || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied) - ADJUST_SCORE(-10); - else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5)) - ADJUST_SCORE(-4); - break; - case EFFECT_DOODLE: // Same as Role Play, but also check if the partner's ability should be replaced - if (aiData->abilities[battlerAtk] == aiData->abilities[battlerDef] - || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == aiData->abilities[battlerDef] - || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[BATTLE_PARTNER(battlerAtk)]].cantBeSuppressed - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeCopied) - ADJUST_SCORE(-10); - else if (IsAbilityOfRating(aiData->abilities[battlerAtk], 5) || IsAbilityOfRating(aiData->abilities[BATTLE_PARTNER(battlerAtk)], 5)) - ADJUST_SCORE(-4); - break; case EFFECT_WISH: if (gWishFutureKnock.wishCounter[battlerAtk] > gBattleTurnCounter) ADJUST_SCORE(-10); @@ -2401,40 +2381,15 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (PartnerMoveActivatesSleepClause(aiData->partnerMove)) ADJUST_SCORE(-20); break; - case EFFECT_SKILL_SWAP: - if (aiData->abilities[battlerAtk] == ABILITY_NONE || aiData->abilities[battlerDef] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeSwapped - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeSwapped - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - ADJUST_SCORE(-10); - break; - case EFFECT_WORRY_SEED: - if (aiData->abilities[battlerDef] == ABILITY_INSOMNIA - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - break; - case EFFECT_GASTRO_ACID: - if (gStatuses3[battlerDef] & STATUS3_GASTRO_ACID - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeSuppressed) - ADJUST_SCORE(-10); - break; + case EFFECT_DOODLE: case EFFECT_ENTRAINMENT: - if (aiData->abilities[battlerAtk] == ABILITY_NONE - || gAbilitiesInfo[aiData->abilities[battlerAtk]].cantBeCopied - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); - else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - ADJUST_SCORE(-10); - break; + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: case EFFECT_SIMPLE_BEAM: - if (aiData->abilities[battlerDef] == ABILITY_SIMPLE - || gAbilitiesInfo[aiData->abilities[battlerDef]].cantBeOverwritten - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) - ADJUST_SCORE(-10); + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + if (!CanEffectChangeAbility(battlerAtk, battlerDef, moveEffect, aiData)) + ADJUST_AND_RETURN_SCORE(NO_DAMAGE_OR_FAILS); break; case EFFECT_SNATCH: if (!HasMoveWithFlag(battlerDef, MoveCanBeSnatched) @@ -2442,27 +2397,27 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_POWER_TRICK: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].defense >= gBattleMons[battlerAtk].attack && !HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) ADJUST_SCORE(-10); break; case EFFECT_POWER_SWAP: // Don't use if attacker's stat stages are higher than opponents - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].statStages[STAT_ATK] >= gBattleMons[battlerDef].statStages[STAT_ATK] && gBattleMons[battlerAtk].statStages[STAT_SPATK] >= gBattleMons[battlerDef].statStages[STAT_SPATK]) ADJUST_SCORE(-10); break; case EFFECT_GUARD_SWAP: // Don't use if attacker's stat stages are higher than opponents - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].statStages[STAT_DEF] >= gBattleMons[battlerDef].statStages[STAT_DEF] && gBattleMons[battlerAtk].statStages[STAT_SPDEF] >= gBattleMons[battlerDef].statStages[STAT_SPDEF]) ADJUST_SCORE(-10); break; case EFFECT_SPEED_SWAP: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2475,7 +2430,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_HEART_SWAP: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2492,7 +2447,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_POWER_SPLIT: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2509,7 +2464,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_GUARD_SPLIT: - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { ADJUST_SCORE(-10); } @@ -2674,14 +2629,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_HEAL_PULSE: // and floral healing - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) // Don't heal enemies + if (!IsTargetingPartner(battlerAtk, battlerDef)) // Don't heal enemies { ADJUST_SCORE(-10); break; } // fallthrough case EFFECT_HIT_ENEMY_HEAL_ALLY: // pollen puff - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) return 0; // cannot even select @@ -2698,7 +2653,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_TOPSY_TURVY: - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 targetPositiveStages = CountPositiveStatStages(battlerDef); u32 targetNegativeStages = CountNegativeStatStages(battlerDef); @@ -2743,7 +2698,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (isDoubleBattle) { - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (!IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); } else @@ -2766,7 +2721,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: - if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef) + if (!IsTargetingPartner(battlerAtk, battlerDef) || !isDoubleBattle || AI_IsSlower(battlerAtk, battlerDef, move) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) @@ -2943,7 +2898,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 movesetIndex = gAiThinkingStruct->movesetIndex; - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (IsBattleMoveStatus(move)) @@ -2984,7 +2939,6 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 atkPartnerHoldEffect = aiData->holdEffects[BATTLE_PARTNER(battlerAtk)]; enum BattleMoveEffects partnerEffect = GetMoveEffect(aiData->partnerMove); bool32 partnerProtecting = IsAllyProtectingFromMove(battlerAtk, move, aiData->partnerMove) && !MoveIgnoresProtect(move); - bool32 attackerHasBadAbility = (gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating < 0); bool32 partnerHasBadAbility = (gAbilitiesInfo[atkPartnerAbility].aiRating < 0); u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); @@ -3174,7 +3128,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - ADJUST_SCORE(-DECENT_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); } } // No reason to kill partner has been found. @@ -3203,7 +3157,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // check specific target - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { bool32 isMoveAffectedByPartnerAbility = TRUE; @@ -3252,7 +3206,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - else if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + else if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3298,7 +3252,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - else if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + else if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3314,7 +3268,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case ABILITY_WATER_COMPACTION: if (moveType == TYPE_WATER && isFriendlyFireOK - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3333,7 +3287,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case ABILITY_STEAM_ENGINE: if (isFriendlyFireOK && (moveType == TYPE_WATER || moveType == TYPE_FIRE) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3349,7 +3303,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_THERMAL_EXCHANGE: if (moveType == TYPE_FIRE && isFriendlyFireOK && !IsBattleMoveStatus(move) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3376,7 +3330,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(DECENT_EFFECT); } - if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3394,7 +3348,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(DECENT_EFFECT); } - if (ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { RETURN_SCORE_PLUS(WEAK_EFFECT); } @@ -3407,7 +3361,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_JUSTIFIED: if (moveType == TYPE_DARK && isFriendlyFireOK && !IsBattleMoveStatus(move) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3429,7 +3383,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_RATTLED: if (!IsBattleMoveStatus(move) && isFriendlyFireOK && (moveType == TYPE_DARK || moveType == TYPE_GHOST || moveType == TYPE_BUG) - && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3445,7 +3399,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_CONTRARY: case ABILITY_DEFIANT: case ABILITY_COMPETITIVE: - if (IsStatLoweringEffect(effect) && isFriendlyFireOK && ShouldTriggerAbility(battlerAtkPartner, atkPartnerAbility)) + if (IsStatLoweringEffect(effect) && isFriendlyFireOK && ShouldTriggerAbility(battlerAtk, battlerAtkPartner, atkPartnerAbility)) { if (moveTarget == MOVE_TARGET_FOES_AND_ALLY) { @@ -3471,6 +3425,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (effect) { + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + AbilityChangeScore(battlerAtk, battlerAtkPartner, effect, &score, aiData); + return score; case EFFECT_SPICY_EXTRACT: if (AI_ShouldSpicyExtract(battlerAtk, battlerAtkPartner, move, aiData)) { @@ -3519,51 +3482,6 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) RETURN_SCORE_PLUS(WEAK_EFFECT); } break; - case EFFECT_SKILL_SWAP: - if (aiData->abilities[battlerAtk] != aiData->abilities[BATTLE_PARTNER(battlerAtk)] && !attackerHasBadAbility) - { - // Partner abilities - if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_TRUANT) - { - ADJUST_SCORE(10); - } - else if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_INTIMIDATE) - { - ADJUST_SCORE(DECENT_EFFECT); - } - // Active mon abilities - if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES - && HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)])) - { - ADJUST_SCORE(GOOD_EFFECT); - } - else if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY && HasMoveThatLowersOwnStats(battlerAtkPartner)) - { - ADJUST_SCORE(GOOD_EFFECT); - } - return score; - } - break; - case EFFECT_ROLE_PLAY: - if (attackerHasBadAbility && !partnerHasBadAbility) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); - } - break; - case EFFECT_WORRY_SEED: - case EFFECT_GASTRO_ACID: - case EFFECT_SIMPLE_BEAM: - if (partnerHasBadAbility) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); - } - break; - case EFFECT_ENTRAINMENT: - if (partnerHasBadAbility && IsAbilityOfRating(aiData->abilities[battlerAtk], 0)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); - } - break; case EFFECT_SOAK: if (atkPartnerAbility == ABILITY_WONDER_GUARD && !IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_WATER) @@ -3619,6 +3537,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else // checking opponent { // these checks mostly handled in AI_CheckBadMove and AI_CheckViability +/* switch (effect) { case EFFECT_SKILL_SWAP: @@ -3630,7 +3549,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) default: break; } - +*/ // lightning rod, flash fire against enemy handled in AI_CheckBadMove } @@ -3800,7 +3719,7 @@ static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) } else { - ADJUST_SCORE(-DECENT_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); } } break; @@ -4622,11 +4541,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } } break; - case EFFECT_ROLE_PLAY: - case EFFECT_DOODLE: - if (IsAbilityOfRating(aiData->abilities[battlerDef], 5)) - ADJUST_SCORE(DECENT_EFFECT); - break; case EFFECT_INGRAIN: ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) @@ -4663,29 +4577,15 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_AURORA_VEIL) ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_SKILL_SWAP: - if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - break; - else if (gAbilitiesInfo[aiData->abilities[battlerDef]].aiRating > gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating) - ADJUST_SCORE(DECENT_EFFECT); - break; - case EFFECT_WORRY_SEED: + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: case EFFECT_SIMPLE_BEAM: - if (IsAbilityOfRating(aiData->abilities[battlerDef], 5)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case EFFECT_ENTRAINMENT: - if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) - break; - if (aiData->abilities[battlerDef] != aiData->abilities[battlerAtk] && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID)) - { - if (gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 0) - ADJUST_SCORE(DECENT_EFFECT); - else if (IsAbilityOfRating(aiData->abilities[battlerDef], 5) && gAbilitiesInfo[aiData->abilities[battlerAtk]].aiRating <= 3) - ADJUST_SCORE(WEAK_EFFECT); - } - break; + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + AbilityChangeScore(battlerAtk, battlerDef, moveEffect, &score, aiData); + return score; case EFFECT_IMPRISON: if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove)) ADJUST_SCORE(DECENT_EFFECT); @@ -5301,7 +5201,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // Targeting partner, check benefits of doing that instead - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetMovePower(move) != 0) @@ -5328,7 +5228,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u8 i; - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) + if (IsTargetingPartner(battlerAtk, battlerDef) || gBattleResults.battleTurnCounter != 0) return score; @@ -5459,7 +5359,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u8 i; struct AiLogicData *aiData = gAiLogicData; - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetMoveCriticalHitStage(move) > 0) @@ -5532,7 +5432,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Adds score bonus to OHKOs and 2HKOs static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) return score; if (GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING) == 1) @@ -5546,7 +5446,7 @@ static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Prefers moves that are good for baton pass static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) + if (IsTargetingPartner(battlerAtk, battlerDef) || CountUsablePartyMons(battlerAtk) == 0 || !IsBattleMoveStatus(move) || !HasMoveWithEffect(battlerAtk, EFFECT_BATON_PASS) @@ -5604,7 +5504,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + if (IsTargetingPartner(battlerAtk, battlerDef)) { if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY) || (moveType == TYPE_ELECTRIC && gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_VOLT_ABSORB) @@ -6002,7 +5902,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ION_DELUGE: case EFFECT_MAGIC_COAT: case EFFECT_SNATCH: - ADJUST_SCORE(-BEST_EFFECT); + ADJUST_SCORE(WORST_EFFECT); break; // Get stuck in bad matchup @@ -6012,7 +5912,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INGRAIN: case EFFECT_NO_RETREAT: case EFFECT_MEAN_LOOK: - ADJUST_SCORE(-GOOD_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); break; default: @@ -6025,17 +5925,17 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (GetMoveAdditionalEffectById(move, i)->moveEffect) { case MOVE_EFFECT_WRAP: - ADJUST_SCORE(-GOOD_EFFECT); + ADJUST_SCORE(AWFUL_EFFECT); break; case MOVE_EFFECT_FEINT: - ADJUST_SCORE(-BEST_EFFECT); + ADJUST_SCORE(WORST_EFFECT); break; } } // Take advantage of ability damage bonus if ((ability == ABILITY_STAKEOUT || ability == ABILITY_ANALYTIC) && IsBattleMoveStatus(move)) - ADJUST_SCORE(-WEAK_EFFECT); + ADJUST_SCORE(BAD_EFFECT); // This must be last or the player can gauge whether the AI is predicting based on how long it thinks if (!IsBattlerPredictedToSwitch(battlerDef)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 645a34beba..fd08bd7c0c 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1982,6 +1982,9 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) // Don't decrese stat if opposing battler has Encore if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) return NO_INCREASE; + + if (DoesAbilityRaiseStatsWhenLowered(gAiLogicData->abilities[battlerDef])) + return NO_INCREASE; // TODO: Avoid decreasing stat if // player can kill ai in 2 hits with decreased attack / sp atk stages @@ -2358,6 +2361,28 @@ bool32 HasMoveThatLowersOwnStats(u32 battlerId) return FALSE; } +bool32 HasMoveThatRaisesOwnStats(u32 battlerId) +{ + s32 i, j; + u32 aiMove; + u16 *moves = GetMovesArray(battlerId); + for (i = 0; i < MAX_MON_MOVES; i++) + { + aiMove = moves[i]; + if (aiMove != MOVE_NONE && aiMove != MOVE_UNAVAILABLE) + { + u32 additionalEffectCount = GetMoveAdditionalEffectCount(aiMove); + for (j = 0; j < additionalEffectCount; j++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(aiMove, j); + if (IsSelfStatRaisingEffect(additionalEffect->moveEffect) && additionalEffect->self) + return TRUE; + } + } + } + return FALSE; +} + bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) { s32 i; @@ -2588,6 +2613,31 @@ bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect) } } +bool32 IsSelfStatRaisingEffect(enum BattleMoveEffects effect) +{ + // Self stat lowering moves like Power Up Punch or Charge Beam + switch (effect) + { + case MOVE_EFFECT_ATK_PLUS_1: + case MOVE_EFFECT_DEF_PLUS_1: + case MOVE_EFFECT_SPD_PLUS_1: + case MOVE_EFFECT_SP_ATK_PLUS_1: + case MOVE_EFFECT_SP_DEF_PLUS_1: + case MOVE_EFFECT_EVS_PLUS_1: + case MOVE_EFFECT_ACC_PLUS_1: + case MOVE_EFFECT_ATK_PLUS_2: + case MOVE_EFFECT_DEF_PLUS_2: + case MOVE_EFFECT_SPD_PLUS_2: + case MOVE_EFFECT_SP_ATK_PLUS_2: + case MOVE_EFFECT_SP_DEF_PLUS_2: + case MOVE_EFFECT_EVS_PLUS_2: + case MOVE_EFFECT_ACC_PLUS_2: + return TRUE; + default: + return FALSE; + } +} + bool32 IsSwitchOutEffect(enum BattleMoveEffects effect) { // Switch out effects like U-Turn, Volt Switch, etc. @@ -3618,6 +3668,12 @@ bool32 IsValidDoubleBattle(u32 battlerAtk) return FALSE; } +// TODO: Handling for when the 'partner' is not actually a partner, a la Battle Royale or B_WILD_NATURAL_ENEMIES +bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef) +{ + return ((battlerAtk) == (battlerDef ^ BIT_FLANK)); +} + u32 GetAllyChosenMove(u32 battlerId) { u32 partnerBattler = BATTLE_PARTNER(battlerId); @@ -4887,50 +4943,411 @@ bool32 IsMoxieTypeAbility(u32 ability) } } -// Should the AI use a spread move to deliberately activate its partner's ability? -bool32 ShouldTriggerAbility(u32 battler, u32 ability) +bool32 DoesAbilityRaiseStatsWhenLowered(u32 ability) +{ + switch (ability) + { + case ABILITY_CONTRARY: + case ABILITY_COMPETITIVE: + case ABILITY_DEFIANT: + return TRUE; + default: + return FALSE; + } +} + +bool32 DoesIntimidateRaiseStats(u32 ability) { switch (ability) { + case ABILITY_COMPETITIVE: + case ABILITY_CONTRARY: + case ABILITY_DEFIANT: + case ABILITY_GUARD_DOG: + case ABILITY_RATTLED: + return TRUE; + default: + return FALSE; + } +} + +// TODO: work out when to attack into the player's contextually 'beneficial' ability +bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability) +{ + if (IsTargetingPartner(battlerAtk, battlerDef)) + { + switch (ability) + { case ABILITY_LIGHTNING_ROD: case ABILITY_STORM_DRAIN: if (B_REDIRECT_ABILITY_IMMUNITY < GEN_5) return FALSE; else - return (BattlerStatCanRise(battler, ability, STAT_SPATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_SPECIAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_SPATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)); case ABILITY_DEFIANT: case ABILITY_JUSTIFIED: case ABILITY_MOXIE: case ABILITY_SAP_SIPPER: case ABILITY_THERMAL_EXCHANGE: - return (BattlerStatCanRise(battler, ability, STAT_ATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_ATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL)); case ABILITY_COMPETITIVE: - return (BattlerStatCanRise(battler, ability, STAT_SPATK) && HasMoveWithCategory(battler, DAMAGE_CATEGORY_SPECIAL)); + return (BattlerStatCanRise(battlerDef, ability, STAT_SPATK) && HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)); + // TODO: logic for when to trigger Contrary case ABILITY_CONTRARY: return TRUE; case ABILITY_DRY_SKIN: case ABILITY_VOLT_ABSORB: case ABILITY_WATER_ABSORB: - return (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_HP_AWARE); + return (gAiThinkingStruct->aiFlags[battlerDef] & AI_FLAG_HP_AWARE); case ABILITY_RATTLED: case ABILITY_STEAM_ENGINE: - return BattlerStatCanRise(battler, ability, STAT_SPEED); + return BattlerStatCanRise(battlerDef, ability, STAT_SPEED); case ABILITY_FLASH_FIRE: - return (HasMoveWithType(battler, TYPE_FIRE) && !gDisableStructs[battler].flashFireBoosted); + return (HasMoveWithType(battlerDef, TYPE_FIRE) && !gDisableStructs[battlerDef].flashFireBoosted); case ABILITY_WATER_COMPACTION: case ABILITY_WELL_BAKED_BODY: - return (BattlerStatCanRise(battler, ability, STAT_DEF)); + return (BattlerStatCanRise(battlerDef, ability, STAT_DEF)); default: return FALSE; + } + } + else + { + return FALSE; + } +} + +// Used by CheckBadMove; this is determining purely if the effect CAN change an ability, not if it SHOULD. +// At the moment, the parts about Mummy and Wandering Spirit are not actually used. +bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData) +{ + // Dynamaxed Pokemon are immune to some ability-changing effects. + if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) + { + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_SKILL_SWAP: + return FALSE; + default: + break; + } + } + + if (gStatuses3[battlerDef] & STATUS3_GASTRO_ACID) + return FALSE; + + u32 atkAbility = aiData->abilities[battlerAtk]; + u32 defAbility = aiData->abilities[battlerDef]; + bool32 hasSameAbility = (atkAbility == defAbility); + + if (defAbility == ABILITY_NONE) + return FALSE; + + if (atkAbility == ABILITY_NONE) + { + switch (effect) + { + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_ROLE_PLAY: + case EFFECT_SKILL_SWAP: + return FALSE; + + default: + break; + } } + + // Checking for Ability-specific immunities. + switch (effect) + { + case EFFECT_DOODLE: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSuppressed || gAbilitiesInfo[defAbility].cantBeCopied) + return FALSE; + + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + { + u32 partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; + if (gAbilitiesInfo[partnerAbility].cantBeSuppressed) + return FALSE; + if (partnerAbility == defAbility) + return FALSE; + } + break; + + case EFFECT_ROLE_PLAY: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSuppressed || gAbilitiesInfo[defAbility].cantBeCopied) + return FALSE; + break; + + case EFFECT_SKILL_SWAP: + if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSwapped || gAbilitiesInfo[defAbility].cantBeSwapped) + return FALSE; + break; + + case EFFECT_GASTRO_ACID: + if (gAbilitiesInfo[defAbility].cantBeSuppressed) + return FALSE; + break; + + case EFFECT_ENTRAINMENT: + if (hasSameAbility || gAbilitiesInfo[defAbility].cantBeOverwritten || gAbilitiesInfo[atkAbility].cantBeCopied) + return FALSE; + break; + + case EFFECT_SIMPLE_BEAM: + if (defAbility == ABILITY_SIMPLE || gAbilitiesInfo[defAbility].cantBeOverwritten) + return FALSE; + break; + + case EFFECT_WORRY_SEED: + if (defAbility == ABILITY_INSOMNIA || gAbilitiesInfo[defAbility].cantBeOverwritten) + return FALSE; + break; + + default: + return FALSE; + } + + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_ABILITY_SHIELD) + { + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + return FALSE; + default: + break; + } + } + + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD) + { + switch (effect) + { + case EFFECT_DOODLE: + case EFFECT_ROLE_PLAY: + case EFFECT_SKILL_SWAP: + return FALSE; + default: + break; + } + } + + return TRUE; +} + +bool32 DoesEffectReplaceTargetAbility(u32 effect) +{ + switch (effect) + { + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + return TRUE; + default: + return FALSE; + } +} + +void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, struct AiLogicData *aiData) +{ + bool32 isTargetingPartner = IsTargetingPartner(battlerAtk, battlerDef); + u32 abilityAtk = aiData->abilities[battlerAtk]; + u32 abilityDef = aiData->abilities[battlerDef]; + bool32 partnerHasBadAbility = FALSE; + u32 partnerAbility = ABILITY_NONE; + bool32 attackerHasBadAbility = (gAbilitiesInfo[abilityAtk].aiRating < 0); + s32 currentAbilityScore, transferredAbilityScore = 0; + + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + { + partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; + if (!(gAbilitiesInfo[partnerAbility].cantBeSuppressed) && (gAbilitiesInfo[partnerAbility].aiRating < 0)) + partnerHasBadAbility = TRUE; + } + + if (effect == EFFECT_GASTRO_ACID) + abilityAtk = ABILITY_NONE; + else if (effect == EFFECT_SIMPLE_BEAM) + abilityAtk = ABILITY_SIMPLE; + else if (effect == EFFECT_WORRY_SEED) + abilityAtk = ABILITY_INSOMNIA; + + if (effect == EFFECT_DOODLE || effect == EFFECT_ROLE_PLAY || effect == EFFECT_SKILL_SWAP) + { + if (partnerHasBadAbility && effect == EFFECT_DOODLE) + ADJUST_SCORE_PTR(DECENT_EFFECT); + + if (attackerHasBadAbility) + ADJUST_SCORE_PTR(DECENT_EFFECT); + + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerAtk, abilityAtk, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerAtk, abilityDef, aiData); + ADJUST_SCORE_PTR(transferredAbilityScore - currentAbilityScore); + } + + if (isTargetingPartner) + { + if (DoesEffectReplaceTargetAbility(effect)) + { + if (partnerHasBadAbility) + ADJUST_SCORE_PTR(BEST_EFFECT); + + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityDef, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityAtk, aiData); + ADJUST_SCORE_PTR(transferredAbilityScore - currentAbilityScore); + } + else // This is only Role Play as Doodle can't target the partner + { + ADJUST_SCORE_PTR(-20); + } + + // Trigger Plus or Minus in modern gens. This is not in the overarching function because Skill Swap is rarely beneficial here. + if (B_PLUS_MINUS_INTERACTION >= GEN_5) + { + if (((effect == EFFECT_ENTRAINMENT) && (abilityAtk == ABILITY_PLUS || abilityAtk == ABILITY_MINUS)) || ((effect == EFFECT_ROLE_PLAY) && (abilityDef == ABILITY_PLUS || abilityDef == ABILITY_MINUS))) + ADJUST_SCORE_PTR(DECENT_EFFECT); + } + + } + // Targeting an opponent. + else + { + // We already checked if we want their ability, so now we look to see if we want them to lose their ability. + if (DoesEffectReplaceTargetAbility(effect)) + { + currentAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityDef, aiData); + transferredAbilityScore = BattlerBenefitsFromAbilityScore(battlerDef, abilityAtk, aiData); + ADJUST_SCORE_PTR(currentAbilityScore - transferredAbilityScore); + } + } +} + +s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData *aiData) +{ + if (gAbilitiesInfo[ability].aiRating < 0) + return WORST_EFFECT; + + switch (ability) + { + // Transferrable abilities that can be assumed to be always beneficial. + case ABILITY_CLEAR_BODY: + case ABILITY_GOOD_AS_GOLD: + case ABILITY_MAGIC_GUARD: + case ABILITY_MOODY: + case ABILITY_PURIFYING_SALT: + case ABILITY_SPEED_BOOST: + case ABILITY_WHITE_SMOKE: + return GOOD_EFFECT; + // Conditional ability logic goes here. + case ABILITY_COMPOUND_EYES: + if (HasMoveWithLowAccuracy(battler, FOE(battler), 90, TRUE, aiData->abilities[battler], aiData->abilities[FOE(battler)], aiData->holdEffects[battler], aiData->holdEffects[FOE(battler)])) + return GOOD_EFFECT; + break; + case ABILITY_CONTRARY: + if (HasMoveThatLowersOwnStats(battler)) + return BEST_EFFECT; + if (HasMoveThatRaisesOwnStats(battler)) + return AWFUL_EFFECT; + break; + case ABILITY_FRIEND_GUARD: + case ABILITY_POWER_SPOT: + case ABILITY_VICTORY_STAR: + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)) && aiData->abilities[BATTLE_PARTNER(battler)] != ability) + return GOOD_EFFECT; + break; + case ABILITY_GUTS: + if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_REFRESH)) + return GOOD_EFFECT; + break; + case ABILITY_HUGE_POWER: + case ABILITY_PURE_POWER: + if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL)) + return BEST_EFFECT; + break; + // Also used to Worry Seed WORRY_SEED + case ABILITY_INSOMNIA: + case ABILITY_VITAL_SPIRIT: + if (HasMoveWithEffect(battler, EFFECT_REST)) + return WORST_EFFECT; + return NO_INCREASE; + case ABILITY_INTIMIDATE: + u32 abilityDef = aiData->abilities[FOE(battler)]; + if (DoesIntimidateRaiseStats(abilityDef)) + { + return AWFUL_EFFECT; + } + else + { + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(FOE(battler)))) + { + abilityDef = aiData->abilities[BATTLE_PARTNER(FOE(battler))]; + if (DoesIntimidateRaiseStats(abilityDef)) + { + return AWFUL_EFFECT; + } + else + { + s32 score1 = IncreaseStatDownScore(battler, FOE(battler), STAT_ATK); + s32 score2 = IncreaseStatDownScore(battler, BATTLE_PARTNER(FOE(battler)), STAT_ATK); + if (score1 > score2) + return score1; + else + return score2; + } + } + return IncreaseStatDownScore(battler, FOE(battler), STAT_ATK); + } + case ABILITY_NO_GUARD: + if (HasLowAccuracyMove(battler, FOE(battler))) + return GOOD_EFFECT; + break; + // Toxic counter ticks upward while Poison Healed; losing Poison Heal while Toxiced can KO. + case ABILITY_POISON_HEAL: + if (gBattleMons[battler].status1 & (STATUS1_POISON)) + return WEAK_EFFECT; + if (gBattleMons[battler].status1 & (STATUS1_TOXIC_POISON)) + return BEST_EFFECT; + break; + // Also used to Simple Beam SIMPLE_BEAM. + case ABILITY_SIMPLE: + // Prioritize moves like Metal Claw, Charge Beam, or Power up Punch + if (HasMoveThatRaisesOwnStats(battler)) + return GOOD_EFFECT; + return NO_INCREASE; + case ABILITY_BEADS_OF_RUIN: + case ABILITY_SWORD_OF_RUIN: + case ABILITY_TABLETS_OF_RUIN: + case ABILITY_VESSEL_OF_RUIN: + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + if (aiData->abilities[BATTLE_PARTNER(battler)] != ability) + return GOOD_EFFECT; + else + return NO_INCREASE; + } + return GOOD_EFFECT; + default: + break; + } + + return NO_INCREASE; } u32 GetThinkingBattler(u32 battler) diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index 0a5a9ff3df..47cf2450a9 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -278,3 +278,35 @@ AI_SINGLE_BATTLE_TEST("AI uses Wide Guard against Earthquake when opponent would TURN { MOVE(player, MOVE_EARTHQUAKE); EXPECT_MOVE(opponent, MOVE_WIDE_GUARD); } } } + +AI_SINGLE_BATTLE_TEST("AI uses Worry Seed against Rest") +{ + GIVEN { + PLAYER(SPECIES_ZUBAT) { Moves(MOVE_REST, MOVE_SLEEP_TALK, MOVE_AIR_CUTTER); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); + OPPONENT(SPECIES_BUDEW) { Moves(MOVE_WORRY_SEED, MOVE_SLUDGE_BOMB); } + } WHEN { + TURN { MOVE(player, MOVE_AIR_CUTTER); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Simple Beam against Contrary Leaf Storm") +{ + u32 ability, move; + PARAMETRIZE { ability = ABILITY_CONTRARY; move = MOVE_LEAF_STORM; } + PARAMETRIZE { ability = ABILITY_CONTRARY; move = MOVE_CHARGE_BEAM; } + PARAMETRIZE { ability = ABILITY_OVERGROW; move = MOVE_CHARGE_BEAM; } + + GIVEN { + PLAYER(SPECIES_SERPERIOR) { Moves(move); Ability(ability); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + OPPONENT(SPECIES_SWOOBAT) { Moves(MOVE_GUST, MOVE_SIMPLE_BEAM); } + } WHEN { + if (ability == ABILITY_CONTRARY && move == MOVE_LEAF_STORM) + TURN { MOVE(player, move); EXPECT_MOVE(opponent, MOVE_SIMPLE_BEAM); } + else + TURN { MOVE(player, move); NOT_EXPECT_MOVE(opponent, MOVE_SIMPLE_BEAM); } + } +} + + From e53709aa2553933dd77ab625c1022b1c033ba8f3 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Sat, 5 Jul 2025 15:51:56 +0100 Subject: [PATCH 049/283] Fix incorrect status in beneficial ability Guts check (#7285) --- src/battle_ai_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index fd08bd7c0c..163c6b7e5e 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -5273,7 +5273,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return GOOD_EFFECT; break; case ABILITY_GUTS: - if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_REFRESH)) + if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_CAN_MOVE)) return GOOD_EFFECT; break; case ABILITY_HUGE_POWER: From f8082019450f46652b0ec4db69e1d3436b9d773a Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 5 Jul 2025 21:05:35 +0200 Subject: [PATCH 050/283] Fixes Natural Gift moveend execution (#7274) --- data/battle_scripts_1.s | 8 +-- include/constants/battle_script_commands.h | 2 +- src/battle_script_commands.c | 57 +++++++++++++++---- test/battle/move_effect/natural_gift.c | 61 +++++++++++++++++++++ tools/compresSmol/compresSmol | Bin 0 -> 100384 bytes tools/compresSmol/compresSmolTilemap | Bin 0 -> 104416 bytes 6 files changed, 108 insertions(+), 20 deletions(-) create mode 100755 tools/compresSmol/compresSmol create mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e32dfd2859..60432842f9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2841,13 +2841,7 @@ BattleScript_EffectNaturalGift:: jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailed jumpifstatus3 BS_ATTACKER, STATUS3_EMBARGO, BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE - call BattleScript_EffectHit_RetFromCritCalc - jumpifmovehadnoeffect BattleScript_EffectNaturalGiftEnd - checkparentalbondcounter 2, BattleScript_EffectNaturalGiftEnd - removeitem BS_ATTACKER -BattleScript_EffectNaturalGiftEnd: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + call BattleScript_HitFromCritCalc BattleScript_MakeMoveMissed:: setmoveresultflags MOVE_RESULT_MISSED diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 1da5f3b134..9e0556d8c5 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -283,8 +283,8 @@ enum MoveEndEffects MOVEEND_HIT_ESCAPE, MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts MOVEEND_PICKPOCKET, - MOVEEND_REMOVE_TERRAIN, MOVEEND_WHITE_HERB, + MOVEEND_THIRD_MOVE_BLOCK, MOVEEND_CHANGED_ITEMS, MOVEEND_SAME_MOVE_TURNS, MOVEEND_CLEAR_BITS, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 25edc5d759..664fa22f25 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -347,6 +347,7 @@ static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move); static void ResetValuesForCalledMove(void); static void TryRestoreDamageAfterCheekPouch(u32 battler); +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -7363,21 +7364,50 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_REMOVE_TERRAIN: - if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases - && IsBattlerTurnDamaged(gBattlerTarget)) + case MOVEEND_THIRD_MOVE_BLOCK: + // Special case for Steel Roller since it has to check the chosen move + if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER && IsBattlerTurnDamaged(gBattlerTarget)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_RemoveTerrain; effect = TRUE; + gBattleScripting.moveendState++; + break; } - else if (moveEffect == EFFECT_ICE_SPINNER - && IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget)) + + switch (moveEffect) { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_RemoveTerrain; - effect = TRUE; + case EFFECT_ICE_SPINNER: + if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RemoveTerrain; + effect = TRUE; + } + break; + case EFFECT_NATURAL_GIFT: + if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && GetItemPocket(gBattleMons[gBattlerAttacker].item) == POCKET_BERRIES) + { + u32 item = gBattleMons[gBattlerAttacker].item; + gBattleMons[gBattlerAttacker].item = ITEM_NONE; + gBattleStruct->battlerState[gBattlerAttacker].canPickupItem = TRUE; + gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)] = item; + CheckSetUnburden(gBattlerAttacker); + BtlController_EmitSetMonData( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + REQUEST_HELDITEM_BATTLE, + 0, + sizeof(gBattleMons[gBattlerAttacker].item), + &gBattleMons[gBattlerAttacker].item); + MarkBattlerForControllerExec(gBattlerAttacker); + ClearBattlerItemEffectHistory(gBattlerAttacker); + + if (!TrySymbiosis(gBattlerAttacker, item, TRUE)) + effect = TRUE; + } + default: + break; } gBattleScripting.moveendState++; break; @@ -9193,7 +9223,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef) } // Called by Cmd_removeitem. itemId represents the item that was removed, not being given. -static bool32 TrySymbiosis(u32 battler, u32 itemId) +static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { if (!gBattleStruct->itemLost[B_SIDE_PLAYER][gBattlerPartyIndexes[battler]].stolen && gBattleStruct->changedItems[battler] == ITEM_NONE @@ -9207,7 +9237,10 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId) BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); - BattleScriptPush(gBattlescriptCurrInstr + 2); + if (moveEnd) + BattleScriptPushCursor(); + else + BattleScriptPush(gBattlescriptCurrInstr + 2); gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; return TRUE; } @@ -9245,7 +9278,7 @@ static void Cmd_removeitem(void) MarkBattlerForControllerExec(battler); ClearBattlerItemEffectHistory(battler); - if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId)) + if (!TryCheekPouch(battler, itemId) && !TrySymbiosis(battler, itemId, FALSE)) gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/test/battle/move_effect/natural_gift.c b/test/battle/move_effect/natural_gift.c index dd9b0bd466..ab483db1da 100644 --- a/test/battle/move_effect/natural_gift.c +++ b/test/battle/move_effect/natural_gift.c @@ -1,4 +1,65 @@ #include "global.h" #include "test/battle.h" +SINGLE_BATTLE_TEST("Natural Gift removes berry if move fails due to an immunity") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_PHANPY); + } WHEN { + TURN { MOVE(player, MOVE_NATURAL_GIFT); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Natural Gift does not remove berry if user is ejected out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + } WHEN { + TURN { MOVE(player, MOVE_NATURAL_GIFT); } + TURN { SWITCH(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } THEN { + EXPECT(player->item == ITEM_PECHA_BERRY); + } +} + +SINGLE_BATTLE_TEST("Natural Gift does not remove berry if user is unable to use a move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_THUNDER_WAVE); MOVE(player, MOVE_NATURAL_GIFT, WITH_RNG(RNG_PARALYSIS, FALSE)); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_PECHA_BERRY); + } +} + +SINGLE_BATTLE_TEST("Natural Gift removes the berry if user missed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PECHA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SAND_ATTACK); MOVE(player, MOVE_NATURAL_GIFT, hit: FALSE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAND_ATTACK, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_NATURAL_GIFT, player); + } THEN { + EXPECT(player->item == ITEM_NONE); + } +} + TO_DO_BATTLE_TEST("TODO: Write Natural Gift (Move Effect) test titles") diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol new file mode 100755 index 0000000000000000000000000000000000000000..c518f8381b4a471181752509730a92c1967e738b GIT binary patch literal 100384 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 U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Sun, 6 Jul 2025 14:10:50 +0100 Subject: [PATCH 051/283] Added missing braces (#7288) --- src/battle_ai_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 163c6b7e5e..5f8b6bb4be 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -5288,6 +5288,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return WORST_EFFECT; return NO_INCREASE; case ABILITY_INTIMIDATE: + { u32 abilityDef = aiData->abilities[FOE(battler)]; if (DoesIntimidateRaiseStats(abilityDef)) { @@ -5314,6 +5315,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData } return IncreaseStatDownScore(battler, FOE(battler), STAT_ATK); } + } case ABILITY_NO_GUARD: if (HasLowAccuracyMove(battler, FOE(battler))) return GOOD_EFFECT; From a24353d184a3e2cc9a6d1133ec1d0a0fc34c3a4e Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sun, 6 Jul 2025 09:11:04 -0400 Subject: [PATCH 052/283] Add Overcoat Tests (#7287) Co-authored-by: ghoulslash Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- test/battle/ability/overcoat.c | 60 ++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c index 96f3ffcb08..da067a8771 100644 --- a/test/battle/ability/overcoat.c +++ b/test/battle/ability/overcoat.c @@ -16,6 +16,60 @@ SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves") } } -TO_DO_BATTLE_TEST("Overcoat blocks damage from hail"); -TO_DO_BATTLE_TEST("Overcoat blocks damage from sandstorm"); -TO_DO_BATTLE_TEST("Overcoat blocks Effect Spore's effect"); +DOUBLE_BATTLE_TEST("Overcoat blocks damage from sandstorm") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT) { Speed(50); } + PLAYER(SPECIES_HELIOLISK) { Speed(40); Ability(ABILITY_SAND_VEIL); } + OPPONENT(SPECIES_PINECO) { Speed(30); Ability(ABILITY_OVERCOAT); } + OPPONENT(SPECIES_STARLY) { Speed(20); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SANDSTORM); } + } SCENE { + MESSAGE("Wynaut used Sandstorm!"); + MESSAGE("The sandstorm is raging."); + HP_BAR(playerLeft); + NONE_OF { + HP_BAR(playerRight); + HP_BAR(opponentLeft); + } + HP_BAR(opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Overcoat blocks damage from hail") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT) { Speed(50); Ability(ABILITY_SNOW_CLOAK); } + PLAYER(SPECIES_SOLOSIS) { Speed(40); Ability(ABILITY_RUN_AWAY); } + OPPONENT(SPECIES_PINECO) { Speed(30); Ability(ABILITY_OVERCOAT); } + OPPONENT(SPECIES_SNORUNT) { Speed(20); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_HAIL); MOVE(playerRight, MOVE_SKILL_SWAP, target: playerLeft); } + } SCENE { + MESSAGE("Wynaut used Hail!"); + MESSAGE("Solosis used Skill Swap!"); + HP_BAR(playerLeft); + NONE_OF { + HP_BAR(playerRight); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); // ice type + } + } +} + +SINGLE_BATTLE_TEST("Overcoat blocks Effect Spore's effect") +{ + GIVEN { + 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); + } THEN { + EXPECT_EQ(player->status1, 0); + } +} + From 80b9c23d0af9cdde79fa2cd6a539f7e1a144d96d Mon Sep 17 00:00:00 2001 From: Raymond Dodge Date: Sun, 6 Jul 2025 13:49:47 -0400 Subject: [PATCH 053/283] Fix RL compressed data alignment `RLUnComp`, like `LZ77UnComp`, expects the source data to be word-aligned. So, to mirror how lz-compressed data is defined as `u32[]` to enforce word-alignment, this changes rl-compressed data to be defined as `u32[]` to enforce word-alignment. --- include/gba/syscall.h | 4 ++-- src/contest_painting.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/gba/syscall.h b/include/gba/syscall.h index c922084d5f..50f5781988 100644 --- a/include/gba/syscall.h +++ b/include/gba/syscall.h @@ -61,9 +61,9 @@ void LZ77UnCompWram(const u32 *src, void *dest); void LZ77UnCompVram(const u32 *src, void *dest); -void RLUnCompWram(const void *src, void *dest); +void RLUnCompWram(const u32 *src, void *dest); -void RLUnCompVram(const void *src, void *dest); +void RLUnCompVram(const u32 *src, void *dest); int MultiBoot(struct MultiBootParam *mp); diff --git a/src/contest_painting.c b/src/contest_painting.c index c72d0dc6af..e12fa4c4d7 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -69,19 +69,19 @@ extern const u8 gContestPaintingTough1[]; extern const u8 gContestPaintingTough2[]; extern const u8 gContestPaintingTough3[]; -static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); -static const u8 sPictureFrameTiles_Cool[] = INCBIN_U8("graphics/picture_frame/cool.4bpp.rl"); -static const u8 sPictureFrameTiles_Beauty[] = INCBIN_U8("graphics/picture_frame/beauty.4bpp.rl"); -static const u8 sPictureFrameTiles_Cute[] = INCBIN_U8("graphics/picture_frame/cute.4bpp.rl"); -static const u8 sPictureFrameTiles_Smart[] = INCBIN_U8("graphics/picture_frame/smart.4bpp.rl"); -static const u8 sPictureFrameTiles_Tough[] = INCBIN_U8("graphics/picture_frame/tough.4bpp.rl"); -static const u8 sPictureFrameTiles_HallLobby[] = INCBIN_U8("graphics/picture_frame/lobby.4bpp.rl"); -static const u8 sPictureFrameTilemap_Cool[] = INCBIN_U8("graphics/picture_frame/cool_map.bin.rl"); -static const u8 sPictureFrameTilemap_Beauty[] = INCBIN_U8("graphics/picture_frame/beauty_map.bin.rl"); -static const u8 sPictureFrameTilemap_Cute[] = INCBIN_U8("graphics/picture_frame/cute_map.bin.rl"); -static const u8 sPictureFrameTilemap_Smart[] = INCBIN_U8("graphics/picture_frame/smart_map.bin.rl"); -static const u8 sPictureFrameTilemap_Tough[] = INCBIN_U8("graphics/picture_frame/tough_map.bin.rl"); -static const u8 sPictureFrameTilemap_HallLobby[] = INCBIN_U8("graphics/picture_frame/lobby_map.bin.rl"); +static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); +static const u32 sPictureFrameTiles_Cool[] = INCBIN_U32("graphics/picture_frame/cool.4bpp.rl"); +static const u32 sPictureFrameTiles_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty.4bpp.rl"); +static const u32 sPictureFrameTiles_Cute[] = INCBIN_U32("graphics/picture_frame/cute.4bpp.rl"); +static const u32 sPictureFrameTiles_Smart[] = INCBIN_U32("graphics/picture_frame/smart.4bpp.rl"); +static const u32 sPictureFrameTiles_Tough[] = INCBIN_U32("graphics/picture_frame/tough.4bpp.rl"); +static const u32 sPictureFrameTiles_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby.4bpp.rl"); +static const u32 sPictureFrameTilemap_Cool[] = INCBIN_U32("graphics/picture_frame/cool_map.bin.rl"); +static const u32 sPictureFrameTilemap_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty_map.bin.rl"); +static const u32 sPictureFrameTilemap_Cute[] = INCBIN_U32("graphics/picture_frame/cute_map.bin.rl"); +static const u32 sPictureFrameTilemap_Smart[] = INCBIN_U32("graphics/picture_frame/smart_map.bin.rl"); +static const u32 sPictureFrameTilemap_Tough[] = INCBIN_U32("graphics/picture_frame/tough_map.bin.rl"); +static const u32 sPictureFrameTilemap_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby_map.bin.rl"); static const u8 *const sContestCategoryNames_Unused[] = { From 4cb6afdec91b374114424a4109e4c64665e18555 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:20:23 -0400 Subject: [PATCH 054/283] Ally Switch swap gLastX values (#7290) Co-authored-by: ghoulslash --- src/battle_anim_effects_1.c | 27 ++++++++++++++++++++++----- test/battle/move_effect/ally_switch.c | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index bc3b4a2c44..74444065b8 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6864,6 +6864,25 @@ static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp); } +static void SwapBattlerMoveData(u32 battler1, u32 battler2) +{ + u32 temp; + SWAP(gBattleStruct->chosenMovePositions[battler1], gBattleStruct->chosenMovePositions[battler2], temp); + SWAP(gChosenMoveByBattler[battler1], gChosenMoveByBattler[battler2], temp); + SWAP(gBattleStruct->moveTarget[battler1], gBattleStruct->moveTarget[battler2], temp); + SWAP(gMoveSelectionCursor[battler1], gMoveSelectionCursor[battler2], temp); + SWAP(gLockedMoves[battler1], gLockedMoves[battler2], temp); + + // update last moves + SWAP(gLastPrintedMoves[battler1], gLastPrintedMoves[battler2], temp); + SWAP(gLastMoves[battler1], gLastMoves[battler2], temp); + SWAP(gLastLandedMoves[battler1], gLastLandedMoves[battler2], temp); + SWAP(gLastHitByType[battler1], gLastHitByType[battler2], temp); + SWAP(gLastUsedMoveType[battler1], gLastUsedMoveType[battler2], temp); + SWAP(gLastResultingMoves[battler1], gLastResultingMoves[battler2], temp); + SWAP(gLastHitBy[battler1], gLastHitBy[battler2], temp); +} + static void AnimTask_AllySwitchDataSwap(u8 taskId) { s32 i, j; @@ -6890,11 +6909,9 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp); - SWAP(gBattleStruct->chosenMovePositions[battlerAtk], gBattleStruct->chosenMovePositions[battlerPartner], temp); - SWAP(gChosenMoveByBattler[battlerAtk], gChosenMoveByBattler[battlerPartner], temp); - SWAP(gLockedMoves[battlerAtk], gLockedMoves[battlerPartner], temp); - SWAP(gBattleStruct->moveTarget[battlerAtk], gBattleStruct->moveTarget[battlerPartner], temp); - SWAP(gMoveSelectionCursor[battlerAtk], gMoveSelectionCursor[battlerPartner], temp); + + SwapBattlerMoveData(battlerAtk, battlerPartner); + // Swap turn order, so that all the battlers take action SWAP(gChosenActionByBattler[battlerAtk], gChosenActionByBattler[battlerPartner], temp); for (i = 0; i < gBattlersCount; i++) diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index 1c28e51a9b..a8e9944e34 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -311,5 +311,27 @@ DOUBLE_BATTLE_TEST("Ally Switch swaps Illusion data") } } +DOUBLE_BATTLE_TEST("Ally switch updates last used moves for Mimic") +{ + GIVEN { + PLAYER(SPECIES_XATU) { Speed(100); } + PLAYER(SPECIES_RIOLU) { Speed(150); } + OPPONENT(SPECIES_FEAROW) { Speed(20); } + OPPONENT(SPECIES_ARON) { Speed(30); } + } WHEN { + TURN { MOVE(playerRight, MOVE_FAKE_OUT, target: opponentRight); MOVE(playerLeft, MOVE_ALLY_SWITCH); + MOVE(opponentLeft, MOVE_MIMIC, target: playerLeft); + } + } SCENE { + MESSAGE("Riolu used Fake Out!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, playerRight); + MESSAGE("Xatu used Ally Switch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); + MESSAGE("Xatu and Riolu switched places!"); + MESSAGE("The opposing Fearow used Mimic!"); + MESSAGE("The opposing Fearow learned Fake Out!"); + } +} + // Triple Battles required to test //TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle"); From 94ddf6dea0ce072954838e2a3d69f5ede7626b87 Mon Sep 17 00:00:00 2001 From: pokesidv <216572922+pokesidv@users.noreply.github.com> Date: Mon, 7 Jul 2025 19:26:44 +0200 Subject: [PATCH 055/283] fix: added warning about dns tutorial and triple-layer metatiles tutorial compatibility to the dns tutorial. (#7256) --- docs/tutorials/dns.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/tutorials/dns.md b/docs/tutorials/dns.md index 350957f076..908329761e 100644 --- a/docs/tutorials/dns.md +++ b/docs/tutorials/dns.md @@ -12,6 +12,9 @@ If you intend to use vanilla maps and have not already edited them, revert commi If you _have_ edited vanilla maps, the merge conflicts from reverting that commit will cause problems. If you are using vanilla maps, manually copy some of the tileset changes, `.pal`, and `.pla` files in your branch, and begin rebuilding your metatiles to have windows use the palettes that have a `.pla` for light blending the correct color slots. [Triple-layer metatiles](https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles) are highly recommended. +WARNING: [As per issue #7034](https://github.com/rh-hideout/pokeemerald-expansion/issues/7034) if you follow this tutorial reverting the previously mentioned commit to use the updated palettes in the Hoenn maps and *after* that you try to follow the [Triple-layer metatiles tutorial](https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles), you'll encounter an issue when running the script to update old tilesets to support triple-layer metatiles. +Follow the band-aid fix proposed in that issue after this tutorial but before following the triple-layer metatiles tutorial if you want everythign to work properly with light-blended palettes and triple-layer metatiles together. + You will also want to add the lighting object events from that commit. If you are not using Hoenn maps, the primary concern is that you do not use the exact same palette indices for colors you want to be darkened during night time and colors you want to light up. Err towards not light blending a color if you aren't sure how to avoid conflicts. From 0422a013c4ef8ce48184eb3a2bd550f32d370938 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 7 Jul 2025 19:33:57 +0200 Subject: [PATCH 056/283] Add Set Hidden Nature option to the debug menu (#7281) --- data/scripts/debug.inc | 89 ++++++++++++++++++++++++++++++++++++++++++ data/specials.inc | 1 + src/debug.c | 4 +- src/field_specials.c | 7 ++++ 4 files changed, 100 insertions(+), 1 deletion(-) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 05eeb4ecaf..e43df32813 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -353,6 +353,44 @@ Debug_EventScript_InflictStatus1_Single: releaseall end +Debug_EventScript_SetHiddenNature:: + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_EventScript_InflictStatus1_Close + specialvar VAR_RESULT, ScriptGetPartyMonSpecies + goto_if_eq VAR_RESULT, SPECIES_EGG, Debug_EventScript_InflictStatus1_Close + dynmultipush Debug_EventScript_ChangeNature_Text_Hardy, 0 + dynmultipush Debug_EventScript_ChangeNature_Text_Lonely, 1 + dynmultipush Debug_EventScript_ChangeNature_Text_Brave, 2 + dynmultipush Debug_EventScript_ChangeNature_Text_Adamant, 3 + dynmultipush Debug_EventScript_ChangeNature_Text_Naughty, 4 + dynmultipush Debug_EventScript_ChangeNature_Text_Bold, 5 + dynmultipush Debug_EventScript_ChangeNature_Text_Docile, 6 + dynmultipush Debug_EventScript_ChangeNature_Text_Relaxed, 7 + dynmultipush Debug_EventScript_ChangeNature_Text_Impish, 8 + dynmultipush Debug_EventScript_ChangeNature_Text_Lax, 9 + dynmultipush Debug_EventScript_ChangeNature_Text_Timid, 10 + dynmultipush Debug_EventScript_ChangeNature_Text_Hasty, 11 + dynmultipush Debug_EventScript_ChangeNature_Text_Serious, 12 + dynmultipush Debug_EventScript_ChangeNature_Text_Jolly, 13 + dynmultipush Debug_EventScript_ChangeNature_Text_Naive, 14 + dynmultipush Debug_EventScript_ChangeNature_Text_Modest, 15 + dynmultipush Debug_EventScript_ChangeNature_Text_Mild, 16 + dynmultipush Debug_EventScript_ChangeNature_Text_Quiet, 17 + dynmultipush Debug_EventScript_ChangeNature_Text_Bashful, 18 + dynmultipush Debug_EventScript_ChangeNature_Text_Rash, 19 + dynmultipush Debug_EventScript_ChangeNature_Text_Calm, 20 + dynmultipush Debug_EventScript_ChangeNature_Text_Gentle, 21 + dynmultipush Debug_EventScript_ChangeNature_Text_Sassy, 22 + dynmultipush Debug_EventScript_ChangeNature_Text_Careful, 23 + dynmultipush Debug_EventScript_ChangeNature_Text_Quirky, 24 + dynmultistack 0, 0, TRUE, 7, FALSE, 0, NULL + switch VAR_RESULT + case MULTI_B_PRESSED, Debug_EventScript_InflictStatus1_Close + special SetHiddenNature + releaseall + end + Debug_EventScript_InflictStatus1_Single_Poison: setstatus1 STATUS1_POISON, VAR_0x8004 releaseall @@ -461,6 +499,57 @@ Debug_EventScript_InflictStatus1_Text_Freeze: Debug_EventScript_InflictStatus1_Text_Frostbite: .string "Frostbite$" +Debug_EventScript_ChangeNature_Text_Hardy: + .string "Hardy$" +Debug_EventScript_ChangeNature_Text_Lonely: + .string "Lonely$" +Debug_EventScript_ChangeNature_Text_Brave: + .string "Brave$" +Debug_EventScript_ChangeNature_Text_Adamant: + .string "Adamant$" +Debug_EventScript_ChangeNature_Text_Naughty: + .string "Naughty$" +Debug_EventScript_ChangeNature_Text_Bold: + .string "Bold$" +Debug_EventScript_ChangeNature_Text_Docile: + .string "Docile$" +Debug_EventScript_ChangeNature_Text_Relaxed: + .string "Relaxed$" +Debug_EventScript_ChangeNature_Text_Impish: + .string "Impish$" +Debug_EventScript_ChangeNature_Text_Lax: + .string "Lax$" +Debug_EventScript_ChangeNature_Text_Timid: + .string "Timid$" +Debug_EventScript_ChangeNature_Text_Hasty: + .string "Hasty$" +Debug_EventScript_ChangeNature_Text_Serious: + .string "Serious$" +Debug_EventScript_ChangeNature_Text_Jolly: + .string "Jolly$" +Debug_EventScript_ChangeNature_Text_Naive: + .string "Naive$" +Debug_EventScript_ChangeNature_Text_Modest: + .string "Modest$" +Debug_EventScript_ChangeNature_Text_Mild: + .string "Mild$" +Debug_EventScript_ChangeNature_Text_Quiet: + .string "Quiet$" +Debug_EventScript_ChangeNature_Text_Bashful: + .string "Bashful$" +Debug_EventScript_ChangeNature_Text_Rash: + .string "Rash$" +Debug_EventScript_ChangeNature_Text_Calm: + .string "Calm$" +Debug_EventScript_ChangeNature_Text_Gentle: + .string "Gentle$" +Debug_EventScript_ChangeNature_Text_Sassy: + .string "Sassy$" +Debug_EventScript_ChangeNature_Text_Careful: + .string "Careful$" +Debug_EventScript_ChangeNature_Text_Quirky: + .string "Quirky$" + Debug_EventScript_EWRAMCounters:: callnative CheckEWRAMCounters msgbox Debug_EventScript_EWRAMCounters_Text, MSGBOX_DEFAULT diff --git a/data/specials.inc b/data/specials.inc index c95cea9a7e..0a2ae2da50 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -563,3 +563,4 @@ gSpecials:: def_special UseBlankMessageToCancelPokemonPic def_special EnterCode def_special GetCodeFeedback + def_special SetHiddenNature diff --git a/src/debug.c b/src/debug.c index 3f970ae7fc..041734ebf5 100644 --- a/src/debug.c +++ b/src/debug.c @@ -345,6 +345,7 @@ extern const u8 Debug_EventScript_FontTest[]; extern const u8 Debug_EventScript_CheckEVs[]; extern const u8 Debug_EventScript_CheckIVs[]; extern const u8 Debug_EventScript_InflictStatus1[]; +extern const u8 Debug_EventScript_SetHiddenNature[]; extern const u8 Debug_EventScript_Script_1[]; extern const u8 Debug_EventScript_Script_2[]; extern const u8 Debug_EventScript_Script_3[]; @@ -572,6 +573,7 @@ static const struct DebugMenuOption sDebugMenu_Actions_Party[] = { COMPOUND_STRING("Hatch an Egg"), DebugAction_ExecuteScript, Debug_HatchAnEgg }, { COMPOUND_STRING("Heal party"), DebugAction_Party_HealParty }, { COMPOUND_STRING("Inflict Status1"), DebugAction_ExecuteScript, Debug_EventScript_InflictStatus1 }, + { COMPOUND_STRING("Set Hidden Nature"), DebugAction_ExecuteScript, Debug_EventScript_SetHiddenNature }, { COMPOUND_STRING("Check EVs"), DebugAction_ExecuteScript, Debug_EventScript_CheckEVs }, { COMPOUND_STRING("Check IVs"), DebugAction_ExecuteScript, Debug_EventScript_CheckIVs }, { COMPOUND_STRING("Clear Party"), DebugAction_Party_ClearParty }, @@ -3418,7 +3420,7 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId) } } -static const u32 gDebugFollowerNPCGraphics[] = +static const u32 gDebugFollowerNPCGraphics[] = { OBJ_EVENT_GFX_RIVAL_BRENDAN_NORMAL, OBJ_EVENT_GFX_RIVAL_MAY_NORMAL, diff --git a/src/field_specials.c b/src/field_specials.c index 927326e399..549a3b9198 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -4361,3 +4361,10 @@ void GetCodeFeedback(void) else gSpecialVar_Result = 0; } + +void SetHiddenNature(void) +{ + u32 hiddenNature = gSpecialVar_Result; + SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_HIDDEN_NATURE, &hiddenNature); + CalculateMonStats(&gPlayerParty[gSpecialVar_0x8004]); +} From 7ae97ab6e930376cf6b385c9a3fb4c2af96a5987 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 7 Jul 2025 19:36:21 +0200 Subject: [PATCH 057/283] Refactor move Synchronise (#7271) --- asm/macros/battle_script.inc | 5 ++ data/battle_scripts_1.s | 46 +++++----------- include/battle_scripts.h | 2 +- include/constants/battle.h | 1 + src/battle_script_commands.c | 73 +++++++++++++++++++------- src/battle_util.c | 3 +- test/battle/gimmick/terastal.c | 2 +- test/battle/move_effect/synchronoise.c | 70 ++++++++++++++++++++++++ 8 files changed, 147 insertions(+), 55 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b23992d332..d9a7ca5fed 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2461,6 +2461,11 @@ .byte \battler .endm + .macro trysynchronoise jumpInstr:req + callnative BS_TrySynchronoise + .4byte \jumpInstr + .endm + .macro setallytonexttarget jumpInstr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a57ce67c25..6f20b90345 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1622,42 +1622,20 @@ BattleScript_EffectPsychoShiftCanWork: BattleScript_EffectSynchronoise:: attackcanceler attackstring + pause B_WAIT_TIME_MED ppreduce - selectfirstvalidtarget -BattleScript_SynchronoiseLoop: - movevaluescleanup - jumpifcantusesynchronoise BattleScript_SynchronoiseNoEffect - accuracycheck BattleScript_SynchronoiseMissed, ACC_CURR_MOVE - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + trysynchronoise BattleScript_MoveEnd + accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc + +BattleScript_ItDoesntAffectFoe:: + savetarget + copybyte gBattlerTarget, sBATTLER + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_SHORT flushtextbox - tryfaintmon BS_TARGET -BattleScript_SynchronoiseMoveTargetEnd: - moveendto MOVEEND_NEXT_TARGET - jumpifnexttargetvalid BattleScript_SynchronoiseLoop - end -BattleScript_SynchronoiseMissed: - pause B_WAIT_TIME_SHORT - resultmessage - waitmessage B_WAIT_TIME_LONG - goto BattleScript_SynchronoiseMoveTargetEnd -BattleScript_SynchronoiseNoEffect: - pause B_WAIT_TIME_SHORT - printstring STRINGID_NOEFFECTONTARGET - waitmessage B_WAIT_TIME_LONG - goto BattleScript_SynchronoiseMoveTargetEnd + restoretarget + return BattleScript_MoveEffectSmackDown:: printstring STRINGID_FELLSTRAIGHTDOWN diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 525d3aefe4..dba2ad49d0 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -526,7 +526,6 @@ extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraFormChange[]; extern const u8 BattleScript_SleepClausePreventsEnd[]; extern const u8 BattleScript_PowerConstruct[]; - extern const u8 BattleScript_AbilityProtectsDoesntAffect[]; extern const u8 BattleScript_ImmunityProtected[]; extern const u8 BattleScript_SafeguardProtected[]; @@ -538,6 +537,7 @@ extern const u8 BattleScript_AlreadyPoisoned[]; extern const u8 BattleScript_AlreadyParalyzed[]; extern const u8 BattleScript_AlreadyBurned[]; extern const u8 BattleScript_PrintAbilityMadeIneffective[]; +extern const u8 BattleScript_ItDoesntAffectFoe[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index e785498489..9064eb3863 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -345,6 +345,7 @@ enum TypeSideHazard #define MOVE_RESULT_FOE_HUNG_ON (1 << 7) #define MOVE_RESULT_STURDIED (1 << 8) #define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) +#define MOVE_RESULT_SYNCHRONOISE_AFFECTED (1 << 10) #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) enum BattleWeather diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ff4104b19e..32c2111488 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1242,22 +1242,24 @@ static void Cmd_attackcanceler(void) u32 abilityDef = GetBattlerAbility(gBattlerTarget); - if (CanAbilityBlockMove(gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - abilityDef, - gCurrentMove, - ABILITY_RUN_SCRIPT)) + if (CanAbilityBlockMove( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + abilityDef, + gCurrentMove, + ABILITY_RUN_SCRIPT)) return; if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS) { - if (CanAbilityAbsorbMove(gBattlerAttacker, - gBattlerTarget, - abilityDef, - gCurrentMove, - GetBattleMoveType(gCurrentMove), - ABILITY_RUN_SCRIPT)) + if (CanAbilityAbsorbMove( + gBattlerAttacker, + gBattlerTarget, + abilityDef, + gCurrentMove, + GetBattleMoveType(gCurrentMove), + ABILITY_RUN_SCRIPT)) return; } @@ -2418,6 +2420,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) if (IsDoubleSpreadMove()) { u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + if (!gBattleStruct->printedStrongWindsWeakenedAttack) { for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) @@ -5957,9 +5960,10 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) u32 battler; for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) { - if (battler != gBattlerAttacker - && !(excludeCurrent && battler == gBattlerTarget) - && IsBattlerAlive(battler) + if (battler == gBattlerAttacker || !IsBattlerAlive(battler)) + continue; + + if (!(excludeCurrent && battler == gBattlerTarget) && !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler] && (!IsBattlerAlly(battler, gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) break; @@ -6665,8 +6669,9 @@ static void Cmd_moveend(void) MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; - if (moveEffect == EFFECT_EXPLOSION || moveEffect == EFFECT_MISTY_EXPLOSION) - BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets + 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 + BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); else BattleScriptPush(GetMoveBattleScript(gCurrentMove)); gBattlescriptCurrInstr = BattleScript_FlushMessageBox; @@ -17907,7 +17912,6 @@ void BS_JumpIfSleepClause(void) void BS_FickleBeamDamageCalculation(void) { NATIVE_ARGS(); - gBattleStruct->fickleBeamBoosted = FALSE; if (RandomPercentage(RNG_FICKLE_BEAM, 30)) { @@ -18671,3 +18675,36 @@ void BS_TryActivateAbilityShield(void) BattleScriptCall(BattleScript_AbilityShieldProtects); } } + +void BS_TrySynchronoise(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + bool32 atleastOneSharedType = FALSE; + + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SYNCHRONOISE_AFFECTED + || gBattlerAttacker == battlerDef + || !IsBattlerAlive(battlerDef)) + continue; + + if (DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + atleastOneSharedType = TRUE; + continue; + } + + if (!DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + gBattleScripting.battler = battlerDef; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_NO_EFFECT | MOVE_RESULT_SYNCHRONOISE_AFFECTED; + BattleScriptCall(BattleScript_ItDoesntAffectFoe); + return; + } + } + + if (atleastOneSharedType) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 76786d1f44..e40020e11f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2513,6 +2513,7 @@ static enum MoveCanceller CancellerMultiTargetMoves(void) if (gBattlerAttacker == battlerDef || !IsBattlerAlive(battlerDef) + || (GetMoveEffect(gCurrentMove) == EFFECT_SYNCHRONOISE && !DoBattlersShareType(gBattlerAttacker, battlerDef)) || (moveTarget == MOVE_TARGET_BOTH && gBattlerAttacker == BATTLE_PARTNER(battlerDef)) || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check { @@ -7914,7 +7915,7 @@ static inline u32 IsFieldMudSportAffected(u32 moveType) return TRUE; } } - + return FALSE; } diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index 7ce10a5942..441487c002 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -385,7 +385,7 @@ SINGLE_BATTLE_TEST("(TERA) Synchronoise uses a Terastallized Pokemon's Tera Type } SCENE { // turn 1 MESSAGE("The opposing Wobbuffet used Synchronoise!"); - MESSAGE("It won't have any effect on Wobbuffet!"); + MESSAGE("It doesn't affect Wobbuffet…"); // turn 2 MESSAGE("The opposing Wobbuffet used Synchronoise!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, opponent); diff --git a/test/battle/move_effect/synchronoise.c b/test/battle/move_effect/synchronoise.c index 9b68ccc63a..45b4f125ea 100644 --- a/test/battle/move_effect/synchronoise.c +++ b/test/battle/move_effect/synchronoise.c @@ -1,4 +1,74 @@ #include "global.h" #include "test/battle.h" +DOUBLE_BATTLE_TEST("Synchronoise hits all Pokemon that share a type with the attacker") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft); + HP_BAR(opponentLeft); + HP_BAR(playerRight); + HP_BAR(opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Synchronoise will fail if there is no corresponding typing on the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_BULBASAUR); + OPPONENT(SPECIES_BULBASAUR); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft); + MESSAGE("Wobbuffet used Synchronoise!"); + MESSAGE("It doesn't affect the opposing Bulbasaur…"); + MESSAGE("It doesn't affect Bulbasaur…"); + MESSAGE("It doesn't affect the opposing Bulbasaur…"); + NOT MESSAGE("But it failed!"); + } +} + +DOUBLE_BATTLE_TEST("Synchronoise will hit if there is at least one target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BULBASAUR); + } WHEN { + TURN { MOVE(playerLeft, MOVE_SYNCHRONOISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft); + HP_BAR(opponentLeft); + NONE_OF { + HP_BAR(playerRight); + HP_BAR(opponentRight); + MESSAGE("But it failed!"); + } + } +} + +DOUBLE_BATTLE_TEST("Synchronoise will fail if the corresponding typing mon protects") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_BULBASAUR); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BULBASAUR); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_PROTECT); MOVE(playerLeft, MOVE_SYNCHRONOISE); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft); + } +} + TO_DO_BATTLE_TEST("TODO: Write Synchronoise (Move Effect) test titles") From 31a561201b2ecbc218f7118bd691f64da6bf5d3b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 7 Jul 2025 21:30:35 +0200 Subject: [PATCH 058/283] Adds hazard queue (#7295) --- data/battle_scripts_1.s | 48 +-- include/battle.h | 25 +- include/battle_scripts.h | 12 +- include/battle_util.h | 6 + include/constants/battle.h | 41 +-- src/battle_ai_main.c | 49 ++- src/battle_ai_switch_items.c | 12 +- src/battle_ai_util.c | 32 +- src/battle_debug.c | 225 +++++++++----- src/battle_message.c | 18 ++ src/battle_script_commands.c | 325 ++++++++++---------- src/battle_util.c | 76 +++++ test/battle/hazards.c | 40 +++ test/battle/move_effect/court_change.c | 16 +- test/battle/move_effect/defog.c | 24 +- test/battle/move_effect/hit_switch_target.c | 4 +- test/battle/move_effect/rapid_spin.c | 29 ++ test/battle/move_effect/spikes.c | 27 ++ test/battle/move_effect/tidy_up.c | 4 +- test/battle/move_effect/toxic_spikes.c | 25 ++ 20 files changed, 659 insertions(+), 379 deletions(-) create mode 100644 test/battle/hazards.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6f20b90345..3bec1be182 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6113,53 +6113,13 @@ BattleScript_LeechSeedFree:: waitmessage B_WAIT_TIME_LONG return -BattleScript_SpikesFree:: - printstring STRINGID_PKMNBLEWAWAYSPIKES +BattleScript_SpinHazardsAway:: + printfromtable gSpinHazardsStringIds waitmessage B_WAIT_TIME_LONG return -BattleScript_ToxicSpikesFree:: - printstring STRINGID_PKMNBLEWAWAYTOXICSPIKES - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StickyWebFree:: - printstring STRINGID_PKMNBLEWAWAYSTICKYWEB - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StealthRockFree:: - printstring STRINGID_PKMNBLEWAWAYSTEALTHROCK - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SteelsurgeFree:: - printstring STRINGID_PKMNBLEWAWAYSHARPSTEEL - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SpikesDefog:: - printstring STRINGID_SPIKESDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_ToxicSpikesDefog:: - printstring STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StickyWebDefog:: - printstring STRINGID_STICKYWEBDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_StealthRockDefog:: - printstring STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM - waitmessage B_WAIT_TIME_LONG - return - -BattleScript_SteelsurgeDefog:: - printstring STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM +BattleScript_DefogClearHazards:: + printfromtable gDefogHazardsStringIds waitmessage B_WAIT_TIME_LONG return diff --git a/include/battle.h b/include/battle.h index e113edd6d4..cdeac89719 100644 --- a/include/battle.h +++ b/include/battle.h @@ -117,24 +117,20 @@ struct DisableStruct u8 tarShot:1; u8 octolock:1; u8 cudChew:1; - u8 spikesDone:1; - u8 toxicSpikesDone:1; - u8 stickyWebDone:1; - u8 stealthRockDone:1; u8 weatherAbilityDone:1; u8 terrainAbilityDone:1; u8 syrupBombIsShiny:1; - u8 steelSurgeDone:1; u8 usedProteanLibero:1; u8 flashFireBoosted:1; - u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 boosterEnergyActivated:1; + u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 roostActive:1; u8 unburdenActive:1; u8 neutralizingGas:1; u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in - u8 padding:3; + u8 hazardsDone:1; + u8 padding:1; }; // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects @@ -222,21 +218,18 @@ struct SideTimer u16 lightscreenTimer; u16 mistTimer; u16 safeguardTimer; - u16 spikesAmount; // debug menu complains. might be better to solve there instead if possible - u16 toxicSpikesAmount; - u16 stealthRockAmount; - u16 stickyWebAmount; + u8 spikesAmount:4; + u8 toxicSpikesAmount:4; u8 stickyWebBattlerId; u8 stickyWebBattlerSide; // Used for Court Change u16 auroraVeilTimer; u16 tailwindTimer; u16 luckyChantTimer; - u16 steelsurgeAmount; // Timers below this point are not swapped by Court Change - u16 followmeTimer; + u8 followmeTimer:4; u8 followmeTarget:3; u8 followmePowder:1; // Rage powder, does not affect grass type pokemon. - u16 retaliateTimer; + u8 retaliateTimer; u16 damageNonTypesTimer; u8 damageNonTypesType; u16 rainbowTimer; @@ -780,6 +773,10 @@ struct BattleStruct s16 savedcheekPouchDamage; // Cheek Pouch can happen in the middle of an attack execution so we need to store the current dmg struct MessageStatus slideMessageStatus; u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT]; + u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT]; + u8 numHazards[NUM_BATTLE_SIDES]; + u8 hazardsCounter:4; // Counter for applying hazard on switch in + u8 padding2:4; }; struct AiBattleData diff --git a/include/battle_scripts.h b/include/battle_scripts.h index dba2ad49d0..06a7e90107 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -92,7 +92,7 @@ extern const u8 BattleScript_AllStatsUp[]; extern const u8 BattleScript_RapidSpinAway[]; extern const u8 BattleScript_WrapFree[]; extern const u8 BattleScript_LeechSeedFree[]; -extern const u8 BattleScript_SpikesFree[]; +extern const u8 BattleScript_SpinHazardsAway[]; extern const u8 BattleScript_MonTookFutureAttack[]; extern const u8 BattleScript_NoMovesLeft[]; extern const u8 BattleScript_SelectingMoveWithNoPP[]; @@ -312,13 +312,7 @@ extern const u8 BattleScript_SelectingNotAllowedMoveGravityInPalace[]; extern const u8 BattleScript_SelectingNotAllowedMoveHealBlock[]; extern const u8 BattleScript_MoveUsedHealBlockPrevents[]; extern const u8 BattleScript_SelectingNotAllowedMoveHealBlockInPalace[]; -extern const u8 BattleScript_ToxicSpikesFree[]; -extern const u8 BattleScript_StickyWebFree[]; -extern const u8 BattleScript_StealthRockFree[]; -extern const u8 BattleScript_SpikesDefog[]; -extern const u8 BattleScript_ToxicSpikesDefog[]; -extern const u8 BattleScript_StickyWebDefog[]; -extern const u8 BattleScript_StealthRockDefog[]; +extern const u8 BattleScript_DefogClearHazards[]; extern const u8 BattleScript_MegaEvolution[]; extern const u8 BattleScript_WishMegaEvolution[]; extern const u8 BattleScript_MoveEffectClearSmog[]; @@ -555,8 +549,6 @@ extern const u8 BattleScript_EffectSetWeather[]; extern const u8 BattleScript_EffectSetTerrain[]; extern const u8 BattleScript_EffectStonesurge[]; extern const u8 BattleScript_EffectSteelsurge[]; -extern const u8 BattleScript_SteelsurgeFree[]; -extern const u8 BattleScript_SteelsurgeDefog[]; extern const u8 BattleScript_DamageNonTypesStarts[]; extern const u8 BattleScript_DamageNonTypesContinues[]; extern const u8 BattleScript_DefogTryHazards[]; diff --git a/include/battle_util.h b/include/battle_util.h index a95d76c61a..dd7a908e57 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -400,5 +400,11 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID); u32 GetMonVolatile(u32 battler, enum Volatile volatile); void SetMonVolatile(u32 battler, enum Volatile volatile, u32 newValue); u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); +void PushHazardTypeToQueue(u32 side, enum Hazards hazardType); +bool32 IsHazardOnSide(u32 side, enum Hazards hazardType); +bool32 AreAnyHazardsOnSide(u32 side); +void RemoveAllHazardsFromField(u32 side); +bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType); +void RemoveHazardFromField(u32 side, enum Hazards hazardType); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 9064eb3863..6d207177c4 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -289,28 +289,31 @@ enum Volatile // Per-side statuses that affect an entire party #define SIDE_STATUS_REFLECT (1 << 0) #define SIDE_STATUS_LIGHTSCREEN (1 << 1) -#define SIDE_STATUS_STICKY_WEB (1 << 2) -#define SIDE_STATUS_SPIKES (1 << 4) -#define SIDE_STATUS_SAFEGUARD (1 << 5) -#define SIDE_STATUS_FUTUREATTACK (1 << 6) -#define SIDE_STATUS_MIST (1 << 8) -// (1 << 9) previously was SIDE_STATUS_SPIKES_DAMAGED -#define SIDE_STATUS_TAILWIND (1 << 10) -#define SIDE_STATUS_AURORA_VEIL (1 << 11) -#define SIDE_STATUS_LUCKY_CHANT (1 << 12) -#define SIDE_STATUS_TOXIC_SPIKES (1 << 13) -#define SIDE_STATUS_STEALTH_ROCK (1 << 14) -// Missing flags previously were SIDE_STATUS_TOXIC_SPIKES_DAMAGED, SIDE_STATUS_STEALTH_ROCK_DAMAGED, SIDE_STATUS_STICKY_WEB_DAMAGED -#define SIDE_STATUS_STEELSURGE (1 << 18) -#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 19) -#define SIDE_STATUS_RAINBOW (1 << 20) -#define SIDE_STATUS_SEA_OF_FIRE (1 << 21) -#define SIDE_STATUS_SWAMP (1 << 22) - -#define SIDE_STATUS_HAZARDS_ANY (SIDE_STATUS_SPIKES | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE) +#define SIDE_STATUS_SAFEGUARD (1 << 2) +#define SIDE_STATUS_FUTUREATTACK (1 << 3) +#define SIDE_STATUS_MIST (1 << 4) +#define SIDE_STATUS_TAILWIND (1 << 5) +#define SIDE_STATUS_AURORA_VEIL (1 << 6) +#define SIDE_STATUS_LUCKY_CHANT (1 << 7) +#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 8) +#define SIDE_STATUS_RAINBOW (1 << 9) +#define SIDE_STATUS_SEA_OF_FIRE (1 << 10) +#define SIDE_STATUS_SWAMP (1 << 11) + #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) #define SIDE_STATUS_PLEDGE_ANY (SIDE_STATUS_RAINBOW | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) +enum Hazards +{ + HAZARDS_NONE, + HAZARDS_SPIKES, + HAZARDS_STICKY_WEB, + HAZARDS_TOXIC_SPIKES, + HAZARDS_STEALTH_ROCK, + HAZARDS_STEELSURGE, + HAZARDS_MAX_COUNT, +}; + // Used for damaging entry hazards based on type enum TypeSideHazard { diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index bc3c35db84..e66c77ce87 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1817,7 +1817,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // only one mon needs to set up the last layer of Spikes break; case EFFECT_STEALTH_ROCK: - if (gSideTimers[GetBattlerSide(battlerDef)].stealthRockAmount > 0 + if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STEALTH_ROCK) || PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) //Only one mon needs to set up Stealth Rocks ADJUST_SCORE(-10); break; @@ -1828,9 +1828,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // only one mon needs to set up the last layer of Toxic Spikes break; case EFFECT_STICKY_WEB: - if (gSideTimers[GetBattlerSide(battlerDef)].stickyWebAmount) + if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); - else if (PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) && gSideTimers[GetBattlerSide(battlerDef)].stickyWebAmount) + else if (PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) && IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: @@ -2283,9 +2283,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-9); break; case EFFECT_DEFOG: - if (gSideStatuses[GetBattlerSide(battlerDef)] - & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) - || gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY) + if (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) + || AreAnyHazardsOnSide(GetBattlerSide(battlerAtk))) { if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { @@ -2294,7 +2293,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } } - if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef))) { ADJUST_SCORE(-10); //Don't blow away opposing hazards break; @@ -4390,12 +4389,12 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //ADJUST_SCORE(8); break; case EFFECT_DEFOG: - if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) + if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) || (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST))) { ADJUST_SCORE(GOOD_EFFECT); } - else if (!(gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SPIKES)) //Don't blow away hazards if you set them up + else if (!IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_SPIKES)) //Don't blow away hazards if you set them up { if (isDoubleBattle) { @@ -4939,7 +4938,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RAPID_SPIN: - if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) + if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)) ADJUST_SCORE(GOOD_EFFECT); case EFFECT_SPECTRAL_THIEF: @@ -5789,13 +5788,31 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score return score; } +bool32 DoesSideHaveDamagingHazards(u32 side) +{ + for (u32 counter = 0; counter < HAZARDS_MAX_COUNT; counter++) + { + switch (gBattleStruct->hazardsQueue[side][counter]) + { + case HAZARDS_SPIKES: + case HAZARDS_TOXIC_SPIKES: + case HAZARDS_STEALTH_ROCK: + case HAZARDS_STEELSURGE: + return TRUE; + default: + return FALSE; + } + } + return FALSE; +} + static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 i; u32 unmodifiedScore = score; u32 ability = gBattleMons[battlerAtk].ability; - u32 opposingHazardFlags = gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_TOXIC_SPIKES); - u32 aiHazardFlags = gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_HAZARDS_ANY); + bool32 opposingHazardFlags = DoesSideHaveDamagingHazards(GetBattlerSide(battlerDef)); + bool32 aiHazardFlags = AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)); enum BattleMoveEffects moveEffect = GetMoveEffect(move); struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; @@ -5856,21 +5873,21 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_HIT_SWITCH_TARGET: - if (opposingHazardFlags != 0) + if (opposingHazardFlags) ADJUST_SCORE(BEST_EFFECT); else ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_ROAR: - if (opposingHazardFlags != 0) + if (opposingHazardFlags) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_RAPID_SPIN: - if (aiHazardFlags != 0) + if (aiHazardFlags) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_DEFOG: - if (aiHazardFlags != 0) + if (aiHazardFlags) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_WISH: diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 550a2f91f7..e7bcf00e7b 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1529,20 +1529,20 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon u16 heldItemEffect = GetItemHoldEffect(battleMon->item); u32 maxHP = battleMon->maxHP, ability = battleMon->ability, status = battleMon->status1; u32 spikesDamage = 0, tSpikesDamage = 0, hazardDamage = 0; - u32 hazardFlags = gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_SAFEGUARD); + u32 side = GetBattlerSide(battler); // Check ways mon might avoid all hazards if (ability != ABILITY_MAGIC_GUARD || (heldItemEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !((gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) || ability == ABILITY_KLUTZ))) { // Stealth Rock - if ((hazardFlags & SIDE_STATUS_STEALTH_ROCK) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) + if (IsHazardOnSide(side, HAZARDS_STEALTH_ROCK) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, defType1, defType2, battleMon->maxHP); // G-Max Steelsurge - if ((hazardFlags & SIDE_STATUS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) + if (IsHazardOnSide(side, HAZARDS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, defType1, defType2, battleMon->maxHP); // Spikes - if ((hazardFlags & SIDE_STATUS_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) + if (IsHazardOnSide(side, HAZARDS_TOXIC_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) { spikesDamage = maxHP / ((5 - gSideTimers[GetBattlerSide(battler)].spikesAmount) * 2); if (spikesDamage == 0) @@ -1550,11 +1550,11 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon hazardDamage += spikesDamage; } - if ((hazardFlags & SIDE_STATUS_TOXIC_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON + if (IsHazardOnSide(side, HAZARDS_SPIKES) && (defType1 != TYPE_POISON && defType2 != TYPE_POISON && defType1 != TYPE_STEEL && defType2 != TYPE_STEEL && ability != ABILITY_IMMUNITY && ability != ABILITY_POISON_HEAL && ability != ABILITY_COMATOSE && status == 0 - && !(hazardFlags & SIDE_STATUS_SAFEGUARD) + && !(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) && !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL) && !IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) && !IsAbilityStatusProtected(battler, ability) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 5f8b6bb4be..149aada871 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1982,7 +1982,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) // Don't decrese stat if opposing battler has Encore if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) return NO_INCREASE; - + if (DoesAbilityRaiseStatsWhenLowered(gAiLogicData->abilities[battlerDef])) return NO_INCREASE; @@ -2979,13 +2979,13 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) u32 ability = GetMonAbility(mon); // we know our own party data enum ItemHoldEffect holdEffect; u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); s32 hazardDamage = 0; u32 type1 = GetSpeciesType(species, 0); u32 type2 = GetSpeciesType(species, 1); u32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); + u32 side = GetBattlerSide(currBattler); - if (flags == 0) + if (!AreAnyHazardsOnSide(side)) return FALSE; if (ability == ABILITY_MAGIC_GUARD) @@ -2997,12 +2997,12 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) if (holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) return FALSE; - if (flags & SIDE_STATUS_STEALTH_ROCK) + if (IsHazardOnSide(side, HAZARDS_STEALTH_ROCK)) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, type1, type2, maxHp); - if ((flags & SIDE_STATUS_STEELSURGE)) + if (IsHazardOnSide(side, HAZARDS_STEELSURGE)) hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, type1, type2, maxHp); - if (flags & SIDE_STATUS_SPIKES && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING + if (IsHazardOnSide(side, HAZARDS_SPIKES) && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING && ability != ABILITY_LEVITATE && holdEffect != HOLD_EFFECT_AIR_BALLOON) || holdEffect == HOLD_EFFECT_IRON_BALL || gFieldStatuses & STATUS_FIELD_GRAVITY)) { @@ -3070,7 +3070,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov return SHOULD_PIVOT; /* TODO - check if switchable mon unafffected by/will remove hazards - if (gSideStatuses[battlerAtk] & SIDE_STATUS_SPIKES && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) + if (IsHazardOnSide(GetBattlerSide(battlerAtk, HAZARDS_SPIKES) && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) return SHOULD_PIVOT;*/ /*if (BattlerWillFaintFromSecondaryDamage(battlerAtk, gAiLogicData->abilities[battlerAtk]) && switchScore >= SWITCHING_INCREASE_WALLS_FOE) @@ -3152,7 +3152,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (!hasStatBoost) { // TODO - check if switching prevents/removes hazards - //if (gSideStatuses[battlerAtk] & SIDE_STATUS_SPIKES && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) + //if (IsHazardOnSide(GetBattlerSide(battlerAtk, HAZARDS_SPIKES) && switchScore >= SWITCHING_INCREASE_CAN_REMOVE_HAZARDS) //return SHOULD_PIVOT; // TODO - not always a good idea @@ -4787,9 +4787,9 @@ bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) { - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) ADJUST_SCORE_PTR(GOOD_EFFECT); - if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerDef) != 0) + if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerDef) != 0) ADJUST_SCORE_PTR(-2); if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_IsFaster(battlerAtk, battlerDef, move)) @@ -5029,7 +5029,7 @@ bool32 ShouldTriggerAbility(u32 battlerAtk, u32 battlerDef, u32 ability) // At the moment, the parts about Mummy and Wandering Spirit are not actually used. bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct AiLogicData *aiData) { - // Dynamaxed Pokemon are immune to some ability-changing effects. + // Dynamaxed Pokemon are immune to some ability-changing effects. if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) { switch (effect) @@ -5044,7 +5044,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct if (gStatuses3[battlerDef] & STATUS3_GASTRO_ACID) return FALSE; - + u32 atkAbility = aiData->abilities[battlerAtk]; u32 defAbility = aiData->abilities[battlerDef]; bool32 hasSameAbility = (atkAbility == defAbility); @@ -5078,7 +5078,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct { u32 partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; if (gAbilitiesInfo[partnerAbility].cantBeSuppressed) - return FALSE; + return FALSE; if (partnerAbility == defAbility) return FALSE; } @@ -5113,7 +5113,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct if (defAbility == ABILITY_INSOMNIA || gAbilitiesInfo[defAbility].cantBeOverwritten) return FALSE; break; - + default: return FALSE; } @@ -5217,14 +5217,14 @@ void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, { ADJUST_SCORE_PTR(-20); } - + // Trigger Plus or Minus in modern gens. This is not in the overarching function because Skill Swap is rarely beneficial here. if (B_PLUS_MINUS_INTERACTION >= GEN_5) { if (((effect == EFFECT_ENTRAINMENT) && (abilityAtk == ABILITY_PLUS || abilityAtk == ABILITY_MINUS)) || ((effect == EFFECT_ROLE_PLAY) && (abilityDef == ABILITY_PLUS || abilityDef == ABILITY_MINUS))) ADJUST_SCORE_PTR(DECENT_EFFECT); } - + } // Targeting an opponent. else diff --git a/src/battle_debug.c b/src/battle_debug.c index a98b3a12a5..30f3d6766b 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -107,6 +107,7 @@ enum LIST_ITEM_VOLATILE, LIST_ITEM_STATUS3, LIST_ITEM_STATUS4, + LIST_ITEM_HAZARDS, LIST_ITEM_SIDE_STATUS, LIST_ITEM_AI, LIST_ITEM_AI_MOVES_PTS, @@ -176,18 +177,22 @@ enum enum { - LIST_SIDE_REFLECT, - LIST_SIDE_LIGHTSCREEN, LIST_SIDE_STICKY_WEB, LIST_SIDE_SPIKES, + LIST_SIDE_TOXIC_SPIKES, + LIST_SIDE_STEALTH_ROCK, + LIST_SIDE_STEELSURGE, +}; + +enum +{ + LIST_SIDE_REFLECT, + LIST_SIDE_LIGHTSCREEN, LIST_SIDE_SAFEGUARD, LIST_SIDE_MIST, LIST_SIDE_TAILWIND, LIST_SIDE_AURORA_VEIL, LIST_SIDE_LUCKY_CHANT, - LIST_SIDE_TOXIC_SPIKES, - LIST_SIDE_STEALTH_ROCK, - LIST_SIDE_STEELSURGE, LIST_SIDE_DAMAGE_NON_TYPES, LIST_SIDE_RAINBOW, LIST_SIDE_SEA_OF_FIRE, @@ -250,6 +255,7 @@ enum VAL_BITFIELD_16, VAL_BITFIELD_32, VAL_VOLATILE, + VAL_HAZARDS, VAR_SIDE_STATUS, VAR_SHOW_HP, VAR_SUBSTITUTE, @@ -352,23 +358,24 @@ static const struct BitfieldInfo sAIBitfield[] = static const struct ListMenuItem sMainListItems[] = { - {COMPOUND_STRING("Moves"), LIST_ITEM_MOVES}, - {sText_Ability, LIST_ITEM_ABILITY}, - {sText_HeldItem, LIST_ITEM_HELD_ITEM}, - {COMPOUND_STRING("PP"), LIST_ITEM_PP}, - {COMPOUND_STRING("Types"), LIST_ITEM_TYPES}, - {COMPOUND_STRING("Stats"), LIST_ITEM_STATS}, - {COMPOUND_STRING("Stat Stages"), LIST_ITEM_STAT_STAGES}, - {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, - {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, - {COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3}, - {COMPOUND_STRING("Status4"), LIST_ITEM_STATUS4}, - {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, - {COMPOUND_STRING("AI"), LIST_ITEM_AI}, - {COMPOUND_STRING("AI Pts/Dmg"), LIST_ITEM_AI_MOVES_PTS}, - {COMPOUND_STRING("AI Info"), LIST_ITEM_AI_INFO}, - {COMPOUND_STRING("AI Party"), LIST_ITEM_AI_PARTY}, - {COMPOUND_STRING("Various"), LIST_ITEM_VARIOUS}, + {COMPOUND_STRING("Moves"), LIST_ITEM_MOVES}, + {sText_Ability, LIST_ITEM_ABILITY}, + {sText_HeldItem, LIST_ITEM_HELD_ITEM}, + {COMPOUND_STRING("PP"), LIST_ITEM_PP}, + {COMPOUND_STRING("Types"), LIST_ITEM_TYPES}, + {COMPOUND_STRING("Stats"), LIST_ITEM_STATS}, + {COMPOUND_STRING("Stat Stages"), LIST_ITEM_STAT_STAGES}, + {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, + {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, + {COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3}, + {COMPOUND_STRING("Status4"), LIST_ITEM_STATUS4}, + {COMPOUND_STRING("Hazards"), LIST_ITEM_HAZARDS}, + {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, + {COMPOUND_STRING("AI"), LIST_ITEM_AI}, + {COMPOUND_STRING("AI Pts/Dmg"), LIST_ITEM_AI_MOVES_PTS}, + {COMPOUND_STRING("AI Info"), LIST_ITEM_AI_INFO}, + {COMPOUND_STRING("AI Party"), LIST_ITEM_AI_PARTY}, + {COMPOUND_STRING("Various"), LIST_ITEM_VARIOUS}, }; static const struct ListMenuItem sStatsListItems[] = @@ -448,20 +455,24 @@ static const struct ListMenuItem sStatus4ListItems[] = {COMPOUND_STRING("Glaive Rush"), LIST_STATUS4_GLAIVE_RUSH}, }; +static const struct ListMenuItem sHazardsListItems[] = +{ + {COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES}, + {COMPOUND_STRING("Sticky Web"), LIST_SIDE_STICKY_WEB}, + {COMPOUND_STRING("Toxic Spikes"), LIST_SIDE_TOXIC_SPIKES}, + {COMPOUND_STRING("Stealth Rock"), LIST_SIDE_STEALTH_ROCK}, + {COMPOUND_STRING("Steelsurge"), LIST_SIDE_STEELSURGE}, +}; + static const struct ListMenuItem sSideStatusListItems[] = { {COMPOUND_STRING("Reflect"), LIST_SIDE_REFLECT}, {COMPOUND_STRING("Light Screen"), LIST_SIDE_LIGHTSCREEN}, - {COMPOUND_STRING("Sticky Web"), LIST_SIDE_STICKY_WEB}, - {COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES}, {COMPOUND_STRING("Safeguard"), LIST_SIDE_SAFEGUARD}, {COMPOUND_STRING("Mist"), LIST_SIDE_MIST}, {COMPOUND_STRING("Tailwind"), LIST_SIDE_TAILWIND}, {COMPOUND_STRING("Aurora Veil"), LIST_SIDE_AURORA_VEIL}, {COMPOUND_STRING("Lucky Chant"), LIST_SIDE_LUCKY_CHANT}, - {COMPOUND_STRING("Toxic Spikes"), LIST_SIDE_TOXIC_SPIKES}, - {COMPOUND_STRING("Stealth Rock"), LIST_SIDE_STEALTH_ROCK}, - {COMPOUND_STRING("Steelsurge"), LIST_SIDE_STEELSURGE}, {COMPOUND_STRING("Damage Non-Types"), LIST_SIDE_DAMAGE_NON_TYPES}, {COMPOUND_STRING("Rainbow"), LIST_SIDE_RAINBOW}, {COMPOUND_STRING("Sea of Fire"), LIST_SIDE_SEA_OF_FIRE}, @@ -659,6 +670,8 @@ static void PrintDigitChars(struct BattleDebugMenu *data); static void SetUpModifyArrows(struct BattleDebugMenu *data); static void UpdateBattlerValue(struct BattleDebugMenu *data); static void UpdateMonData(struct BattleDebugMenu *data); +static void ChangeHazardsValue(struct BattleDebugMenu *data); +static u32 GetHazardsValue(struct BattleDebugMenu *data); static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue); static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp); static void SwitchToDebugView(u8 taskId); @@ -1424,6 +1437,10 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) listTemplate.items = sVariousListItems; itemsCount = ARRAY_COUNT(sVariousListItems); break; + case LIST_ITEM_HAZARDS: + listTemplate.items = sHazardsListItems; + itemsCount = ARRAY_COUNT(sHazardsListItems); + break; case LIST_ITEM_SIDE_STATUS: listTemplate.items = sSideStatusListItems; itemsCount = ARRAY_COUNT(sSideStatusListItems); @@ -1625,6 +1642,9 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data) case VAL_VOLATILE: SetMonVolatile(data->battlerId, data->currentSecondaryListItemId, data->modifyArrows.currValue); break; + case VAL_HAZARDS: + ChangeHazardsValue(data); + break; case VAR_SIDE_STATUS: *GetSideStatusValue(data, TRUE, data->modifyArrows.currValue != 0) = data->modifyArrows.currValue; break; @@ -1702,6 +1722,83 @@ static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits) charDigits[i] = valueDigits[i] + CHAR_0; } +static void ChangeHazardsValue(struct BattleDebugMenu *data) +{ + u32 side = GetBattlerSide(data->battlerId); + + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: + if (data->modifyArrows.currValue > 0) + { + if (gSideTimers[side].spikesAmount == 0) + PushHazardTypeToQueue(side, HAZARDS_SPIKES); + gSideTimers[side].spikesAmount = data->modifyArrows.currValue; + } + else if (data->modifyArrows.currValue == 0) + { + gSideTimers[side].spikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_SPIKES); + } + break; + case LIST_SIDE_TOXIC_SPIKES: + if (data->modifyArrows.currValue > 0) + { + if (gSideTimers[side].toxicSpikesAmount == 0) + PushHazardTypeToQueue(side, HAZARDS_TOXIC_SPIKES); + gSideTimers[side].toxicSpikesAmount = data->modifyArrows.currValue; + } + else if (data->modifyArrows.currValue == 0) + { + gSideTimers[side].toxicSpikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES); + } + break; + case LIST_SIDE_STICKY_WEB: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STICKY_WEB); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STICKY_WEB); + break; + case LIST_SIDE_STEALTH_ROCK: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STEALTH_ROCK); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STEALTH_ROCK); + break; + case LIST_SIDE_STEELSURGE: + if (data->modifyArrows.currValue > 0) + PushHazardTypeToQueue(side, HAZARDS_STEELSURGE); + else if (data->modifyArrows.currValue == 0) + RemoveHazardFromField(side, HAZARDS_STEELSURGE); + break; + } +} + +static u32 GetHazardsValue(struct BattleDebugMenu *data) +{ + u32 hazardsLayers = 0; + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: + hazardsLayers = gSideTimers[GetBattlerSide(data->battlerId)].spikesAmount; + break; + case LIST_SIDE_TOXIC_SPIKES: + hazardsLayers = gSideTimers[GetBattlerSide(data->battlerId)].toxicSpikesAmount; + break; + case LIST_SIDE_STICKY_WEB: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STICKY_WEB); + break; + case LIST_SIDE_STEALTH_ROCK: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STEALTH_ROCK); + break; + case LIST_SIDE_STEELSURGE: + hazardsLayers = IsHazardOnSide(GetBattlerSide(data->battlerId), HAZARDS_STEELSURGE); + break; + } + return hazardsLayers; +} + static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue) { struct SideTimer *sideTimer = &gSideTimers[GetBattlerSide(data->battlerId)]; @@ -1726,26 +1823,6 @@ static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LIGHTSCREEN; } return &sideTimer->lightscreenTimer; - case LIST_SIDE_STICKY_WEB: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STICKY_WEB; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STICKY_WEB; - sideTimer->stickyWebBattlerId = data->battlerId; - sideTimer->stickyWebBattlerSide = GetBattlerSide(data->battlerId); - } - return &sideTimer->stickyWebAmount; - case LIST_SIDE_SPIKES: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SPIKES; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SPIKES; - } - return &sideTimer->spikesAmount; case LIST_SIDE_SAFEGUARD: if (changeStatus) { @@ -1791,33 +1868,6 @@ static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LUCKY_CHANT; } return &sideTimer->luckyChantTimer; - case LIST_SIDE_TOXIC_SPIKES: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TOXIC_SPIKES; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TOXIC_SPIKES; - } - return &sideTimer->toxicSpikesAmount; - case LIST_SIDE_STEALTH_ROCK: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEALTH_ROCK; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEALTH_ROCK; - } - return &sideTimer->stealthRockAmount; - case LIST_SIDE_STEELSURGE: - if (changeStatus) - { - if (statusTrue) - *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEELSURGE; - else - *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEELSURGE; - } - return &sideTimer->steelsurgeAmount; case LIST_SIDE_DAMAGE_NON_TYPES: if (changeStatus) { @@ -2034,16 +2084,29 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.maxValue = (1 << data->bitfield[data->currentSecondaryListItemId].bitsCount) - 1; data->modifyArrows.maxDigits = MAX_DIGITS(data->modifyArrows.maxValue); break; - case LIST_ITEM_SIDE_STATUS: + case LIST_ITEM_HAZARDS: data->modifyArrows.minValue = 0; - - if (data->currentSecondaryListItemId == LIST_SIDE_SPIKES) + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_SPIKES: data->modifyArrows.maxValue = 3; - else if (data->currentSecondaryListItemId == LIST_SIDE_STEALTH_ROCK || data->currentSecondaryListItemId == LIST_SIDE_STICKY_WEB) + break; + case LIST_SIDE_TOXIC_SPIKES: + data->modifyArrows.maxValue = 2; + break; + case LIST_SIDE_STICKY_WEB: + case LIST_SIDE_STEALTH_ROCK: + case LIST_SIDE_STEELSURGE: data->modifyArrows.maxValue = 1; - else - data->modifyArrows.maxValue = 9; - + break; + } + data->modifyArrows.maxDigits = 2; + data->modifyArrows.typeOfVal = VAL_HAZARDS; + data->modifyArrows.currValue = GetHazardsValue(data); + break; + case LIST_ITEM_SIDE_STATUS: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 9; data->modifyArrows.maxDigits = 2; data->modifyArrows.modifiedValPtr = &gSideStatuses[GetBattlerSide(data->battlerId)]; data->modifyArrows.typeOfVal = VAR_SIDE_STATUS; diff --git a/src/battle_message.c b/src/battle_message.c index 860a3d5ac2..6be243ba51 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1400,6 +1400,24 @@ const u16 gDamageNonTypesDmgStringIds[] = [B_MSG_HURT_BY_ROCKS_THROWN] = STRINGID_PKMNHURTBYROCKSTHROWN, }; +const u16 gDefogHazardsStringIds[] = +{ + [HAZARDS_SPIKES] = STRINGID_SPIKESDISAPPEAREDFROMTEAM, + [HAZARDS_STICKY_WEB] = STRINGID_STICKYWEBDISAPPEAREDFROMTEAM, + [HAZARDS_TOXIC_SPIKES] = STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM, + [HAZARDS_STEALTH_ROCK] = STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM, + [HAZARDS_STEELSURGE] = STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM, +}; + +const u16 gSpinHazardsStringIds[] = +{ + [HAZARDS_SPIKES] = STRINGID_PKMNBLEWAWAYSPIKES, + [HAZARDS_STICKY_WEB] = STRINGID_PKMNBLEWAWAYSTICKYWEB, + [HAZARDS_TOXIC_SPIKES] = STRINGID_PKMNBLEWAWAYTOXICSPIKES, + [HAZARDS_STEALTH_ROCK] = STRINGID_PKMNBLEWAWAYSTEALTHROCK, + [HAZARDS_STEELSURGE] = STRINGID_PKMNBLEWAWAYSHARPSTEEL, +}; + const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); const u8 gText_CongratsPkmnEvolved[] = _("Congratulations! Your {STR_VAR_1}\nevolved into {STR_VAR_2}!{WAIT_SE}\p"); const u8 gText_PkmnStoppedEvolving[] = _("Huh? {STR_VAR_1}\nstopped evolving!\p"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 32c2111488..567bdd85ee 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3848,7 +3848,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_STEALTH_ROCK: - if (!(gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_STEALTH_ROCK)) + if (!IsHazardOnSide(GetBattlerSide(gEffectBattler), HAZARDS_STEALTH_ROCK)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4284,7 +4284,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; } case MOVE_EFFECT_STEELSURGE: - if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEELSURGE)) + if (!IsHazardOnSide(GetBattlerSide(gBattlerTarget), HAZARDS_STEELSURGE)) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS; BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4293,8 +4293,8 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_DEFOG: if (gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_SCREEN_ANY - || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_HAZARDS_ANY - || gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_HAZARDS_ANY + || AreAnyHazardsOnSide(GetBattlerSide(gBattlerTarget)) + || AreAnyHazardsOnSide(GetBattlerSide(gBattlerAttacker)) || gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -8026,6 +8026,25 @@ static void Cmd_switchhandleorder(void) gBattlescriptCurrInstr = cmd->nextInstr; } +bool32 DoSwitchInAbilities(u32 battler) +{ + return (TryPrimalReversion(battler) + || AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0) + || (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect() && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0)) + || (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0))); +} + +static void UpdateSentMonFlags(u32 battler) +{ + UpdateSentPokesToOpponentValue(battler); + + gHitMarker &= ~HITMARKER_FAINTED(battler); + gSpecialStatuses[battler].faintedHasReplacement = FALSE; + + if (!BattlerHasAi(battler)) + gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[battler]; +} + static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) { gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND; @@ -8043,28 +8062,89 @@ static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) BattleScriptCall(BattleScript_DmgHazardsOnFaintedBattler); } -bool32 DoSwitchInAbilities(u32 battler) -{ - return (TryPrimalReversion(battler) - || AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0) - || (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect() && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0)) - || (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0))); -} - -static void UpdateSentMonFlags(u32 battler) +void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType) { - UpdateSentPokesToOpponentValue(battler); + switch (hazardType) + { + case HAZARDS_NONE: + break; + case HAZARDS_SPIKES: + if (GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD + && IsBattlerAffectedByHazards(battler, FALSE) + && IsBattlerGrounded(battler)) + { + u8 spikesDmg = (5 - gSideTimers[side].spikesAmount) * 2; + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (spikesDmg); + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES); + } + break; + case HAZARDS_STICKY_WEB: + if (IsBattlerAffectedByHazards(battler, FALSE) && IsBattlerGrounded(battler)) + { + gBattleScripting.battler = battler; + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + BattleScriptCall(BattleScript_StickyWebOnSwitchIn); + } + break; + case HAZARDS_TOXIC_SPIKES: + if (!IsBattlerGrounded(battler)) + break; - gHitMarker &= ~HITMARKER_FAINTED(battler); - gSpecialStatuses[battler].faintedHasReplacement = FALSE; + if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes. + { + gBattleStruct->hazardsCounter--; // reduce counter so the next hazard can be applied + gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0; + RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES); + gBattleScripting.battler = battler; + BattleScriptCall(BattleScript_ToxicSpikesAbsorbed); + } + else if (IsBattlerAffectedByHazards(battler, TRUE) + && CanBePoisoned(battler, battler, GetBattlerAbility(battler), GetBattlerAbility(battler))) + { + gBattleScripting.battler = battler; + BattleScriptPushCursor(); + if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) + { + gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned; + gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON; + } + else + { + gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned; + gBattleMons[battler].status1 |= STATUS1_POISON; + } - if (!BattlerHasAi(battler)) - gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[battler]; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + } + break; + case HAZARDS_STEALTH_ROCK: + if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); + if (gBattleStruct->moveDamage[battler] != 0) + SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); + } + break; + case HAZARDS_STEELSURGE: + if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); + if (gBattleStruct->moveDamage[battler] != 0) + SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); + } + break; + case HAZARDS_MAX_COUNT: + break; + } } static bool32 DoSwitchInEffectsForBattler(u32 battler) { u32 i = 0; + u32 side = GetBattlerSide(battler); // Neutralizing Gas announces itself before hazards if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS && gSpecialStatuses[battler].announceNeutralizingGas == 0) { @@ -8091,86 +8171,18 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->battlerState[battler].storedLunarDance = FALSE; } } - else if (!(gDisableStructs[battler].spikesDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SPIKES) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD - && IsBattlerAffectedByHazards(battler, FALSE) - && IsBattlerGrounded(battler)) - { - u8 spikesDmg = (5 - gSideTimers[GetBattlerSide(battler)].spikesAmount) * 2; - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (spikesDmg); - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - - gDisableStructs[battler].spikesDone = TRUE; - SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES); - } - else if (!(gDisableStructs[battler].stealthRockDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEALTH_ROCK) - && IsBattlerAffectedByHazards(battler, FALSE) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) - { - gDisableStructs[battler].stealthRockDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); - - if (gBattleStruct->moveDamage[battler] != 0) - SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); - } - else if (!(gDisableStructs[battler].toxicSpikesDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TOXIC_SPIKES) - && IsBattlerGrounded(battler)) + else if (!gDisableStructs[battler].hazardsDone) { - gDisableStructs[battler].toxicSpikesDone = TRUE; - if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes. + TryHazardsOnSwitchIn(battler, side, gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter]); + gBattleStruct->hazardsCounter++; + // Done once we reach the first element without any hazard type or the array is full + if (gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter] == HAZARDS_NONE + || gBattleStruct->hazardsCounter == HAZARDS_MAX_COUNT) { - gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_TOXIC_SPIKES; - gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0; - gBattleScripting.battler = battler; - BattleScriptCall(BattleScript_ToxicSpikesAbsorbed); - } - else if (IsBattlerAffectedByHazards(battler, TRUE)) - { - if (CanBePoisoned(gBattlerAttacker, battler, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(battler))) - { - gBattleScripting.battler = battler; - BattleScriptPushCursor(); - if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2) - { - gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned; - gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON; - } - else - { - gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned; - gBattleMons[battler].status1 |= STATUS1_POISON; - } - - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } + gDisableStructs[battler].hazardsDone = TRUE; + gBattleStruct->hazardsCounter = 0; } } - else if (!(gDisableStructs[battler].stickyWebDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STICKY_WEB) - && IsBattlerAffectedByHazards(battler, FALSE) - && IsBattlerGrounded(battler)) - { - gDisableStructs[battler].stickyWebDone = TRUE; - gBattleScripting.battler = battler; - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - BattleScriptCall(BattleScript_StickyWebOnSwitchIn); - } - else if (!(gDisableStructs[battler].steelSurgeDone) - && (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_STEELSURGE) - && IsBattlerAffectedByHazards(battler, FALSE) - && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) - { - gDisableStructs[battler].steelSurgeDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); - - if (gBattleStruct->moveDamage[battler] != 0) - SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); - } else if (gBattleMons[battler].hp != gBattleMons[battler].maxHP && gBattleStruct->zmove.healReplacement) { gBattleStruct->zmove.healReplacement = FALSE; @@ -8220,12 +8232,6 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) return TRUE; } - gDisableStructs[battler].stickyWebDone = FALSE; - gDisableStructs[battler].spikesDone = FALSE; - gDisableStructs[battler].toxicSpikesDone = FALSE; - gDisableStructs[battler].stealthRockDone = FALSE; - gDisableStructs[battler].steelSurgeDone = FALSE; - for (i = 0; i < gBattlersCount; i++) { if (gBattlerByTurnOrder[i] == battler) @@ -8234,6 +8240,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; } + gDisableStructs[battler].hazardsDone = FALSE; gBattleStruct->battlerState[battler].forcedSwitch = FALSE; return FALSE; } @@ -9567,6 +9574,32 @@ static void RemoveAllTerrains(void) } \ } +static bool32 DefogClearHazards(u32 saveBattler, u32 side, bool32 clear) +{ + if (!AreAnyHazardsOnSide(side)) + return FALSE; + + for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) + { + bool32 checkOrClear = clear ? IsHazardOnSideAndClear(side, hazardType) : IsHazardOnSide(side, hazardType); + if (checkOrClear) + { + if (clear) + { + gBattleStruct->numHazards[side]--; + gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; + BattleScriptCall(BattleScript_DefogClearHazards); + } + else + { + gBattlerAttacker = saveBattler; + } + return TRUE; + } + } + return FALSE; +} + static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) { s32 i; @@ -9589,11 +9622,8 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { gBattlerAttacker = i; // For correct battle string. Ally's / Foe's - DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEELSURGE, steelsurgeAmount, BattleScript_SteelsurgeDefog, 0); + if (DefogClearHazards(saveBattler, i, clear)) + return TRUE; } if (gBattleWeather & B_WEATHER_FOG) { @@ -9621,14 +9651,9 @@ static bool32 TryTidyUpClear(u32 battlerAtk, bool32 clear) for (i = 0; i < NUM_BATTLE_SIDES; i++) { - struct SideTimer *sideTimer = &gSideTimers[i]; - u32 *sideStatuses = &gSideStatuses[i]; - gBattlerAttacker = i; // For correct battle string. Ally's / Foe's - DEFOG_CLEAR(SIDE_STATUS_SPIKES, spikesAmount, BattleScript_SpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); - DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); + if (DefogClearHazards(saveBattler, i, clear)) + return TRUE; } for (i = 0; i < MAX_BATTLERS_COUNT; i++) @@ -9780,17 +9805,23 @@ void BS_CourtChangeSwapSideStatuses(void) COURTCHANGE_SWAP(SIDE_STATUS_TAILWIND, tailwindTimer, temp); // Lucky Chant doesn't exist in gen 8, but seems like it should be affected by Court Change COURTCHANGE_SWAP(SIDE_STATUS_LUCKY_CHANT, luckyChantTimer, temp); - COURTCHANGE_SWAP(SIDE_STATUS_SPIKES, spikesAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STICKY_WEB, stickyWebAmount, temp); - COURTCHANGE_SWAP(SIDE_STATUS_STEELSURGE, steelsurgeAmount, temp); COURTCHANGE_SWAP(SIDE_STATUS_DAMAGE_NON_TYPES, damageNonTypesTimer, temp); // Track Pledge effect side COURTCHANGE_SWAP(SIDE_STATUS_RAINBOW, rainbowTimer, temp); COURTCHANGE_SWAP(SIDE_STATUS_SEA_OF_FIRE, seaOfFireTimer, temp); COURTCHANGE_SWAP(SIDE_STATUS_SWAMP, swampTimer, temp); + // Hazards + u32 tempQueue[HAZARDS_MAX_COUNT] = {HAZARDS_NONE}; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + tempQueue[i] = gBattleStruct->hazardsQueue[B_SIDE_PLAYER][i]; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[B_SIDE_PLAYER][i] = gBattleStruct->hazardsQueue[B_SIDE_OPPONENT][i]; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[B_SIDE_OPPONENT][i] = tempQueue[i]; + SWAP(sideTimerPlayer->spikesAmount, sideTimerOpp->spikesAmount, temp); + SWAP(sideTimerPlayer->toxicSpikesAmount, sideTimerOpp->toxicSpikesAmount, temp); + // Change battler IDs of swapped effects. Needed for the correct string when they expire UPDATE_COURTCHANGED_BATTLER(stickyWebBattlerId); @@ -13950,7 +13981,8 @@ static void Cmd_trysetspikes(void) } else { - gSideStatuses[targetSide] |= SIDE_STATUS_SPIKES; + if (gSideTimers[targetSide].spikesAmount == 0) // Add only once to the queue + PushHazardTypeToQueue(targetSide, HAZARDS_SPIKES); gSideTimers[targetSide].spikesAmount++; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -14313,35 +14345,18 @@ static void Cmd_rapidspinfree(void) gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED_BATTLER; BattleScriptCall(BattleScript_LeechSeedFree); } - else if (gSideStatuses[atkSide] & SIDE_STATUS_SPIKES) + else if (AreAnyHazardsOnSide(atkSide)) { - gSideStatuses[atkSide] &= ~SIDE_STATUS_SPIKES; - gSideTimers[atkSide].spikesAmount = 0; - BattleScriptCall(BattleScript_SpikesFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_TOXIC_SPIKES) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_TOXIC_SPIKES; - gSideTimers[atkSide].toxicSpikesAmount = 0; - BattleScriptCall(BattleScript_ToxicSpikesFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STICKY_WEB) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STICKY_WEB; - gSideTimers[atkSide].stickyWebAmount = 0; - BattleScriptCall(BattleScript_StickyWebFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STEALTH_ROCK) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STEALTH_ROCK; - gSideTimers[atkSide].stealthRockAmount = 0; - BattleScriptCall(BattleScript_StealthRockFree); - } - else if (gSideStatuses[atkSide] & SIDE_STATUS_STEELSURGE) - { - gSideStatuses[atkSide] &= ~SIDE_STATUS_STEELSURGE; - gSideTimers[atkSide].steelsurgeAmount = 0; - BattleScriptCall(BattleScript_SteelsurgeFree); + for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) + { + if (IsHazardOnSideAndClear(atkSide, hazardType)) + { + gBattleStruct->numHazards[atkSide]--; + gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; + BattleScriptCall(BattleScript_SpinHazardsAway); + return; + } + } } else { @@ -14432,16 +14447,15 @@ static void Cmd_setstickyweb(void) u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STICKY_WEB) + if (IsHazardOnSide(targetSide, HAZARDS_STICKY_WEB)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; + PushHazardTypeToQueue(targetSide, HAZARDS_STICKY_WEB); gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side - gSideTimers[targetSide].stickyWebAmount = 1; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14967,8 +14981,9 @@ static void Cmd_settoxicspikes(void) } else { + if (gSideTimers[targetSide].toxicSpikesAmount == 0) + PushHazardTypeToQueue(targetSide, HAZARDS_TOXIC_SPIKES); gSideTimers[targetSide].toxicSpikesAmount++; - gSideStatuses[targetSide] |= SIDE_STATUS_TOXIC_SPIKES; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -15158,14 +15173,13 @@ static void Cmd_setstealthrock(void) CMD_ARGS(const u8 *failInstr); u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STEALTH_ROCK) + if (IsHazardOnSide(targetSide, HAZARDS_STEALTH_ROCK)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STEALTH_ROCK; - gSideTimers[targetSide].stealthRockAmount = 1; + PushHazardTypeToQueue(targetSide, HAZARDS_STEALTH_ROCK); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -18544,14 +18558,13 @@ void BS_SetSteelsurge(void) { NATIVE_ARGS(const u8 *failInstr); u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideStatuses[targetSide] & SIDE_STATUS_STEELSURGE) + if (IsHazardOnSide(targetSide, HAZARDS_STEELSURGE)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gSideStatuses[targetSide] |= SIDE_STATUS_STEELSURGE; - gSideTimers[targetSide].steelsurgeAmount = 1; + PushHazardTypeToQueue(targetSide, HAZARDS_STEELSURGE); gBattlescriptCurrInstr = cmd->nextInstr; } } diff --git a/src/battle_util.c b/src/battle_util.c index e40020e11f..8664fb417d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11445,3 +11445,79 @@ void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue) return; } } + +// Hazards are added to a queue and applied based in order (FIFO) +void PushHazardTypeToQueue(u32 side, enum Hazards hazardType) +{ + if (!IsHazardOnSide(side, hazardType)) // Failsafe + gBattleStruct->hazardsQueue[side][gBattleStruct->numHazards[side]++] = hazardType; +} + +bool32 IsHazardOnSide(u32 side, enum Hazards hazardType) +{ + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + return TRUE; + } + return FALSE; +} + +bool32 AreAnyHazardsOnSide(u32 side) +{ + return gBattleStruct->numHazards[side] > 0; +} + +bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType) +{ + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + if (hazardType == HAZARDS_SPIKES) + gSideTimers[side].spikesAmount = 0; + else if (hazardType == HAZARDS_TOXIC_SPIKES) + gSideTimers[side].toxicSpikesAmount = 0; + return TRUE; + } + } + return FALSE; +} + +void RemoveAllHazardsFromField(u32 side) +{ + gSideTimers[side].spikesAmount = 0; + gSideTimers[side].toxicSpikesAmount = 0; + gBattleStruct->numHazards[side] = 0; + for (u32 i = 0; i < HAZARDS_MAX_COUNT; i++) + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; +} + +void RemoveHazardFromField(u32 side, enum Hazards hazardType) +{ + u32 i; + for (i = 0; i < HAZARDS_MAX_COUNT; i++) + { + if (gBattleStruct->hazardsQueue[side][i] == hazardType) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + gBattleStruct->numHazards[side]--; + if (hazardType == HAZARDS_SPIKES) + gSideTimers[side].spikesAmount = 0; + else if (hazardType == HAZARDS_TOXIC_SPIKES) + gSideTimers[side].toxicSpikesAmount = 0; + break; + } + } + while (i < HAZARDS_MAX_COUNT) + { + if (i+1 == HAZARDS_MAX_COUNT) + { + gBattleStruct->hazardsQueue[side][i] = HAZARDS_NONE; + break; + } + gBattleStruct->hazardsQueue[side][i] = gBattleStruct->hazardsQueue[side][i+1]; + i++; + } +} diff --git a/test/battle/hazards.c b/test/battle/hazards.c new file mode 100644 index 0000000000..9c974bb7b1 --- /dev/null +++ b/test/battle/hazards.c @@ -0,0 +1,40 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Hazards are applied based on order of set up") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_GRIMER); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); } + TURN { MOVE(opponent, MOVE_STICKY_WEB); } + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); SWITCH(player, 1); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); SWITCH(player, 2); } + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); SWITCH(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + MESSAGE("Wobbuffet was poisoned!"); + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); + MESSAGE("Wobbuffet was hurt by the spikes!"); + MESSAGE("The poison spikes disappeared from the ground around your team!"); + MESSAGE("Pointed stones dug into Wynaut!"); + MESSAGE("Wynaut was caught in a sticky web!"); + MESSAGE("Wynaut was hurt by the spikes!"); + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_STEALTH_ROCK); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_STICKY_WEB); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + } +} diff --git a/test/battle/move_effect/court_change.c b/test/battle/move_effect/court_change.c index 41381df18c..56d38c165d 100644 --- a/test/battle/move_effect/court_change.c +++ b/test/battle/move_effect/court_change.c @@ -29,16 +29,16 @@ DOUBLE_BATTLE_TEST("Court Change swaps entry hazards used by the opponent") MESSAGE("Wynaut swapped the battle effects affecting each side of the field!"); SEND_IN_MESSAGE("Wynaut"); NONE_OF { - MESSAGE("Wynaut was hurt by the spikes!"); + MESSAGE("Wynaut was caught in a sticky web!"); MESSAGE("Pointed stones dug into Wynaut!"); + MESSAGE("Wynaut was hurt by the spikes!"); MESSAGE("Wynaut was poisoned!"); - MESSAGE("Wynaut was caught in a sticky web!"); } MESSAGE("2 sent out Wobbuffet!"); - MESSAGE("The opposing Wobbuffet was hurt by the spikes!"); + MESSAGE("The opposing Wobbuffet was caught in a sticky web!"); MESSAGE("Pointed stones dug into the opposing Wobbuffet!"); + MESSAGE("The opposing Wobbuffet was hurt by the spikes!"); MESSAGE("The opposing Wobbuffet was poisoned!"); - MESSAGE("The opposing Wobbuffet was caught in a sticky web!"); } } @@ -64,16 +64,16 @@ DOUBLE_BATTLE_TEST("Court Change swaps entry hazards used by the player") MESSAGE("The opposing Wynaut used Court Change!"); MESSAGE("The opposing Wynaut swapped the battle effects affecting each side of the field!"); SEND_IN_MESSAGE("Wobbuffet"); - MESSAGE("Wobbuffet was hurt by the spikes!"); + MESSAGE("Wobbuffet was caught in a sticky web!"); MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was hurt by the spikes!"); MESSAGE("Wobbuffet was poisoned!"); - MESSAGE("Wobbuffet was caught in a sticky web!"); MESSAGE("2 sent out Wynaut!"); NONE_OF { - MESSAGE("The opposing Wynaut was hurt by the spikes!"); + MESSAGE("The opposing Wynaut was caught in a sticky web!"); MESSAGE("Pointed stones dug into the opposing Wynaut!"); + MESSAGE("The opposing Wynaut was hurt by the spikes!"); MESSAGE("The opposing Wynaut was poisoned!"); - MESSAGE("The opposing Wynaut was caught in a sticky web!"); } } } diff --git a/test/battle/move_effect/defog.c b/test/battle/move_effect/defog.c index ce0ab844c7..96b79438f1 100644 --- a/test/battle/move_effect/defog.c +++ b/test/battle/move_effect/defog.c @@ -154,8 +154,8 @@ DOUBLE_BATTLE_TEST("Defog removes Stealth Rock and Sticky Web from user's side ( ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentRight); ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); if (move == MOVE_DEFOG && B_DEFOG_EFFECT_CLEARING >= GEN_6) { - MESSAGE("The pointed stones disappeared from around your team!"); MESSAGE("The sticky web has disappeared from the ground around your team!"); + MESSAGE("The pointed stones disappeared from around your team!"); } // Switch happens SWITCH_OUT_MESSAGE("Wobbuffet"); @@ -365,16 +365,30 @@ DOUBLE_BATTLE_TEST("Defog removes everything it can") if (B_DEFOG_EFFECT_CLEARING >= GEN_6) { MESSAGE("The spikes disappeared from the ground around your team!"); - MESSAGE("The pointed stones disappeared from around your team!"); - MESSAGE("The poison spikes disappeared from the ground around your team!"); MESSAGE("The sticky web has disappeared from the ground around your team!"); + MESSAGE("The poison spikes disappeared from the ground around your team!"); + MESSAGE("The pointed stones disappeared from around your team!"); // Opponent side MESSAGE("The spikes disappeared from the ground around the opposing team!"); - MESSAGE("The pointed stones disappeared from around the opposing team!"); - MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); MESSAGE("The sticky web has disappeared from the ground around the opposing team!"); + MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); + MESSAGE("The pointed stones disappeared from around the opposing team!"); } + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + + EXPECT_EQ(gBattleStruct->hazardsQueue[1][0], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[1][5], HAZARDS_NONE); } } diff --git a/test/battle/move_effect/hit_switch_target.c b/test/battle/move_effect/hit_switch_target.c index 251279e198..76a500bd46 100644 --- a/test/battle/move_effect/hit_switch_target.c +++ b/test/battle/move_effect/hit_switch_target.c @@ -159,8 +159,8 @@ SINGLE_BATTLE_TEST("Dragon Tail switches target out and incoming mon has Levitat ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player); HP_BAR(opponent); MESSAGE("The opposing Weezing was dragged out!"); - HP_BAR(opponent); - NOT STATUS_ICON(opponent, poison: TRUE); MESSAGE("The poison spikes disappeared from the ground around the opposing team!"); + NOT STATUS_ICON(opponent, poison: TRUE); + HP_BAR(opponent); } } diff --git a/test/battle/move_effect/rapid_spin.c b/test/battle/move_effect/rapid_spin.c index 9d142bf32e..852b4d69a7 100644 --- a/test/battle/move_effect/rapid_spin.c +++ b/test/battle/move_effect/rapid_spin.c @@ -63,3 +63,32 @@ SINGLE_BATTLE_TEST("Rapid Spin: Mortal Spin blows away Wrap, hazards and poisons MESSAGE("Wobbuffet blew away Stealth Rock!"); } } + +SINGLE_BATTLE_TEST("Rapid Spin blows away all hazards") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_RAPID_SPIN) == EFFECT_RAPID_SPIN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); } + TURN { MOVE(opponent, MOVE_STICKY_WEB); } + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_SPIKES); MOVE(player, MOVE_RAPID_SPIN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAPID_SPIN, player); + + MESSAGE("Wobbuffet blew away Spikes!"); + MESSAGE("Wobbuffet blew away Sticky Web!"); + MESSAGE("Wobbuffet blew away Toxic Spikes!"); + MESSAGE("Wobbuffet blew away Stealth Rock!"); + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + } +} diff --git a/test/battle/move_effect/spikes.c b/test/battle/move_effect/spikes.c index 03dcec84f4..4b458f5c68 100644 --- a/test/battle/move_effect/spikes.c +++ b/test/battle/move_effect/spikes.c @@ -133,3 +133,30 @@ SINGLE_BATTLE_TEST("Spikes do not damage airborne Pokemon") } } } + +SINGLE_BATTLE_TEST("Toxic Spikes: Only three layers can be set up") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_SPIKES); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKES, opponent); + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + u32 spikesAmount = gSideTimers[0].spikesAmount; + EXPECT_EQ(spikesAmount, 3); + } +} diff --git a/test/battle/move_effect/tidy_up.c b/test/battle/move_effect/tidy_up.c index 842c186ab0..61468e8cea 100644 --- a/test/battle/move_effect/tidy_up.c +++ b/test/battle/move_effect/tidy_up.c @@ -43,9 +43,9 @@ SINGLE_BATTLE_TEST("Tidy Up removes hazards and raises Stats") MESSAGE("Wobbuffet used Tidy Up!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_TIDY_UP, player); MESSAGE("The spikes disappeared from the ground around your team!"); - MESSAGE("The pointed stones disappeared from around your team!"); - MESSAGE("The poison spikes disappeared from the ground around your team!"); MESSAGE("The sticky web has disappeared from the ground around your team!"); + MESSAGE("The poison spikes disappeared from the ground around your team!"); + MESSAGE("The pointed stones disappeared from around your team!"); MESSAGE("Tidying up complete!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Wobbuffet's Attack rose!"); diff --git a/test/battle/move_effect/toxic_spikes.c b/test/battle/move_effect/toxic_spikes.c index 4d4dbf7c43..3d21c0693b 100644 --- a/test/battle/move_effect/toxic_spikes.c +++ b/test/battle/move_effect/toxic_spikes.c @@ -266,3 +266,28 @@ SINGLE_BATTLE_TEST("Toxic Spikes print bad poison for 2 layers") MESSAGE("The opposing Wynaut was badly poisoned!"); } } + +SINGLE_BATTLE_TEST("Toxic Spikes: Only two layers can be set up") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponent, MOVE_TOXIC_SPIKES); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_SPIKES, opponent); + } THEN { + EXPECT_EQ(gBattleStruct->hazardsQueue[0][0], HAZARDS_TOXIC_SPIKES); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][1], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][2], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][3], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][4], HAZARDS_NONE); + EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE); + u32 toxicSpikesAmount = gSideTimers[0].toxicSpikesAmount; + EXPECT_EQ(toxicSpikesAmount, 2); + } +} From 5a6e7749abe93da9c5acb834497de05f566c623f Mon Sep 17 00:00:00 2001 From: Nephrite Date: Tue, 8 Jul 2025 17:17:05 +0300 Subject: [PATCH 059/283] Removed all instances of .chance = 100, SHEER_FORCE_NO_BOOST (#7300) --- src/data/moves_info.h | 117 +----------------------------------------- 1 file changed, 1 insertion(+), 116 deletions(-) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 2de237f01b..465d3c0153 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -17178,8 +17178,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .contestComboMoves = {0}, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ION_DELUGE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_PlasmaFists, }, @@ -17228,8 +17226,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = #if B_UPDATED_MOVE_DATA >= GEN_8 .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_EVS_PLUS_1, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, + .self = TRUE, }), #endif .battleAnimScript = gBattleAnimMove_ZippyZap, @@ -17346,8 +17343,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_BuzzyBuzz, }, @@ -17372,8 +17367,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_BURN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SizzlySlide, }, @@ -17396,8 +17389,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LIGHT_SCREEN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_GlitzyGlow, }, @@ -17420,8 +17411,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REFLECT, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_BaddyBad, }, @@ -17445,8 +17434,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LEECH_SEED, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SappySeed, }, @@ -17469,8 +17456,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HAZE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_FreezyFrost, }, @@ -17493,8 +17478,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AROMATHERAPY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), .battleAnimScript = gBattleAnimMove_SparklySwirl, }, @@ -21756,8 +21739,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxFlare, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SUN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21778,8 +21759,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxFlutterby, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SP_ATK_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21800,8 +21779,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxLightning, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ELECTRIC_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21822,8 +21799,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxStrike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SPEED_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21844,8 +21819,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxKnuckle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_ATTACK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21866,8 +21839,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxPhantasm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_DEFENSE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21888,8 +21859,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxHailstorm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HAIL, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21910,8 +21879,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxOoze, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_ATK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21932,8 +21899,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxGeyser, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21954,8 +21919,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxAirstream, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SPEED, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21976,8 +21939,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxStarfall, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_MISTY_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -21998,8 +21959,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxWyrmwind, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_ATTACK_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22020,8 +21979,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxMindstorm, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PSYCHIC_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22042,8 +21999,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxRockfall, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SANDSTORM, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22065,8 +22020,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxQuake, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_DEF, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22087,8 +22040,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxDarkness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SP_DEF_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22109,8 +22060,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxOvergrowth, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_GRASSY_TERRAIN, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22131,8 +22080,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_MaxSteelspike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RAISE_TEAM_DEFENSE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22153,8 +22100,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVineLash, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_VINE_LASH, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22175,8 +22120,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxWildfire, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WILDFIRE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22197,8 +22140,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCannonade, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CANNONADE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22219,8 +22160,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxBefuddle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_EFFECT_SPORE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22241,8 +22180,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVoltCrash, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYZE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22263,8 +22200,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxGoldRush, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22285,8 +22220,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxChiStrike, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CRIT_PLUS_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22307,8 +22240,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxTerror, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PREVENT_ESCAPE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22329,8 +22260,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFoamBurst, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_SPEED_2_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22351,8 +22280,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxResonance, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AURORA_VEIL, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22373,8 +22300,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCuddle, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_INFATUATE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22395,8 +22320,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxReplenish, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_RECYCLE_BERRIES, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22417,8 +22340,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxMalodor, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22439,8 +22360,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxMeltdown, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_TORMENT_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22462,8 +22381,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxDrumSolo, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22485,8 +22402,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFireball, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22508,8 +22423,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxHydrosnipe, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIXED_POWER, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22530,8 +22443,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxWindRage, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_DEFOG, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22552,8 +22463,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxGravitas, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_GRAVITY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22574,8 +22483,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxStonesurge, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_STEALTH_ROCK, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22596,8 +22503,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxVolcalith, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_VOLCALITH, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22618,8 +22523,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxTartness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_LOWER_EVASIVENESS_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22640,8 +22543,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSweetness, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_AROMATHERAPY, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22662,8 +22563,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSandblast, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SANDBLAST_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22684,8 +22583,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxStunShock, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_POISON_PARALYZE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22706,8 +22603,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxCentiferno, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FIRE_SPIN_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22728,8 +22623,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSmite, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_CONFUSE_SIDE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22751,8 +22644,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSnooze, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_YAWN_FOE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22773,8 +22664,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxFinale, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_HEAL_TEAM, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22795,8 +22684,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxSteelsurge, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_STEELSURGE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, @@ -22817,8 +22704,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .battleAnimScript = gBattleAnimMove_GMaxDepletion, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_SPITE, - .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, }), }, From 57dad22ac463a10aab81ee5e2f0911748c1dbf53 Mon Sep 17 00:00:00 2001 From: khbsd Date: Tue, 8 Jul 2025 18:52:42 +0000 Subject: [PATCH 060/283] feat: separate water and rock smash encounter rate checks (#7293) --- include/wild_encounter.h | 7 +++--- src/dexnav.c | 2 +- src/wild_encounter.c | 51 ++++++++++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/include/wild_encounter.h b/include/wild_encounter.h index 8a0eb671f6..c8f60712f9 100644 --- a/include/wild_encounter.h +++ b/include/wild_encounter.h @@ -63,9 +63,10 @@ bool8 StandardWildEncounter_Debug(void); u32 CalculateChainFishingShinyRolls(void); void CreateWildMon(u16 species, u8 level); u16 GetCurrentMapWildMonHeaderId(void); -u8 ChooseWildMonIndex_Land(void); -u8 ChooseWildMonIndex_WaterRock(void); -u8 ChooseHiddenMonIndex(void); +u32 ChooseWildMonIndex_Land(void); +u32 ChooseWildMonIndex_Water(void); +u32 ChooseWildMonIndex_Rocks(void); +u32 ChooseHiddenMonIndex(void); bool32 MapHasNoEncounterData(void); enum TimeOfDay GetTimeOfDayForEncounters(u32 headerId, enum WildPokemonArea area); diff --git a/src/dexnav.c b/src/dexnav.c index 38a5323994..e1fc4a497f 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -2577,7 +2577,7 @@ bool8 TryFindHiddenPokemon(void) } else { - species = gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo->wildPokemon[ChooseWildMonIndex_WaterRock()].species; + species = gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; environment = ENCOUNTER_TYPE_WATER; } diff --git a/src/wild_encounter.c b/src/wild_encounter.c index b5de5d7415..eafd522d78 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -178,7 +178,7 @@ static void FeebasSeedRng(u16 seed) } // LAND_WILD_COUNT -u8 ChooseWildMonIndex_Land(void) +u32 ChooseWildMonIndex_Land(void) { u8 wildMonIndex = 0; bool8 swap = FALSE; @@ -218,10 +218,10 @@ u8 ChooseWildMonIndex_Land(void) return wildMonIndex; } -// ROCK_WILD_COUNT / WATER_WILD_COUNT -u8 ChooseWildMonIndex_WaterRock(void) +// WATER_WILD_COUNT +u32 ChooseWildMonIndex_Water(void) { - u8 wildMonIndex = 0; + u32 wildMonIndex = 0; bool8 swap = FALSE; u8 rand = Random() % ENCOUNTER_CHANCE_WATER_MONS_TOTAL; @@ -245,8 +245,35 @@ u8 ChooseWildMonIndex_WaterRock(void) return wildMonIndex; } +// ROCK_WILD_COUNT +u32 ChooseWildMonIndex_Rocks(void) +{ + u32 wildMonIndex = 0; + bool8 swap = FALSE; + u8 rand = Random() % ENCOUNTER_CHANCE_ROCK_SMASH_MONS_TOTAL; + + if (rand < ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_0) + wildMonIndex = 0; + else if (rand >= ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_0 && rand < ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_1) + wildMonIndex = 1; + else if (rand >= ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_1 && rand < ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_2) + wildMonIndex = 2; + else if (rand >= ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_2 && rand < ENCOUNTER_CHANCE_ROCK_SMASH_MONS_SLOT_3) + wildMonIndex = 3; + else + wildMonIndex = 4; + + if (LURE_STEP_COUNT != 0 && (Random() % 10 < 2)) + swap = TRUE; + + if (swap) + wildMonIndex = 4 - wildMonIndex; + + return wildMonIndex; +} + // FISH_WILD_COUNT -static u8 ChooseWildMonIndex_Fishing(u8 rod) +static u32 ChooseWildMonIndex_Fishing(u8 rod) { u8 wildMonIndex = 0; bool8 swap = FALSE; @@ -411,7 +438,7 @@ enum TimeOfDay GetTimeOfDayForEncounters(u32 headerId, enum WildPokemonArea area } } - if (wildMonInfo == NULL && !OW_TIME_OF_DAY_DISABLE_FALLBACK) + if (wildMonInfo == NULL && !OW_TIME_OF_DAY_DISABLE_FALLBACK) return OW_TIME_OF_DAY_FALLBACK; else return timeOfDay; @@ -529,10 +556,10 @@ static bool8 TryGenerateWildMon(const struct WildPokemonInfo *wildMonInfo, enum if (OW_STORM_DRAIN >= GEN_8 && TRY_GET_ABILITY_INFLUENCED_WILD_MON_INDEX(wildMonInfo->wildPokemon, TYPE_WATER, ABILITY_STORM_DRAIN, &wildMonIndex, WATER_WILD_COUNT)) break; - wildMonIndex = ChooseWildMonIndex_WaterRock(); + wildMonIndex = ChooseWildMonIndex_Water(); break; case WILD_AREA_ROCKS: - wildMonIndex = ChooseWildMonIndex_WaterRock(); + wildMonIndex = ChooseWildMonIndex_Rocks(); break; default: case WILD_AREA_FISHING: @@ -1007,7 +1034,7 @@ u16 GetLocalWildMon(bool8 *isWaterMon) else if (landMonsInfo == NULL && waterMonsInfo != NULL) { *isWaterMon = TRUE; - return waterMonsInfo->wildPokemon[ChooseWildMonIndex_WaterRock()].species; + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; } // Either land or water Pokémon if ((Random() % 100) < 80) @@ -1017,7 +1044,7 @@ u16 GetLocalWildMon(bool8 *isWaterMon) else { *isWaterMon = TRUE; - return waterMonsInfo->wildPokemon[ChooseWildMonIndex_WaterRock()].species; + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; } } @@ -1033,7 +1060,7 @@ u16 GetLocalWaterMon(void) const struct WildPokemonInfo *waterMonsInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].waterMonsInfo; if (waterMonsInfo) - return waterMonsInfo->wildPokemon[ChooseWildMonIndex_WaterRock()].species; + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; } return SPECIES_NONE; } @@ -1226,7 +1253,7 @@ bool8 StandardWildEncounter_Debug(void) return TRUE; } -u8 ChooseHiddenMonIndex(void) +u32 ChooseHiddenMonIndex(void) { #ifdef ENCOUNTER_CHANCE_HIDDEN_MONS_TOTAL u8 rand = Random() % ENCOUNTER_CHANCE_HIDDEN_MONS_TOTAL; From b5a13d5e7f2f22ec7b147c126a2c807ed1f5dbe8 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 8 Jul 2025 16:00:37 -0400 Subject: [PATCH 061/283] Fixed Flag Vars menu keeping artifacts from bag menu + cleanup (#7226) --- src/debug.c | 208 +++++++++++++++++----------------------------------- 1 file changed, 66 insertions(+), 142 deletions(-) diff --git a/src/debug.c b/src/debug.c index 041734ebf5..ba91351b98 100644 --- a/src/debug.c +++ b/src/debug.c @@ -231,19 +231,20 @@ EWRAM_DATA u64 gDebugAIFlags = 0; // ******************************* // Define functions static void Debug_ShowMenu(DebugFunc HandleInput, const struct DebugMenuOption *items); +static u8 Debug_GenerateListMenuNames(void); static void Debug_DestroyMenu(u8 taskId); static void DebugAction_Cancel(u8 taskId); static void DebugAction_DestroyExtraWindow(u8 taskId); static void Debug_RefreshListMenu(u8 taskId); static void DebugAction_OpenSubMenu(u8 taskId, const struct DebugMenuOption *items); -static void DebugAction_OpenSubMenuFlagsVars(u8 taskId); +static void DebugAction_OpenSubMenuFlagsVars(u8 taskId, const struct DebugMenuOption *items); static void DebugAction_OpenSubMenuFakeRTC(u8 taskId, const struct DebugMenuOption *items); static void DebugAction_OpenSubMenuCreateFollowerNPC(u8 taskId, const struct DebugMenuOption *items); static void DebugAction_ExecuteScript(u8 taskId, const u8 *script); +static void DebugAction_ToggleFlag(u8 taskId); static void DebugTask_HandleMenuInput_General(u8 taskId); -static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId); static void DebugAction_Util_Fly(u8 taskId); static void DebugAction_Util_Warp_Warp(u8 taskId); @@ -637,20 +638,20 @@ static const struct DebugMenuOption sDebugMenu_Actions_Flags[] = [DEBUG_FLAGVAR_MENU_ITEM_VARS] = { COMPOUND_STRING("Set Var XYZ…"), DebugAction_FlagsVars_Vars }, [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = { COMPOUND_STRING("Pokédex Flags All"), DebugAction_FlagsVars_PokedexFlags_All }, [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = { COMPOUND_STRING("Pokédex Flags Reset"), DebugAction_FlagsVars_PokedexFlags_Reset }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}Pokédex"), DebugAction_FlagsVars_SwitchDex }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}National Dex"), DebugAction_FlagsVars_SwitchNatDex }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = { COMPOUND_STRING("Toggle {STR_VAR_1}PokéNav"), DebugAction_FlagsVars_SwitchPokeNav }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}Match Call"), DebugAction_FlagsVars_SwitchMatchCall }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = { COMPOUND_STRING("Toggle {STR_VAR_1}Running Shoes"), DebugAction_FlagsVars_RunningShoes }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Fly Flags"), DebugAction_FlagsVars_ToggleFlyFlags }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}All badges"), DebugAction_FlagsVars_ToggleBadgeFlags }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = { COMPOUND_STRING("Toggle {STR_VAR_1}Game clear"), DebugAction_FlagsVars_ToggleGameClear }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Frontier Pass"), DebugAction_FlagsVars_ToggleFrontierPass }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = { COMPOUND_STRING("Toggle {STR_VAR_1}Collision OFF"), DebugAction_FlagsVars_CollisionOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = { COMPOUND_STRING("Toggle {STR_VAR_1}Encounter OFF"), DebugAction_FlagsVars_EncounterOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Trainer See OFF"), DebugAction_FlagsVars_TrainerSeeOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Bag Use OFF"), DebugAction_FlagsVars_BagUseOnOff }, - [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = { COMPOUND_STRING("Toggle {STR_VAR_1}Catching OFF"), DebugAction_FlagsVars_CatchingOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}Pokédex"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = { COMPOUND_STRING("Toggle {STR_VAR_1}National Dex"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchNatDex }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = { COMPOUND_STRING("Toggle {STR_VAR_1}PokéNav"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchPokeNav }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}Match Call"), DebugAction_ToggleFlag, DebugAction_FlagsVars_SwitchMatchCall }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = { COMPOUND_STRING("Toggle {STR_VAR_1}Running Shoes"), DebugAction_ToggleFlag, DebugAction_FlagsVars_RunningShoes }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Fly Flags"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFlyFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = { COMPOUND_STRING("Toggle {STR_VAR_1}All badges"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleBadgeFlags }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_GAME_CLEAR] = { COMPOUND_STRING("Toggle {STR_VAR_1}Game clear"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleGameClear }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = { COMPOUND_STRING("Toggle {STR_VAR_1}Frontier Pass"), DebugAction_ToggleFlag, DebugAction_FlagsVars_ToggleFrontierPass }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLLISION] = { COMPOUND_STRING("Toggle {STR_VAR_1}Collision OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CollisionOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = { COMPOUND_STRING("Toggle {STR_VAR_1}Encounter OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_EncounterOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Trainer See OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_TrainerSeeOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = { COMPOUND_STRING("Toggle {STR_VAR_1}Bag Use OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_BagUseOnOff }, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = { COMPOUND_STRING("Toggle {STR_VAR_1}Catching OFF"), DebugAction_ToggleFlag, DebugAction_FlagsVars_CatchingOnOff }, { NULL } }; @@ -776,49 +777,6 @@ static const struct DebugMenuOption *Debug_GetCurrentCallbackMenu(void) return callbackItems; } -static void Debug_ShowMenuFromTemplate(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate) -{ - struct ListMenuTemplate menuTemplate; - u8 windowId; - u8 menuTaskId; - u8 inputTaskId; - - // create window - HideMapNamePopUpWindow(); - LoadMessageBoxAndBorderGfx(); - windowId = AddWindow(&sDebugMenuWindowTemplateMain); - DrawStdWindowFrame(windowId, FALSE); - - // create list menu - menuTemplate = LMtemplate; - menuTemplate.maxShowed = DEBUG_MENU_HEIGHT_MAIN; - menuTemplate.windowId = windowId; - menuTemplate.header_X = 0; - menuTemplate.item_X = 8; - menuTemplate.cursor_X = 0; - menuTemplate.upText_Y = 1; - menuTemplate.cursorPal = 2; - menuTemplate.fillValue = 1; - menuTemplate.cursorShadowPal = 3; - menuTemplate.lettersSpacing = 1; - menuTemplate.itemVerticalPadding = 0; - menuTemplate.scrollMultiple = LIST_NO_MULTIPLE_SCROLL; - menuTemplate.fontId = DEBUG_MENU_FONT; - menuTemplate.cursorKind = 0; - menuTaskId = ListMenuInit(&menuTemplate, 0, 0); - - // create input handler task - inputTaskId = CreateTask(HandleInput, 3); - gTasks[inputTaskId].tMenuTaskId = menuTaskId; - gTasks[inputTaskId].tWindowId = windowId; - gTasks[inputTaskId].tSubWindowId = 0; - - Debug_RefreshListMenu(inputTaskId); - - // draw everything - CopyWindowToVram(windowId, COPYWIN_FULL); -} - static bool32 IsSubMenuAction(const void *action) { return action == DebugAction_OpenSubMenu @@ -845,21 +803,30 @@ static void Debug_ShowMenu(DebugFunc HandleInput, const struct DebugMenuOption * windowId = AddWindow(&sDebugMenuWindowTemplateMain); DrawStdWindowFrame(windowId, FALSE); - u32 i = 0; - for (i = 0; items[i].text != NULL; i++) + u32 totalItems = 0; + + if (sDebugMenuListData->listId == 1) { - sDebugMenuListData->listItems[i].id = i; - StringExpandPlaceholders(gStringVar4, items[i].text); - if (IsSubMenuAction(items[i].action)) - StringAppend(gStringVar4, sDebugText_Arrow); - StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); - sDebugMenuListData->listItems[i].name = &sDebugMenuListData->itemNames[i][0]; + totalItems = Debug_GenerateListMenuNames(); + } + else + { + for (u32 i = 0; items[i].text != NULL; i++) + { + sDebugMenuListData->listItems[i].id = i; + StringExpandPlaceholders(gStringVar4, items[i].text); + if (IsSubMenuAction(items[i].action)) + StringAppend(gStringVar4, sDebugText_Arrow); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); + sDebugMenuListData->listItems[i].name = &sDebugMenuListData->itemNames[i][0]; + totalItems++; + } } // create list menu menuTemplate.items = sDebugMenuListData->listItems; menuTemplate.moveCursorFunc = ListMenuDefaultCursorMoveFunc; - menuTemplate.totalItems = i; + menuTemplate.totalItems = totalItems; menuTemplate.maxShowed = DEBUG_MENU_HEIGHT_MAIN; menuTemplate.windowId = windowId; menuTemplate.header_X = 0; @@ -1068,13 +1035,18 @@ static u8 Debug_CheckToggleFlags(u8 id) return result; } -static void Debug_GenerateListMenuNames(u32 totalItems) +static u8 Debug_GenerateListMenuNames(void) { const u8 sColor_Red[] = _("{COLOR RED}"); const u8 sColor_Green[] = _("{COLOR GREEN}"); u32 i, flagResult = 0; u8 const *name = NULL; + u8 totalItems = 0; + if (sDebugMenuListData->listId == 1) + // Failsafe to prevent memory corruption + totalItems = min(ARRAY_COUNT(sDebugMenu_Actions_Flags) - 1, DEBUG_MAX_MENU_ITEMS); + // Copy item names for all entries but the last (which is Cancel) for (i = 0; i < totalItems; i++) { @@ -1104,25 +1076,12 @@ static void Debug_GenerateListMenuNames(u32 totalItems) sDebugMenuListData->listItems[i].name = &sDebugMenuListData->itemNames[i][0]; sDebugMenuListData->listItems[i].id = i; } + return totalItems; } static void Debug_RefreshListMenu(u8 taskId) { - u8 totalItems = 0; - - if (sDebugMenuListData->listId == 1) - { - for (u32 i = 0; i < ARRAY_COUNT(sDebugMenu_Actions_Flags); i++) - { - sDebugMenuListData->listItems[i].id = i; - sDebugMenuListData->listItems[i].name = sDebugMenu_Actions_Flags[i].text; - } - totalItems = gMultiuseListMenuTemplate.totalItems = ARRAY_COUNT(sDebugMenu_Actions_Flags) - 1; - } - - // Failsafe to prevent memory corruption - totalItems = min(totalItems, DEBUG_MAX_MENU_ITEMS); - Debug_GenerateListMenuNames(totalItems); + u8 totalItems = Debug_GenerateListMenuNames(); // Set list menu data gMultiuseListMenuTemplate.items = sDebugMenuListData->listItems; @@ -1143,17 +1102,6 @@ static void Debug_RefreshListMenu(u8 taskId) gMultiuseListMenuTemplate.cursorKind = 0; } -static void Debug_RedrawListMenu(u8 taskId) -{ - u8 listTaskId = gTasks[taskId].tMenuTaskId; - u16 scrollOffset, selectedRow; - ListMenuGetScrollAndRow(listTaskId, &scrollOffset, &selectedRow); - - DestroyListMenuTask(gTasks[taskId].tMenuTaskId, &scrollOffset, &selectedRow); - Debug_RefreshListMenu(taskId); - gTasks[taskId].tMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, scrollOffset, selectedRow); -} - static void DebugTask_HandleMenuInput_General(u8 taskId) { const struct DebugMenuOption *options = Debug_GetCurrentCallbackMenu(); @@ -1166,11 +1114,22 @@ static void DebugTask_HandleMenuInput_General(u8 taskId) if (option.action != NULL) { if (IsSubMenuAction(option.action)) + { ((DebugSubmenuFunc)option.action)(taskId, option.actionParams); + } else if (option.action == DebugAction_ExecuteScript) + { Debug_DestroyMenu_Full_Script(taskId, (const u8 *)option.actionParams); + } + else if (option.action == DebugAction_ToggleFlag) + { + ((DebugFunc)option.actionParams)(taskId); + DebugAction_ToggleFlag(taskId); + } else + { ((DebugFunc)option.action)(taskId); + } } } else if (JOY_NEW(B_BUTTON)) @@ -1179,10 +1138,9 @@ static void DebugTask_HandleMenuInput_General(u8 taskId) if (Debug_GetCurrentCallbackMenu() != NULL && Debug_RemoveCallbackMenu() != 0) { Debug_DestroyMenu(taskId); - if (sDebugMenuListData->listId == 1) - Debug_ShowMenu(DebugTask_HandleMenuInput_FlagsVars, NULL); - else - Debug_ShowMenu(DebugTask_HandleMenuInput_General, NULL); + if (sDebugMenuListData->listId != 0) + sDebugMenuListData->listId = 0; + Debug_ShowMenu(DebugTask_HandleMenuInput_General, NULL); } else { @@ -1192,57 +1150,17 @@ static void DebugTask_HandleMenuInput_General(u8 taskId) } } - -static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId) -{ - DebugSubmenuFunc func; - u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); - - if (JOY_NEW(A_BUTTON)) - { - PlaySE(SE_SELECT); - if ((func = sDebugMenu_Actions_Flags[input].action) != NULL) - { - if (input == DEBUG_FLAGVAR_MENU_ITEM_FLAGS || input == DEBUG_FLAGVAR_MENU_ITEM_VARS) - { - Debug_RedrawListMenu(taskId); - func(taskId, sDebugMenu_Actions_Flags[input].actionParams); - } - else - { - func(taskId, sDebugMenu_Actions_Flags[input].actionParams); - Debug_GenerateListMenuNames(gMultiuseListMenuTemplate.totalItems); - RedrawListMenu(gTasks[taskId].tMenuTaskId); - } - - // Remove TRUE/FALSE window for functions that haven't been assigned flags - if (gTasks[taskId].tInput == 0xFF) - { - ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, TRUE); - RemoveWindow(gTasks[taskId].tSubWindowId); - Free(sDebugMenuListData); - } - } - } - else if (JOY_NEW(B_BUTTON)) - { - PlaySE(SE_SELECT); - Debug_DestroyMenu(taskId); - Debug_ShowMainMenu(); - } -} - -static void DebugAction_OpenSubMenuFlagsVars(u8 taskId) +static void DebugAction_OpenSubMenuFlagsVars(u8 taskId, const struct DebugMenuOption *items) { Debug_DestroyMenu(taskId); sDebugMenuListData->listId = 1; - Debug_RefreshListMenu(taskId); - Debug_ShowMenuFromTemplate(DebugTask_HandleMenuInput_FlagsVars, gMultiuseListMenuTemplate); + Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); } static void DebugAction_OpenSubMenu(u8 taskId, const struct DebugMenuOption *items) { Debug_DestroyMenu(taskId); + sDebugMenuListData->listId = 0; Debug_ShowMenu(DebugTask_HandleMenuInput_General, items); } @@ -1264,6 +1182,12 @@ static void DebugAction_ExecuteScript(u8 taskId, const u8 *script) Debug_DestroyMenu_Full_Script(taskId, script); } +static void DebugAction_ToggleFlag(u8 taskId) +{ + Debug_GenerateListMenuNames(); + RedrawListMenu(gTasks[taskId].tMenuTaskId); +} + static void DebugAction_OpenSubMenuCreateFollowerNPC(u8 taskId, const struct DebugMenuOption *items) { if (FNPC_ENABLE_NPC_FOLLOWERS) From f4cc802656cc714cbf10ef20825171d7c5c37bdb Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 9 Jul 2025 08:02:55 +0100 Subject: [PATCH 062/283] Fix crashing tests looping (#7299) --- include/test/battle.h | 11 +++++++++++ include/test/test.h | 13 +++++++++++++ ld_script_test.ld | 12 ++++++------ test/test_runner.c | 29 +++++++++++++++++++---------- test/test_test_runner.c | 9 +++++++++ 5 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 test/test_test_runner.c diff --git a/include/test/battle.h b/include/test/battle.h index 431e0f98f9..c323207b30 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -219,6 +219,17 @@ * { * KNOWN_FAILING; // #2596. * + * KNOWN_CRASHING + * Marks a test as crashing due to a bug. If there is an issue number + * associated with the bug it should be included in a comment. If the + * test passes the developer will be notified to remove KNOWN_CRASHING. + * For example: + * TEST("Crashes") + * { + * KNOWN_CRASHING; // #7255 + * void (*f)(void) = NULL; + * f(); // Crashes! + * * PARAMETRIZE * Runs a test multiple times. i will be set to which parameter is * running, and results will contain an entry for each parameter, e.g.: diff --git a/include/test/test.h b/include/test/test.h index 092b603ec0..835634df7b 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -54,6 +54,14 @@ struct TestRunnerState u32 timeoutSeconds; }; +struct PersistentTestRunnerState +{ + u32 address:28; + u32 state:1; + u32 expectCrash:1; + u32 unused_30:2; +}; + extern const u8 gTestRunnerN; extern const u8 gTestRunnerI; extern const char gTestRunnerArgv[256]; @@ -71,11 +79,13 @@ extern const struct TestRunner gFunctionTestRunner; extern struct FunctionTestRunnerState *gFunctionTestRunnerState; extern struct TestRunnerState gTestRunnerState; +extern struct PersistentTestRunnerState gPersistentTestRunnerState; void CB2_TestRunner(void); void Test_ExpectedResult(enum TestResult); void Test_ExpectLeaks(bool32); +void Test_ExpectCrash(bool32); void Test_ExitWithResult(enum TestResult, u32 stopLine, const char *fmt, ...); u32 SourceLine(u32 sourceLineOffset); u32 SourceLineOffset(u32 sourceLine); @@ -220,6 +230,9 @@ static inline struct Benchmark BenchmarkStop(void) #define KNOWN_LEAKING \ Test_ExpectLeaks(TRUE) +#define KNOWN_CRASHING \ + Test_ExpectCrash(TRUE) + #define PARAMETRIZE if (gFunctionTestRunnerState->parameters++ == gFunctionTestRunnerState->runParameter) #define PARAMETRIZE_LABEL(f, label) if (gFunctionTestRunnerState->parameters++ == gFunctionTestRunnerState->runParameter && (Test_MgbaPrintf(":N%s: " f " (%d/%d)", gTestRunnerState.test->name, label, gFunctionTestRunnerState->runParameter + 1, gFunctionTestRunnerState->parameters), 1)) diff --git a/ld_script_test.ld b/ld_script_test.ld index d279d6b4f6..db6c638883 100644 --- a/ld_script_test.ld +++ b/ld_script_test.ld @@ -6,9 +6,10 @@ gInitialMainCB2 = CB2_TestRunner; MEMORY { - EWRAM (rwx) : ORIGIN = 0x2000000, LENGTH = 256K - IWRAM (rwx) : ORIGIN = 0x3000000, LENGTH = 32K - ROM (rx) : ORIGIN = 0x8000000, LENGTH = 32M + EWRAM (rwx) : ORIGIN = 0x2000000, LENGTH = 256K + IWRAM (rwx) : ORIGIN = 0x3000000, LENGTH = 0x7F00 + IWRAM_PERSISTENT (rwx) : ORIGIN = 0x3007F00, LENGTH = 0x100 + ROM (rx) : ORIGIN = 0x8000000, LENGTH = 32M } SECTIONS { @@ -60,13 +61,11 @@ SECTIONS { /* .persistent starts at 0x3007F00 */ /* WARNING: This is the end of the IRQ stack, if there's too * much data it WILL be overwritten. */ - - . = 0x03007F00; .iwram.persistent (NOLOAD) : ALIGN(4) { test/*.o(.persistent); - } > IWRAM + } > IWRAM_PERSISTENT /* BEGIN ROM DATA */ . = 0x8000000; @@ -135,6 +134,7 @@ SECTIONS { ALIGN(4) { __start_tests = .; + test/test_test_runner.o(.tests); /* Sanity checks first. */ test/*.o(.tests); __stop_tests = .; test/*.o(.text); diff --git a/test/test_runner.c b/test/test_runner.c index a1460365e0..99ba3f42ab 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -22,10 +22,7 @@ enum { CURRENT_TEST_STATE_RUN, }; -__attribute__((section(".persistent"))) static struct { - u32 address:28; - u32 state:1; -} sCurrentTest = {0}; +__attribute__((section(".persistent"))) struct PersistentTestRunnerState gPersistentTestRunnerState = {0}; void TestRunner_Battle(const struct Test *); @@ -184,15 +181,16 @@ void CB2_TestRunner(void) gSaveBlock2Ptr->optionsBattleStyle = OPTIONS_BATTLE_STYLE_SET; // The current test restarted the ROM (e.g. by jumping to NULL). - if (sCurrentTest.address != 0) + if (gPersistentTestRunnerState.address != 0) { gTestRunnerState.test = __start_tests; - while ((uintptr_t)gTestRunnerState.test != sCurrentTest.address) + while ((uintptr_t)gTestRunnerState.test != gPersistentTestRunnerState.address) { AssignCostToRunner(); gTestRunnerState.test++; } - if (sCurrentTest.state == CURRENT_TEST_STATE_ESTIMATE) + + if (gPersistentTestRunnerState.state == CURRENT_TEST_STATE_ESTIMATE) { u32 runner = MinCostProcess(); gTestRunnerState.processCosts[runner] += 1; @@ -211,6 +209,9 @@ void CB2_TestRunner(void) gTestRunnerState.state = STATE_REPORT_RESULT; gTestRunnerState.result = TEST_RESULT_CRASH; } + + if (gPersistentTestRunnerState.expectCrash) + gTestRunnerState.expectedResult = TEST_RESULT_CRASH; } else { @@ -252,8 +253,8 @@ void CB2_TestRunner(void) REG_TM2CNT_L = UINT16_MAX - (274 * 60); // Approx. 1 second. REG_TM2CNT_H = TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_1024CLK; - sCurrentTest.address = (uintptr_t)gTestRunnerState.test; - sCurrentTest.state = CURRENT_TEST_STATE_ESTIMATE; + gPersistentTestRunnerState.address = (uintptr_t)gTestRunnerState.test; + gPersistentTestRunnerState.state = CURRENT_TEST_STATE_ESTIMATE; // If AssignCostToRunner fails, we want to report the failure. gTestRunnerState.state = STATE_REPORT_RESULT; @@ -266,7 +267,8 @@ void CB2_TestRunner(void) case STATE_RUN_TEST: gTestRunnerState.state = STATE_REPORT_RESULT; - sCurrentTest.state = CURRENT_TEST_STATE_RUN; + gPersistentTestRunnerState.state = CURRENT_TEST_STATE_RUN; + gPersistentTestRunnerState.expectCrash = FALSE; SeedRng(0); SeedRng2(0); if (gTestRunnerState.test->runner->setUp) @@ -423,6 +425,13 @@ void Test_ExpectLeaks(bool32 expectLeaks) gTestRunnerState.expectLeaks = expectLeaks; } +void Test_ExpectCrash(bool32 expectCrash) +{ + gPersistentTestRunnerState.expectCrash = expectCrash; + if (expectCrash) + Test_ExpectedResult(TEST_RESULT_CRASH); +} + static void FunctionTest_SetUp(void *data) { (void)data; diff --git a/test/test_test_runner.c b/test/test_test_runner.c new file mode 100644 index 0000000000..670be27674 --- /dev/null +++ b/test/test_test_runner.c @@ -0,0 +1,9 @@ +#include "global.h" +#include "test/test.h" + +TEST("Tests resume after CRASH") +{ + KNOWN_CRASHING; + void (*f)(void) = NULL; + f(); +} From 6367ce71beb0fc050d6ab305ec9da60e15038855 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 9 Jul 2025 09:55:07 +0200 Subject: [PATCH 063/283] Remove wrongly added binary files (#7307) Co-authored-by: Hedara --- .gitignore | 2 ++ tools/compresSmol/compresSmol | Bin 100384 -> 0 bytes tools/compresSmol/compresSmolTilemap | Bin 104416 -> 0 bytes 3 files changed, 2 insertions(+) delete mode 100755 tools/compresSmol/compresSmol delete mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/.gitignore b/.gitignore index 6d9453242a..54192a472d 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ prefabs.json /pokeemerald-*.png src/data/map_group_count.h tools/trainerproc/trainerproc +tools/compresSmol/compresSmol +tools/compresSmol/compresSmolTilemap *.Identifier *.smol *.fastSmol diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol deleted file mode 100755 index c518f8381b4a471181752509730a92c1967e738b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100384 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 U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Wed, 9 Jul 2025 17:21:49 -0400 Subject: [PATCH 064/283] Fix switch AI not seeing absorbing abilities (#7309) --- src/battle_ai_switch_items.c | 2 ++ test/battle/ai/ai_switching.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index c6a4b8708f..7695a0a154 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -397,6 +397,8 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) { aiMove = gBattleMons[battler].moves[moveIndex]; if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE + && !CanAbilityAbsorbMove(battler, opposingBattler, gBattleMons[opposingBattler].ability, aiMove, GetBattleMoveType(aiMove), ABILITY_CHECK_TRIGGER_AI) + && !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gBattleMons[opposingBattler].ability, aiMove, ABILITY_CHECK_TRIGGER_AI) && (!ALL_MOVES_BAD_STATUS_MOVES_BAD || gMovesInfo[aiMove].power != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero return FALSE; } diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 41a480135d..e9ad61bdfa 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1156,6 +1156,23 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if all moves } } +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if all moves deal zero damage (absorbing ability)") +{ + PASSES_RANDOMLY(SHOULD_SWITCH_ALL_SCORES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_SCORES_BAD); + GIVEN { + ASSUME(GetMoveType(MOVE_THUNDER_PUNCH) == TYPE_ELECTRIC); + ASSUME(GetMoveType(MOVE_FAKE_OUT) == TYPE_NORMAL); + ASSUME(GetMoveType(MOVE_RETURN) == TYPE_NORMAL); + ASSUME(GetMoveType(MOVE_DRAIN_PUNCH) == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_MAROWAK_ALOLA].types[1] == TYPE_GHOST); + PLAYER(SPECIES_MAROWAK_ALOLA) { Ability(ABILITY_LIGHTNING_ROD); Moves(MOVE_SHADOW_BONE); } + OPPONENT(SPECIES_LOPUNNY) { Moves(MOVE_FAKE_OUT, MOVE_RETURN, MOVE_DRAIN_PUNCH, MOVE_THUNDER_PUNCH); Ability(ABILITY_LIMBER); } + OPPONENT(SPECIES_CHANDELURE) { Moves(MOVE_SHADOW_BALL); } + } WHEN { + TURN { MOVE(player, MOVE_SHADOW_BONE); EXPECT_SWITCH(opponent, 1); } + } +} + AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if Palafin-Zero isn't transformed yet") { GIVEN { From d15c490223d3a2c7731f3c1ae1ce16a923d9d15e Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:33:48 +0200 Subject: [PATCH 065/283] Changes AccuracyCalcHelper into CanMoveSkipAccuracyCalc (#7303) --- include/battle_util.h | 23 ++- src/battle_ai_main.c | 21 ++- src/battle_ai_switch_items.c | 4 +- src/battle_ai_util.c | 6 +- src/battle_script_commands.c | 224 ++--------------------- src/battle_util.c | 337 ++++++++++++++++++++++++++++------- 6 files changed, 316 insertions(+), 299 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index dd7a908e57..9eca2dacd7 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -23,17 +23,12 @@ #define MOVE_LIMITATION_PLACEHOLDER (1 << 15) #define MOVE_LIMITATIONS_ALL 0xFFFF -enum NonVolatileStatus +// Switches between simulated battle calc and actual battle combat +enum FunctionCallOption { - STATUS_CHECK_TRIGGER, - STATUS_RUN_SCRIPT, -}; - -enum AbilityEffectOptions -{ - ABILITY_CHECK_TRIGGER, - ABILITY_CHECK_TRIGGER_AI, - ABILITY_RUN_SCRIPT, + CHECK_TRIGGER, // Check the function without running scripts / setting any flags. + AI_CHECK, // Check the function without running scripts / setting any flags. Same as CHECK_TRIGGER but only used when additional data has to be fetched during ai calcs + RUN_SCRIPT, // Used during actual combat where a script has to be run / flags need to be set }; enum MoveAbsorbed @@ -245,8 +240,8 @@ enum MoveCanceller AtkCanceller_MoveSuccessOrder(void); void SetAtkCancellerForCalledMove(void); bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2); bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility); -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum AbilityEffectOptions option); -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option); +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option); +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum FunctionCallOption option); u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg); bool32 TryPrimalReversion(u32 battler); bool32 IsNeutralizingGasOnField(void); @@ -360,7 +355,7 @@ bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 ability); bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef); bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef); bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects secondaryMoveEffect, enum NonVolatileStatus option); +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects secondaryMoveEffect, enum FunctionCallOption option); bool32 CanBeConfused(u32 battler); bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag); u32 GetBattlerAffectionHearts(u32 battler); @@ -406,5 +401,7 @@ bool32 AreAnyHazardsOnSide(u32 side); void RemoveAllHazardsFromField(u32 side); bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType); void RemoveHazardFromField(u32 side, enum Hazards hazardType); +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option); +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index e66c77ce87..f3976fae4a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -547,18 +547,27 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) aiData->speedStats[battler] = GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); } +#define BYPASSES_ACCURACY_CALC 101 // 101 indicates for ai that the move will always hit static u32 Ai_SetMoveAccuracy(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 move) { u32 accuracy; u32 abilityAtk = aiData->abilities[battlerAtk]; u32 abilityDef = aiData->abilities[battlerDef]; - if (abilityAtk == ABILITY_NO_GUARD || abilityDef == ABILITY_NO_GUARD || GetMoveAccuracy(move) == 0) // Moves with accuracy 0 or no guard ability always hit. - accuracy = 100; + if (CanMoveSkipAccuracyCalc(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) + { + accuracy = BYPASSES_ACCURACY_CALC; + } else + { accuracy = GetTotalAccuracy(battlerAtk, battlerDef, move, abilityAtk, abilityDef, aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]); + // Cap normal accuracy at 100 for ai calcs. + // Done for comparison with moves that bypass accuracy checks (will be seen as 101 for ai calcs)) + accuracy = (accuracy > 100) ? 100 : accuracy; + } return accuracy; } +#undef BYPASSES_ACCURACY_CALC static void CalcBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef, u32 weather) { @@ -672,8 +681,8 @@ static u32 PpStallReduction(u32 move, u32 battlerAtk) u32 abilityAtk = ABILITY_NONE; u32 abilityDef = GetPartyMonAbility(&gPlayerParty[partyIndex]); u32 moveType = GetBattleMoveType(move); // Probably doesn't handle dynamic types right now - if (CanAbilityAbsorbMove(battlerAtk, tempBattleMonIndex, abilityDef, move, moveType, ABILITY_CHECK_TRIGGER) - || CanAbilityBlockMove(battlerAtk, tempBattleMonIndex, abilityAtk, abilityDef, move, ABILITY_CHECK_TRIGGER) + if (CanAbilityAbsorbMove(battlerAtk, tempBattleMonIndex, abilityDef, move, moveType, CHECK_TRIGGER) + || CanAbilityBlockMove(battlerAtk, tempBattleMonIndex, abilityAtk, abilityDef, move, CHECK_TRIGGER) || (CalcPartyMonTypeEffectivenessMultiplier(move, species, abilityDef) == 0)) { totalStallValue += currentStallValue; @@ -1105,10 +1114,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // check non-user target if (!(moveTarget & MOVE_TARGET_USER)) { - if (CanAbilityBlockMove(battlerAtk, battlerDef, abilityAtk, abilityDef, move, ABILITY_CHECK_TRIGGER_AI)) + if (CanAbilityBlockMove(battlerAtk, battlerDef, abilityAtk, abilityDef, move, AI_CHECK)) RETURN_SCORE_MINUS(20); - if (CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, move, moveType, ABILITY_CHECK_TRIGGER_AI)) + if (CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, move, moveType, AI_CHECK)) RETURN_SCORE_MINUS(20); switch (abilityDef) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index e7bcf00e7b..393eb054bf 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1010,8 +1010,8 @@ static bool32 ShouldSwitchIfBadChoiceLock(u32 battler) bool32 moveAffectsTarget = TRUE; if (lastUsedMove != MOVE_NONE && (AI_GetMoveEffectiveness(lastUsedMove, battler, opposingBattler) == UQ_4_12(0.0) - || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, GetMoveType(lastUsedMove), ABILITY_CHECK_TRIGGER) - || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, ABILITY_CHECK_TRIGGER))) + || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, GetMoveType(lastUsedMove), AI_CHECK) + || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, AI_CHECK))) moveAffectsTarget = FALSE; if (HOLD_EFFECT_CHOICE(holdEffect) && IsBattlerItemEnabled(battler)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 149aada871..6d2fb0afce 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -514,16 +514,16 @@ bool32 IsDamageMoveUnusable(struct DamageContext *ctx) partnerDefAbility = aiData->abilities[BATTLE_PARTNER(ctx->battlerDef)]; } - if (CanAbilityBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, battlerDefAbility, ctx->move, ABILITY_CHECK_TRIGGER)) + if (CanAbilityBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, battlerDefAbility, ctx->move, AI_CHECK)) return TRUE; - if (CanAbilityAbsorbMove(ctx->battlerAtk, ctx->battlerDef, battlerDefAbility, ctx->move, ctx->moveType, ABILITY_CHECK_TRIGGER)) + if (CanAbilityAbsorbMove(ctx->battlerAtk, ctx->battlerDef, battlerDefAbility, ctx->move, ctx->moveType, AI_CHECK)) return TRUE; // Limited to Lighning Rod and Storm Drain because otherwise the AI would consider Water Absorb, etc... if (partnerDefAbility == ABILITY_LIGHTNING_ROD || partnerDefAbility == ABILITY_STORM_DRAIN) { - if (CanAbilityAbsorbMove(ctx->battlerAtk, BATTLE_PARTNER(ctx->battlerDef), partnerDefAbility, ctx->move, ctx->moveType, ABILITY_CHECK_TRIGGER)) + if (CanAbilityAbsorbMove(ctx->battlerAtk, BATTLE_PARTNER(ctx->battlerDef), partnerDefAbility, ctx->move, ctx->moveType, AI_CHECK)) return TRUE; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 567bdd85ee..f148129b2d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1248,7 +1248,7 @@ static void Cmd_attackcanceler(void) GetBattlerAbility(gBattlerAttacker), abilityDef, gCurrentMove, - ABILITY_RUN_SCRIPT)) + RUN_SCRIPT)) return; if (GetMoveNonVolatileStatus(gCurrentMove) == MOVE_EFFECT_PARALYSIS) @@ -1259,7 +1259,7 @@ static void Cmd_attackcanceler(void) abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), - ABILITY_RUN_SCRIPT)) + RUN_SCRIPT)) return; } @@ -1432,7 +1432,7 @@ static void JumpIfMoveFailed(u32 adder, u32 move, u32 moveType, const u8 *failIn GetBattlerAbility(gBattlerTarget), move, moveType, - ABILITY_RUN_SCRIPT)) + RUN_SCRIPT)) return; } @@ -1464,211 +1464,6 @@ static bool32 JumpIfMoveAffectedByProtect(u32 move, u32 battler, u32 shouldJump, return affected; } -static bool32 AccuracyCalcHelper(u32 move, u32 battler) -{ - bool32 effect = FALSE; - u32 ability = ABILITY_NONE; - enum BattleMoveEffects moveEffect = GetMoveEffect(move); - u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - - if ((gStatuses3[battler] & STATUS3_ALWAYS_HITS && gDisableStructs[battler].battlerWithSureHit == gBattlerAttacker) - || (B_TOXIC_NEVER_MISS >= GEN_6 - && nonVolatileStatus == MOVE_EFFECT_TOXIC - && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)) - || gStatuses4[battler] & STATUS4_GLAIVE_RUSH) - { - effect = TRUE; - } - // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. - else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD - && !(gStatuses3[battler] & STATUS3_COMMANDER) - && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battler] == SKY_DROP_NO_TARGET)) - { - effect = TRUE; - ability = ABILITY_NO_GUARD; - } - // If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits. - else if (GetBattlerAbility(battler) == ABILITY_NO_GUARD - && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battler] == SKY_DROP_NO_TARGET)) - { - effect = TRUE; - ability = ABILITY_NO_GUARD; - } - // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. - else if (gStatuses3[battler] & STATUS3_TELEKINESIS - && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && moveEffect != EFFECT_OHKO - && moveEffect != EFFECT_SHEER_COLD) - { - effect = TRUE; - } - else if (gBattleStruct->battlerState[battler].pursuitTarget) - { - effect = TRUE; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)) - { - effect = TRUE; - } - else if ((gStatuses3[battler] & STATUS3_COMMANDER) - || (gStatuses3[battler] & STATUS3_PHANTOM_FORCE) - || ((gStatuses3[battler] & STATUS3_ON_AIR) && !(MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move))) - || ((gStatuses3[battler] & STATUS3_UNDERGROUND) && !MoveDamagesUnderground(move)) - || ((gStatuses3[battler] & STATUS3_UNDERWATER) && !MoveDamagesUnderWater(move))) - { - gBattleStruct->moveResultFlags[battler] |= MOVE_RESULT_MISSED; - effect = TRUE; - } - else if (B_MINIMIZE_DMG_ACC >= GEN_6 - && (gStatuses3[battler] & STATUS3_MINIMIZED) - && MoveIncreasesPowerToMinimizedTargets(move)) - { - effect = TRUE; - } - else if (GetMoveAccuracy(move) == 0) - { - effect = TRUE; - } - - if (!effect && HasWeatherEffect()) - { - if (MoveAlwaysHitsInRain(move) && IsBattlerWeatherAffected(battler, B_WEATHER_RAIN)) - effect = TRUE; - else if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) - effect = TRUE; - - if (effect) - return effect; - } - - if (ability != ABILITY_NONE) - RecordAbilityBattle(gBattlerAttacker, ABILITY_NO_GUARD); - - return effect; -} - -u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) -{ - u32 calc, moveAcc; - s8 buff, accStage, evasionStage; - u32 atkParam = GetBattlerHoldEffectParam(battlerAtk); - u32 defParam = GetBattlerHoldEffectParam(battlerDef); - u32 atkAlly = BATTLE_PARTNER(battlerAtk); - u32 atkAllyAbility = GetBattlerAbility(atkAlly); - - gPotentialItemEffectBattler = battlerDef; - accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; - evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; - if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE - || (B_ILLUMINATE_EFFECT >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) - evasionStage = DEFAULT_STAT_STAGE; - if (MoveIgnoresDefenseEvasionStages(move)) - evasionStage = DEFAULT_STAT_STAGE; - if (defAbility == ABILITY_UNAWARE) - accStage = DEFAULT_STAT_STAGE; - - if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) - buff = accStage; - else - buff = accStage + DEFAULT_STAT_STAGE - evasionStage; - - if (buff < MIN_STAT_STAGE) - buff = MIN_STAT_STAGE; - if (buff > MAX_STAT_STAGE) - buff = MAX_STAT_STAGE; - - moveAcc = GetMoveAccuracy(move); - // Check Thunder and Hurricane on sunny weather. - if (IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) - moveAcc = 50; - // Check Wonder Skin. - if (defAbility == ABILITY_WONDER_SKIN && IsBattleMoveStatus(move) && moveAcc > 50) - moveAcc = 50; - - calc = gAccuracyStageRatios[buff].dividend * moveAcc; - calc /= gAccuracyStageRatios[buff].divisor; - - // Attacker's ability - switch (atkAbility) - { - case ABILITY_COMPOUND_EYES: - calc = (calc * 130) / 100; // 1.3 compound eyes boost - break; - case ABILITY_VICTORY_STAR: - calc = (calc * 110) / 100; // 1.1 victory star boost - break; - case ABILITY_HUSTLE: - if (IsBattleMovePhysical(move)) - calc = (calc * 80) / 100; // 1.2 hustle loss - break; - } - - // Target's ability - switch (defAbility) - { - case ABILITY_SAND_VEIL: - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) - calc = (calc * 80) / 100; // 1.2 sand veil loss - break; - case ABILITY_SNOW_CLOAK: - if (HasWeatherEffect() && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) - calc = (calc * 80) / 100; // 1.2 snow cloak loss - break; - case ABILITY_TANGLED_FEET: - if (gBattleMons[battlerDef].volatiles.confusionTurns) - calc = (calc * 50) / 100; // 1.5 tangled feet loss - break; - } - - // Attacker's ally's ability - switch (atkAllyAbility) - { - case ABILITY_VICTORY_STAR: - if (IsBattlerAlive(atkAlly)) - calc = (calc * 110) / 100; // 1.1 ally's victory star boost - break; - } - - // Attacker's hold effect - switch (atkHoldEffect) - { - case HOLD_EFFECT_WIDE_LENS: - calc = (calc * (100 + atkParam)) / 100; - break; - case HOLD_EFFECT_ZOOM_LENS: - if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)) - calc = (calc * (100 + atkParam)) / 100; - break; - } - - // Target's hold effect - switch (defHoldEffect) - { - case HOLD_EFFECT_EVASION_UP: - calc = (calc * (100 - defParam)) / 100; - break; - } - - if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) - { - if (atkAbility == ABILITY_RIPEN) - calc = (calc * 140) / 100; // ripen gives 40% acc boost - else - calc = (calc * 120) / 100; // 20% acc boost - } - - if (gFieldStatuses & STATUS_FIELD_GRAVITY) - calc = (calc * 5) / 3; // 1.66 Gravity acc boost - - if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerDef) == AFFECTION_FIVE_HEARTS) - calc = (calc * 90) / 100; - - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_FOG) - calc = (calc * 60) / 100; // modified by 3/5 - - return calc; -} - static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u8 *failInstr, u16 move) { if (move == ACC_CURR_MOVE) @@ -1696,7 +1491,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u GetBattlerAbility(gBattlerTarget), gCurrentMove, GetBattleMoveType(gCurrentMove), - ABILITY_RUN_SCRIPT); + RUN_SCRIPT); } } else if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT @@ -1726,10 +1521,11 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u continue; numTargets++; - if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE, failInstr) || AccuracyCalcHelper(move, battlerDef)) + u32 abilityDef = GetBattlerAbility(battlerDef); + if (JumpIfMoveAffectedByProtect(move, battlerDef, FALSE, failInstr) + || CanMoveSkipAccuracyCalc(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, move, RUN_SCRIPT)) continue; - u32 abilityDef = GetBattlerAbility(battlerDef); u32 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); u32 accuracy = GetTotalAccuracy(gBattlerAttacker, battlerDef, @@ -3337,7 +3133,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai GetBattlerAbility(gBattlerAttacker), battlerAbility, gBattleScripting.moveEffect, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); break; case MOVE_EFFECT_CONFUSION: @@ -12548,7 +12344,7 @@ static void Cmd_trynonvolatilestatus(void) GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget), GetMoveNonVolatileStatus(gCurrentMove), - STATUS_RUN_SCRIPT)) + RUN_SCRIPT)) canInflictStatus = FALSE; if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) @@ -13008,7 +12804,7 @@ static void Cmd_checknonvolatiletrigger(void) GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget), cmd->nonVolatile, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) gBattlescriptCurrInstr = cmd->failInstr; else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) gBattlescriptCurrInstr = cmd->failInstr; diff --git a/src/battle_util.c b/src/battle_util.c index 8664fb417d..d882f28fa4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -65,8 +65,8 @@ static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); static bool32 CanBeInfinitelyConfused(u32 battler); static bool32 IsAnyTargetAffected(u32 battlerAtk); -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum NonVolatileStatus option); -static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonVolatileStatus option); +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option); +static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent); ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent); @@ -2520,13 +2520,13 @@ static enum MoveCanceller CancellerMultiTargetMoves(void) gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; gBattleStruct->noResultString[battlerDef] = TRUE; } - else if (CanAbilityBlockMove(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER) + else if (CanAbilityBlockMove(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, CHECK_TRIGGER) || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetBattleMovePriority(gBattlerAttacker, abilityAtk, gCurrentMove) > 0)) { gBattleStruct->moveResultFlags[battlerDef] = 0; gBattleStruct->noResultString[battlerDef] = TRUE; } - else if (CanAbilityAbsorbMove(gBattlerAttacker, battlerDef, abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), ABILITY_CHECK_TRIGGER)) + else if (CanAbilityAbsorbMove(gBattlerAttacker, battlerDef, abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; gBattleStruct->noResultString[battlerDef] = DO_ACCURACY_CHECK; @@ -2962,13 +2962,13 @@ static void ChooseStatBoostAnimation(u32 battler) #undef ANIM_STAT_ACC #undef ANIM_STAT_EVASION -bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum AbilityEffectOptions option) +bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option) { const u8 *battleScriptBlocksMove = NULL; u32 battlerAbility = battlerDef; s32 atkPriority = 0; - if (option == ABILITY_CHECK_TRIGGER_AI) + if (option == AI_CHECK) atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); else atkPriority = GetChosenMovePriority(battlerAtk, abilityAtk); @@ -3018,7 +3018,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a && BlocksPrankster(move, battlerAtk, battlerDef, TRUE) && !(IsBattleMoveStatus(move) && (abilityDef == ABILITY_MAGIC_BOUNCE || gProtectStructs[battlerDef].bounceMove))) { - if (option == ABILITY_RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) + if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; @@ -3031,7 +3031,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a && IsBattlerAlive(partnerDef) && !IsBattlerAlly(battlerAtk, partnerDef)) { - if (option == ABILITY_CHECK_TRIGGER_AI) + if (option == AI_CHECK) abilityDef = gAiLogicData->abilities[partnerDef]; else abilityDef = GetBattlerAbility(partnerDef); @@ -3053,7 +3053,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a if (battleScriptBlocksMove == NULL) return FALSE; - if (option == ABILITY_RUN_SCRIPT) + if (option == RUN_SCRIPT) { gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed. gLastUsedAbility = abilityDef; @@ -3065,7 +3065,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a return TRUE; } -bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option) +bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum FunctionCallOption option) { enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY; const u8 *battleScript = NULL; @@ -3139,7 +3139,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 break; } - if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option != ABILITY_RUN_SCRIPT) + if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option != RUN_SCRIPT) return effect; switch (effect) @@ -5122,7 +5122,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gLastUsedAbility, GetBattlerAbility(gBattlerAttacker), gBattleStruct->synchronizeMoveEffect, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) { if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; @@ -5152,7 +5152,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gLastUsedAbility, GetBattlerAbility(gBattlerAttacker), gBattleStruct->synchronizeMoveEffect, - STATUS_CHECK_TRIGGER)) + CHECK_TRIGGER)) { if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; @@ -5499,24 +5499,26 @@ bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClau if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause) return FALSE; - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_SLEEP, // also covers yawn - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_SLEEP, // also covers yawn + CHECK_TRIGGER)) return TRUE; return FALSE; } bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - abilityAtk, - abilityDef, - MOVE_EFFECT_TOXIC, // also covers poison - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + abilityAtk, + abilityDef, + MOVE_EFFECT_TOXIC, // also covers poison + CHECK_TRIGGER)) return TRUE; return FALSE; } @@ -5524,36 +5526,39 @@ bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 ability // TODO: check order of battlerAtk and battlerDef bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_BURN, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_BURN, + CHECK_TRIGGER)) return TRUE; return FALSE; } bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_PARALYSIS, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_PARALYSIS, + CHECK_TRIGGER)) return TRUE; return FALSE; } bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_FREEZE, - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_FREEZE, + CHECK_TRIGGER)) return TRUE; return FALSE; } @@ -5561,17 +5566,18 @@ bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef) // Unused, technically also redundant bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) { - if (CanSetNonVolatileStatus(battlerAtk, - battlerDef, - ABILITY_NONE, // attacker ability does not matter - abilityDef, - MOVE_EFFECT_FREEZE_OR_FROSTBITE, // also covers frostbite - STATUS_CHECK_TRIGGER)) + if (CanSetNonVolatileStatus( + battlerAtk, + battlerDef, + ABILITY_NONE, // attacker ability does not matter + abilityDef, + MOVE_EFFECT_FREEZE_OR_FROSTBITE, // also covers frostbite + CHECK_TRIGGER)) return TRUE; return FALSE; } -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects effect, enum NonVolatileStatus option) +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects effect, enum FunctionCallOption option) { const u8 *battleScript = NULL; u32 sideBattler = ABILITY_NONE; @@ -5614,7 +5620,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_NotAffected; } - else if (option == STATUS_RUN_SCRIPT // Check only important during battle execution for moves + else if (option == RUN_SCRIPT // Check only important during battle execution for moves && CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), battlerAtk, battlerDef, abilityDef, TRUE) && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) { @@ -5741,11 +5747,11 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u return TRUE; } -static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum NonVolatileStatus option) +static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option) { if (battleScript != NULL) { - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) { if (battleScript != BattleScript_NotAffected) gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FAILED; @@ -5766,17 +5772,17 @@ static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abi return FALSE; } -static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonVolatileStatus option) +static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option) { // Can freely sleep own partner if (IsDoubleBattle() && IsSleepClauseEnabled() && IsBattlerAlly(battlerAtk, battlerDef)) { - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) gBattleStruct->battlerState[battlerDef].sleepClauseEffectExempt = TRUE; return FALSE; } - if (option == STATUS_RUN_SCRIPT) + if (option == RUN_SCRIPT) gBattleStruct->battlerState[battlerDef].sleepClauseEffectExempt = FALSE; // Can't sleep if clause is active otherwise if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef))) @@ -9767,7 +9773,7 @@ uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) MulByTypeEffectiveness(&ctx, &modifier, type2); if ((modifier <= UQ_4_12(1.0) && abilityDef == ABILITY_WONDER_GUARD) - || CanAbilityAbsorbMove(0, 0, abilityDef, MOVE_NONE, moveType, ABILITY_CHECK_TRIGGER)) + || CanAbilityAbsorbMove(0, 0, abilityDef, MOVE_NONE, moveType, CHECK_TRIGGER)) modifier = UQ_4_12(0.0); return modifier; @@ -11158,8 +11164,8 @@ static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerD { u32 abilityDef = GetBattlerAbility(battlerDef); - return CanAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER) - || CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, gCurrentMove, moveType, ABILITY_CHECK_TRIGGER); + return CanAbilityBlockMove(battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), abilityDef, gCurrentMove, CHECK_TRIGGER) + || CanAbilityAbsorbMove(battlerAtk, battlerDef, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER); } bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef) @@ -11329,11 +11335,11 @@ void UpdateStallMons(void) u32 moveType = GetBattleMoveType(gCurrentMove); // Probably doesn't handle dynamic move types right now u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 abilityDef = GetBattlerAbility(gBattlerTarget); - if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, abilityDef, gCurrentMove, moveType, ABILITY_CHECK_TRIGGER)) + if (CanAbilityAbsorbMove(gBattlerAttacker, gBattlerTarget, abilityDef, gCurrentMove, moveType, CHECK_TRIGGER)) { gAiBattleData->playerStallMons[gBattlerPartyIndexes[gBattlerTarget]]++; } - else if (CanAbilityBlockMove(gBattlerAttacker, gBattlerTarget, abilityAtk, abilityDef, gCurrentMove, ABILITY_CHECK_TRIGGER)) + else if (CanAbilityBlockMove(gBattlerAttacker, gBattlerTarget, abilityAtk, abilityDef, gCurrentMove, CHECK_TRIGGER)) { gAiBattleData->playerStallMons[gBattlerPartyIndexes[gBattlerTarget]]++; } @@ -11521,3 +11527,212 @@ void RemoveHazardFromField(u32 side, enum Hazards hazardType) i++; } } + +bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option) +{ + bool32 effect = FALSE; + u32 ability = ABILITY_NONE; + enum BattleMoveEffects moveEffect = GetMoveEffect(move); + u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); + + if ((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) + || (B_TOXIC_NEVER_MISS >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + || gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH) + { + effect = TRUE; + } + // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. + else if (abilityAtk == ABILITY_NO_GUARD + && !(gStatuses3[battlerDef] & STATUS3_COMMANDER) + && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET)) + { + effect = TRUE; + ability = ABILITY_NO_GUARD; + } + // If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits. + else if (abilityDef == ABILITY_NO_GUARD + && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET)) + { + effect = TRUE; + ability = ABILITY_NO_GUARD; + } + // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. + else if (gStatuses3[battlerDef] & STATUS3_TELEKINESIS + && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE) + && moveEffect != EFFECT_OHKO + && moveEffect != EFFECT_SHEER_COLD) + { + effect = TRUE; + } + else if (gBattleStruct->battlerState[battlerDef].pursuitTarget) + { + effect = TRUE; + } + else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + { + effect = TRUE; + } + else if ((gStatuses3[battlerDef] & STATUS3_COMMANDER) + || (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) + || ((gStatuses3[battlerDef] & STATUS3_ON_AIR) && !(MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move))) + || ((gStatuses3[battlerDef] & STATUS3_UNDERGROUND) && !MoveDamagesUnderground(move)) + || ((gStatuses3[battlerDef] & STATUS3_UNDERWATER) && !MoveDamagesUnderWater(move))) + { + if (option == RUN_SCRIPT) + { + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_MISSED; + effect = TRUE; + } + else + { + effect = FALSE; + } + } + else if (B_MINIMIZE_DMG_ACC >= GEN_6 + && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) + && MoveIncreasesPowerToMinimizedTargets(move)) + { + effect = TRUE; + } + else if (GetMoveAccuracy(move) == 0) + { + effect = TRUE; + } + + if (!effect && HasWeatherEffect()) + { + if (MoveAlwaysHitsInRain(move) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_RAIN)) + effect = TRUE; + else if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) + effect = TRUE; + + if (effect) + return effect; + } + + if (ability != ABILITY_NONE && option == RUN_SCRIPT) + RecordAbilityBattle(battlerAtk, ABILITY_NO_GUARD); + + return effect; +} + +u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect) +{ + u32 calc, moveAcc; + s8 buff, accStage, evasionStage; + u32 atkParam = GetBattlerHoldEffectParam(battlerAtk); + u32 defParam = GetBattlerHoldEffectParam(battlerDef); + + gPotentialItemEffectBattler = battlerDef; + accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; + evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; + if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE + || (B_ILLUMINATE_EFFECT >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) + evasionStage = DEFAULT_STAT_STAGE; + if (MoveIgnoresDefenseEvasionStages(move)) + evasionStage = DEFAULT_STAT_STAGE; + if (defAbility == ABILITY_UNAWARE) + accStage = DEFAULT_STAT_STAGE; + + if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) + buff = accStage; + else + buff = accStage + DEFAULT_STAT_STAGE - evasionStage; + + if (buff < MIN_STAT_STAGE) + buff = MIN_STAT_STAGE; + if (buff > MAX_STAT_STAGE) + buff = MAX_STAT_STAGE; + + moveAcc = GetMoveAccuracy(move); + // Check Thunder and Hurricane on sunny weather. + if (IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) + moveAcc = 50; + // Check Wonder Skin. + if (defAbility == ABILITY_WONDER_SKIN && IsBattleMoveStatus(move) && moveAcc > 50) + moveAcc = 50; + + calc = gAccuracyStageRatios[buff].dividend * moveAcc; + calc /= gAccuracyStageRatios[buff].divisor; + + // Attacker's ability + switch (atkAbility) + { + case ABILITY_COMPOUND_EYES: + calc = (calc * 130) / 100; // 1.3 compound eyes boost + break; + case ABILITY_VICTORY_STAR: + calc = (calc * 110) / 100; // 1.1 victory star boost + break; + case ABILITY_HUSTLE: + if (IsBattleMovePhysical(move)) + calc = (calc * 80) / 100; // 1.2 hustle loss + break; + } + + // Target's ability + switch (defAbility) + { + case ABILITY_SAND_VEIL: + if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) + calc = (calc * 80) / 100; // 1.2 sand veil loss + break; + case ABILITY_SNOW_CLOAK: + if (HasWeatherEffect() && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + calc = (calc * 80) / 100; // 1.2 snow cloak loss + break; + case ABILITY_TANGLED_FEET: + if (gBattleMons[battlerDef].volatiles.confusionTurns) + calc = (calc * 50) / 100; // 1.5 tangled feet loss + break; + } + + // Attacker's ally's ability + u32 atkAlly = BATTLE_PARTNER(battlerAtk); + switch (GetBattlerAbility(atkAlly)) + { + case ABILITY_VICTORY_STAR: + if (IsBattlerAlive(atkAlly)) + calc = (calc * 110) / 100; // 1.1 ally's victory star boost + break; + } + + // Attacker's hold effect + switch (atkHoldEffect) + { + case HOLD_EFFECT_WIDE_LENS: + calc = (calc * (100 + atkParam)) / 100; + break; + case HOLD_EFFECT_ZOOM_LENS: + if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)) + calc = (calc * (100 + atkParam)) / 100; + break; + } + + // Target's hold effect + switch (defHoldEffect) + { + case HOLD_EFFECT_EVASION_UP: + calc = (calc * (100 - defParam)) / 100; + break; + } + + if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) + { + if (atkAbility == ABILITY_RIPEN) + calc = (calc * 140) / 100; // ripen gives 40% acc boost + else + calc = (calc * 120) / 100; // 20% acc boost + } + + if (gFieldStatuses & STATUS_FIELD_GRAVITY) + calc = (calc * 5) / 3; // 1.66 Gravity acc boost + + if (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerDef) == AFFECTION_FIVE_HEARTS) + calc = (calc * 90) / 100; + + if (HasWeatherEffect() && gBattleWeather & B_WEATHER_FOG) + calc = (calc * 60) / 100; // modified by 3/5 + + return calc; +} From 95a02dddb9887906ce973320ed7a0cd2757b4c2d Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 9 Jul 2025 18:11:39 -0400 Subject: [PATCH 066/283] Improved logic for Guard Split and Power Split. (#7298) --- include/config/ai.h | 6 ++ src/battle_ai_main.c | 121 ++++++++++++++++++++++++++++-------- test/battle/ai/ai_doubles.c | 54 ++++++++++++++++ 3 files changed, 155 insertions(+), 26 deletions(-) diff --git a/include/config/ai.h b/include/config/ai.h index 91ee3525ae..c51ff6d790 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -79,4 +79,10 @@ #define FRIENDLY_FIRE_NORMAL_THRESHOLD 3 #define FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD 4 +// AI's desired stat changes for Guard Split and Power Split, treated as % +#define GUARD_SPLIT_ALLY_PERCENTAGE 200 +#define GUARD_SPLIT_ENEMY_PERCENTAGE 50 +#define POWER_SPLIT_ALLY_PERCENTAGE 150 +#define POWER_SPLIT_ENEMY_PERCENTAGE 50 + #endif // GUARD_CONFIG_AI_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index f3976fae4a..dae2895d96 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2455,11 +2455,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_POWER_SPLIT: - if (IsTargetingPartner(battlerAtk, battlerDef)) - { - ADJUST_SCORE(-10); - } - else + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 atkAttack = gBattleMons[battlerAtk].attack; u32 defAttack = gBattleMons[battlerDef].attack; @@ -2472,11 +2468,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_GUARD_SPLIT: - if (IsTargetingPartner(battlerAtk, battlerDef)) - { - ADJUST_SCORE(-10); - } - else + if (!IsTargetingPartner(battlerAtk, battlerDef)) { u32 atkDefense = gBattleMons[battlerAtk].defense; u32 defDefense = gBattleMons[battlerDef].defense; @@ -3530,6 +3522,55 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2) RETURN_SCORE_PLUS(WEAK_EFFECT); break; + case EFFECT_SPEED_SWAP: + break; + case EFFECT_GUARD_SPLIT: + { + u32 atkDefense = gBattleMons[battlerAtk].defense; + u32 defDefense = gBattleMons[battlerDef].defense; + u32 atkSpDefense = gBattleMons[battlerAtk].spDefense; + u32 defSpDefense = gBattleMons[battlerDef].spDefense; + + // It's actually * 100 and / 2 + u32 newDefense = (atkDefense + defDefense) * 50; + u32 newSpDefense = (atkSpDefense + defSpDefense) * 50; + + // We want to massively raise our defense. + if (newDefense > atkDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > atkSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newDefense > defDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > defSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); + break; + } + case EFFECT_POWER_SPLIT: + { + u32 atkAttack = gBattleMons[battlerAtk].attack; + u32 defAttack = gBattleMons[battlerDef].attack; + u32 atkSpAttack = gBattleMons[battlerAtk].spAttack; + u32 defSpAttack = gBattleMons[battlerDef].spAttack; + + // * 100 and / 2 + u32 newAttack = (atkAttack + defAttack) * 50; + u32 newSpAtk = (atkSpAttack + defSpAttack) * 50; + + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && newAttack > atkAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) && newAttack > defAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > atkSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > defSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + ADJUST_SCORE(WORST_EFFECT); + break; + } default: break; } // attacker move effects @@ -4721,26 +4762,54 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (gBattleMons[battlerDef].speed > gBattleMons[battlerAtk].speed) ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_GUARD_SPLIT: - { - u32 newDefense = (gBattleMons[battlerAtk].defense + gBattleMons[battlerDef].defense) / 2; - u32 newSpDef = (gBattleMons[battlerAtk].spDefense + gBattleMons[battlerDef].spDefense) / 2; +case EFFECT_GUARD_SPLIT: + { + u32 atkDefense = gBattleMons[battlerAtk].defense; + u32 defDefense = gBattleMons[battlerDef].defense; + u32 atkSpDefense = gBattleMons[battlerAtk].spDefense; + u32 defSpDefense = gBattleMons[battlerDef].spDefense; + + // It's actually * 100 and / 2; + u32 newDefense = (atkDefense + defDefense) * 50; + u32 newSpDefense = (atkSpDefense + defSpDefense) * 50; + + // We want to massively raise our defense. + if (newDefense > atkDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense > atkSpDefense * GUARD_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + + // We also want to massively lower theirs. + if (newDefense < defDefense * GUARD_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpDefense < defSpDefense * GUARD_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); - if ((newDefense > gBattleMons[battlerAtk].defense && newSpDef >= gBattleMons[battlerAtk].spDefense) - || (newSpDef > gBattleMons[battlerAtk].spDefense && newDefense >= gBattleMons[battlerAtk].defense)) - ADJUST_SCORE(DECENT_EFFECT); - } + ADJUST_SCORE(WORST_EFFECT); break; + } case EFFECT_POWER_SPLIT: - { - u32 newAttack = (gBattleMons[battlerAtk].attack + gBattleMons[battlerDef].attack) / 2; - u32 newSpAtk = (gBattleMons[battlerAtk].spAttack + gBattleMons[battlerDef].spAttack) / 2; + { + u32 atkAttack = gBattleMons[battlerAtk].attack; + u32 defAttack = gBattleMons[battlerDef].attack; + u32 atkSpAttack = gBattleMons[battlerAtk].spAttack; + u32 defSpAttack = gBattleMons[battlerDef].spAttack; + + // It's actually * 100 and / 2 + u32 newAttack = (atkAttack + defAttack) * 50; + u32 newSpAtk = (atkSpAttack + defSpAttack) * 50; + + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && newAttack > atkAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL) && newSpAtk > atkSpAttack * POWER_SPLIT_ALLY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newAttack < defAttack * POWER_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); + if (newSpAtk < defSpAttack * POWER_SPLIT_ENEMY_PERCENTAGE) + ADJUST_AND_RETURN_SCORE(GOOD_EFFECT); - if ((newAttack > gBattleMons[battlerAtk].attack && newSpAtk >= gBattleMons[battlerAtk].spAttack) - || (newSpAtk > gBattleMons[battlerAtk].spAttack && newAttack >= gBattleMons[battlerAtk].attack)) - ADJUST_SCORE(DECENT_EFFECT); - } - break; + ADJUST_SCORE(WORST_EFFECT); + } case EFFECT_ELECTRIC_TERRAIN: case EFFECT_MISTY_TERRAIN: if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 5edc271fff..243c6611e9 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -410,3 +410,57 @@ AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons tha } } +AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats") +{ + + u32 player, opponent; + + PARAMETRIZE { player = SPECIES_SHUCKLE; opponent = SPECIES_PHEROMOSA; } + PARAMETRIZE { player = SPECIES_PHEROMOSA; opponent = SPECIES_SHUCKLE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_GUARD_SPLIT) == EFFECT_GUARD_SPLIT); + ASSUME(gSpeciesInfo[SPECIES_PHEROMOSA].baseDefense < gSpeciesInfo[SPECIES_WOBBUFFET].baseDefense); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseDefense < gSpeciesInfo[SPECIES_SHUCKLE].baseDefense); + ASSUME(gSpeciesInfo[SPECIES_PHEROMOSA].baseSpDefense < gSpeciesInfo[SPECIES_WOBBUFFET].baseSpDefense); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseSpDefense < gSpeciesInfo[SPECIES_SHUCKLE].baseSpDefense); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(player); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_GUARD_SPLIT, MOVE_NIGHT_SHADE); } + OPPONENT(opponent); + } WHEN { + if (player == SPECIES_SHUCKLE) + TURN { EXPECT_MOVE(opponentLeft, MOVE_GUARD_SPLIT, target:playerLeft); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_GUARD_SPLIT, target:opponentRight); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Power Split to improve its stats") +{ + + u32 player, opponent; + + PARAMETRIZE { player = SPECIES_SHUCKLE; opponent = SPECIES_PHEROMOSA; } + PARAMETRIZE { player = SPECIES_PHEROMOSA; opponent = SPECIES_SHUCKLE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_POWER_SPLIT) == EFFECT_POWER_SPLIT); + ASSUME(gSpeciesInfo[SPECIES_PHEROMOSA].baseAttack > gSpeciesInfo[SPECIES_WOBBUFFET].baseAttack); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseAttack > gSpeciesInfo[SPECIES_SHUCKLE].baseAttack); + ASSUME(gSpeciesInfo[SPECIES_PHEROMOSA].baseSpAttack > gSpeciesInfo[SPECIES_WOBBUFFET].baseSpAttack); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseSpAttack > gSpeciesInfo[SPECIES_SHUCKLE].baseSpAttack); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(player); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POWER_SPLIT, MOVE_TACKLE, MOVE_ROUND); } + OPPONENT(opponent) { Moves(MOVE_TACKLE, MOVE_ROUND); } + } WHEN { + if (player == SPECIES_PHEROMOSA) + TURN { EXPECT_MOVE(opponentLeft, MOVE_POWER_SPLIT, target:playerLeft); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_POWER_SPLIT, target:opponentRight); } + } +} + From e4d92982001d08342548e881bd08199dceac44cd Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 10 Jul 2025 03:51:46 -0400 Subject: [PATCH 067/283] Fix move comparison scoring (#7301) --- include/battle_ai_util.h | 9 ++ include/math_util.h | 1 + src/battle_ai_main.c | 179 ++++++++++++++++++++++----------------- src/math_util.c | 9 ++ test/battle/ai/ai.c | 16 ++++ 5 files changed, 137 insertions(+), 77 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 66fe8d550d..6890096a79 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -23,6 +23,15 @@ enum DamageCalcContext AI_ATTACKING, }; +// Higher priority at the bottom; note that these are used in the formula MAX_MON_MOVES ^ AiCompareMovesPriority, which must fit within a u32. +// In expansion where MAX_MON_MOVES is 4, this means that AiCompareMovesPriority can range from 0 - 15 inclusive. +enum AiCompareMovesPriority +{ + PRIORITY_EFFECT, + PRIORITY_ACCURACY, + PRIORITY_NOT_CHARGING +}; + enum AIPivot { DONT_PIVOT, diff --git a/include/math_util.h b/include/math_util.h index 04013fc03f..71d79d9ba8 100755 --- a/include/math_util.h +++ b/include/math_util.h @@ -10,5 +10,6 @@ s32 MathUtil_Div32(s32 x, s32 y); s16 MathUtil_Inv16(s16 y); s16 MathUtil_Inv16Shift(u8 s, s16 y); s32 MathUtil_Inv32(s32 y); +u32 MathUtil_Exponent(u32 x, u32 y); #endif // GUARD_MATH_UTIL_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 1b8520fa5d..acf0bdb722 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -14,6 +14,7 @@ #include "debug.h" #include "event_data.h" #include "item.h" +#include "math_util.h" #include "pokemon.h" #include "random.h" #include "recorded_battle.h" @@ -37,6 +38,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battler); static inline void BattleAI_DoAIProcessing(struct AiThinkingStruct *aiThink, u32 battlerAtk, u32 battlerDef); static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AiThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef); static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect); +static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef); // ewram EWRAM_DATA const u8 *gAIScriptPtr = NULL; // Still used in contests @@ -693,6 +695,9 @@ static u32 ChooseMoveOrAction_Singles(u32 battler) gAiThinkingStruct->aiLogicId++; } + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CHECK_VIABILITY) + AI_CompareDamagingMoves(battler, opposingBattler); + for (i = 0; i < MAX_MON_MOVES; i++) { gAiBattleData->finalScore[battler][opposingBattler][i] = gAiThinkingStruct->score[i]; @@ -769,6 +774,8 @@ static u32 ChooseMoveOrAction_Doubles(u32 battler) flags >>= (u64)1; gAiThinkingStruct->aiLogicId++; } + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CHECK_VIABILITY) + AI_CompareDamagingMoves(battler, gBattlerTarget); mostViableMovesScores[0] = gAiThinkingStruct->score[0]; mostViableMovesIndices[0] = 0; @@ -3648,104 +3655,124 @@ static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 mov && noOfHitsToFaintPartner < (friendlyFireThreshold * 2)); } -static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) +static bool32 ShouldCompareMove(u32 battlerAtk, u32 battlerDef, u32 moveIndex, u16 move) { - u32 i; + if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) + return FALSE; + if (GetMovePower(move) == 0) + return FALSE; + if (GetNoOfHitsToKOBattler(battlerAtk, battlerDef, moveIndex, AI_ATTACKING) == 0) + return FALSE; + if (gAiThinkingStruct->aiFlags[battlerAtk] & (AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE) && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + return FALSE; + return TRUE; +} + +static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef) +{ + u32 i, currId; + u32 tempMoveScores[MAX_MON_MOVES]; + u32 moveComparisonScores[MAX_MON_MOVES]; + u32 bestScore = AI_SCORE_DEFAULT; bool32 multipleBestMoves = FALSE; - s32 viableMoveScores[MAX_MON_MOVES]; - s32 bestViableMoveScore; s32 noOfHits[MAX_MON_MOVES]; - s32 score = 0; s32 leastHits = 1000; u16 *moves = GetMovesArray(battlerAtk); bool8 isTwoTurnNotSemiInvulnerableMove[MAX_MON_MOVES]; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (moves[i] != MOVE_NONE && GetMovePower(moves[i]) != 0) - { - noOfHits[i] = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, i, AI_ATTACKING); - if (ShouldUseSpreadDamageMove(battlerAtk,moves[i], i, noOfHits[i])) - { - noOfHits[i] = -1; - viableMoveScores[i] = 0; - isTwoTurnNotSemiInvulnerableMove[i] = FALSE; - } - else if (noOfHits[i] < leastHits && noOfHits[i] != 0) - { - leastHits = noOfHits[i]; - } - viableMoveScores[i] = AI_SCORE_DEFAULT; - isTwoTurnNotSemiInvulnerableMove[i] = IsTwoTurnNotSemiInvulnerableMove(battlerAtk, moves[i]); - } - else - { - noOfHits[i] = -1; - viableMoveScores[i] = 0; - isTwoTurnNotSemiInvulnerableMove[i] = FALSE; - } - } - - // Priority list: - // 1. Less no of hits to ko - // 2. Not charging - // 3. More accuracy - // 4. Better effect - - // Current move requires the least hits to KO. Compare with other moves. - if (leastHits == noOfHits[currId]) + for (currId = 0; currId < MAX_MON_MOVES; currId++) { + moveComparisonScores[currId] = 0; + if (!ShouldCompareMove(battlerAtk, battlerDef, currId, moves[currId])) + continue; for (i = 0; i < MAX_MON_MOVES; i++) { - if (i == currId) - continue; - if (noOfHits[currId] == noOfHits[i]) + if (moves[i] != MOVE_NONE && GetMovePower(moves[i]) != 0) { - multipleBestMoves = TRUE; - // We need to make sure it's the current move which is objectively better. - if (isTwoTurnNotSemiInvulnerableMove[i] && !isTwoTurnNotSemiInvulnerableMove[currId]) - viableMoveScores[i] -= 3; - else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId]) - viableMoveScores[currId] -= 3; - - switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) + noOfHits[i] = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, i, AI_ATTACKING); + if (ShouldUseSpreadDamageMove(battlerAtk,moves[i], i, noOfHits[i])) { - case 1: - viableMoveScores[i] -= 2; - break; - case -1: - viableMoveScores[currId] -= 2; - break; + noOfHits[i] = -1; + tempMoveScores[i] = 0; + isTwoTurnNotSemiInvulnerableMove[i] = FALSE; } - switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) + else if (noOfHits[i] < leastHits && noOfHits[i] != 0) { - case 1: - viableMoveScores[i] -= 1; - break; - case -1: - viableMoveScores[currId] -= 1; - break; + leastHits = noOfHits[i]; } + tempMoveScores[i] = AI_SCORE_DEFAULT; + isTwoTurnNotSemiInvulnerableMove[i] = IsTwoTurnNotSemiInvulnerableMove(battlerAtk, moves[i]); + } + else + { + noOfHits[i] = -1; + tempMoveScores[i] = 0; + isTwoTurnNotSemiInvulnerableMove[i] = FALSE; } } - // Turns out the current move deals the most dmg compared to the other 3. - if (!multipleBestMoves) - ADJUST_SCORE(BEST_DAMAGE_MOVE); - else + + // Priority list: + // 1. Less no of hits to ko + // 2. Not charging + // 3. More accuracy + // 4. Better effect + + // Current move requires the least hits to KO. Compare with other moves. + if (leastHits == noOfHits[currId]) { - bestViableMoveScore = 0; for (i = 0; i < MAX_MON_MOVES; i++) { - if (viableMoveScores[i] > bestViableMoveScore) - bestViableMoveScore = viableMoveScores[i]; + if (i == currId) + continue; + if (noOfHits[currId] == noOfHits[i]) + { + multipleBestMoves = TRUE; + // We need to make sure it's the current move which is objectively better. + if (isTwoTurnNotSemiInvulnerableMove[i] && !isTwoTurnNotSemiInvulnerableMove[currId]) + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_NOT_CHARGING); + else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId]) + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_NOT_CHARGING); + + switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) + { + case 1: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); + break; + case -1: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); + break; + } + switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) + { + case 1: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); + break; + case -1: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); + break; + } + } } - // Unless a better move was found increase score of current move - if (viableMoveScores[currId] == bestViableMoveScore) - ADJUST_SCORE(BEST_DAMAGE_MOVE); + // Turns out the current move deals the most dmg compared to the other 3. + if (!multipleBestMoves) + moveComparisonScores[currId] = UINT32_MAX; + else + moveComparisonScores[currId] = tempMoveScores[currId]; } } - - return score; + + // Find highest comparison score + for (int i = 0; i < MAX_MON_MOVES; i++) + { + if (moveComparisonScores[i] > bestScore) + bestScore = moveComparisonScores[i]; + } + // Increase score for corresponding move(s), accomodating ties + for (int i = 0; i < MAX_MON_MOVES; i++) + { + if (moveComparisonScores[i] == bestScore) + gAiThinkingStruct->score[i] += BEST_DAMAGE_MOVE; + } } static u32 AI_CalcHoldEffectMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) @@ -5336,8 +5363,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score if (gAiThinkingStruct->aiFlags[battlerAtk] & (AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE) && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) ADJUST_SCORE(BEST_DAMAGE_MOVE); - else - ADJUST_SCORE(AI_CompareDamagingMoves(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex)); } } diff --git a/src/math_util.c b/src/math_util.c index f77c82608a..a29b03a15b 100644 --- a/src/math_util.c +++ b/src/math_util.c @@ -84,3 +84,12 @@ s32 MathUtil_Inv32(s32 y) x = 0x10000; return x / y; } + +u32 MathUtil_Exponent(u32 x, u32 y) +{ + u32 result = 1; + for (u32 index = 0; index < y; index++) + result *= x; + + return result; +} diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 249e686c16..3fe975fc66 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -865,3 +865,19 @@ AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect") TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_RAIN_DANCE); } } } + +AI_SINGLE_BATTLE_TEST("Move scoring comparison properly awards bonus point to best OHKO move") +{ + GIVEN { + ASSUME(MoveHasAdditionalEffect(MOVE_THUNDER, MOVE_EFFECT_PARALYSIS)); + ASSUME(GetMoveAdditionalEffectCount(MOVE_WATER_SPOUT) == 0); + ASSUME(GetMoveAdditionalEffectCount(MOVE_WATER_GUN) == 0); + ASSUME(GetMoveAdditionalEffectCount(MOVE_ORIGIN_PULSE) == 0); + ASSUME(GetMoveAccuracy(MOVE_WATER_SPOUT) > GetMoveAccuracy(MOVE_THUNDER)); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_WAILORD) { Level(50); } + OPPONENT(SPECIES_WAILORD) { Moves(MOVE_THUNDER, MOVE_WATER_SPOUT, MOVE_WATER_GUN, MOVE_SURF); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_WATER_SPOUT); } + } +} From 0f22cd26c863a3df13c2f8b2b2514f690fced80c Mon Sep 17 00:00:00 2001 From: bassforte123 <130828119+bassforte123@users.noreply.github.com> Date: Thu, 10 Jul 2025 05:06:40 -0400 Subject: [PATCH 068/283] Typo fixes in tests (#7312) --- test/battle/spread_moves.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/spread_moves.c b/test/battle/spread_moves.c index 869d5bbebb..a37fb847db 100644 --- a/test/battle/spread_moves.c +++ b/test/battle/spread_moves.c @@ -188,7 +188,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (right) and } } -DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (left) and Lightning Rod (reft)") +DOUBLE_BATTLE_TEST("Spread Moves: AOE move vs Disguise, Volt Absorb (left) and Lightning Rod (right)") { GIVEN { ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); From 0d09e5cce81ed9dd51f3018a72f230685d83cd0d Mon Sep 17 00:00:00 2001 From: mudskipper13 <105766191+mudskipper13@users.noreply.github.com> Date: Fri, 11 Jul 2025 00:09:52 +0700 Subject: [PATCH 069/283] battle_interface: overhaul ability pop up (#7227) --- data/battle_scripts_1.s | 11 +- graphics/battle_interface/ability_pop_up.png | Bin 284 -> 234 bytes graphics_file_rules.mk | 3 + include/sprite.h | 1 + src/battle_interface.c | 567 ++++++++----------- src/battle_script_commands.c | 5 +- src/sprite.c | 1 - 7 files changed, 262 insertions(+), 326 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3bec1be182..f7d988026d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7153,7 +7153,7 @@ BattleScript_AbilityPopUp:: tryactivateabilityshield BS_ABILITY_BATTLER .if B_ABILITY_POP_UP == TRUE showabilitypopup BS_ABILITY_BATTLER - pause 40 + pause B_WAIT_TIME_SHORT .endif recordability BS_ABILITY_BATTLER sethword sABILITY_OVERWRITE, 0 @@ -7166,13 +7166,13 @@ BattleScript_AbilityPopUpScripting: BattleScript_AbilityPopUpOverwriteThenNormal: setbyte sFIXED_ABILITY_POPUP, TRUE showabilitypopup BS_ABILITY_BATTLER - pause 60 + pause B_WAIT_TIME_SHORT sethword sABILITY_OVERWRITE, 0 updateabilitypopup BS_ABILITY_BATTLER - pause 20 + pause B_WAIT_TIME_SHORT recordability BS_ABILITY_BATTLER destroyabilitypopup - pause 40 + setbyte sFIXED_ABILITY_POPUP, FALSE return BattleScript_SpeedBoostActivates:: @@ -7401,7 +7401,6 @@ BattleScript_TryIntimidateHoldEffectsRet: BattleScript_IntimidateActivates:: savetarget call BattleScript_AbilityPopUp - destroyabilitypopup setbyte gBattlerTarget, 0 BattleScript_IntimidateLoop: jumpiftargetally BattleScript_IntimidateLoopIncrement @@ -7964,8 +7963,8 @@ BattleScript_CursedBodyActivates:: BattleScript_MummyActivates:: .if B_ABILITY_POP_UP == TRUE - call BattleScript_AbilityPopUpTarget setbyte sFIXED_ABILITY_POPUP, TRUE + call BattleScript_AbilityPopUpTarget copybyte gBattlerAbility, gBattlerAttacker copyhword sABILITY_OVERWRITE, gLastUsedAbility call BattleScript_AbilityPopUpOverwriteThenNormal diff --git a/graphics/battle_interface/ability_pop_up.png b/graphics/battle_interface/ability_pop_up.png index ede0a7b5d7e3efd42ad54dff69f5b28e891b1d56..fa0f09dba38e527f29092bcc76e8b00f69b175b1 100644 GIT binary patch delta 206 zcmbQk^omijGr-TCmrII^fq{Y7)59eQNH+kn0tYjYeEX+Ce4?IOeRgrNmlH_p+O=~n zJv~51F!PezK&sT!#W5tJ_3d;+z6Jvx=Ghjl|NqbUz`)bJ`N3@MpRW`rUC&ZldgPJI zq9qO5Ebqjfe$^+iMeaOW!lKRa>d#(BEeVZ=@Cl+-jT;(Rbq=tyEnqs%5b{9g0FxL{ z;D_p!=a;=XUg#UDe9%#tue$!S%bwHw)*63K*E^JAx!)kiH5cdt22WQ%mvv4FO#oR^ BO#}b{ delta 256 zcmaFGIEP8EGr-TCmrII^fq{Y7)59eQNIQTq2Q!eIyS?!ZkYX$ja(7}_cTVQzL`AiF zpa2?ZoIm>tP-vE?i(^Pc>)Wdb`5F{>m@o7;{rfL(ebHF;O82gNm60WpXO-fvU7o*q zo%+4Si+&WH@zVA6;9+=L8_aIO=>I^tVG4tpCgYnRA&&=aW`Yb`La${l74N=~9lkZS zE&hah!$bQ+EQVGyJU1#WIP@dKy*%52S+y5 nRAc5*_(~E2yZ_pg`wW diff --git a/graphics_file_rules.mk b/graphics_file_rules.mk index 75460992f8..2b9cb9df8b 100644 --- a/graphics_file_rules.mk +++ b/graphics_file_rules.mk @@ -340,6 +340,9 @@ $(UNUSEDGFXDIR)/color_frames.4bpp: %.4bpp: %.png $(BATINTGFXDIR)/unused_window2bar.4bpp: %.4bpp: %.png $(GFX) $< $@ -num_tiles 5 -Wnum_tiles +$(BATINTGFXDIR)/ability_pop_up.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 8 -mheight 4 + $(JPCONTESTGFXDIR)/composite_1.4bpp: $(JPCONTESTGFXDIR)/frame_1.4bpp \ $(JPCONTESTGFXDIR)/floor.4bpp \ $(JPCONTESTGFXDIR)/frame_2.4bpp \ diff --git a/include/sprite.h b/include/sprite.h index 5b5fd5e62f..7919075053 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -324,5 +324,6 @@ void ResetAffineAnimData(void); u32 GetSpanPerImage(u32 shape, u32 size); void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images); void SetSpriteOamFlipBits(struct Sprite *sprite, u8 hFlip, u8 vFlip); +u8 IndexOfSpriteTileTag(u16 tag); #endif //GUARD_SPRITE_H diff --git a/src/battle_interface.c b/src/battle_interface.c index f26a7af98f..2aee6460cb 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -2410,30 +2410,69 @@ static void SafariTextIntoHealthboxObject(void *dest, u8 *windowTileData, u32 wi CpuCopy32(windowTileData + 256, dest + 256, windowWidth * TILE_SIZE_4BPP); } -#define ABILITY_POP_UP_TAG 0xD720 +#define ABILITY_POP_UP_POS_X_DIFF 64 +#define ABILITY_POP_UP_POS_X_SLIDE 128 +#define ABILITY_POP_UP_POS_X_SPEED 4 + +#define ABILITY_POP_UP_WIN_WIDTH 10 +#define ABILITY_POP_UP_STR_WIDTH (ABILITY_POP_UP_WIN_WIDTH * 8) + +#define ABILITY_POP_UP_PLAYER_LEFT_WIN_W 6 +#define ABILITY_POP_UP_PLAYER_RIGHT_WIN_W 4 +#define ABILITY_POP_UP_OPPONENT_LEFT_WIN_W 7 +#define ABILITY_POP_UP_OPPONENT_RIGHT_WIN_W 3 + +#define ABILITY_POP_UP_WAIT_FRAMES 48 + +/* + * BG = BackGround + * FG = ForeGround + * SH = SHadow + */ +#define ABILITY_POP_UP_BATTLER_BG_TXTCLR 2 +#define ABILITY_POP_UP_BATTLER_FG_TXTCLR 7 +#define ABILITY_POP_UP_BATTLER_SH_TXTCLR 1 + +#define ABILITY_POP_UP_ABILITY_BG_TXTCLR 7 +#define ABILITY_POP_UP_ABILITY_FG_TXTCLR 9 +#define ABILITY_POP_UP_ABILITY_SH_TXTCLR 1 + +#define sState data[0] +#define sAutoDestroy data[1] +#define sTimer data[2] +#define sIsPlayerSide data[3] +#define sBattlerId data[4] +#define sIsMain data[5] -// for sprite -#define tOriginalX data[0] -#define tHide data[1] -#define tFrames data[2] -#define tRightToLeft data[3] -#define tBattlerId data[4] -#define tIsMain data[5] +enum +{ + APU_STATE_SLIDE_IN = 0, + APU_STATE_IDLE, + APU_STATE_SLIDE_OUT, + APU_STATE_END +}; -// for task -#define tSpriteId1 data[6] -#define tSpriteId2 data[7] +enum +{ + TAG_ABILITY_POP_UP = 0xD720, // Only used for the SpritePalette, the rest below is for the SpriteSheets. + TAG_ABILITY_POP_UP_PLAYER1 = TAG_ABILITY_POP_UP, + TAG_ABILITY_POP_UP_OPPONENT1, + TAG_ABILITY_POP_UP_PLAYER2, + TAG_ABILITY_POP_UP_OPPONENT2, + TAG_LAST_BALL_WINDOW, +}; -static const u8 ALIGNED(4) sAbilityPopUpGfx[] = INCBIN_U8("graphics/battle_interface/ability_pop_up.4bpp"); +static const u32 sAbilityPopUpGfx[] = INCBIN_U32("graphics/battle_interface/ability_pop_up.4bpp"); static const u16 sAbilityPopUpPalette[] = INCBIN_U16("graphics/battle_interface/ability_pop_up.gbapal"); static const struct SpriteSheet sSpriteSheet_AbilityPopUp = { - sAbilityPopUpGfx, sizeof(sAbilityPopUpGfx), ABILITY_POP_UP_TAG + sAbilityPopUpGfx, sizeof(sAbilityPopUpGfx), TAG_ABILITY_POP_UP }; + static const struct SpritePalette sSpritePalette_AbilityPopUp = { - sAbilityPopUpPalette, ABILITY_POP_UP_TAG + sAbilityPopUpPalette, TAG_ABILITY_POP_UP }; static const struct OamData sOamData_AbilityPopUp = @@ -2447,8 +2486,8 @@ static const struct OamData sOamData_AbilityPopUp = static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp = { - .tileTag = ABILITY_POP_UP_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .tileTag = TAG_NONE, // Changed on the fly. + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_AbilityPopUp, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2456,279 +2495,153 @@ static const struct SpriteTemplate sSpriteTemplate_AbilityPopUp = .callback = SpriteCb_AbilityPopUp }; -#define ABILITY_POP_UP_POS_X_DIFF (64 - 7) // Hide second sprite underneath to gain proper letter spacing -#define ABILITY_POP_UP_POS_X_SLIDE 68 - static const s16 sAbilityPopUpCoordsDoubles[MAX_BATTLERS_COUNT][2] = { - {29, 80}, // player left - {186, 19}, // opponent left - {29, 97}, // player right - {186, 36}, // opponent right + { 24, 80}, // Player left + {178, 19}, // Opponent left + { 24, 97}, // Player right + {178, 36}, // Opponent right }; static const s16 sAbilityPopUpCoordsSingles[MAX_BATTLERS_COUNT][2] = { - {29, 97}, // player - {186, 57}, // opponent + { 24, 97}, // Player + {178, 57}, // Opponent }; -#define POPUP_WINDOW_WIDTH 8 -#define MAX_POPUP_STRING_WIDTH (POPUP_WINDOW_WIDTH * 8) - -static u8* AddTextPrinterAndCreateWindowOnAbilityPopUp(const u8 *str, u32 x, u32 y, u32 color1, u32 color2, u32 color3, u32 *windowId) +static u8 *AddTextPrinterAndCreateWindowOnAbilityPopUp(const u8 *str, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 *windowId) { u32 fontId; - u8 color[3] = {color1, color2, color3}; + u8 color[3] = {bgColor, fgColor, shadowColor}; struct WindowTemplate winTemplate = {0}; - winTemplate.width = POPUP_WINDOW_WIDTH; + winTemplate.width = ABILITY_POP_UP_WIN_WIDTH; winTemplate.height = 2; *windowId = AddWindow(&winTemplate); - FillWindowPixelBuffer(*windowId, PIXEL_FILL(color1)); + FillWindowPixelBuffer(*windowId, PIXEL_FILL(bgColor)); - fontId = GetFontIdToFit(str, FONT_SMALL, 0, 76); + fontId = GetFontIdToFit(str, FONT_SMALL, 0, ABILITY_POP_UP_STR_WIDTH); AddTextPrinterParameterized4(*windowId, fontId, x, y, 0, 0, color, TEXT_SKIP_DRAW, str); + return (u8 *)(GetWindowAttribute(*windowId, WINDOW_TILE_DATA)); } -static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 xTileAmount, bool32 arg3) +static void TextIntoAbilityPopUp(void *dest, u8 *windowTileData, s32 windowWidth, bool32 printNickname) { - CpuCopy32(windowTileData + 256, dest + 256, xTileAmount * 32); - if (xTileAmount > 0) + #define PIXELS(n) (n * 4) + if (windowWidth > 0) { do { - if (arg3) - CpuCopy32(windowTileData + 16, dest + 16, 16); + if (printNickname) + { + CpuCopy32(windowTileData + PIXELS(3), dest + PIXELS(3), PIXELS(5)); + CpuCopy32(windowTileData + TILE_OFFSET_4BPP(ABILITY_POP_UP_WIN_WIDTH), dest + TILE_OFFSET_4BPP(8), PIXELS(5)); + } else - CpuCopy32(windowTileData + 20, dest + 20, 12); - dest += 32, windowTileData += 32; - xTileAmount--; - } while (xTileAmount != 0); + { + CpuCopy32(windowTileData + PIXELS(7), dest + PIXELS(7), PIXELS(1)); + CpuCopy32(windowTileData + TILE_OFFSET_4BPP(ABILITY_POP_UP_WIN_WIDTH), dest + TILE_OFFSET_4BPP(8), TILE_SIZE_4BPP); + } + + dest += TILE_SIZE_4BPP, windowTileData += TILE_SIZE_4BPP; + windowWidth--; + } while (windowWidth != 0); } + #undef PIXELS } -static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x1, u32 x2, u32 y, u32 color1, u32 color2, u32 color3) +static void PrintOnAbilityPopUp(const u8 *str, u8 *spriteTileData1, u8 *spriteTileData2, u32 x, u32 y, u32 bgColor, u32 fgColor, u32 shadowColor, u32 printNickname, u32 battler) { - u32 windowId; - u8 *windowTileData; - u16 width; + u32 windowId, fontId; + u8 *windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x, y, bgColor, fgColor, shadowColor, &windowId); + u32 size1 = ABILITY_POP_UP_OPPONENT_LEFT_WIN_W, size2 = ABILITY_POP_UP_OPPONENT_RIGHT_WIN_W; - windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x1, y, color1, color2, color3, &windowId); - TextIntoAbilityPopUp(spriteTileData1, windowTileData, 8, (y == 0)); - RemoveWindow(windowId); - - width = GetStringWidth(FONT_SMALL, str, 0); + spriteTileData1 += TILE_OFFSET_4BPP(1); + if (IsOnPlayerSide(battler)) + { + size1 = ABILITY_POP_UP_PLAYER_LEFT_WIN_W, size2 = ABILITY_POP_UP_PLAYER_RIGHT_WIN_W; + // Increment again as the *first* column of the sprite + // is not shown for player's pop up when sliding in. + spriteTileData1 += TILE_OFFSET_4BPP(1); + } - if (width > MAX_POPUP_STRING_WIDTH - 5) + TextIntoAbilityPopUp(spriteTileData1, windowTileData, size1, printNickname); + fontId = GetFontIdToFit(str, FONT_SMALL, 0, ABILITY_POP_UP_STR_WIDTH); + if (GetStringWidth(fontId, str, 0) > (size1 * 8)) { - windowTileData = AddTextPrinterAndCreateWindowOnAbilityPopUp(str, x2 - MAX_POPUP_STRING_WIDTH, y, color1, color2, color3, &windowId); - TextIntoAbilityPopUp(spriteTileData2, windowTileData, 3, (y == 0)); - RemoveWindow(windowId); + windowTileData += TILE_OFFSET_4BPP(size1); + TextIntoAbilityPopUp(spriteTileData2, windowTileData, size2, printNickname); } -} -static const u8 sText_Spaces20[]= _(" "); -static void ClearAbilityName(u8 spriteId1, u8 spriteId2) -{ - PrintOnAbilityPopUp(sText_Spaces20, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, - 5, 12, - 4, - 7, 9, 1); + RemoveWindow(windowId); } static void PrintBattlerOnAbilityPopUp(u8 battler, u8 spriteId1, u8 spriteId2) { - int i; - u8 lastChar; - u8* textPtr; - u8 monName[POKEMON_NAME_LENGTH + 3] = {0}; + u32 totalChar = 0, lastChar; struct Pokemon *illusionMon = GetIllusionMonPtr(battler); - u8 nick[POKEMON_NAME_LENGTH + 1] = {0}; if (illusionMon != NULL) - GetMonData(illusionMon, MON_DATA_NICKNAME, nick); + GetMonData(illusionMon, MON_DATA_NICKNAME, gStringVar1); else - GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, nick); - - for (i = 0; i < POKEMON_NAME_LENGTH; ++i) - { - if (nick[i] == EOS) // End of string - break; - - monName[i] = nick[i]; - } - - textPtr = monName + i; + GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, gStringVar1); - lastChar = *(textPtr - 1); + while (gStringVar1[totalChar] != EOS) + totalChar++; - // Make the string say "[NAME]'s" instead of "[NAME]" - textPtr[0] = CHAR_SGL_QUOTE_RIGHT; // apostraphe - textPtr++; + lastChar = gStringVar1[totalChar - 1]; + StringAppend(gStringVar1, COMPOUND_STRING("'")); if (lastChar != CHAR_S && lastChar != CHAR_s) - { - textPtr[0] = CHAR_s; - textPtr++; - } + StringAppend(gStringVar1, COMPOUND_STRING("s")); - textPtr[0] = EOS; - - PrintOnAbilityPopUp((const u8 *)monName, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32), - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32), - 5, 12, - 0, - 2, 7, 1); + PrintOnAbilityPopUp(gStringVar1, + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum), + 0, 0, + ABILITY_POP_UP_BATTLER_BG_TXTCLR, ABILITY_POP_UP_BATTLER_FG_TXTCLR, ABILITY_POP_UP_BATTLER_SH_TXTCLR, + TRUE, gSprites[spriteId1].sBattlerId); } static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2) { - ClearAbilityName(spriteId1, spriteId2); + PrintOnAbilityPopUp(COMPOUND_STRING(" "), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum) + TILE_OFFSET_4BPP(8), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum) + TILE_OFFSET_4BPP(8), + 0, 4, + ABILITY_POP_UP_ABILITY_BG_TXTCLR, ABILITY_POP_UP_ABILITY_FG_TXTCLR, ABILITY_POP_UP_ABILITY_SH_TXTCLR, + FALSE, gSprites[spriteId1].sBattlerId); PrintOnAbilityPopUp(gAbilitiesInfo[ability].name, - (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, - (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, - 5, 12, - 4, - 7, 9, 1); -} - -#define PIXEL_COORDS_TO_OFFSET(x, y)( \ -/*Add tiles by X*/ \ -((y / 8) * 32 * 8) \ -/*Add tiles by X*/ \ -+ ((x / 8) * 32) \ -/*Add pixels by Y*/ \ -+ ((((y) - ((y / 8) * 8))) * 4) \ -/*Add pixels by X*/ \ -+ ((((x) - ((x / 8) * 8)) / 2))) - -static const u16 sOverwrittenPixelsTable[][2] = -{ - {PIXEL_COORDS_TO_OFFSET(0, 0), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 1), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 2), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 3), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 4), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 5), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 6), 5}, - {PIXEL_COORDS_TO_OFFSET(0, 7), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 8), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 9), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 10), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 11), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 12), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 13), 8}, - - {PIXEL_COORDS_TO_OFFSET(8, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(24, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(32, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(40, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(48, 13), 8}, - {PIXEL_COORDS_TO_OFFSET(56, 13), 8}, - - {PIXEL_COORDS_TO_OFFSET(0, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(24, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(32, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(40, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(48, 14), 8}, - {PIXEL_COORDS_TO_OFFSET(56, 14), 8}, - - {PIXEL_COORDS_TO_OFFSET(0, 15), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 16), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 17), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 18), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 19), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 20), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 21), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 22), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 23), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 24), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 25), 3}, - {PIXEL_COORDS_TO_OFFSET(0, 26), 3}, - -//Second Row Of Image - {PIXEL_COORDS_TO_OFFSET(0, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(0, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(0, 47), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(8, 47), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 45), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 46), 8}, - {PIXEL_COORDS_TO_OFFSET(16, 47), 8}, -}; - -static inline void CopyPixels(u8 *dest, const u8 *src, u32 pixelCount) -{ - u32 i = 0; - - if (pixelCount & 1) - { - while (pixelCount != 0) - { - dest[i] &= ~(0xF); - dest[i] |= (src[i] & 0xF); - if (--pixelCount != 0) - { - dest[i] &= ~(0xF0); - dest[i] |= (src[i] & 0xF0); - pixelCount--; - } - i++; - } - } - else - { - for (i = 0; i < pixelCount / 2; i++) - dest[i] = src[i]; - } -} - -static void RestoreOverwrittenPixels(u8 *tiles) -{ - u32 i; - u8 *buffer = Alloc(sizeof(sAbilityPopUpGfx) * 2); - - CpuCopy32(tiles, buffer, sizeof(sAbilityPopUpGfx)); - - for (i = 0; i < ARRAY_COUNT(sOverwrittenPixelsTable); i++) - { - CopyPixels(buffer + sOverwrittenPixelsTable[i][0], - sAbilityPopUpGfx + sOverwrittenPixelsTable[i][0], - sOverwrittenPixelsTable[i][1]); - } - - CpuCopy32(buffer, tiles, sizeof(sAbilityPopUpGfx)); - Free(buffer); + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId1].oam.tileNum) + TILE_OFFSET_4BPP(8), + (void *)(OBJ_VRAM0) + TILE_OFFSET_4BPP(gSprites[spriteId2].oam.tileNum) + TILE_OFFSET_4BPP(8), + 0, 4, + ABILITY_POP_UP_ABILITY_BG_TXTCLR, ABILITY_POP_UP_ABILITY_FG_TXTCLR, ABILITY_POP_UP_ABILITY_SH_TXTCLR, + FALSE, gSprites[spriteId1].sBattlerId); } static inline bool32 IsAnyAbilityPopUpActive(void) { + u32 activeAbilityPopUps = 0; for (u32 battler = 0; battler < gBattlersCount; battler++) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) - return TRUE; + activeAbilityPopUps++; } - return FALSE; + return activeAbilityPopUps; } void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) { + u8 *spriteIds; + u32 xSlide, tileTag, battlerPosition = GetBattlerPosition(battler); + struct SpriteTemplate template; const s16 (*coords)[2]; - u8 spriteId1, spriteId2, battlerPosition, taskId; - if (B_ABILITY_POP_UP == FALSE) + if (!B_ABILITY_POP_UP) return; - if (gBattleScripting.abilityPopupOverwrite != 0) + if (gBattleScripting.abilityPopupOverwrite) ability = gBattleScripting.abilityPopupOverwrite; if (gTestRunnerEnabled) @@ -2739,111 +2652,122 @@ void CreateAbilityPopUp(u8 battler, u32 ability, bool32 isDoubleBattle) } if (!IsAnyAbilityPopUpActive()) - { - LoadSpriteSheet(&sSpriteSheet_AbilityPopUp); LoadSpritePalette(&sSpritePalette_AbilityPopUp); + + tileTag = (TAG_ABILITY_POP_UP_PLAYER1 + battler); + if (IndexOfSpriteTileTag(tileTag) == 0xFF) + { + struct SpriteSheet sheet = sSpriteSheet_AbilityPopUp; + sheet.tag = tileTag; + LoadSpriteSheet(&sheet); } - gBattleStruct->battlerState[battler].activeAbilityPopUps = TRUE; - battlerPosition = GetBattlerPosition(battler); + coords = isDoubleBattle ? sAbilityPopUpCoordsDoubles : sAbilityPopUpCoordsSingles; + xSlide = IsOnPlayerSide(battler) ? -ABILITY_POP_UP_POS_X_SLIDE : ABILITY_POP_UP_POS_X_SLIDE; - if (isDoubleBattle) - coords = sAbilityPopUpCoordsDoubles; - else - coords = sAbilityPopUpCoordsSingles; + template = sSpriteTemplate_AbilityPopUp; + template.tileTag = tileTag; + spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; + spriteIds[0] = CreateSprite(&template, coords[battlerPosition][0] + xSlide, + coords[battlerPosition][1], 0); + spriteIds[1] = CreateSprite(&template, coords[battlerPosition][0] + xSlide + ABILITY_POP_UP_POS_X_DIFF, + coords[battlerPosition][1], 0); - if ((battlerPosition & BIT_SIDE) == B_SIDE_PLAYER) + if (IsOnPlayerSide(battler)) { - spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE, - coords[battlerPosition][1], 0); - spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] - ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF, - coords[battlerPosition][1], 1); //Appears below - - gSprites[spriteId1].tRightToLeft = TRUE; - gSprites[spriteId2].tRightToLeft = TRUE; + gSprites[spriteIds[0]].sIsPlayerSide = TRUE; + gSprites[spriteIds[1]].sIsPlayerSide = TRUE; } - else - { - spriteId1 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE, - coords[battlerPosition][1], 0); - spriteId2 = CreateSprite(&sSpriteTemplate_AbilityPopUp, - coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_SLIDE + ABILITY_POP_UP_POS_X_DIFF, - coords[battlerPosition][1], 1); //Appears below - gSprites[spriteId1].tRightToLeft = FALSE; - gSprites[spriteId2].tRightToLeft = FALSE; - } + gSprites[spriteIds[1]].oam.tileNum += 32; // Second half of the pop up tiles. - gSprites[spriteId1].tOriginalX = coords[battlerPosition][0]; - gSprites[spriteId2].tOriginalX = coords[battlerPosition][0] + ABILITY_POP_UP_POS_X_DIFF; - gSprites[spriteId2].oam.tileNum += (8 * 4); //Second half of pop up - - gBattleStruct->abilityPopUpSpriteIds[battler][0] = spriteId1; - gBattleStruct->abilityPopUpSpriteIds[battler][1] = spriteId2; - - taskId = CreateTask(Task_FreeAbilityPopUpGfx, 5); - gTasks[taskId].tSpriteId1 = spriteId1; - gTasks[taskId].tSpriteId2 = spriteId2; + // Create only one instance, as it's only used for + // tracking the SpriteSheet(s) and SpritePalette. + if (!IsAnyAbilityPopUpActive()) + CreateTask(Task_FreeAbilityPopUpGfx, 5); - gSprites[spriteId1].tIsMain = TRUE; - gSprites[spriteId1].tBattlerId = battler; - gSprites[spriteId2].tBattlerId = battler; + gBattleStruct->battlerState[battler].activeAbilityPopUps = TRUE; - StartSpriteAnim(&gSprites[spriteId1], 0); - StartSpriteAnim(&gSprites[spriteId2], 0); + gSprites[spriteIds[0]].sIsMain = TRUE; + gSprites[spriteIds[0]].sBattlerId = battler; + gSprites[spriteIds[1]].sBattlerId = battler; - PrintBattlerOnAbilityPopUp(battler, spriteId1, spriteId2); - PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); - RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); + PrintBattlerOnAbilityPopUp(battler, spriteIds[0], spriteIds[1]); + PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } void UpdateAbilityPopup(u8 battler) { - u8 spriteId1 = gBattleStruct->abilityPopUpSpriteIds[battler][0]; - u8 spriteId2 = gBattleStruct->abilityPopUpSpriteIds[battler][1]; - u16 ability = (gBattleScripting.abilityPopupOverwrite != 0) ? gBattleScripting.abilityPopupOverwrite : gBattleMons[battler].ability; - - PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); - RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); + u8 *spriteIds = gBattleStruct->abilityPopUpSpriteIds[battler]; + u16 ability = (gBattleScripting.abilityPopupOverwrite) ? gBattleScripting.abilityPopupOverwrite + : gBattleMons[battler].ability; + PrintAbilityOnAbilityPopUp(ability, spriteIds[0], spriteIds[1]); } -#define FRAMES_TO_WAIT 48 - static void SpriteCb_AbilityPopUp(struct Sprite *sprite) { - if (!sprite->tHide) // Show + s16 *data = sprite->data; + u32 battlerPosition = GetBattlerPosition(sBattlerId); + u32 fullX = sprite->x + sprite->x2; + u32 speed; + + switch (sState) { - if (sprite->tIsMain && ++sprite->tFrames == 4) + case APU_STATE_SLIDE_IN: + { + const s16 (*coords)[2] = IsDoubleBattle() ? sAbilityPopUpCoordsDoubles : sAbilityPopUpCoordsSingles; + u32 xCoord = coords[battlerPosition][0]; + + if (sIsMain && ++sTimer == 4) PlaySE(SE_BALL_TRAY_ENTER); - if ((!sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX) - || (sprite->tRightToLeft && (sprite->x += 4) >= sprite->tOriginalX) - ) - { - sprite->x = sprite->tOriginalX; - sprite->tHide = TRUE; - sprite->tFrames = FRAMES_TO_WAIT; - } + + if (!sIsMain) + xCoord += ABILITY_POP_UP_POS_X_DIFF; + + if (fullX == xCoord) + { + sTimer = ABILITY_POP_UP_WAIT_FRAMES; + sState = APU_STATE_IDLE; + break; + } + + speed = sIsPlayerSide ? ABILITY_POP_UP_POS_X_SPEED : -ABILITY_POP_UP_POS_X_SPEED; + sprite->x2 += speed; + break; } - else // Hide + case APU_STATE_IDLE: { - if (sprite->tFrames == 0) + if (!sTimer || sAutoDestroy) { - if ((!sprite->tRightToLeft && (sprite->x += 4) >= sprite->tOriginalX + ABILITY_POP_UP_POS_X_SLIDE) - ||(sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE) - ) - { - gBattleStruct->battlerState[sprite->tBattlerId].activeAbilityPopUps = FALSE; - DestroySprite(sprite); - } - } - else - { - if (!gBattleScripting.fixedPopup) - sprite->tFrames--; + sState = APU_STATE_SLIDE_OUT; + break; } + + if (!gBattleScripting.fixedPopup) + sTimer--; + + break; + } + case APU_STATE_SLIDE_OUT: + { + if (fullX == sprite->x) + { + sState = APU_STATE_END; + break; + } + + speed = sIsPlayerSide ? -ABILITY_POP_UP_POS_X_SPEED : ABILITY_POP_UP_POS_X_SPEED; + sprite->x2 += speed; + break; + } + case APU_STATE_END: + { + if (sIsMain) + gBattleStruct->battlerState[sBattlerId].activeAbilityPopUps = FALSE; + + DestroySprite(sprite); + break; + } } } @@ -2851,26 +2775,33 @@ void DestroyAbilityPopUp(u8 battler) { if (gBattleStruct->battlerState[battler].activeAbilityPopUps) { - gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][0]].tFrames = 0; - gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][1]].tFrames = 0; + gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][0]].sAutoDestroy = TRUE; + gSprites[gBattleStruct->abilityPopUpSpriteIds[battler][1]].sAutoDestroy = TRUE; } - gBattleScripting.fixedPopup = FALSE; } static void Task_FreeAbilityPopUpGfx(u8 taskId) { - if (!gSprites[gTasks[taskId].tSpriteId1].inUse - && !gSprites[gTasks[taskId].tSpriteId2].inUse - && !IsAnyAbilityPopUpActive()) + if (!IsAnyAbilityPopUpActive()) { - FreeSpriteTilesByTag(ABILITY_POP_UP_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (IndexOfSpriteTileTag(TAG_ABILITY_POP_UP_PLAYER1 + battler) != 0xFF) + FreeSpriteTilesByTag(TAG_ABILITY_POP_UP_PLAYER1 + battler); + } + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroyTask(taskId); } } +#undef sState +#undef sAutoDestroy +#undef sTimer +#undef sIsPlayerSide +#undef sBattlerId +#undef sIsMain + // last used ball -#define LAST_BALL_WINDOW_TAG 0xD721 static const struct OamData sOamData_LastUsedBall = { @@ -2891,8 +2822,8 @@ static const struct OamData sOamData_LastUsedBall = static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = { - .tileTag = LAST_BALL_WINDOW_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .tileTag = TAG_LAST_BALL_WINDOW, + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_LastUsedBall, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2922,7 +2853,7 @@ static const struct OamData sOamData_MoveInfoWindow = static const struct SpriteTemplate sSpriteTemplate_MoveInfoWindow = { .tileTag = MOVE_INFO_WINDOW_TAG, - .paletteTag = ABILITY_POP_UP_TAG, + .paletteTag = TAG_ABILITY_POP_UP, .oam = &sOamData_MoveInfoWindow, .anims = gDummySpriteAnimTable, .images = NULL, @@ -2941,7 +2872,7 @@ static const struct SpriteTemplate sSpriteTemplate_MoveInfoWindow = #endif static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = { - sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), LAST_BALL_WINDOW_TAG + sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), TAG_LAST_BALL_WINDOW }; #if B_MOVE_DESCRIPTION_BUTTON == R_BUTTON @@ -3020,7 +2951,7 @@ void TryAddLastUsedBallItemSprites(void) // window LoadSpritePalette(&sSpritePalette_AbilityPopUp); - if (GetSpriteTileStartByTag(LAST_BALL_WINDOW_TAG) == 0xFFFF) + if (GetSpriteTileStartByTag(TAG_LAST_BALL_WINDOW) == 0xFFFF) LoadSpriteSheet(&sSpriteSheet_LastUsedBallWindow); if (gBattleStruct->ballSpriteIds[1] == MAX_SPRITES) @@ -3038,8 +2969,8 @@ void TryAddLastUsedBallItemSprites(void) static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) { - FreeSpriteTilesByTag(LAST_BALL_WINDOW_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + FreeSpriteTilesByTag(TAG_LAST_BALL_WINDOW); + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; } @@ -3076,7 +3007,7 @@ void TryToHideMoveInfoWindow(void) static void DestroyMoveInfoWinGfx(struct Sprite *sprite) { FreeSpriteTilesByTag(MOVE_INFO_WINDOW_TAG); - FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + FreeSpritePaletteByTag(TAG_ABILITY_POP_UP); DestroySprite(sprite); gBattleStruct->moveInfoSpriteId = MAX_SPRITES; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f148129b2d..c0842af259 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10795,7 +10795,10 @@ static void Cmd_various(void) case VARIOUS_DESTROY_ABILITY_POPUP: { VARIOUS_ARGS(); - DestroyAbilityPopUp(battler); + for (u32 i = 0; i < gBattlersCount; i++) + { + DestroyAbilityPopUp(i); + } break; } case VARIOUS_TOTEM_BOOST: diff --git a/src/sprite.c b/src/sprite.c index 225c181f42..1b89a50be1 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -85,7 +85,6 @@ static void ApplyAffineAnimFrameRelativeAndUpdateMatrix(u8 matrixNum, struct Aff static s16 ConvertScaleParam(s16 scale); static void GetAffineAnimFrame(u8 matrixNum, struct Sprite *sprite, struct AffineAnimFrameCmd *frameCmd); static void ApplyAffineAnimFrame(u8 matrixNum, struct AffineAnimFrameCmd *frameCmd); -static u8 IndexOfSpriteTileTag(u16 tag); static void AllocSpriteTileRange(u16 tag, u16 start, u16 count); static void DoLoadSpritePalette(const u16 *src, u16 paletteOffset); static void UpdateSpriteMatrixAnchorPos(struct Sprite *, s32, s32); From 419219bb3102a54b3db85b9787f5cc98e6e8a2e5 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:58:31 -0400 Subject: [PATCH 070/283] Add AI_FLAG_ASSUME_STAB (#6797) --- docs/tutorials/ai_flags.md | 3 ++ include/battle_ai_util.h | 1 + include/config/ai.h | 13 +++-- include/constants/battle_ai.h | 3 +- include/pokemon.h | 1 + src/battle_ai_main.c | 14 ++++++ src/battle_ai_switch_items.c | 6 ++- src/battle_ai_util.c | 13 ++++- src/pokemon.c | 8 ++++ test/battle/ai/ai_assume_stab.c | 85 +++++++++++++++++++++++++++++++++ test/battle/ai/ai_flag_risky.c | 2 +- test/battle/ai/ai_switching.c | 6 +-- 12 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 test/battle/ai/ai_assume_stab.c diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index af3d3c0718..7910049fbe 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -144,6 +144,9 @@ Marks the last two Pokémon in the party as Ace Pokémon, with the same behaviou ## `AI_FLAG_OMNISCIENT` AI has full knowledge of player moves, abilities, and hold items, and can use this knowledge when making decisions. +## `AI_FLAG_ASSUME_STAB` +A significantly more restricted version of `AI_FLAG_OMNISCIENT`, the AI only knows the player's STAB moves, as their existence would be reasonable to assume in almost any case. + ## `AI_FLAG_SMART_MON_CHOICES` Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled. diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 991584a534..b0ad69f5d9 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -60,6 +60,7 @@ u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcC bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); +bool32 IsAiBattlerAssumingStab(void); void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordAllMoves(u32 battler); diff --git a/include/config/ai.h b/include/config/ai.h index c51ff6d790..57fc7ecb60 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -69,10 +69,15 @@ #define AI_CONSERVE_TERA_CHANCE_PER_MON 10 // Chance for AI with smart tera flag to decide not to tera before considering defensive benefit is this*(X-1), where X is the number of alive pokemon that could tera #define AI_TERA_PREDICT_CHANCE 40 // Chance for AI with smart tera flag to tera in the situation where tera would save it from a KO, but could be punished by a KO from a different move. -// AI PP Stall detection chance per roll -#define PP_STALL_DISREGARD_MOVE_PERCENTAGE 50 -// Score reduction if any roll for PP stall detection passes -#define PP_STALL_SCORE_REDUCTION 20 +// AI_FLAG_PP_STALL_PREVENTION settings +#define PP_STALL_DISREGARD_MOVE_PERCENTAGE 50 // Detection chance per roll +#define PP_STALL_SCORE_REDUCTION 20 // Score reduction if any roll for PP stall detection passes + +// AI_FLAG_ASSUME_STAB settings +#define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience. + +// AI_FLAG_SMART_SWITCHING settings +#define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise // AI's acceptable number of hits to KO the partner via friendly fire in a double battle. #define FRIENDLY_FIRE_RISKY_THRESHOLD 2 diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 1f19d3e966..4fc13aaa1b 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -33,8 +33,9 @@ #define AI_FLAG_PP_STALL_PREVENTION (1 << 25) // AI keeps track of the player's switches where the incoming mon is immune to the chosen move #define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT #define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). +#define AI_FLAG_ASSUME_STAB (1 << 28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. -#define AI_FLAG_COUNT 28 +#define AI_FLAG_COUNT 29 // Flags at and after 32 need different formatting, as in // #define AI_FLAG_PLACEHOLDER ((u64)1 << 32) diff --git a/include/pokemon.h b/include/pokemon.h index f6c242606f..1a6bb8c696 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -881,5 +881,6 @@ u32 GetTeraTypeFromPersonality(struct Pokemon *mon); struct Pokemon *GetSavedPlayerPartyMon(u32 index); u8 *GetSavedPlayerPartyCount(void); void SavePlayerPartyMon(u32 index, struct Pokemon *mon); +u32 IsSpeciesOfType(u32 species, u32 type); #endif // GUARD_POKEMON_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index dae2895d96..6fee14ca15 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -533,6 +533,17 @@ void Ai_UpdateFaintData(u32 battler) aiMon->isFainted = TRUE; } +void RecordMovesBasedOnStab(u32 battler) +{ + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 playerMove = gBattleMons[battler].moves[i]; + if (IsSpeciesOfType(gBattleMons[battler].species, GetMoveType(playerMove)) && GetMovePower(playerMove != 0)) + RecordKnownMove(battler, playerMove); + } +} + void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) { u32 ability, holdEffect; @@ -545,6 +556,9 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) aiData->hpPercents[battler] = GetHealthPercentage(battler); aiData->moveLimitations[battler] = CheckMoveLimitations(battler, 0, MOVE_LIMITATIONS_ALL); aiData->speedStats[battler] = GetBattlerTotalSpeedStatArgs(battler, ability, holdEffect); + + if (IsAiBattlerAssumingStab()) + RecordMovesBasedOnStab(battler); } #define BYPASSES_ACCURACY_CALC 101 // 101 indicates for ai that the move will always hit diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 393eb054bf..587b085500 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -192,6 +192,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler)); opposingBattler = GetBattlerAtPosition(opposingPosition); + u16 *playerMoves = GetMovesArray(opposingBattler); // Gets types of player (opposingBattler) and computer (battler) atkType1 = gBattleMons[opposingBattler].types[0]; @@ -255,7 +256,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) // Get max damage mon could take for (i = 0; i < MAX_MON_MOVES; i++) { - playerMove = gBattleMons[opposingBattler].moves[i]; + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) { damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); @@ -1941,11 +1942,12 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle { int i = 0; u32 playerMove; + u16 *playerMoves = GetMovesArray(opposingBattler); s32 damageTaken = 0, maxDamageTaken = 0; for (i = 0; i < MAX_MON_MOVES; i++) { - playerMove = gBattleMons[opposingBattler].moves[i]; + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) { damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 6d2fb0afce..f0defb570a 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -132,6 +132,15 @@ bool32 IsAiBattlerAware(u32 battlerId) return BattlerHasAi(battlerId); } +bool32 IsAiBattlerAssumingStab() +{ + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_STAB + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_STAB) + return TRUE; + + return FALSE; +} + bool32 IsAiBattlerPredictingAbility(u32 battlerId) { if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_WEIGH_ABILITY_PREDICTION @@ -1423,8 +1432,8 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId) if (gDisableStructs[battlerId].overwrittenAbility) return gDisableStructs[battlerId].overwrittenAbility; - // The AI knows its own ability. - if (IsAiBattlerAware(battlerId)) + // The AI knows its own ability, and omniscience handling + if (IsAiBattlerAware(battlerId) || (IsAiBattlerAssumingStab() && ASSUME_STAB_SEES_ABILITY)) return knownAbility; // Check neutralizing gas, gastro acid diff --git a/src/pokemon.c b/src/pokemon.c index 4a3b0bf706..91524ae97d 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -7154,3 +7154,11 @@ void SavePlayerPartyMon(u32 index, struct Pokemon *mon) { gSaveBlock1Ptr->playerParty[index] = *mon; } + +u32 IsSpeciesOfType(u32 species, u32 type) +{ + if (gSpeciesInfo[species].types[0] == type + || gSpeciesInfo[species].types[1] == type) + return TRUE; + return FALSE; +} diff --git a/test/battle/ai/ai_assume_stab.c b/test/battle/ai/ai_assume_stab.c new file mode 100644 index 0000000000..6147229ae7 --- /dev/null +++ b/test/battle/ai/ai_assume_stab.c @@ -0,0 +1,85 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_SINGLE_BATTLE_TEST("AI_FLAG_ASSUME_STAB sees the player's STAB moves") +{ + u32 aiFlag = 0; + PARAMETRIZE { aiFlag = AI_FLAG_ASSUME_STAB; } + PARAMETRIZE { aiFlag = AI_FLAG_OMNISCIENT; } + PARAMETRIZE { aiFlag = 0; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | aiFlag); + PLAYER(SPECIES_TYPHLOSION) { Speed(5); Moves(MOVE_TACKLE, MOVE_FLAMETHROWER); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(1); Moves(MOVE_TACKLE); Level(1); } + OPPONENT(SPECIES_SCIZOR) { Speed(4); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_BLISSEY) { Speed(4); Moves(MOVE_TACKLE); } + } WHEN { + if (aiFlag == AI_FLAG_ASSUME_STAB || aiFlag == AI_FLAG_OMNISCIENT) + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } + else + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_ASSUME_STAB does not see the player's non-STAB moves") +{ + u32 aiFlag = 0; + PARAMETRIZE { aiFlag = AI_FLAG_ASSUME_STAB; } + PARAMETRIZE { aiFlag = AI_FLAG_OMNISCIENT; } + PARAMETRIZE { aiFlag = 0; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | aiFlag); + PLAYER(SPECIES_GOREBYSS) { Speed(5); Moves(MOVE_TACKLE, MOVE_FLAMETHROWER); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(1); Moves(MOVE_TACKLE); Level(1); } + OPPONENT(SPECIES_SCIZOR) { Speed(4); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_BLISSEY) { Speed(4); Moves(MOVE_TACKLE); } + } WHEN { + if (aiFlag == AI_FLAG_OMNISCIENT) + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } + else + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 1); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI correctly records assumed STAB moves") +{ + u32 aiFlag = 0; + // Not checking Omniscient here because it doesn't change the battle history + PARAMETRIZE { aiFlag = AI_FLAG_ASSUME_STAB; } + PARAMETRIZE { aiFlag = 0; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiFlag); + PLAYER(SPECIES_TYPHLOSION) { Moves(MOVE_TACKLE, MOVE_FLAMETHROWER, MOVE_SMOG); } + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE, MOVE_HEADBUTT, MOVE_THUNDERBOLT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(playerRight, MOVE_THUNDERBOLT, target:opponentRight); } + } THEN { + if (aiFlag == AI_FLAG_ASSUME_STAB) + { + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_FLAMETHROWER); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); + + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_HEADBUTT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); + } + else if (aiFlag == 0) + { + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); + + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); + } + } +} diff --git a/test/battle/ai/ai_flag_risky.c b/test/battle/ai/ai_flag_risky.c index 5a076f6fe1..5af51b9e8c 100644 --- a/test/battle/ai/ai_flag_risky.c +++ b/test/battle/ai/ai_flag_risky.c @@ -64,7 +64,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: Mid-battle switches prioritize offensive o PARAMETRIZE { aiRiskyFlag = AI_FLAG_RISKY; } GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | aiRiskyFlag); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT | aiRiskyFlag); PLAYER(SPECIES_SWELLOW) { Level(30); Moves(MOVE_WING_ATTACK, MOVE_BOOMBURST); Speed(5); } OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(4); } // Forces switchout OPPONENT(SPECIES_ARON) { Level(30); Moves(MOVE_HEADBUTT); Speed(4); SpDefense(41); } // Mid battle, AI sends out Aron diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 4dce36a219..8a41e9fdfe 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -85,7 +85,7 @@ AI_SINGLE_BATTLE_TEST("AI will switch out if it has no move that affects the pla AI_SINGLE_BATTLE_TEST("When AI switches out due to having no move that affects the player, AI will send in a mon that can hit the player, even if not ideal") { GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL, MOVE_CELEBRATE); } OPPONENT(SPECIES_ABRA) { Moves(MOVE_TACKLE); } OPPONENT(SPECIES_ABRA) { Moves(MOVE_TACKLE); } @@ -314,7 +314,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize defensive options") { GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_SWELLOW) { Level(30); Moves(MOVE_WING_ATTACK, MOVE_BOOMBURST); Speed(5); SpAttack(50); } OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(4); } // Forces switchout OPPONENT(SPECIES_ARON) { Level(30); Moves(MOVE_IRON_HEAD); Speed(4); SpDefense(50); } // Mid battle, AI sends out Aron @@ -373,7 +373,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize GIVEN { ASSUME(gItemsInfo[ITEM_EJECT_PACK].holdEffect == HOLD_EFFECT_EJECT_PACK); ASSUME(MoveHasAdditionalEffectSelf(MOVE_OVERHEAT, MOVE_EFFECT_SP_ATK_MINUS_2) == TRUE); - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_SWELLOW) { Level(30); Moves(MOVE_WING_ATTACK, MOVE_BOOMBURST); Speed(5); SpAttack(50); } OPPONENT(SPECIES_PONYTA) { Level(1); Item(ITEM_EJECT_PACK); Moves(MOVE_OVERHEAT); Speed(6); } // Forces switchout OPPONENT(SPECIES_ARON) { Level(30); Moves(MOVE_IRON_HEAD); Speed(4); SpDefense(50); } From cb03086c1d64c5e47cba87ac5ff5962dff5640f5 Mon Sep 17 00:00:00 2001 From: surskitty Date: Thu, 10 Jul 2025 14:02:31 -0400 Subject: [PATCH 071/283] AI checks the partner's moves for Flatter, Swagger, and Soak. (#7306) --- include/constants/battle.h | 3 +++ src/battle_ai_main.c | 27 +++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 6d207177c4..f0861ad43a 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -302,6 +302,9 @@ enum Volatile #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) #define SIDE_STATUS_PLEDGE_ANY (SIDE_STATUS_RAINBOW | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) +#define SIDE_STATUS_GOOD_FOG (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) +#define SIDE_STATUS_GOOD_COURT (SIDE_STATUS_GOOD_FOG | SIDE_STATUS_TAILWIND | SIDE_STATUS_LUCKY_CHANT | SIDE_STATUS_RAINBOW) +#define SIDE_STATUS_BAD_COURT (SIDE_STATUS_DAMAGE_NON_TYPES | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) enum Hazards { diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6fee14ca15..38999fcf65 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4316,8 +4316,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_HAIL: if (ShouldSetHail(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) { - if ((HasMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_AURORA_VEIL)) - && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) ADJUST_SCORE(GOOD_EFFECT); ADJUST_SCORE(DECENT_EFFECT); @@ -4332,8 +4331,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_SNOWSCAPE: if (ShouldSetSnow(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) { - if ((HasMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_AURORA_VEIL)) - && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) ADJUST_SCORE(GOOD_EFFECT); ADJUST_SCORE(DECENT_EFFECT); @@ -4421,10 +4419,17 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; case EFFECT_SWAGGER: + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_FOUL_PLAY) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) + ADJUST_SCORE(DECENT_EFFECT); + if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) + ADJUST_SCORE(GOOD_EFFECT); + IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); + break; case EFFECT_FLATTER: - if (HasMoveWithEffect(battlerAtk, EFFECT_FOUL_PLAY) - || HasMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) - || HasMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_PSYCH_UP) + || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) ADJUST_SCORE(DECENT_EFFECT); if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) ADJUST_SCORE(GOOD_EFFECT); @@ -4454,11 +4459,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_DEFOG: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) - || (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST))) + || (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_GOOD_FOG)) { ADJUST_SCORE(GOOD_EFFECT); } - else if (!IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_SPIKES)) //Don't blow away hazards if you set them up + else if (!AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) || CountUsablePartyMons(battlerDef) == 0) //Don't blow away hazards if you set them up { if (isDoubleBattle) { @@ -4919,7 +4924,9 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_SOAK: - if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) || (HasMoveWithEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && GetMoveArgType(move) == TYPE_WATER) ) + if (HasMoveWithType(battlerAtk, TYPE_ELECTRIC) || HasMoveWithType(battlerAtk, TYPE_GRASS) + || HasMoveWithType(BATTLE_PARTNER(battlerAtk), TYPE_ELECTRIC) || HasMoveWithType(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) + || (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_SUPER_EFFECTIVE_ON_ARG) && GetMoveArgType(move) == TYPE_WATER) ) ADJUST_SCORE(DECENT_EFFECT); // Get some super effective moves break; case EFFECT_THIRD_TYPE: From 4e558af76e939eb2a7ad878f79d012a74830caec Mon Sep 17 00:00:00 2001 From: surskitty Date: Thu, 10 Jul 2025 14:03:46 -0400 Subject: [PATCH 072/283] AI uses After You to help set up Trick Room. (#7310) --- src/battle_ai_main.c | 15 +++++++++++++-- test/battle/ai/ai_doubles.c | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 38999fcf65..43d01dfa2e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2991,6 +2991,14 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsMoveEffectWeather(move)) ADJUST_SCORE(-10); break; + case EFFECT_AFTER_YOU: + if (effect == EFFECT_TRICK_ROOM) + ADJUST_SCORE(DECENT_EFFECT); + break; + case EFFECT_TRICK_ROOM: + if (effect == EFFECT_AFTER_YOU) + ADJUST_SCORE(DECENT_EFFECT); + break; default: break; } @@ -3521,12 +3529,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_AFTER_YOU: + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)) + ADJUST_SCORE(DECENT_EFFECT); + if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove) // Opponent mon 1 goes before partner - || AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove)) // Opponent mon 2 goes before partner + && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove)) // Opponent mon 2 goes before partner { if (partnerEffect == EFFECT_COUNTER || partnerEffect == EFFECT_MIRROR_COAT) break; // These moves need to go last - RETURN_SCORE_PLUS(WEAK_EFFECT); + ADJUST_SCORE(WEAK_EFFECT); } break; case EFFECT_HEAL_PULSE: diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 243c6611e9..cbf7c3423b 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -410,6 +410,29 @@ AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons tha } } +AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TRICK_ROOM; } + PARAMETRIZE { move = MOVE_MOONBLAST; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); + ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + OPPONENT(SPECIES_INDEEDEE_M) { Speed(5); Moves(MOVE_AFTER_YOU, MOVE_PSYCHIC); } + OPPONENT(SPECIES_CLEFAIRY) { Speed(3); Moves(move, MOVE_PSYCHIC); } + } WHEN { + if (move == MOVE_TRICK_ROOM) + TURN { EXPECT_MOVE(opponentLeft, MOVE_AFTER_YOU, target:opponentRight); EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_AFTER_YOU); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats") { From 424c127b8bab529ef7b8834e3d8b74c9281bb672 Mon Sep 17 00:00:00 2001 From: surskitty Date: Thu, 10 Jul 2025 16:08:14 -0400 Subject: [PATCH 073/283] AI Tests + accompanying bugfixes for Skill Swap, Worry Seed, weather setting in double battles, and Discharging into an ally's lightningrod (#7297) --- include/battle_ai_main.h | 3 +- src/battle_ai_util.c | 10 ++-- test/battle/ai/ai_check_viability.c | 37 +++++++++++-- test/battle/ai/ai_doubles.c | 84 +++++++++++++++++++++++------ 4 files changed, 111 insertions(+), 23 deletions(-) diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 6c58063350..547395d480 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -39,9 +39,10 @@ enum AIScore DECENT_EFFECT = 2, GOOD_EFFECT = 3, BEST_EFFECT = 4, + PERFECT_EFFECT = 10, BAD_EFFECT = -1, AWFUL_EFFECT = -3, - WORST_EFFECT = -5 + WORST_EFFECT = -10 }; // AI_TryToFaint diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index f0defb570a..48403d4e11 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -5279,7 +5279,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData case ABILITY_POWER_SPOT: case ABILITY_VICTORY_STAR: if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)) && aiData->abilities[BATTLE_PARTNER(battler)] != ability) - return GOOD_EFFECT; + return BEST_EFFECT; break; case ABILITY_GUTS: if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_CAN_MOVE)) @@ -5295,7 +5295,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData case ABILITY_VITAL_SPIRIT: if (HasMoveWithEffect(battler, EFFECT_REST)) return WORST_EFFECT; - return NO_INCREASE; + break; case ABILITY_INTIMIDATE: { u32 abilityDef = aiData->abilities[FOE(battler)]; @@ -5335,6 +5335,8 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return WEAK_EFFECT; if (gBattleMons[battler].status1 & (STATUS1_TOXIC_POISON)) return BEST_EFFECT; + if (gBattleMons[battler].status1 & STATUS1_ANY) + return NO_INCREASE; break; // Also used to Simple Beam SIMPLE_BEAM. case ABILITY_SIMPLE: @@ -5354,11 +5356,13 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return NO_INCREASE; } return GOOD_EFFECT; + case ABILITY_NONE: + return NO_INCREASE; default: break; } - return NO_INCREASE; + return WEAK_EFFECT; } u32 GetThinkingBattler(u32 battler) diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index 47cf2450a9..1407023ece 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -281,12 +281,22 @@ AI_SINGLE_BATTLE_TEST("AI uses Wide Guard against Earthquake when opponent would AI_SINGLE_BATTLE_TEST("AI uses Worry Seed against Rest") { + u32 move; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT; + + PARAMETRIZE { move = MOVE_REST; } + PARAMETRIZE { move = MOVE_EXTREME_SPEED; } + PARAMETRIZE { move = MOVE_REST; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; } + PARAMETRIZE { move = MOVE_EXTREME_SPEED; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; } GIVEN { - PLAYER(SPECIES_ZUBAT) { Moves(MOVE_REST, MOVE_SLEEP_TALK, MOVE_AIR_CUTTER); } - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); - OPPONENT(SPECIES_BUDEW) { Moves(MOVE_WORRY_SEED, MOVE_SLUDGE_BOMB); } + AI_FLAGS(aiFlags); + PLAYER(SPECIES_ZIGZAGOON) { Moves(move, MOVE_SLEEP_TALK, MOVE_HEADBUTT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_WORRY_SEED, MOVE_HEADBUTT); } } WHEN { - TURN { MOVE(player, MOVE_AIR_CUTTER); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); } + if (move == MOVE_REST) + TURN { MOVE(player, MOVE_HEADBUTT); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); } + else + TURN { MOVE(player, MOVE_HEADBUTT); NOT_EXPECT_MOVE(opponent, MOVE_WORRY_SEED); } } } @@ -309,4 +319,23 @@ AI_SINGLE_BATTLE_TEST("AI uses Simple Beam against Contrary Leaf Storm") } } +AI_SINGLE_BATTLE_TEST("AI uses Skill Swap against Poison Heal") +{ + u8 status; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT; + PARAMETRIZE { status = STATUS1_POISON; } + PARAMETRIZE { status = STATUS1_POISON; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; } + PARAMETRIZE { status = STATUS1_TOXIC_POISON; } + PARAMETRIZE { status = STATUS1_TOXIC_POISON; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; } + GIVEN { + PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(status); } + AI_FLAGS(aiFlags); + OPPONENT(SPECIES_SPINDA) { Moves(MOVE_SKILL_SWAP, MOVE_HEADBUTT); } + } WHEN { + if (status == STATUS1_TOXIC_POISON) + TURN { EXPECT_MOVE(opponent, MOVE_SKILL_SWAP); } + else + TURN { NOT_EXPECT_MOVE(opponent, MOVE_SKILL_SWAP); } + } +} diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index cbf7c3423b..33c3eca074 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -348,7 +348,7 @@ AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners") } } -AI_DOUBLE_BATTLE_TEST("AI knows if redirection abilities provide immunity to allies") +AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 4)") { KNOWN_FAILING; ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); @@ -356,26 +356,44 @@ AI_DOUBLE_BATTLE_TEST("AI knows if redirection abilities provide immunity to all ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY); ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER); - u32 ability, move, species, config; + u32 ability, move, species; - PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; config = GEN_4; } - PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; config = GEN_5; } - PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; config = GEN_4; } - PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; config = GEN_5; } + PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; } + PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; } GIVEN { - ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE); - WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config); - PLAYER(SPECIES_ZIGZAGOON); - PLAYER(SPECIES_ZIGZAGOON); - OPPONENT(SPECIES_SLAKING) { Moves(move, MOVE_SCRATCH); } + WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_4); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_HEADBUTT); } OPPONENT(species) { HP(1); Ability(ability); Moves(MOVE_ROUND); } } WHEN { - if (config == GEN_5) - TURN { EXPECT_MOVE(opponentLeft, move); } - else - TURN { EXPECT_MOVE(opponentLeft, MOVE_SCRATCH); } + TURN { EXPECT_MOVE(opponentLeft, MOVE_HEADBUTT); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 5+)") +{ + ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC); + ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER); + + u32 ability, move, species; + + PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; } + PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE); + WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_5); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_HEADBUTT); } + OPPONENT(species) { HP(1); Ability(ability); Moves(MOVE_ROUND); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } } } @@ -410,6 +428,41 @@ AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons tha } } +// Sandstorm is omitted on purpose. +// Tornadus is currently not willing to set up Sandstorm for its ally, but the actual purpose of this test is to demonstrate that Tornadus or Whimsicott will perform standard VGC openers. +// Rain Dance, Sunny Day, and Snowscape are the actually important ones; setting up a good Sandstorm test + functionality is less important and will be done in later PRs. +AI_DOUBLE_BATTLE_TEST("AI will set up weather for its ally") +{ + u32 goodWeather, badWeather, weatherTrigger; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; + + PARAMETRIZE { goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; } + PARAMETRIZE { goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; } + PARAMETRIZE { goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } + PARAMETRIZE { goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } +// PARAMETRIZE { goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } +// PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; +// goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } + + GIVEN { + AI_FLAGS(aiFlags); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TORNADUS) { Ability(ABILITY_PRANKSTER); Moves(goodWeather, badWeather, MOVE_RETURN, MOVE_TAUNT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(weatherTrigger, MOVE_EARTH_POWER); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, goodWeather); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") { u32 move; @@ -433,6 +486,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") } } + AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats") { From c5f788444a919e5b46135b69f0f4e3a83fc853eb Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:49:16 -0400 Subject: [PATCH 074/283] Fix choice AI not seeing Gorilla Tactics (#7316) --- src/battle_ai_switch_items.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 7695a0a154..9138f59d59 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -160,10 +160,12 @@ static inline bool32 SetSwitchinAndSwitch(u32 battler, u32 switchinId) return TRUE; } -static bool32 AI_DoesChoiceItemBlockMove(u32 battler, u32 move) +static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) { // Choice locked into something else - if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move && HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) + if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move + && ((HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) + || gBattleMons[battler].ability == ABILITY_GORILLA_TACTICS)) return TRUE; return FALSE; } @@ -225,12 +227,12 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (!IsBattleMoveStatus(aiMove)) { // Check if mon has a super effective move - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceItemBlockMove(battler, aiMove)) + if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) hasSuperEffectiveMove = TRUE; // Get maximum damage mon can deal damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData); - if (damageDealt > maxDamageDealt && !AI_DoesChoiceItemBlockMove(battler, aiMove)) + if (damageDealt > maxDamageDealt && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) { maxDamageDealt = damageDealt; aiBestMove = aiMove; @@ -483,7 +485,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) // Only check damage if it's a damaging move if (!IsBattleMoveStatus(aiMove)) { - if (!AI_DoesChoiceItemBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp) + if (!AI_DoesChoiceEffectBlockMove(battler, aiMove) && AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData) > gBattleMons[opposingBattler].hp) return FALSE; } } @@ -802,7 +804,7 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { move = gBattleMons[battler].moves[i]; - if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move)) + if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) @@ -821,7 +823,7 @@ static bool32 CanUseSuperEffectiveMoveAgainstOpponents(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { move = gBattleMons[battler].moves[i]; - if (move == MOVE_NONE || AI_DoesChoiceItemBlockMove(battler, move)) + if (move == MOVE_NONE || AI_DoesChoiceEffectBlockMove(battler, move)) continue; if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0)) From cb606cee6a64fcef48fef51d1cfde1b77ca5e904 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Thu, 10 Jul 2025 23:37:06 +0200 Subject: [PATCH 075/283] Fix HGSS dex running out of heap (#7317) Co-authored-by: Hedara --- src/pokedex_plus_hgss.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index db7ff38ee0..49e1016d32 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -4228,6 +4228,13 @@ static void Task_ExitCaughtMonPage(u8 taskId) paletteNum = gSprites[gTasks[taskId].tMonSpriteId].oam.paletteNum; paletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality); LoadPalette(paletteData, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); + + if (sPokedexView) + { + Free(sPokedexView); + sPokedexView = NULL; + } + DestroyTask(taskId); } } From 3ee93c69ecf5349f88f4114a9548309621016bc8 Mon Sep 17 00:00:00 2001 From: surskitty Date: Thu, 10 Jul 2025 23:38:08 -0400 Subject: [PATCH 076/283] Preliminary handling for AI_FLAG_ASSUME_POWERFUL_STATUS, not actually yet called. --- docs/tutorials/ai_flags.md | 4 ++ include/battle_ai_util.h | 2 + include/config/ai.h | 5 ++ include/constants/battle_ai.h | 3 +- src/battle_ai_main.c | 11 +++++ src/battle_ai_util.c | 90 +++++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 7910049fbe..9f39090b65 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -147,6 +147,10 @@ AI has full knowledge of player moves, abilities, and hold items, and can use th ## `AI_FLAG_ASSUME_STAB` A significantly more restricted version of `AI_FLAG_OMNISCIENT`, the AI only knows the player's STAB moves, as their existence would be reasonable to assume in almost any case. +## `AI_FLAG_ASSUME_POWERFUL_STATUS` +A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know if the player has certain iconic status moves, plus also Fake Out and fixed percentage moves like Super Fang. + + ## `AI_FLAG_SMART_MON_CHOICES` Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled. diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b0ad69f5d9..1e03090dde 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -61,6 +61,8 @@ bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); bool32 IsAiBattlerAssumingStab(void); +bool32 IsAiBattlerAssumingPowerfulStatus(void); +bool32 ShouldRecordStatusMove(u32 move); void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordAllMoves(u32 battler); diff --git a/include/config/ai.h b/include/config/ai.h index 57fc7ecb60..be091649af 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -76,6 +76,11 @@ // AI_FLAG_ASSUME_STAB settings #define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience. +// AI_FLAG_ASSUME_POWERFUL_STATUS settings +#define ASSUME_POWERFUL_STATUS_HIGH_ODDS 95 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore +#define ASSUME_POWERFUL_STATUS_MEDIUM_ODDS 75 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect +#define ASSUME_POWERFUL_STATUS_LOW_ODDS 50 // Chance for AI to see niche moves a pokemon may have but probably won't, like Trick Room or Speed Swap + // AI_FLAG_SMART_SWITCHING settings #define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 4fc13aaa1b..fa2a96ee5d 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -34,8 +34,9 @@ #define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT #define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). #define AI_FLAG_ASSUME_STAB (1 << 28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ASSUME_POWERFUL_STATUS (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. -#define AI_FLAG_COUNT 29 +#define AI_FLAG_COUNT 30 // Flags at and after 32 need different formatting, as in // #define AI_FLAG_PLACEHOLDER ((u64)1 << 32) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 43d01dfa2e..a69edaa48f 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -544,6 +544,17 @@ void RecordMovesBasedOnStab(u32 battler) } } +void RecordPowerfulStatusMoves(u32 battler) +{ + u32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 playerMove = gBattleMons[battler].moves[i]; + if (ShouldRecordStatusMove(playerMove)) + RecordKnownMove(battler, playerMove); + } +} + void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) { u32 ability, holdEffect; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 48403d4e11..b6a208a9c7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -249,6 +249,96 @@ void SaveBattlerData(u32 battlerId) gAiThinkingStruct->saved[battlerId].types[1] = gBattleMons[battlerId].types[1]; } +bool32 ShouldRecordStatusMove(u32 move) +{ + u32 rand = Random() % 100; + + if (rand >= ASSUME_POWERFUL_STATUS_HIGH_ODDS) + return FALSE; + + switch (GetMoveEffect(move)) + { + // variable odds by additional effect + case EFFECT_NON_VOLATILE_STATUS: + if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP) + return TRUE; + else if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS) + return TRUE; + break; + // High odds + case EFFECT_AURORA_VEIL: + case EFFECT_CHILLY_RECEPTION: + case EFFECT_CONVERSION: + case EFFECT_FIRST_TURN_ONLY: + case EFFECT_FOLLOW_ME: + case EFFECT_INSTRUCT: + case EFFECT_JUNGLE_HEALING: + case EFFECT_REVIVAL_BLESSING: + case EFFECT_SHED_TAIL: + case EFFECT_STICKY_WEB: + return TRUE; + // Medium odds + case EFFECT_AFTER_YOU: + case EFFECT_DEFOG: + case EFFECT_ENCORE: + case EFFECT_HAZE: + case EFFECT_HEAL_BELL: + case EFFECT_HEALING_WISH: + case EFFECT_LIFE_DEW: + case EFFECT_MEMENTO: + case EFFECT_PARTING_SHOT: + case EFFECT_PROTECT: + case EFFECT_RESTORE_HP: + case EFFECT_ROAR: + case EFFECT_TAUNT: + case EFFECT_TAILWIND: + case EFFECT_TELEPORT: + case EFFECT_TRICK: + // defoggables / screens and hazards + case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: + case EFFECT_SPIKES: + case EFFECT_STEALTH_ROCK: + case EFFECT_TOXIC_SPIKES: + // field status + case EFFECT_HAIL: + case EFFECT_RAIN_DANCE: + case EFFECT_SANDSTORM: + case EFFECT_SNOWSCAPE: + case EFFECT_SUNNY_DAY: + case EFFECT_TRICK_ROOM: + case EFFECT_ELECTRIC_TERRAIN: + case EFFECT_GRASSY_TERRAIN: + case EFFECT_MISTY_TERRAIN: + case EFFECT_PSYCHIC_TERRAIN: + if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS) + return TRUE; + break; + // Low odds + case EFFECT_COURT_CHANGE: + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_FIXED_PERCENT_DAMAGE: + case EFFECT_GASTRO_ACID: + case EFFECT_GUARD_SPLIT: + case EFFECT_IMPRISON: + case EFFECT_PERISH_SONG: + case EFFECT_POWER_SPLIT: + case EFFECT_QUASH: + case EFFECT_ROLE_PLAY: + case EFFECT_SKILL_SWAP: + case EFFECT_SPEED_SWAP: + case EFFECT_WORRY_SEED: + if (rand < ASSUME_POWERFUL_STATUS_LOW_ODDS) + return TRUE; + break; + default: + break; + } + + return FALSE; +} + static bool32 ShouldFailForIllusion(u32 illusionSpecies, u32 battlerId) { u32 i, j; From 809379797e3e14a046a8a00309e421bc87f29ac8 Mon Sep 17 00:00:00 2001 From: Phantonomy <131238004+Ddaretrogamer@users.noreply.github.com> Date: Thu, 10 Jul 2025 22:43:43 -0500 Subject: [PATCH 077/283] Better Hydrapple Backsprite (Adapted from DegelAlex on deviantart (#7246) --- graphics/pokemon/hydrapple/back.png | Bin 786 -> 907 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/hydrapple/back.png b/graphics/pokemon/hydrapple/back.png index 19ffd6d199fec84043f0f1be9d8a933cbc9613f7..ec5f77cabe3b754655835fa4aae16c6f868992de 100644 GIT binary patch delta 837 zcmV-L1G@Z@28#!f7-Iwj00013M{Ml?000McNliru=?4lIFA~_!AWi@P02g#cSaefw zW^{L9a%BKVOhiylM<8}(av(DOV1ZP1_ zK>z@;j|==^1(7a3e*ghuOGiWihy@);00087Nkl=tqeC8svfC6_)#0vr4azBIU~m!a-E7si&yiF=AZc`&-)J-8Hxq?69xl7^#ovpVKoF)?J+x+e;=#6TcUQ?@Zm*%Jt*Qs zp69niBA(^>_3e-dlIP!oAra*7-6|LqL045ZJP8`AU`Pa3sU`Ux?T-7L(ou)4@g}cv<|{P04o4U4p8dF&pr)4 z9v~CNf$snqe*#HG6<29f^hsbig9^=3D%DXhP=dshiBjcas{+0W!r&gL7dQUK8LaWf z2oz>NRCTe!jV>TtpfQf}_|Mlaz`2N+K!EFrn}LUuP6@7c6R`pTEhNVAqcce#P1FsG z4Uh^uZ`m;`H702X$P(jRz&LvB13j=wro>VjKU59Sf20pGeb6>ZA|(X+fwM%x=3=>p ze}I}K=D2tfDvF!yK;cm(I0C368B0RF5r<$6Ks|J%EFcv#sYJzI2Ov;TGfHgGrP2}i z+CG>Aq_P0S_AdB%|9H~{D&c^josDj~0K~+VcpUCBcmnwK$pXZ*Y)aq!xN zfRaHHe^_8S5^z{N0(fQC0G$4U)Pl8+SrHha2*mbY`lyDeT1w|w7l7CTc>imBW3sJb z+L%rdcxzP(1Ca3EG1H#6H=TV(;2o1H!1rn9O&%O$Q0%?R=Ep|>ZzhmD2a~bx7>d|G z&$6r8@$}>ZlKs;b@Mvo}*7)%;bL&E?gD(IZS8tEO_corPhJ!h5zHS0X=j{R5W_C5% zdc5?+0rOKFd6vE0jFZ`H=1zDG$w8K#^#P8!c0004VQb$4nuFf3kk$XOW0+2~WK~z|U#g++f z#4rd&gM>N?vXlGYwtzRhr!%b@Rch7bKYy?RAIEP#z|V&Sbjo-i1dLz?o+sib2xP?d zV**RTBHkb%>j3UMBH$eloPqm3PyI`5WVZg=Cq@l0;kp*%(L(@afUeD2mU==V;el+-tqJ^N^|C2K5CjJyfOD5e z@!(uCKtvJYK`;#19*;=i^mFJeVgza&l1NU?)l2{XOMj7<5DzBMy!jh|6mrzNBuIq0-k#ztS3)Qg zO~hjO^Z;v=!nl;hVzqsk= z$u%O35w>>WD(UJ7!DNp>Q#d>|^eTcY#Lz&_l#Jki((qfvh)@i~(Zg!f@f(EihXLm9 znI{KdN6a!cqO+g_ChE)ls~aY)EI^7tE>s|hFg}_vD?$ed`Xe-)G(HvE>xu7nI@f7|5P#?uaSXr?8IbcDk3{YDPIfxkn yDg&J>zU(pL@C<<|5p}RUs4b$E)AC~SFV8nMEIw<{+}~FK0000 Date: Fri, 11 Jul 2025 00:31:47 -0400 Subject: [PATCH 078/283] I suspect the test is set up wrong, more than I have the logic wrong. Though that could also be true. --- include/random.h | 5 +++ src/battle_ai_main.c | 3 ++ src/battle_ai_util.c | 30 +++++++------- test/battle/ai/ai_assume_powerful_status.c | 48 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 test/battle/ai/ai_assume_powerful_status.c diff --git a/include/random.h b/include/random.h index f23ff2f184..df749312fd 100644 --- a/include/random.h +++ b/include/random.h @@ -202,6 +202,11 @@ enum RandomTag RNG_AI_BOOST_INTO_HAZE, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, + RNG_AI_ASSUME_POWERFUL_STATUS_SLEEP, + RNG_AI_ASSUME_POWERFUL_STATUS_NONVOLATILE, + RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS, + RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, + RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS, }; #define RandomWeighted(tag, ...) \ diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a69edaa48f..a14ebd4c1a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -570,6 +570,9 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) if (IsAiBattlerAssumingStab()) RecordMovesBasedOnStab(battler); + + if (IsAiBattlerAssumingPowerfulStatus()) + RecordPowerfulStatusMoves(battler); } #define BYPASSES_ACCURACY_CALC 101 // 101 indicates for ai that the move will always hit diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b6a208a9c7..f09fe2d132 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -141,6 +141,15 @@ bool32 IsAiBattlerAssumingStab() return FALSE; } +bool32 IsAiBattlerAssumingPowerfulStatus() +{ + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_POWERFUL_STATUS + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_POWERFUL_STATUS) + return TRUE; + + return FALSE; +} + bool32 IsAiBattlerPredictingAbility(u32 battlerId) { if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_WEIGH_ABILITY_PREDICTION @@ -251,18 +260,13 @@ void SaveBattlerData(u32 battlerId) bool32 ShouldRecordStatusMove(u32 move) { - u32 rand = Random() % 100; - - if (rand >= ASSUME_POWERFUL_STATUS_HIGH_ODDS) - return FALSE; - switch (GetMoveEffect(move)) { // variable odds by additional effect case EFFECT_NON_VOLATILE_STATUS: - if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP) + if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP && RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_SLEEP, ASSUME_POWERFUL_STATUS_HIGH_ODDS)) return TRUE; - else if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS) + else if (RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_NONVOLATILE, ASSUME_POWERFUL_STATUS_MEDIUM_ODDS)) return TRUE; break; // High odds @@ -276,7 +280,7 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_REVIVAL_BLESSING: case EFFECT_SHED_TAIL: case EFFECT_STICKY_WEB: - return TRUE; + return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS, ASSUME_POWERFUL_STATUS_HIGH_ODDS); // Medium odds case EFFECT_AFTER_YOU: case EFFECT_DEFOG: @@ -288,8 +292,10 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_MEMENTO: case EFFECT_PARTING_SHOT: case EFFECT_PROTECT: + case EFFECT_REST: case EFFECT_RESTORE_HP: case EFFECT_ROAR: + case EFFECT_SLEEP_TALK: case EFFECT_TAUNT: case EFFECT_TAILWIND: case EFFECT_TELEPORT: @@ -311,9 +317,7 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_GRASSY_TERRAIN: case EFFECT_MISTY_TERRAIN: case EFFECT_PSYCHIC_TERRAIN: - if (rand < ASSUME_POWERFUL_STATUS_MEDIUM_ODDS) - return TRUE; - break; + return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, ASSUME_POWERFUL_STATUS_MEDIUM_ODDS); // Low odds case EFFECT_COURT_CHANGE: case EFFECT_DOODLE: @@ -329,9 +333,7 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_SKILL_SWAP: case EFFECT_SPEED_SWAP: case EFFECT_WORRY_SEED: - if (rand < ASSUME_POWERFUL_STATUS_LOW_ODDS) - return TRUE; - break; + return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS, ASSUME_POWERFUL_STATUS_LOW_ODDS); default: break; } diff --git a/test/battle/ai/ai_assume_powerful_status.c b/test/battle/ai/ai_assume_powerful_status.c new file mode 100644 index 0000000000..7c1f08f352 --- /dev/null +++ b/test/battle/ai/ai_assume_powerful_status.c @@ -0,0 +1,48 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_POWERFUL_STATUS correctly records assumed status moves") +{ + PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_HIGH_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS); + PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS); + PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_LOW_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS); + + u32 aiFlag = 0; + PARAMETRIZE { aiFlag = AI_FLAG_ASSUME_POWERFUL_STATUS; } + PARAMETRIZE { aiFlag = 0; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiFlag); + PLAYER(SPECIES_TYPHLOSION) { Moves(MOVE_TACKLE, MOVE_COURT_CHANGE, MOVE_FAKE_OUT); } + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_HAIL, MOVE_SHED_TAIL, MOVE_THUNDERBOLT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(playerRight, MOVE_THUNDERBOLT, target:opponentRight); } + } THEN { + if (aiFlag == AI_FLAG_ASSUME_POWERFUL_STATUS) + { + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_COURT_CHANGE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_FAKE_OUT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); + + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_HAIL); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_SHED_TAIL); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); + } + else if (aiFlag == 0) + { + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); + + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); + } + } +} From c7b2c771e1dd2465fa8c744dbb9c3c85f2e5f89c Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 11 Jul 2025 03:43:14 -0400 Subject: [PATCH 079/283] Cotton down use jumpifabsent (#7318) Co-authored-by: ghoulslash --- data/battle_scripts_1.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 60432842f9..a4d3264d13 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6913,7 +6913,7 @@ BattleScript_CottonDownActivates:: swapattackerwithtarget setbyte gBattlerTarget, 0 BattleScript_CottonDownLoop: - jumpiffainted BS_TARGET, TRUE, BattleScript_CottonDownLoopIncrement + jumpifabsent BS_TARGET, BattleScript_CottonDownLoopIncrement setstatchanger STAT_SPEED, 1, TRUE jumpifbyteequal gBattlerTarget, gEffectBattler, BattleScript_CottonDownLoopIncrement statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_CottonDownLoopIncrement From d63f859db6d7a7c6b2a7a68e7f1e32db1dc6af99 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Fri, 11 Jul 2025 08:53:03 +0100 Subject: [PATCH 080/283] Multibattles Illusion party boundaries fix (#7308) --- include/battle_util.h | 2 +- src/battle_message.c | 2 +- src/battle_util.c | 26 ++++++++++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 57327176a8..ed67d21c3f 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -297,7 +297,7 @@ bool32 TryClearIllusion(u32 battler, u32 caseID); u32 GetIllusionMonSpecies(u32 battler); struct Pokemon *GetIllusionMonPtr(u32 battler); void ClearIllusionMon(u32 battler); -u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon); +u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler); bool32 SetIllusionMon(struct Pokemon *mon, u32 battler); bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler); u32 GetBattleMoveCategory(u32 move); diff --git a/src/battle_message.c b/src/battle_message.c index 78708d47d6..350cddd374 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3187,7 +3187,7 @@ static void IllusionNickHack(u32 battler, u32 partyId, u8 *dst) else partnerMon = mon; - id = GetIllusionMonPartyId(gEnemyParty, mon, partnerMon); + id = GetIllusionMonPartyId(gEnemyParty, mon, partnerMon, battler); } if (id != PARTY_SIZE) diff --git a/src/battle_util.c b/src/battle_util.c index 4f0ffcf962..a544d1484d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10373,11 +10373,29 @@ u32 GetIllusionMonSpecies(u32 battler) return SPECIES_NONE; } -u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon) +u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler) { - s32 id; + s32 partyEnd=6; + s32 partyStart=0; + + // Adjust party search range for Multibattles and Player vs two-trainers + if((GetBattlerSide(battler) == B_SIDE_PLAYER && (gBattleTypeFlags & BATTLE_TYPE_MULTI)) + || (GetBattlerSide(battler) == B_SIDE_OPPONENT && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) + { + if((GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) || (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT)) + { + partyEnd = 3; + partyStart = 0; + } + else + { + partyEnd = 6; + partyStart = 3; + } + } + // Find last alive non-egg pokemon. - for (id = PARTY_SIZE - 1; id >= 0; id--) + for (s32 id = partyEnd - 1; id >= partyStart; id--) { if (GetMonData(&party[id], MON_DATA_SANITY_HAS_SPECIES) && GetMonData(&party[id], MON_DATA_HP) @@ -10411,7 +10429,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler) else partnerMon = mon; - id = GetIllusionMonPartyId(party, mon, partnerMon); + id = GetIllusionMonPartyId(party, mon, partnerMon, battler); if (id != PARTY_SIZE) { gBattleStruct->illusion[battler].state = ILLUSION_ON; From 7d5a949b7106e6e02ac7b9061719186096495b26 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Fri, 11 Jul 2025 12:50:38 +0300 Subject: [PATCH 081/283] Bag refactor 2 (#7166) --- Makefile | 2 +- include/constants/item.h | 2 +- include/gba/defines.h | 1 + include/item.h | 36 ++- src/item.c | 675 +++++++++++++++++---------------------- src/item_menu.c | 17 +- src/item_menu_icons.c | 4 +- src/party_menu.c | 15 +- test/bag.c | 14 +- 9 files changed, 345 insertions(+), 421 deletions(-) diff --git a/Makefile b/Makefile index ebf7679af3..7456a9073b 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ ARMCC := $(PREFIX)gcc PATH_ARMCC := PATH="$(PATH)" $(ARMCC) CC1 := $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init +override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init -Wnonnull ifneq ($(LTO),0) ifneq ($(TEST),1) diff --git a/include/constants/item.h b/include/constants/item.h index a8266c7237..bd35bdb861 100644 --- a/include/constants/item.h +++ b/include/constants/item.h @@ -11,7 +11,7 @@ enum Pocket POCKETS_COUNT, }; -#define POCKET_NONE POCKETS_COUNT +#define POCKET_DUMMY POCKETS_COUNT #define REPEL_LURE_MASK (1 << 15) #define IS_LAST_USED_LURE(var) (var & REPEL_LURE_MASK) diff --git a/include/gba/defines.h b/include/gba/defines.h index 481f203052..674c5fdc14 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -26,6 +26,7 @@ #define ALIGNED(n) __attribute__((aligned(n))) #define PACKED __attribute__((packed)) #define TRANSPARENT __attribute__ ((__transparent_union__)) +#define NONNULL __attribute__((__nonnull__)) #define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) #define INTR_CHECK (*(u16 *)0x3007FF8) diff --git a/include/item.h b/include/item.h index b14d9bdf14..565784c85a 100644 --- a/include/item.h +++ b/include/item.h @@ -68,7 +68,8 @@ struct Item struct ALIGNED(2) BagPocket { struct ItemSlot *itemSlots; - u16 capacity; + u16 capacity:10; + enum Pocket id:6; }; struct TmHmIndexKey @@ -135,35 +136,42 @@ static inline u16 GetTMHMMoveId(enum TMHMIndex index) return gTMHMItemMoveIds[index].moveId; } +enum SortPocket +{ + SORT_NONE, + SORT_POCKET_BY_ITEM_ID, + SORT_POCKET_TM_HM, +}; + +void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity); u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos); u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos); -void SetBagItemQuantity(enum Pocket pocketId, u32 pocketPos, u16 newValue); void ApplyNewEncryptionKeyToBagItems(u32 newKey); void SetBagItemsPointers(void); u8 *CopyItemName(u16 itemId, u8 *dst); u8 *CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity); -bool8 IsBagPocketNonEmpty(enum Pocket pocketId); -bool8 CheckBagHasItem(u16 itemId, u16 count); -bool8 HasAtLeastOneBerry(void); -bool8 HasAtLeastOnePokeBall(void); -bool8 CheckBagHasSpace(u16 itemId, u16 count); +bool32 IsBagPocketNonEmpty(enum Pocket pocketId); +bool32 CheckBagHasItem(u16 itemId, u16 count); +bool32 HasAtLeastOneBerry(void); +bool32 HasAtLeastOnePokeBall(void); +bool32 CheckBagHasSpace(u16 itemId, u16 count); u32 GetFreeSpaceForItemInBag(u16 itemId); -bool8 AddBagItem(u16 itemId, u16 count); -bool8 RemoveBagItem(u16 itemId, u16 count); +bool32 AddBagItem(u16 itemId, u16 count); +bool32 RemoveBagItem(u16 itemId, u16 count); u8 CountUsedPCItemSlots(void); -bool8 CheckPCHasItem(u16 itemId, u16 count); -bool8 AddPCItem(u16 itemId, u16 count); +bool32 CheckPCHasItem(u16 itemId, u16 count); +bool32 AddPCItem(u16 itemId, u16 count); void RemovePCItem(u8 index, u16 count); void CompactPCItems(void); void SwapRegisteredBike(void); void CompactItemsInBagPocket(enum Pocket pocketId); -void SortBerriesOrTMHMs(enum Pocket pocketId); +void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket); void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to); void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to); void ClearBag(void); u16 CountTotalItemQuantityInBag(u16 itemId); -bool8 AddPyramidBagItem(u16 itemId, u16 count); -bool8 RemovePyramidBagItem(u16 itemId, u16 count); +bool32 AddPyramidBagItem(u16 itemId, u16 count); +bool32 RemovePyramidBagItem(u16 itemId, u16 count); const u8 *GetItemName(u16 itemId); u32 GetItemPrice(u16 itemId); const u8 *GetItemEffect(u32 itemId); diff --git a/src/item.c b/src/item.c index f0f9071c5a..45a3dfe421 100644 --- a/src/item.c +++ b/src/item.c @@ -21,10 +21,19 @@ #include "constants/item_effects.h" #include "constants/hold_effects.h" -static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); -static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count); +#define DUMMY_PC_BAG_POCKET \ +{ \ + .id = POCKET_DUMMY, \ + .capacity = PC_ITEMS_COUNT, \ + .itemSlots = gSaveBlock1Ptr->pcItems, \ +} + +static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count); +static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count); static const u8 *GetItemPluralName(u16); static bool32 DoesItemHavePluralName(u16); +static void BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); +static void BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; @@ -52,54 +61,71 @@ const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = #undef UNPACK_TM_ITEM_ID #undef UNPACK_HM_ITEM_ID -static inline u16 GetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos) -{ - return pocket->itemSlots[pocketPos].itemId; -} - -static inline u16 GetBagItemQuantityPocket(struct BagPocket *pocket, u32 pocketPos) -{ - return gSaveBlock2Ptr->encryptionKey ^ pocket->itemSlots[pocketPos].quantity; -} - -static inline void SetBagItemIdPocket(struct BagPocket *pocket, u32 pocketPos, u16 itemId) +static void (*const sBagPocket_GetSetSlotDataFuncs[])(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) = { - pocket->itemSlots[pocketPos].itemId = itemId; -} + [POCKET_ITEMS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_KEY_ITEMS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_POKE_BALLS] = BagPocket_GetSetSlotDataGeneric, + [POCKET_TM_HM] = BagPocket_GetSetSlotDataGeneric, + [POCKET_BERRIES] = BagPocket_GetSetSlotDataGeneric, + [POCKET_DUMMY] = BagPocket_GetSetSlotDataPC, +}; -static inline void SetBagItemQuantityPocket(struct BagPocket *pocket, u32 pocketPos, u16 newValue) +static void NONNULL BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) { - pocket->itemSlots[pocketPos].quantity = newValue ^ gSaveBlock2Ptr->encryptionKey; + if (isSetting) + { + pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero + pocket->itemSlots[pocketPos].quantity = *quantity ^ gSaveBlock2Ptr->encryptionKey; + } + else + { + *itemId = pocket->itemSlots[pocketPos].itemId; + *quantity = pocket->itemSlots[pocketPos].quantity ^ gSaveBlock2Ptr->encryptionKey; + } } -u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos) +static void NONNULL BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) { - return GetBagItemIdPocket(&gBagPockets[pocketId], pocketPos); + if (isSetting) + { + pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero + pocket->itemSlots[pocketPos].quantity = *quantity; + } + else + { + *itemId = pocket->itemSlots[pocketPos].itemId; + *quantity = pocket->itemSlots[pocketPos].quantity; + } } -u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos) +static inline void NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) { - return GetBagItemQuantityPocket(&gBagPockets[pocketId], pocketPos); + sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, FALSE); } -static void SetBagItemId(enum Pocket pocketId, u32 pocketPos, u16 itemId) +static inline void NONNULL BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) { - SetBagItemIdPocket(&gBagPockets[pocketId], pocketPos, itemId); + sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, TRUE); } -void SetBagItemQuantity(enum Pocket pocketId, u32 pocketPos, u16 newValue) +void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity) { - SetBagItemQuantityPocket(&gBagPockets[pocketId], pocketPos, newValue); + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, itemId, quantity); } -static u16 GetPCItemQuantity(u16 *quantity) +u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos) { - return *quantity; + u16 itemId, quantity; + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); + return itemId; } -static void SetPCItemQuantity(u16 *quantity, u16 newValue) +u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos) { - *quantity = newValue; + u16 itemId, quantity; + BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); + return quantity; } void ApplyNewEncryptionKeyToBagItems(u32 newKey) @@ -117,18 +143,23 @@ void SetBagItemsPointers(void) { gBagPockets[POCKET_ITEMS].itemSlots = gSaveBlock1Ptr->bag.items; gBagPockets[POCKET_ITEMS].capacity = BAG_ITEMS_COUNT; + gBagPockets[POCKET_ITEMS].id = POCKET_ITEMS; gBagPockets[POCKET_KEY_ITEMS].itemSlots = gSaveBlock1Ptr->bag.keyItems; gBagPockets[POCKET_KEY_ITEMS].capacity = BAG_KEYITEMS_COUNT; + gBagPockets[POCKET_KEY_ITEMS].id = POCKET_KEY_ITEMS; gBagPockets[POCKET_POKE_BALLS].itemSlots = gSaveBlock1Ptr->bag.pokeBalls; gBagPockets[POCKET_POKE_BALLS].capacity = BAG_POKEBALLS_COUNT; + gBagPockets[POCKET_POKE_BALLS].id = POCKET_POKE_BALLS; gBagPockets[POCKET_TM_HM].itemSlots = gSaveBlock1Ptr->bag.TMsHMs; gBagPockets[POCKET_TM_HM].capacity = BAG_TMHM_COUNT; + gBagPockets[POCKET_TM_HM].id = POCKET_TM_HM; gBagPockets[POCKET_BERRIES].itemSlots = gSaveBlock1Ptr->bag.berries; gBagPockets[POCKET_BERRIES].capacity = BAG_BERRIES_COUNT; + gBagPockets[POCKET_BERRIES].id = POCKET_BERRIES; } u8 *CopyItemName(u16 itemId, u8 *dst) @@ -155,68 +186,56 @@ u8 *CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity) } } -bool8 IsBagPocketNonEmpty(enum Pocket pocketId) +bool32 IsBagPocketNonEmpty(enum Pocket pocketId) { u8 i; for (i = 0; i < gBagPockets[pocketId].capacity; i++) { - if (GetBagItemId(pocketId, i) != 0) + if (GetBagItemId(pocketId, i) != ITEM_NONE) return TRUE; } return FALSE; } -bool8 CheckBagHasItem(u16 itemId, u16 count) +static bool32 NONNULL BagPocket_CheckHasItem(struct BagPocket *pocket, u16 itemId, u16 count) { - u8 i; - enum Pocket pocketId; + u16 tempItemId, tempQuantity; - if (GetItemPocket(itemId) >= POCKETS_COUNT) - return FALSE; - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) - return CheckPyramidBagHasItem(itemId, count); - pocketId = GetItemPocket(itemId); // Check for item slots that contain the item - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (u32 i = 0; i < pocket->capacity && count > 0; i++) { - if (GetBagItemId(pocketId, i) == itemId) - { - u16 quantity; - // Does this item slot contain enough of the item? - quantity = GetBagItemQuantity(pocketId, i); - if (quantity >= count) - return TRUE; - count -= quantity; - // Does this item slot and all previous slots contain enough of the item? - if (count == 0) - return TRUE; - } + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId) + count -= min(count, tempQuantity); } - return FALSE; + + return count == 0; } -bool8 HasAtLeastOneBerry(void) +bool32 CheckBagHasItem(u16 itemId, u16 count) { - u16 i; + if (GetItemPocket(itemId) >= POCKETS_COUNT) + return FALSE; + if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + return CheckPyramidBagHasItem(itemId, count); - for (i = FIRST_BERRY_INDEX; i <= LAST_BERRY_INDEX; i++) - { - if (CheckBagHasItem(i, 1) == TRUE) - { - gSpecialVar_Result = TRUE; - return TRUE; - } - } - gSpecialVar_Result = FALSE; - return FALSE; + return BagPocket_CheckHasItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } -bool8 HasAtLeastOnePokeBall(void) +bool32 HasAtLeastOneBerry(void) { - u16 ballId; + gSpecialVar_Result = FALSE; - for (ballId = BALL_STRANGE; ballId < POKEBALL_COUNT; ballId++) + for (u32 i = FIRST_BERRY_INDEX; i <= LAST_BERRY_INDEX && gSpecialVar_Result == FALSE; i++) + gSpecialVar_Result = CheckBagHasItem(i, 1); + + return gSpecialVar_Result; +} + +bool32 HasAtLeastOnePokeBall(void) +{ + for (u32 ballId = BALL_STRANGE; ballId < POKEBALL_COUNT; ballId++) { if (CheckBagHasItem(ballId, 1) == TRUE) return TRUE; @@ -224,7 +243,7 @@ bool8 HasAtLeastOnePokeBall(void) return FALSE; } -bool8 CheckBagHasSpace(u16 itemId, u16 count) +bool32 CheckBagHasSpace(u16 itemId, u16 count) { if (GetItemPocket(itemId) >= POCKETS_COUNT) return FALSE; @@ -235,335 +254,250 @@ bool8 CheckBagHasSpace(u16 itemId, u16 count) return GetFreeSpaceForItemInBag(itemId) >= count; } -u32 GetFreeSpaceForItemInBag(u16 itemId) +static u32 NONNULL BagPocket_GetFreeSpaceForItem(struct BagPocket *pocket, u16 itemId) { - u8 i; - enum Pocket pocketId = GetItemPocket(itemId); - u16 ownedCount; u32 spaceForItem = 0; - - if (GetItemPocket(itemId) >= POCKETS_COUNT) - return 0; + u16 tempItemId, tempQuantity; // Check space in any existing item slots that already contain this item - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - - if (GetBagItemId(pocketId, i) == itemId) - { - ownedCount = GetBagItemQuantity(pocketId, i); - spaceForItem += max(0, MAX_BAG_ITEM_CAPACITY - ownedCount); - } - else if (GetBagItemId(pocketId, i) == ITEM_NONE) - { - spaceForItem += MAX_BAG_ITEM_CAPACITY; - } + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == ITEM_NONE || tempItemId == itemId) + spaceForItem += (tempItemId ? (MAX_BAG_ITEM_CAPACITY - tempQuantity) : MAX_BAG_ITEM_CAPACITY); } + return spaceForItem; } -static inline u32 PrepareTempPocket(struct BagPocket *tempPocket, enum Pocket pocketId) +u32 GetFreeSpaceForItemInBag(u16 itemId) { - u32 size = gBagPockets[pocketId].capacity * sizeof(struct ItemSlot); - tempPocket->itemSlots = AllocZeroed(size); - tempPocket->capacity = gBagPockets[pocketId].capacity; - memcpy(tempPocket->itemSlots, gBagPockets[pocketId].itemSlots, size); + if (GetItemPocket(itemId) >= POCKETS_COUNT) + return 0; - return size; + return BagPocket_GetFreeSpaceForItem(&gBagPockets[GetItemPocket(itemId)], itemId); } -static inline void ClearTempPocket(struct BagPocket *pocket) +static inline bool32 NONNULL CheckSlotAndUpdateCount(struct BagPocket *pocket, u16 itemId, u32 pocketPos, u32 *nextPocketPos, u16 *count, u16 *tempPocketSlotQuantities) { - Free(pocket->itemSlots); - Free(pocket); -} + u16 tempItemId, tempQuantity; + BagPocket_GetSlotData(pocket, pocketPos, &tempItemId, &tempQuantity); + if (tempItemId == ITEM_NONE || tempItemId == itemId) + { + // The quantity already at the slot - zero if an empty slot + if (!tempItemId) + tempQuantity = 0; -static inline void RestorePocketAndClearTempPocket(struct BagPocket *tempPocket, enum Pocket pocketId, u32 pocketSize) -{ - memcpy(gBagPockets[pocketId].itemSlots, tempPocket->itemSlots, pocketSize); - ClearTempPocket(tempPocket); + // Record slot quantity in tempPocketSlotQuantities, adjust count + tempPocketSlotQuantities[pocketPos] = min(MAX_BAG_ITEM_CAPACITY, *count + tempQuantity); + *count -= min(*count, MAX_BAG_ITEM_CAPACITY - tempQuantity); + + // Set the starting index for the next loop to set items (shifted by one) + if (!*nextPocketPos) + *nextPocketPos = pocketPos + 1; + + return TRUE; + } + + return FALSE; } -bool8 AddBagItem(u16 itemId, u16 count) +static bool32 NONNULL BagPocket_AddItem(struct BagPocket *pocket, u16 itemId, u16 count) { - u8 i; + u32 itemLookupIndex, itemAddIndex = 0; - if (GetItemPocket(itemId) >= POCKETS_COUNT) - return FALSE; + // First, check that there is a free slot for this item + u16 *tempPocketSlotQuantities = AllocZeroed(sizeof(u16) * pocket->capacity); - // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + switch (pocket->id) { - return AddPyramidBagItem(itemId, count); - } - else - { - u16 ownedCount; - enum Pocket pocketId = GetItemPocket(itemId); - struct BagPocket *tempPocket = AllocZeroed(sizeof(struct BagPocket)); - u32 pocketSize = PrepareTempPocket(tempPocket, pocketId); - - for (i = 0; i < gBagPockets[pocketId].capacity; i++) - { - if (GetBagItemIdPocket(tempPocket, i) == itemId) + case POCKET_TM_HM: + case POCKET_BERRIES: + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && count > 0; itemLookupIndex++) { - ownedCount = GetBagItemQuantityPocket(tempPocket, i); - // check if won't exceed max slot capacity - if (ownedCount + count <= MAX_BAG_ITEM_CAPACITY) - { - // successfully added to already existing item's count - SetBagItemQuantityPocket(tempPocket, i, ownedCount + count); - RestorePocketAndClearTempPocket(tempPocket, pocketId, pocketSize); - return TRUE; - } - else + // Check if we found a slot to store the item but weren't able to reduce count to 0 + // This means that we have more than one stack's worth, which isn't allowed in these pockets + if (CheckSlotAndUpdateCount(pocket, itemId, itemLookupIndex, &itemAddIndex, &count, tempPocketSlotQuantities) && count > 0) { - // try creating another instance of the item if possible - if (pocketId == POCKET_TM_HM || pocketId == POCKET_BERRIES) - { - ClearTempPocket(tempPocket); - return FALSE; - } - else - { - count -= MAX_BAG_ITEM_CAPACITY - ownedCount; - SetBagItemQuantityPocket(tempPocket, i, MAX_BAG_ITEM_CAPACITY); - // don't create another instance of the item if it's at max slot capacity and count is equal to 0 - if (count == 0) - { - break; - } - } + Free(tempPocketSlotQuantities); + return FALSE; } } - } + break; + default: + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && count > 0; itemLookupIndex++) + CheckSlotAndUpdateCount(pocket, itemId, itemLookupIndex, &itemAddIndex, &count, tempPocketSlotQuantities); + } - // we're done if quantity is equal to 0 - if (count > 0) + // If the count is still greater than zero, clearly we have not found enough slots for this... + // Otherwise, we have found slots - update the actual pockets with the updated quantities + if (count == 0) + { + for (--itemAddIndex; itemAddIndex < itemLookupIndex; itemAddIndex++) { - // either no existing item was found or we have to create another instance, because the capacity was exceeded - for (i = 0; i < gBagPockets[pocketId].capacity; i++) - { - if (GetBagItemIdPocket(tempPocket, i) == ITEM_NONE) - { - SetBagItemIdPocket(tempPocket, i, itemId); - if (count > MAX_BAG_ITEM_CAPACITY) - { - // try creating a new slot with max capacity if duplicates are possible - if (pocketId == POCKET_TM_HM || pocketId == POCKET_BERRIES) - { - ClearTempPocket(tempPocket); - return FALSE; - } - count -= MAX_BAG_ITEM_CAPACITY; - SetBagItemQuantityPocket(tempPocket, i, MAX_BAG_ITEM_CAPACITY); - } - else - { - // created a new slot and added quantity - SetBagItemQuantityPocket(tempPocket, i, count); - count = 0; - break; - } - } - } - - if (count > 0) - { - ClearTempPocket(tempPocket); - return FALSE; - } + if (tempPocketSlotQuantities[itemAddIndex] > 0) + BagPocket_SetSlotData(pocket, itemAddIndex, &itemId, &tempPocketSlotQuantities[itemAddIndex]); } - RestorePocketAndClearTempPocket(tempPocket, pocketId, pocketSize); - return TRUE; } + + Free(tempPocketSlotQuantities); + return count == 0; } -bool8 RemoveBagItem(u16 itemId, u16 count) +bool32 AddBagItem(u16 itemId, u16 count) { - u8 i; - u16 totalQuantity = 0; - - if (GetItemPocket(itemId) >= POCKETS_COUNT || itemId == ITEM_NONE) + if (GetItemPocket(itemId) >= POCKETS_COUNT) return FALSE; // check Battle Pyramid Bag if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) - { - return RemovePyramidBagItem(itemId, count); - } - else - { - u16 ownedCount, firstStackIndex = 0; - enum Pocket pocketId = GetItemPocket(itemId); + return AddPyramidBagItem(itemId, count); + + return BagPocket_AddItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); +} + +static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, u16 itemId, u16 count) +{ + u32 itemLookupIndex, itemRemoveIndex = 0, totalQuantity = 0; + u16 tempItemId, tempQuantity; + u16 *tempPocketSlotQuantities = AllocZeroed(sizeof(u16) * pocket->capacity); - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && totalQuantity < count; itemLookupIndex++) + { + BagPocket_GetSlotData(pocket, itemLookupIndex, &tempItemId, &tempQuantity); + if (tempItemId == itemId) { - if (GetBagItemId(pocketId, i) == itemId) - { - if (totalQuantity == 0) - firstStackIndex = i; - totalQuantity += GetBagItemQuantity(pocketId, i); - } - } + // Index for the next loop - where we should start removing items + if (!itemRemoveIndex) + itemRemoveIndex = itemLookupIndex + 1; - if (totalQuantity < count) - return FALSE; // We don't have enough of the item + // Gather quantities (+ 1 to tempPocketSlotQuantities so that even if setting to 0 we know which indices to target) + totalQuantity += tempQuantity; + tempPocketSlotQuantities[itemLookupIndex] = (tempQuantity <= count ? 0 : tempQuantity - count) + 1; + } + } + if (totalQuantity >= count) // We have enough of the item + { if (CurMapIsSecretBase() == TRUE) { VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_BAG); VarSet(VAR_SECRET_BASE_LAST_ITEM_USED, itemId); } - for (i = firstStackIndex; i < gBagPockets[pocketId].capacity; i++) + // Update the quantities correctly with the items removed + for (--itemRemoveIndex; itemRemoveIndex < itemLookupIndex; itemRemoveIndex++) { - if (GetBagItemId(pocketId, i) == itemId) + if (tempPocketSlotQuantities[itemRemoveIndex] > 0) { - ownedCount = GetBagItemQuantity(pocketId, i); - if (ownedCount >= count) - { - SetBagItemQuantity(pocketId, i, ownedCount - count); - count = 0; - } - else - { - count -= ownedCount; - SetBagItemQuantity(pocketId, i, 0); - } - - if (GetBagItemQuantity(pocketId, i) == 0) - SetBagItemId(pocketId, i, ITEM_NONE); - - if (count == 0) - return TRUE; + tempPocketSlotQuantities[itemRemoveIndex]--; // Reverse the +1 shift + BagPocket_SetSlotData(pocket, itemRemoveIndex, &itemId, &tempPocketSlotQuantities[itemRemoveIndex]); } } - return TRUE; } + + Free(tempPocketSlotQuantities); + return totalQuantity >= count; } -static s32 FindFreePCItemSlot(void) +bool32 RemoveBagItem(u16 itemId, u16 count) { - s8 i; + if (GetItemPocket(itemId) >= POCKETS_COUNT || itemId == ITEM_NONE) + return FALSE; - for (i = 0; i < PC_ITEMS_COUNT; i++) - { - if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE) - return i; - } - return -1; + // check Battle Pyramid Bag + if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + return RemovePyramidBagItem(itemId, count); + + return BagPocket_RemoveItem(&gBagPockets[GetItemPocket(itemId)], itemId, count); } -u8 CountUsedPCItemSlots(void) +static u8 NONNULL BagPocket_CountUsedItemSlots(struct BagPocket *pocket) { u8 usedSlots = 0; - u8 i; + u16 tempItemId, tempQuantity; - for (i = 0; i < PC_ITEMS_COUNT; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - if (gSaveBlock1Ptr->pcItems[i].itemId != ITEM_NONE) + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId) usedSlots++; } return usedSlots; } -bool8 CheckPCHasItem(u16 itemId, u16 count) +u8 CountUsedPCItemSlots(void) { - u8 i; + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_CountUsedItemSlots(&dummyPocket); +} - for (i = 0; i < PC_ITEMS_COUNT; i++) +static bool32 NONNULL BagPocket_CheckPocketForItemCount(struct BagPocket *pocket, u16 itemId, u16 count) +{ + u16 tempItemId, tempQuantity; + + for (u32 i = 0; i < pocket->capacity; i++) { - if (gSaveBlock1Ptr->pcItems[i].itemId == itemId && GetPCItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity) >= count) + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId && tempQuantity >= count) return TRUE; } return FALSE; } -bool8 AddPCItem(u16 itemId, u16 count) +bool32 CheckPCHasItem(u16 itemId, u16 count) { - u8 i; - s8 freeSlot; - u16 ownedCount; - struct ItemSlot *newItems; - - // Copy PC items - newItems = AllocZeroed(sizeof(gSaveBlock1Ptr->pcItems)); - memcpy(newItems, gSaveBlock1Ptr->pcItems, sizeof(gSaveBlock1Ptr->pcItems)); + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_CheckPocketForItemCount(&dummyPocket, itemId, count); +} - // Use any item slots that already contain this item - for (i = 0; i < PC_ITEMS_COUNT; i++) - { - if (newItems[i].itemId == itemId) - { - ownedCount = GetPCItemQuantity(&newItems[i].quantity); - if (ownedCount + count <= MAX_PC_ITEM_CAPACITY) - { - SetPCItemQuantity(&newItems[i].quantity, ownedCount + count); - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; - } - count += ownedCount - MAX_PC_ITEM_CAPACITY; - SetPCItemQuantity(&newItems[i].quantity, MAX_PC_ITEM_CAPACITY); - if (count == 0) - { - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; - } - } - } +bool32 AddPCItem(u16 itemId, u16 count) +{ + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_AddItem(&dummyPocket, itemId, count); +} - // Put any remaining items into a new item slot. - if (count > 0) +static void NONNULL BagPocket_CompactItems(struct BagPocket *pocket) +{ + u16 itemId, quantity, zero = 0, slotCursor = 0; + for (u32 i = 0; i < pocket->capacity; i++) { - freeSlot = FindFreePCItemSlot(); - if (freeSlot == -1) + BagPocket_GetSlotData(pocket, i, &itemId, &quantity); + if (itemId == ITEM_NONE) { - Free(newItems); - return FALSE; + if (!slotCursor) + slotCursor = i + 1; } - else + else if (slotCursor > 0) { - newItems[freeSlot].itemId = itemId; - SetPCItemQuantity(&newItems[freeSlot].quantity, count); + BagPocket_SetSlotData(pocket, slotCursor - 1, &itemId, &quantity); + BagPocket_SetSlotData(pocket, i, &zero, &zero); + slotCursor++; } } - - // Copy items back to the PC - memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); - Free(newItems); - return TRUE; } void RemovePCItem(u8 index, u16 count) { - gSaveBlock1Ptr->pcItems[index].quantity -= count; - if (gSaveBlock1Ptr->pcItems[index].quantity == 0) - { - gSaveBlock1Ptr->pcItems[index].itemId = ITEM_NONE; - CompactPCItems(); - } + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + + // Get id, quantity at slot + u16 tempItemId, tempQuantity; + BagPocket_GetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + + // Remove quantity + tempQuantity -= count; + BagPocket_SetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + + // Compact if necessary + if (tempQuantity == 0) + BagPocket_CompactItems(&dummyPocket); } void CompactPCItems(void) { - u16 i; - u16 j; - - for (i = 0; i < PC_ITEMS_COUNT - 1; i++) - { - for (j = i + 1; j < PC_ITEMS_COUNT; j++) - { - if (gSaveBlock1Ptr->pcItems[i].itemId == 0) - { - struct ItemSlot temp = gSaveBlock1Ptr->pcItems[i]; - gSaveBlock1Ptr->pcItems[i] = gSaveBlock1Ptr->pcItems[j]; - gSaveBlock1Ptr->pcItems[j] = temp; - } - } - } + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + BagPocket_CompactItems(&dummyPocket); } void SwapRegisteredBike(void) @@ -579,101 +513,80 @@ void SwapRegisteredBike(void) } } -static void SwapItemSlots(enum Pocket pocketId, u32 pocketPosA, u16 pocketPosB) +void CompactItemsInBagPocket(enum Pocket pocketId) { - struct ItemSlot *itemA = &gBagPockets[pocketId].itemSlots[pocketPosA], - *itemB = &gBagPockets[pocketId].itemSlots[pocketPosB], - temp; - SWAP(*itemA, *itemB, temp); + BagPocket_CompactItems(&gBagPockets[pocketId]); } -void CompactItemsInBagPocket(enum Pocket pocketId) +// Opens the possibility of sorting by other means e.g. ghoulslash's advanced sorting +static inline bool32 ItemIndexCompare(u16 itemA, u16 itemB, enum SortPocket sortPocket) { - u16 i, j; - - for (i = 0; i < gBagPockets[pocketId].capacity - 1; i++) + switch (sortPocket) { - for (j = i + 1; j < gBagPockets[pocketId].capacity; j++) - { - if (GetBagItemQuantity(pocketId, i) == 0) - SwapItemSlots(pocketId, i, j); - } + case SORT_POCKET_BY_ITEM_ID: + return itemA > itemB; + case SORT_POCKET_TM_HM: + return GetItemTMHMIndex(itemA) > GetItemTMHMIndex(itemB); + default: + return FALSE; } } -void SortBerriesOrTMHMs(enum Pocket pocketId) +void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket) { - u16 i, j; + u16 itemId_i, quantity_i, itemId_j, quantity_j; + struct BagPocket *pocket = &gBagPockets[pocketId]; - for (i = 0; i < gBagPockets[pocketId].capacity - 1; i++) + for (u32 i = 0; i < pocket->capacity - 1; i++) { - for (j = i + 1; j < gBagPockets[pocketId].capacity; j++) + BagPocket_GetSlotData(pocket, i, &itemId_i, &quantity_i); + for (u32 j = i + 1; j < pocket->capacity; j++) { - if (GetBagItemQuantity(pocketId, i) != 0 || GetBagItemId(pocketId, i) != ITEM_NONE) + BagPocket_GetSlotData(pocket, j, &itemId_j, &quantity_j); + if (itemId_j && (!itemId_i || ItemIndexCompare(itemId_i, itemId_j, sortPocket))) { - if (GetBagItemQuantity(pocketId, j) == 0 || GetBagItemId(pocketId, j) == ITEM_NONE) - continue; - if (pocketId == POCKET_BERRIES && GetBagItemId(pocketId, i) <= GetBagItemId(pocketId, j)) // To do - continue; - if (pocketId == POCKET_TM_HM && GetItemTMHMIndex(GetBagItemId(pocketId, i)) <= GetItemTMHMIndex(GetBagItemId(pocketId, j))) - continue; + BagPocket_SetSlotData(pocket, i, &itemId_j, &quantity_j); + BagPocket_SetSlotData(pocket, j, &itemId_i, &quantity_i); + itemId_i = itemId_j; + quantity_i = quantity_j; } - SwapItemSlots(pocketId, i, j); } } } -void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to) +static inline void NONNULL BagPocket_MoveItemSlot(struct BagPocket *pocket, u32 from, u32 to) { if (from != to) { - u32 i; - s8 shift = -1; - struct BagPocket *pocket = &gBagPockets[pocketId]; + s8 shift = (to > from) ? 1 : -1; + if (to > from) + to--; // Record the values at "from" - u16 fromItemId = GetBagItemIdPocket(pocket, from), - fromQuantity = GetBagItemQuantityPocket(pocket, from); + u16 fromItemId, fromQuantity, tempItemId, tempQuantity; + BagPocket_GetSlotData(pocket, from, &fromItemId, &fromQuantity); // Shuffle items between "to" and "from" - if (to > from) + for (u32 i = from; i == to - shift; i += shift) { - to--; - shift = 1; - } - - for (i = from; i == to - shift; i += shift) - { - SetBagItemIdPocket(pocket, i, GetBagItemIdPocket(pocket, i + shift)); - SetBagItemQuantityPocket(pocket, i, GetBagItemQuantityPocket(pocket, i + shift)); + BagPocket_GetSlotData(pocket, i + shift, &tempItemId, &tempQuantity); + BagPocket_SetSlotData(pocket, i, &tempItemId, &tempQuantity); } // Move the saved "from" to "to" - SetBagItemIdPocket(pocket, to, fromItemId); - SetBagItemQuantityPocket(pocket, to, fromQuantity); + BagPocket_SetSlotData(pocket, to, &fromItemId, &fromQuantity); } } -void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to) +void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to) { - if (from != to) - { - s16 i, count; - struct ItemSlot firstSlot = itemSlots[from]; + BagPocket_MoveItemSlot(&gBagPockets[pocketId], from, to); +} - if (to > from) - { - to--; - for (i = from, count = to; i < count; i++) - itemSlots[i] = itemSlots[i + 1]; - } - else - { - for (i = from, count = to; i > count; i--) - itemSlots[i] = itemSlots[i - 1]; - } - itemSlots[to] = firstSlot; - } +void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to) +{ + struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; + return BagPocket_MoveItemSlot(&dummyPocket, from, to); } void ClearBag(void) @@ -681,22 +594,26 @@ void ClearBag(void) CpuFastFill(0, &gSaveBlock1Ptr->bag, sizeof(struct Bag)); } -u16 CountTotalItemQuantityInBag(u16 itemId) +static inline u16 NONNULL BagPocket_CountTotalItemQuantity(struct BagPocket *pocket, u16 itemId) { - u16 i; - u16 ownedCount = 0; - enum Pocket pocketId = GetItemPocket(itemId); + u16 tempItemId, tempQuantity, ownedCount = 0; - for (i = 0; i < gBagPockets[pocketId].capacity; i++) + for (u32 i = 0; i < pocket->capacity; i++) { - if (GetBagItemId(pocketId, i) == itemId) - ownedCount += GetBagItemQuantity(pocketId, i); + BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); + if (tempItemId == itemId) + ownedCount += tempQuantity; } return ownedCount; } -static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count) +u16 CountTotalItemQuantityInBag(u16 itemId) +{ + return BagPocket_CountTotalItemQuantity(&gBagPockets[GetItemPocket(itemId)], itemId); +} + +static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count) { u8 i; u16 *items = gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode]; @@ -722,7 +639,7 @@ static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count) return FALSE; } -static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count) +static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count) { u8 i; u16 *items = gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode]; @@ -748,7 +665,7 @@ static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count) return FALSE; } -bool8 AddPyramidBagItem(u16 itemId, u16 count) +bool32 AddPyramidBagItem(u16 itemId, u16 count) { u16 i; @@ -826,7 +743,7 @@ bool8 AddPyramidBagItem(u16 itemId, u16 count) } } -bool8 RemovePyramidBagItem(u16 itemId, u16 count) +bool32 RemovePyramidBagItem(u16 itemId, u16 count) { u16 i; diff --git a/src/item_menu.c b/src/item_menu.c index 647b99eb2d..d6e3598b58 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -964,12 +964,11 @@ static void BagMenu_MoveCursorCallback(s32 itemIndex, bool8 onInit, struct ListM static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) { - u16 itemId; - u16 itemQuantity; - int offset; - if (itemIndex != LIST_CANCEL) { + u16 itemId, itemQuantity; + s32 offset; + if (gBagMenu->toSwapPos != NOT_SWAPPING) { // Swapping items, draw cursor at original item's location @@ -979,8 +978,7 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) BagMenu_PrintCursorAtPos(y, COLORID_NONE); } - itemId = GetBagItemId(gBagPosition.pocket, itemIndex); - itemQuantity = GetBagItemQuantity(gBagPosition.pocket, itemIndex); + GetBagItemIdAndQuantity(gBagPosition.pocket, itemIndex, &itemId, &itemQuantity); // Draw HM icon if (gBagPosition.pocket == POCKET_TM_HM && GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) @@ -1133,8 +1131,10 @@ void UpdatePocketItemList(u8 pocketId) switch (pocketId) { case POCKET_TM_HM: + SortPocket(pocketId, SORT_POCKET_TM_HM); + break; case POCKET_BERRIES: - SortBerriesOrTMHMs(pocketId); + SortPocket(pocketId, SORT_POCKET_BY_ITEM_ID); break; default: CompactItemsInBagPocket(pocketId); @@ -1287,8 +1287,7 @@ static void Task_BagMenu_HandleInput(u8 taskId) BagDestroyPocketScrollArrowPair(); BagMenu_PrintCursor(tListTaskId, COLORID_GRAY_CURSOR); tListPosition = listPosition; - tQuantity = GetBagItemQuantity(gBagPosition.pocket, listPosition); - gSpecialVar_ItemId = GetBagItemId(gBagPosition.pocket, listPosition); + GetBagItemIdAndQuantity(gBagPosition.pocket, listPosition, &gSpecialVar_ItemId, (u16*)&tQuantity); sContextMenuFuncs[gBagPosition.location](taskId); break; } diff --git a/src/item_menu_icons.c b/src/item_menu_icons.c index 61413ebeca..fa769b160f 100644 --- a/src/item_menu_icons.c +++ b/src/item_menu_icons.c @@ -101,7 +101,7 @@ static const union AnimCmd *const sBagSpriteAnimTable[] = [POCKET_TM_HM] = sSpriteAnim_Bag_TMsHMs, [POCKET_BERRIES] = sSpriteAnim_Bag_Berries, [POCKET_KEY_ITEMS] = sSpriteAnim_Bag_KeyItems, - [POCKET_NONE] = sSpriteAnim_Bag_Closed, + [POCKET_DUMMY] = sSpriteAnim_Bag_Closed, }; static const union AffineAnimCmd sSpriteAffineAnim_BagNormal[] = @@ -474,7 +474,7 @@ void SetBagVisualPocketId(u8 bagPocketId, bool8 isSwitchingPockets) sprite->y2 = -5; sprite->callback = SpriteCB_BagVisualSwitchingPockets; sprite->sPocketId = bagPocketId; - StartSpriteAnim(sprite, POCKET_NONE); + StartSpriteAnim(sprite, POCKET_DUMMY); } else { diff --git a/src/party_menu.c b/src/party_menu.c index 16ea3522d7..18b577567f 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -426,7 +426,6 @@ static void Task_SacredAshDisplayHPRestored(u8); static void GiveItemOrMailToSelectedMon(u8); static void DisplayItemMustBeRemovedFirstMessage(u8); static void Task_SwitchItemsFromBagYesNo(u8); -static void RemoveItemToGiveFromBag(u16); static void CB2_WriteMailToGiveMonFromBag(void); static void GiveItemToSelectedMon(u8); static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8); @@ -6850,7 +6849,7 @@ static void GiveItemOrMailToSelectedMon(u8 taskId) { if (ItemIsMail(gPartyMenu.bagItem)) { - RemoveItemToGiveFromBag(gPartyMenu.bagItem); + RemoveBagItem(gPartyMenu.bagItem, 1); sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag; Task_ClosePartyMenu(taskId); } @@ -6869,7 +6868,7 @@ static void GiveItemToSelectedMon(u8 taskId) item = gPartyMenu.bagItem; DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 1); GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item); - RemoveItemToGiveFromBag(item); + RemoveBagItem(item, 1); gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu; } } @@ -6948,7 +6947,7 @@ static void Task_HandleSwitchItemsFromBagYesNoInput(u8 taskId) { case 0: // Yes, switch items item = gPartyMenu.bagItem; - RemoveItemToGiveFromBag(item); + RemoveBagItem(item, 1); if (AddBagItem(sPartyMenuItemId, 1) == FALSE) { ReturnGiveItemToBagOrPC(item); @@ -6984,14 +6983,6 @@ static void DisplayItemMustBeRemovedFirstMessage(u8 taskId) gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu; } -static void RemoveItemToGiveFromBag(u16 item) -{ - if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM) // Unused, never occurs - RemovePCItem(item, 1); - else - RemoveBagItem(item, 1); -} - // Returns FALSE if there was no space to return the item // but there always should be, and the return is ignored in all uses static bool8 ReturnGiveItemToBagOrPC(u16 item) diff --git a/test/bag.c b/test/bag.c index a3fb0318dd..6d0620dd6e 100644 --- a/test/bag.c +++ b/test/bag.c @@ -30,7 +30,7 @@ TEST("TMs and HMs are sorted correctly in the bag") additem ITEM_HM02; ); - SortBerriesOrTMHMs(POCKET_TM_HM); + SortPocket(POCKET_TM_HM, SORT_POCKET_TM_HM); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_TM01); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_TM05); @@ -67,7 +67,7 @@ TEST("Berries are sorted correctly in the bag") additem ITEM_CHERI_BERRY; ); - SortBerriesOrTMHMs(POCKET_BERRIES); + SortPocket(POCKET_BERRIES, SORT_POCKET_BY_ITEM_ID); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_CHERI_BERRY); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_ORAN_BERRY); @@ -102,11 +102,17 @@ TEST("Items are correctly compacted in the bag") ); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_NUGGET); + EXPECT_EQ(pocket->itemSlots[0].quantity, 1); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[1].quantity, 1); EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_TINY_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[2].quantity, 1); EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[3].quantity, 1); EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_PEARL); + EXPECT_EQ(pocket->itemSlots[4].quantity, 1); EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[5].quantity, 1); EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); // Try removing the small items, check that everything is compacted correctly @@ -120,11 +126,13 @@ TEST("Items are correctly compacted in the bag") CompactItemsInBagPocket(POCKET_ITEMS); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[0].quantity, 1); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[1].quantity, 1); EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[2].quantity, 1); EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); - } From 9228826ae18823fa18e3226f0be54c295963a6c6 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:14:19 -0400 Subject: [PATCH 082/283] New and polished battle animations (#7074) --- data/battle_anim_scripts.s | 2565 ++++++++++++++--- .../battle_anims/sprites/tatsugiri_curly.png | Bin 0 -> 1045 bytes .../battle_anims/sprites/tatsugiri_droopy.png | Bin 0 -> 1036 bytes .../sprites/tatsugiri_stretchy.png | Bin 0 -> 1040 bytes graphics/battle_anims/sprites/tera_symbol.png | Bin 0 -> 320 bytes include/battle_anim.h | 10 + include/constants/battle_anim.h | 10 + include/graphics.h | 8 + src/battle_anim_dark.c | 15 + src/battle_anim_effects_1.c | 7 +- src/battle_anim_effects_3.c | 35 + src/battle_anim_electric.c | 23 +- src/battle_anim_fire.c | 6 + src/battle_anim_ground.c | 5 +- src/battle_anim_ice.c | 3 +- src/battle_anim_mons.c | 73 +- src/battle_anim_new.c | 322 ++- src/battle_anim_poison.c | 43 +- src/battle_anim_rock.c | 5 +- src/data/battle_anim.h | 8 + src/graphics.c | 12 + test/battle/move_animations/all_anims.c | 257 ++ 22 files changed, 3031 insertions(+), 376 deletions(-) create mode 100644 graphics/battle_anims/sprites/tatsugiri_curly.png create mode 100644 graphics/battle_anims/sprites/tatsugiri_droopy.png create mode 100644 graphics/battle_anims/sprites/tatsugiri_stretchy.png create mode 100644 graphics/battle_anims/sprites/tera_symbol.png diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 9d309ec154..8b504a37f9 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -100,26 +100,16 @@ gBattleAnimMove_WakeUpSlap:: end gBattleAnimMove_HammerArm:: - loadspritegfx ANIM_TAG_IMPACT - loadspritegfx ANIM_TAG_ROCKS - loadspritegfx ANIM_TAG_SLAM_HIT - monbg ANIM_TARGET - setalpha 12, 8 - playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_ATTACKER - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, ANIM_ATTACKER, 20, 3, 0, 4 - delay 1 - createsprite gSlamHitSpriteTemplate, ANIM_ATTACKER, 2, 0, 0 - delay 3 - setarg 7, 0 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 10, -8, ANIM_TARGET, 1 - playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 5, 1 - createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, -12, 32, 3, 4 - createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, 8, 31, 2, 2 - createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, -4, 28, 2, 3 - createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, 12, 30, 4, 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 2, 0, 0, 5 - clearmonbg ANIM_TARGET + loadspritegfx ANIM_TAG_HORSESHOE_SIDE_FIST @punch + loadspritegfx ANIM_TAG_ICE_CRYSTALS @ice + loadspritegfx ANIM_TAG_ECLIPSING_ORB @gray color + loadspritegfx ANIM_TAG_BLACK_SMOKE @smoke + playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_TARGET + createsprite gIceHammerPunchStompTemplate, ANIM_TARGET, 3, 0, -32, 15 + delay 19 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_SquishTarget, 2 + waitforvisualfinish blendoff end @@ -322,6 +312,7 @@ gBattleAnimGeneral_Tailwind:: gBattleAnimMove_Acupressure:: loadspritegfx ANIM_TAG_ACUPRESSURE loadspritegfx ANIM_TAG_SPARK_2 + playsewithpan SE_M_METRONOME, SOUND_PAN_ATTACKER createsprite gAcupressureSpriteTemplate, ANIM_ATTACKER, 40, 0, -40, 40 waitforvisualfinish call ElectricityEffect @@ -377,29 +368,77 @@ gBattleAnimMove_CloseCombat:: loadspritegfx ANIM_TAG_HANDS_AND_FEET call SetHighSpeedBg createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_COMET_PUNCH, +63 - delay 10 + delay 2 createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_VITAL_THROW2, +63 - delay 10 + delay 2 createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_MEGA_KICK2, +63 - delay 10 + delay 2 createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_COMET_PUNCH, +63 - delay 10 + delay 2 createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_VITAL_THROW2, +63 - delay 10 + delay 2 createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 7, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 playsewithpan SE_M_MEGA_KICK2, +63 - delay 10 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_VITAL_THROW2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_MEGA_KICK2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_VITAL_THROW2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_MEGA_KICK2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_VITAL_THROW2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_MEGA_KICK2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_COMET_PUNCH, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_VITAL_THROW2, +63 + delay 2 + createsprite gFistFootRandomPosSpriteTemplate, ANIM_TARGET, 3, 1, 10, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 2, 0, 7, 1 + playsewithpan SE_M_MEGA_KICK2, +63 + delay 1 call UnsetHighSpeedBg clearmonbg ANIM_TARGET blendoff @@ -1179,7 +1218,7 @@ gBattleAnimMove_RockPolish:: setalpha 12, 8 createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 0, F_PAL_BG, 3, 0, 12, RGB_BLACK waitforvisualfinish - loopsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER, 10, 7 + loopsewithpan SE_M_MORNING_SUN, SOUND_PAN_ATTACKER, 10, 7 createsprite gRockPolishStreakSpriteTemplate, ANIM_ATTACKER, 2, -10, 3 delay 1 createsprite gRockPolishStreakSpriteTemplate, ANIM_ATTACKER, 2, 24, -19 @@ -1217,7 +1256,7 @@ gBattleAnimMove_RockPolish:: createsprite gRockPolishStreakSpriteTemplate, ANIM_ATTACKER, 2, -21, -16 delay 2 waitforvisualfinish - playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER createsprite gRockPolishSparkleSpriteTemplate, ANIM_ATTACKER, 2, -20, 9 createsprite gRockPolishSparkleSpriteTemplate, ANIM_ATTACKER, 2, -10, -15 createsprite gRockPolishSparkleSpriteTemplate, ANIM_ATTACKER, 2, 1, 17 @@ -1295,32 +1334,39 @@ gBattleAnimMove_PoisonJab:: end gBattleAnimMove_DarkPulse:: - loadspritegfx ANIM_TAG_THIN_RING + loadspritegfx ANIM_TAG_PURPLE_RING monbg ANIM_TARGET fadetobg BG_DARK waitbgfadein - delay 0 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - createvisualtask AnimTask_SpiteTargetShadow, 2 loopsewithpan SE_M_PSYBEAM, SOUND_PAN_TARGET, 20, 3 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 - delay 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, RGB(9, 8, 7), 12 + createvisualtask AnimTask_SwayMon, ANIM_TARGET, 0, 6, 0x0800, 8, ANIM_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 2, 4, 0, 12, RGB(30, 10, 13) + call DarkPulseParticle + call DarkPulseParticle + call DarkPulseParticle waitforvisualfinish + blendoff clearmonbg ANIM_TARGET - delay 1 restorebg waitbgfadein end +DarkPulseParticle: + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + createsprite gDarkPulseSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + return gBattleAnimMove_NightSlash:: loadspritegfx ANIM_TAG_SLASH @@ -1706,7 +1752,11 @@ gBattleAnimMove_EarthPower:: loadspritegfx ANIM_TAG_FIRE_PLUME createvisualtask AnimTask_HorizontalShake, 3, ANIM_TARGET, 10, 50 playsewithpan SE_M_EARTHQUAKE, SOUND_PAN_TARGET - delay 40 + delay 32 + fadetobg BG_FISSURE + waitbgfadeout + createvisualtask AnimTask_PositionFissureBgOnBattler, 5, ANIM_TARGET, 5, -1 + waitbgfadein loopsewithpan 145, SOUND_PAN_TARGET 11, 3 createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 3, 25, 1 createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 5, 0 @@ -1727,6 +1777,10 @@ gBattleAnimMove_EarthPower:: waitforvisualfinish createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 66, 0, 0, 4 waitforvisualfinish + restorebg + waitbgfadeout + setarg 7, -1 + waitbgfadein end gBattleAnimMove_Switcheroo:: @@ -1925,40 +1979,30 @@ SnowSlide1: delay 2 return +@Credits to Skeli gBattleAnimMove_IceShard:: monbg ANIM_TARGET splitbgprio ANIM_TARGET setalpha 12, 8 loadspritegfx ANIM_TAG_ICE_CRYSTALS - fadetobg BG_ICE - waitbgfadein - createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_BUBBLE_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 4, 4, 0, 10 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, -20, 70, 0, 42, 35 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, -20, 58, 0, 30, 35 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, -20, -12, 0, 22, 40 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, -20, 0, 0, 10, 40 - delay 5 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, -10, -30, 10, -12, 45 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, -10, -42, 10, -24, 45 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, -10, -20, 10, -36, 45 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, -10, -32, 10, -24, 45 - delay 5 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, 0, 10, 20, 22, 45 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, 0, -2, 20, 10, 45 - createsprite gIceBeamOuterCrystalSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 20, -2, 30 - createsprite gIceBeamInnerCrystalSpriteTemplate, ANIM_ATTACKER, 2, 0, 8, 20, 10, 30 + loadspritegfx ANIM_TAG_IMPACT + createsprite gIceShardSpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gIceShardSpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gIceShardSpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gIceShardSpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 delay 1 + createsprite gIceShardSpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 4 createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_TARGET, -31, 0, 7, RGB(0, 20, 31) createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 2, 0, 25, 1 - waitforvisualfinish - delay 20 call IceCrystalEffectShort createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_TARGET, 5, 7, 0, RGB(0, 20, 31) waitforvisualfinish - restorebg - waitbgfadein - clearmonbg ANIM_TARGET blendoff + clearmonbg ANIM_TARGET end gBattleAnimMove_ShadowClaw:: @@ -2700,62 +2744,69 @@ gBattleAnimMove_LeafStorm:: end gBattleAnimMove_PowerWhip:: - loadspritegfx ANIM_TAG_WHIP_HIT + loadspritegfx ANIM_TAG_PUNISHMENT_BLADES + loadspritegfx ANIM_TAG_LEAF @green color + loadspritegfx ANIM_TAG_IMPACT playsewithpan SE_M_JUMP_KICK, SOUND_PAN_ATTACKER createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 10 delay 6 playsewithpan SE_M_SCRATCH, SOUND_PAN_TARGET - createsprite gVineWhipSpriteTemplate, ANIM_TARGET, 2, 0, 0 - delay 6 - call SetImpactBackground - createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 2, 0, 8, 1 + createsprite gSpinningVineSpriteTemplate, ANIM_ATTACKER, 2, -42, -25, 0, 0, 25 + createvisualtask AnimTask_IsTargetPlayerSide, 2 + jumpretfalse PowerWhipOnOpponent + goto PowerWhipOnPlayer +PowerWhipOnOpponent: + fadetobg BG_IMPACT_OPPONENT + goto PowerWhipContinue +PowerWhipOnPlayer: + fadetobg BG_IMPACT_PLAYER + goto PowerWhipContinue +PowerWhipContinue: + waitbgfadeout + delay 5 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 1 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 5, 5, 1 + playsewithpan SE_BANG, SOUND_PAN_TARGET + waitforvisualfinish + delay 20 restorebg waitbgfadein + waitforvisualfinish end gBattleAnimMove_RockWrecker:: - jumpargeq 7, 1, RockWrecker_1 - fadetobg BG_ROCK_WRECKER - waitbgfadeout - createvisualtask AnimTask_StartSlidingBg, 5, -1024, 0, 1, -1 - goto RockWrecker_2 -RockWrecker_1: - fadetobg BG_ROCK_WRECKER - waitbgfadeout - createvisualtask AnimTask_StartSlidingBg, 5, -1024, 0, 0, -1 loadspritegfx ANIM_TAG_ROCKS + loadspritegfx ANIM_TAG_REALLY_BIG_ROCK + loadspritegfx ANIM_TAG_EXPLOSION loadspritegfx ANIM_TAG_IMPACT - createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 - delay 3 + fadetobg BG_ROCK_WRECKER + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0xF000, 0, 0, -1 + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER + call ContinentalCrushStockpileRocks + createsprite gContinentalCrushGrowingRockSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER + call ContinentalCrushStockpileRocks + delay 10 + loopsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER, 10, 3 + waitforvisualfinish playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - createsprite gRockBlastRockSpriteTemplate, ANIM_ATTACKER, 130, 16, 0, 0, 0, 25, (1 << 8) | 1 + createsprite gReallyBigRockBlastRockSpriteTemplate, ANIM_TARGET, 2, 16, 0, 0, 0, 25, 257 waitforvisualfinish createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 0, 0, ANIM_TARGET, 1 playsewithpan SE_M_ROCK_THROW SOUND_PAN_TARGET createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 0, 0, 20, 24, 14, 2 - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 + createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 8, 0, 40, 1 createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 5, 0, -20, 24, 14, 1 createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 0, 5, 20, -18, 14, 2 createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, -5, 0, -20, -18, 14, 2 + call OpposingExplosion2 waitforvisualfinish - call UnsetPsychicBg - end -RockWrecker_2: - loadspritegfx ANIM_TAG_ROCKS - loadspritegfx ANIM_TAG_IMPACT - createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 - delay 3 - playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - createsprite gRockBlastRockSpriteTemplate, ANIM_ATTACKER, 2, 16, 0, 0, 0, 25, 257 - waitforvisualfinish - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 0, 0, ANIM_TARGET, 1 - playsewithpan SE_M_ROCK_THROW SOUND_PAN_TARGET - createsprite gRockFragmentSpriteTemplate ANIM_TARGET, 2, 0, 0, 20, 24, 14, 2 - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 - createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 2, 5, 0, -20, 24, 14, 1 - createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 2, 0, 5, 20, -18, 14, 2 - createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 2, -5, 0, -20, -18, 14, 2 waitforvisualfinish + blendoff call UnsetPsychicBg end @@ -3286,16 +3337,11 @@ gBattleAnimMove_AquaJet:: loadspritegfx ANIM_TAG_ROUND_SHADOW loadspritegfx ANIM_TAG_SPLASH loadspritegfx ANIM_TAG_SWEAT_BEAD - playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER - createsprite gDiveBallSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 13, 336 + createvisualtask AnimTask_AttackerStretchAndDisappear, 2 + playsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER waitforvisualfinish - playsewithpan SE_M_DIVE, SOUND_PAN_ATTACKER - createsprite gDiveWaterSplashSpriteTemplate, ANIM_ATTACKER, 3, 0 - call DiveSetUpWaterDroplets - call DiveSetUpWaterDroplets - call DiveSetUpWaterDroplets - call DiveSetUpWaterDroplets - call DiveSetUpWaterDroplets + delay 1 + createvisualtask AnimTask_SetAttackerInvisibleWaitForSignal, 2 loadspritegfx ANIM_TAG_WATER_IMPACT loadspritegfx ANIM_TAG_SMALL_BUBBLES monbg ANIM_DEF_PARTNER @@ -3310,6 +3356,8 @@ gBattleAnimMove_AquaJet:: delay 12 call RisingWaterHitEffect waitforvisualfinish + createvisualtask AnimTask_ExtremeSpeedMonReappear, 2 + waitforvisualfinish visible ANIM_ATTACKER clearmonbg ANIM_DEF_PARTNER blendoff @@ -4814,16 +4862,17 @@ gBattleAnimMove_ShellSmash:: loadspritegfx ANIM_TAG_IMPACT loadspritegfx ANIM_TAG_ROCKS loadspritegfx ANIM_TAG_HANDS_AND_FEET - playsewithpan SE_M_SCRATCH, SOUND_PAN_ATTACKER - createsprite gShellSmashRightShellSpriteTemplate, ANIM_ATTACKER, 2, 0xffd7, 0x0, 0x2, 0x333, 0x0, 10, 30 - createsprite gShellSmashLeftShellSpriteTemplate, ANIM_ATTACKER, 2, 0x20, 0x0, 0x6, 0xfccd, 0x0, 10, 30 + playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER + createsprite gShellSmashRightShellSpriteTemplate, ANIM_ATTACKER, 2, -41, 0, 2, 819, 0, 10, 30 + createsprite gShellSmashLeftShellSpriteTemplate, ANIM_ATTACKER, 2, 32, 0, 6, -819, 0, 10, 30 delay 10 - createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 1 - createsprite gFistFootSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x8, 0x1, 0x0 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + invisible ANIM_ATTACKER + playsewithpan SE_M_STRENGTH, SOUND_PAN_ATTACKER createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 waitforvisualfinish - playsewithpan SE_M_BUBBLE, SOUND_PAN_TARGET + playsewithpan SE_M_BRICK_BREAK, SOUND_PAN_ATTACKER + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 1 + visible ANIM_ATTACKER createsprite gShellSmashPurpleRocksSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 20, 24, 14, 2 createsprite gShellSmashPurpleRocksSpriteTemplate, ANIM_ATTACKER, 2, 5, 0, -20, 24, 14, 1 createsprite gShellSmashPurpleRocksSpriteTemplate, ANIM_ATTACKER, 2, 0, 5, 20, -24, 14, 2 @@ -8572,17 +8621,22 @@ gBattleAnimMove_WaterShuriken:: loadspritegfx ANIM_TAG_IMPACT @hydro pump hit monbg ANIM_DEF_PARTNER splitbgprio ANIM_TARGET - createsoundtask SoundTask_LoopSEAdjustPanning, 0x7, 0x87, 0xffc0, SOUND_PAN_TARGET, 0x5, 0x5, 0x0, 0x5 - createsprite gWaterShurikenStarTemplate, ANIM_TARGET, 2, 0x0, 0x0, 0x27 + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + createsprite gWaterShurikenStarTemplate, ANIM_TARGET, 2, 0, 0, 20 delay 8 - createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0x0, 0x0, 0x28, 0xf + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 8, 1 + playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_TARGET + createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0, 0, 20, 15 delay 5 - createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0x0, 0x0, 0x28, 0xf + playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_TARGET + createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0, 0, 20, 15 delay 5 - createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0x0, 0x0, 0x28, 0xf + playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_TARGET + createsprite gWaterShurikenRingTemplate, ANIM_TARGET, 2, 0, 0, 20, 15 delay 12 playsewithpan SE_M_SAND_ATTACK, SOUND_PAN_TARGET - createsprite gWaterShurikenImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x1, 0x2 + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 4, 1 + createsprite gWaterShurikenImpactTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 2 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER end @@ -9019,17 +9073,34 @@ gBattleAnimMove_ElectricTerrain:: gBattleAnimMove_DazzlingGleam:: loadspritegfx ANIM_TAG_SPARKLE_2 loadspritegfx ANIM_TAG_BLUE_STAR - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 0, 13, RGB_WHITE - playsewithpan SE_M_TWISTER, SOUND_PAN_ATTACKER - @call 0x081D56B3 -> middle of GrantingStarsEffect + loadspritegfx ANIM_TAG_IMPACT + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 0, 13, RGB(31, 25, 25) + loopsewithpan SE_M_HEAL_BELL, SOUND_PAN_ATTACKER, 16, 3 createsprite gGrantingStarsSpriteTemplate, ANIM_ATTACKER, 2, 12, -5, 0, 0, 32, 60 - delay 8 waitforvisualfinish createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATTACKER, 0, 3, 0, 16, RGB_WHITE - delay 4 - playsewithpan SE_M_GIGA_DRAIN, SOUND_PAN_ATTACKER + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT, 0, 12, 12, RGB(31, 28, 28) + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 21, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 0, 3, 21, 1 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET + delay 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET + delay 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET + delay 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET + delay 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET + delay 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 3, ANIM_TARGET, 2 + createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_HYPER_BEAM, SOUND_PAN_TARGET waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 13, 0, RGB_WHITE + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 13, 0, RGB(31, 25, 25) waitforvisualfinish clearmonbg 0x0 blendoff @@ -9217,7 +9288,7 @@ gBattleAnimMove_OblivionWing:: waitforvisualfinish createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 14, RGB_BLACK @Black waitforvisualfinish - createsoundtask SoundTask_LoopSEAdjustPanning, 0x7, 0xf0, 0xffc0, SOUND_PAN_TARGET, 0x1, 0xf, 0x0, 0x5 + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 15, 0, 5 call OblivionWingBeam call OblivionWingBeam createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 40, 1 @@ -10060,7 +10131,7 @@ gBattleAnimMove_IceHammer:: createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 12, RGB_BLACK waitforvisualfinish playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_TARGET - createsprite gIceHammerPunchStompTemplate, ANIM_TARGET, 3, 0x0, 0xffe0, 0xf + createsprite gIceHammerPunchStompTemplate, ANIM_TARGET, 3, 0, -32, 15 delay 19 playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_SquishTarget, 0x2 @@ -12183,7 +12254,7 @@ gBattleAnimMove_MoongeistBeam:: createsprite gGrowingChargeOrbSpriteTemplate, ANIM_ATTACKER, 2, 0x0 @;Charge circle call MoongeistBeamCharge delay 32 - createsoundtask SoundTask_LoopSEAdjustPanning, 0x7, 0xCC, 0xffc0, SOUND_PAN_TARGET, 0x1, 0xf, 0x0, 0x5 + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 15, 0, 5 createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 0, 4, 50, 1 createvisualtask AnimTask_FlashAnimTagWithColor, 2, ANIM_TAG_ORBS, 1, 12, RGB_RED, 16, 0, 0 call MoongeistBeamOrbs @@ -14363,6 +14434,7 @@ SetSteelBeamBackground: goto SetHighSpeedBgFade SetSteelBeamBgPlayer: fadetobg BG_STEEL_BEAM_PLAYER + goto SetHighSpeedBgFade @Credits to Skeli gBattleAnimMove_ExpandingForce:: @@ -15621,37 +15693,55 @@ gBattleAnimMove_GlacialLance:: gBattleAnimMove_AstralBarrage:: - loadspritegfx ANIM_TAG_FLAT_ROCK - loadspritegfx ANIM_TAG_ICE_CRYSTALS - loadspritegfx ANIM_TAG_GHOSTLY_SPIRIT - createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_FLAT_ROCK, 0, 10, 10, RGB(2, 1, 4) - createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_ICE_CRYSTALS, 0, 10, 10, RGB(2, 1, 4) + loadspritegfx ANIM_TAG_PURPLE_FLAME + loadspritegfx ANIM_TAG_SHADOW_BALL + loadspritegfx ANIM_TAG_THIN_RING + loadspritegfx ANIM_TAG_ICE_CHUNK + loadspritegfx ANIM_TAG_HANDS_AND_FEET monbg ANIM_ATK_PARTNER splitbgprio ANIM_ATTACKER + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER setalpha 12, 8 fadetobg BG_GHOST waitbgfadein - createsprite gShakeMonOrPlatformSpriteTemplate, ANIM_ATTACKER, 2, 4, 1, 180, 1 - createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_FAINT_ATTACK, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 5, 20, 0, 5 - createsprite gSuperpowerRockSpriteTemplate, ANIM_ATTACKER, 41, 200, 96, 1, 120 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + createvisualtask AnimTask_GrudgeFlames, 3 + createsprite gBlackHoleEclipseHoleUserSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_ATTACKER, 0 + createsprite gBlackHoleEclipseBlueRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0 delay 8 - createsprite gSuperpowerRockSpriteTemplate, ANIM_ATTACKER, 41, 20, 248, 4, 112 + createsprite gBlackHoleEclipseBlackRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0 delay 8 - createsprite gSuperpowerRockSpriteTemplate, ANIM_ATTACKER, 41, 130, 160, 2, 104 + createsprite gBlackHoleEclipseBlueRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0 delay 8 - createsprite gSuperpowerRockSpriteTemplate, ANIM_ATTACKER, 41, 160, 192, 0, 96 + createsprite gBlackHoleEclipseBlackRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0 delay 8 - createsprite gSuperpowerRockSpriteTemplate, ANIM_ATTACKER, 41, 60, 288, 3, 88 - delay 74 - panse SE_M_BLIZZARD, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0 - call BlizzardIceCrystals - call BlizzardIceCrystals - playsewithpan SE_M_BLIZZARD2, SOUND_PAN_TARGET + unloadspritegfx ANIM_TAG_SHADOW_BALL + unloadspritegfx ANIM_TAG_THIN_RING + unloadspritegfx ANIM_TAG_ICE_CHUNK + unloadspritegfx ANIM_TAG_HANDS_AND_FEET waitforvisualfinish - playsewithpan SE_M_NIGHTMARE, SOUND_PAN_TARGET + loadspritegfx ANIM_TAG_WISP_FIRE + loadspritegfx ANIM_TAG_EXPLOSION + loadspritegfx ANIM_TAG_GHOSTLY_SPIRIT + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_PURPLE + call AstralBarrageFlames1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 0, 3, 50, 1 + call AstralBarrageFlames2 + call AstralBarrageFlames3 + call AstralBarrageFlames4 + call AstralBarrageFlames5 + waitforvisualfinish + playsewithpan SE_M_FLAME_WHEEL2, SOUND_PAN_TARGET createspriteontargets gCurseGhostSpriteTemplate, ANIM_TARGET, 3, 2, 8, -5, ANIM_TARGET, 0 createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 8, 0, 16, 1 createvisualtask AnimTask_ShakeMon2, 2, ANIM_DEF_PARTNER, 8, 0, 16, 1 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 0 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 42 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 84 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 126 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 168 + createsprite gWillOWispFireSpriteTemplate, ANIM_TARGET, 2, 210 waitforvisualfinish clearmonbg ANIM_ATK_PARTNER restorebg @@ -15659,6 +15749,76 @@ gBattleAnimMove_AstralBarrage:: blendoff delay 1 end +AstralBarrageFlames1: + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, -30, -20 @;Top left + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 6, 5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, 10, 20 @;Bottom left + delay 2 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, -30, -20 @;Top right + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, -16, -15, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, 10, 20 @;Bottom right + delay 2 + return +AstralBarrageFlames2: + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, -30, -20 @;Top left + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 16, -5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, 10, 20 @;Bottom left + delay 2 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, -30, -20 @;Top right + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, -12, 18, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, 10, 20 @;Bottom right + delay 2 + return +AstralBarrageFlames3: + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, -30, -20 @;Top left + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 0, 5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, 10, 20 @;Bottom left + delay 2 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, -30, -20 @;Top right + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 6, 5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, 10, 20 @;Bottom right + delay 2 + return +AstralBarrageFlames4: + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, -30, -20 @;Top left + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, -16, -15, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, 10, 20 @;Bottom left + delay 2 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, -30, -20 @;Top right + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 16, -5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, 10, 20 @;Bottom right + delay 2 + return +AstralBarrageFlames5: + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, -30, -20 @;Top left + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, -12, 18, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, -30, 10, 20 @;Bottom left + delay 2 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, -30, -20 @;Top right + delay 2 + playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET + createsprite gExplosionSpriteTemplate, ANIM_TARGET, 4, 0, 5, 3, 0 + createsprite gSpriteTemplate_InfernalParadeFlame, ANIM_TARGET, 2, 30, 10, 20 @;Bottom right + delay 2 + return @Credits to Skeli @@ -17723,6 +17883,7 @@ gBattleAnimMove_IvyCudgel:: end IvyCudgelFire: loadspritegfx ANIM_TAG_IVY_CUDGEL_FIRE + loadspritegfx ANIM_TAG_SMALL_EMBER createsprite gIvyCudgelFireSpriteTemplate, ANIM_TARGET, 2 delay 60 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 3, 0, 12, 4 @@ -17730,10 +17891,14 @@ IvyCudgelFire: createvisualtask AnimTask_SquishTarget, 0x2 delay 6 call WoodHammerImpact + call FireSpreadEffect + delay 4 + playsewithpan SE_M_FIRE_PUNCH, SOUND_PAN_TARGET waitforvisualfinish end IvyCudgelRock: loadspritegfx ANIM_TAG_IVY_CUDGEL_ROCK + loadspritegfx ANIM_TAG_ROCKS createsprite gIvyCudgelRockSpriteTemplate, ANIM_TARGET, 2 delay 60 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 3, 0, 12, 4 @@ -17741,10 +17906,16 @@ IvyCudgelRock: createvisualtask AnimTask_SquishTarget, 0x2 delay 6 call WoodHammerImpact + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, -12, 32, 3, 4 + createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, 8, 31, 2, 2 + createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, -4, 28, 2, 3 + createsprite gRockScatterSpriteTemplate, ANIM_TARGET, 2, 12, 30, 4, 3 waitforvisualfinish end IvyCudgelWater: loadspritegfx ANIM_TAG_IVY_CUDGEL_WATER + loadspritegfx ANIM_TAG_SPLASH createsprite gIvyCudgelWaterSpriteTemplate, ANIM_TARGET, 2 delay 60 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 3, 0, 12, 4 @@ -17752,6 +17923,8 @@ IvyCudgelWater: createvisualtask AnimTask_SquishTarget, 0x2 delay 6 call WoodHammerImpact + playsewithpan SE_M_DIVE, SOUND_PAN_TARGET + createsprite gDiveWaterSplashSpriteTemplate, ANIM_TARGET, 3, 1 waitforvisualfinish end @@ -18409,30 +18582,46 @@ gBattleAnimMove_RevivalBlessing:: goto gBattleAnimMove_LunarBlessing gBattleAnimMove_TeraStarstorm:: + loadspritegfx ANIM_TAG_CIRCLE_OF_LIGHT loadspritegfx ANIM_TAG_STARSTORM loadspritegfx ANIM_TAG_YELLOW_STAR loadspritegfx ANIM_TAG_IMPACT fadetobg BG_COSMIC waitbgfadein - playsewithpan SE_FALL, SOUND_PAN_ATTACKER + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_CIRCLE_OF_LIGHT, 0, 15, 15, RGB_WHITE + playsewithpan SE_M_CHARGE, SOUND_PAN_ATTACKER + createsprite gGrowingShockWaveOrbSpriteTemplate, ANIM_ATTACKER, 2 + delay 20 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam delay 2 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER call TeraStarstormCreateBeam - delay 2 + delay 20 + playsewithpan SE_M_DETECT, SOUND_PAN_ATTACKER + delay 20 + playsewithpan SE_FALL, SOUND_PAN_ATTACKER jumpifmovetypeequal TYPE_STELLAR, TeraStarstormStellar goto TeraStarstormSingle TeraStarstormStellar: @@ -18440,67 +18629,86 @@ TeraStarstormStellar: TeraStarstormSingle: createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, 0, 30, 0, 1 delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 0, 30, 0, 1 delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 0, 1 delay 3 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -8, 0, ANIM_TARGET, 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 delay 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, -5, 30, 0, 1 delay 3 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -16, 8, ANIM_TARGET, 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 delay 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 5, 30, 0, 1 delay 3 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 16, 8, ANIM_TARGET, 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 delay 2 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 0, 1 delay 3 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, ANIM_TARGET, 2 delay 5 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 24, 0, ANIM_TARGET, 2 delay 5 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 24, 16, ANIM_TARGET, 2 waitforvisualfinish restorebg waitbgfadeout end TeraStarstormDouble: + loadspritegfx ANIM_TAG_EXPLOSION_2 + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION_2, 0, 12, 12, RGB_WHITE createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, 0, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, 0, 30, 1, 1 delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 1, 1 delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 0, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 0, 30, 1, 1 delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 1, 1 delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 1, 1 delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 1, 1 delay 3 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 10, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 10, 30, 1, 1 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -8, 0, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, -8, 0, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 2 @@ -18509,7 +18717,9 @@ TeraStarstormDouble: delay 3 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 1, 1 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -16, 0, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, -16, 0, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 2 @@ -18518,7 +18728,9 @@ TeraStarstormDouble: delay 3 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 1, 1 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 16, 8, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, 16, 8, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 2 @@ -18527,21 +18739,33 @@ TeraStarstormDouble: delay 3 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 1, 1 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 24, 0, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, 24, 0, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 5 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 24, 16, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, 24, 16, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 5 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -24, 16, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, -24, 16, ANIM_DEF_PARTNER, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 delay 5 - playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 - createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 5, 5, 1, 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, -24, -8, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_DEF_PARTNER, 2, -24, -8, ANIM_DEF_PARTNER, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 0, 3, 50, 1 + call ExpandingForceExplosionGeyser + delay 5 + call ExpandingForceExplosionGeyser + delay 5 waitforvisualfinish restorebg waitbgfadeout @@ -19078,11 +19302,104 @@ gBattleAnimMove_BlazingTorque:: call FireSpreadEffect createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + @waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + waitforvisualfinish + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + delay 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end + +gBattleAnimMove_WickedTorque:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_POISON_BUBBLE + loadspritegfx ANIM_TAG_THIN_RING + fadetobg BG_DARK + waitbgfadein + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 + waitforvisualfinish + delay 10 + playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER + waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 + waitforvisualfinish + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + delay 3 + waitforvisualfinish + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_BlendBattleAnimPal, 10, (F_PAL_BG | F_PAL_BATTLERS_2), 3, 10, 0, 0 + createsprite gFoulPlayRingTemplate, ANIM_ATTACKER, 3, 0, 0, 256, 0 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + delay 2 + createsprite gFoulPlayRingTemplate, ANIM_ATTACKER, 3, 0, 0, 256, 0 + waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + waitforvisualfinish + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + delay 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end + +gBattleAnimMove_NoxiousTorque:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_POISON_BUBBLE + fadetobg BG_GUNK_SHOT + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 + waitbgfadein + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 + waitforvisualfinish + delay 10 + playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER + waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 waitforvisualfinish + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + delay 3 + waitforvisualfinish + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 1, 2, 0, 12, RGB(30, 0, 31) + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + delay 5 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 0, 40, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 46, 9, 20 + delay 5 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -43, -12, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 16, -46, 20 + waitforvisualfinish createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE waitforvisualfinish createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 @@ -19096,200 +19413,1741 @@ gBattleAnimMove_BlazingTorque:: call UnsetPsychicBg end -gBattleAnimMove_WickedTorque:: +gBattleAnimMove_CombatTorque:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_METEOR + fadetobg BG_IN_AIR + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0, 0x1000, 0, -1 + waitbgfadein + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 + waitforvisualfinish + delay 10 + playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER + waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 + waitforvisualfinish + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + delay 3 + waitforvisualfinish + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gSuperpowerFireballSpriteTemplate, ANIM_TARGET, 3, ANIM_ATTACKER + delay 4 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + @waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + waitforvisualfinish + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + delay 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + blendoff + call UnsetPsychicBg + end + +gBattleAnimMove_MagicalTorque:: + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_PINK_HEART + loadspritegfx ANIM_TAG_DUCK + loadspritegfx ANIM_TAG_RED_HEART + fadetobg BG_TWINKLE_TACKLE + waitbgfadeout + playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 + waitforvisualfinish + delay 10 + playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER + waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 + waitforvisualfinish + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 128, -16 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 416, -38 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -128, -22 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -384, -31 + delay 0 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 + createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 + delay 3 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + waitforvisualfinish + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + waitforvisualfinish + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + delay 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end + +gBattleAnimMove_TeraBlast:: + jumpifmovetypeequal TYPE_NORMAL, TeraBlastNormal + jumpifmovetypeequal TYPE_FIGHTING, TeraBlastFighting + jumpifmovetypeequal TYPE_FLYING, TeraBlastFlying + jumpifmovetypeequal TYPE_POISON, TeraBlastPoison + jumpifmovetypeequal TYPE_GROUND, TeraBlastGround + jumpifmovetypeequal TYPE_ROCK, TeraBlastRock + jumpifmovetypeequal TYPE_BUG, TeraBlastBug + jumpifmovetypeequal TYPE_GHOST, TeraBlastGhost + jumpifmovetypeequal TYPE_STEEL, TeraBlastSteel + jumpifmovetypeequal TYPE_FIRE, TeraBlastFire + jumpifmovetypeequal TYPE_WATER, TeraBlastWater + jumpifmovetypeequal TYPE_GRASS, TeraBlastGrass + jumpifmovetypeequal TYPE_ELECTRIC, TeraBlastElectric + jumpifmovetypeequal TYPE_PSYCHIC, TeraBlastPsychic + jumpifmovetypeequal TYPE_ICE, TeraBlastIce + jumpifmovetypeequal TYPE_DRAGON, TeraBlastDragon + jumpifmovetypeequal TYPE_DARK, TeraBlastDark + jumpifmovetypeequal TYPE_FAIRY, TeraBlastFairy + jumpifmovetypeequal TYPE_STELLAR, TeraBlastStellar + end +TeraBlastNormal: + loadspritegfx ANIM_TAG_PINKVIO_ORB + loadspritegfx ANIM_TAG_ORBS + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_PINKVIO_ORB, 0, 12, 12, RGB_WHITE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_ORBS, 0, 12, 12, RGB_WHITE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_WHITE + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 12, 0 + waitforvisualfinish + createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_HYPER_BEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 1, 15, 0, 5 + createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 0, 4, 50, 1 + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 50, 1 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 2, 0, 11, RGB(25, 25, 25) + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + call HyperBeamOrbs + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_TARGET, 2, 11, 0, RGB(25, 25, 25) + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 12, 0, 0 + waitforvisualfinish + blendoff + clearmonbg ANIM_ATTACKER + end +TeraBlastFighting: + loadspritegfx ANIM_TAG_PINKVIO_ORB + loadspritegfx ANIM_TAG_HANDS_AND_FEET + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_PINKVIO_ORB, 0, 12, 12, RGB(29, 24, 2) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(29, 24, 2) + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_ROCK_WRECKER + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0xF000, 0, 0, -1 + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 2, 63, 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 24, 0, 0, 10, 1, ANIM_FOOT_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET + delay 2 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -6, 18, 0, 0, 10, 1, ANIM_CHOP, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -64, 16, 0, 0, 10, 1, ANIM_FIST_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 21, 0, 0, 10, 1, ANIM_FOOT_2, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 20, 0, 0, 10, 1, ANIM_FIST_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -32, 23, 0, 0, 10, 1, ANIM_CHOP, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + delay 2 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -64, 17, 0, 0, 10, 1, ANIM_FOOT_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -80, 16, 0, 0, 10, 1, ANIM_FOOT_2, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -96, 21, 0, 0, 10, 1, ANIM_CHOP, 1 + delay 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 24, 0, 0, 10, 1, ANIM_FOOT_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -6, 18, 0, 0, 10, 1, ANIM_CHOP, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -64, 16, 0, 0, 10, 1, ANIM_FIST_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 21, 0, 0, 10, 1, ANIM_FOOT_2, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -48, 20, 0, 0, 10, 1, ANIM_FIST_1, 1 + delay 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 1 + createsprite gAllOutPummelingOnslaughtSpriteTemplate, ANIM_ATTACKER, 2, -32, 23, 0, 0, 10, 1, ANIM_CHOP, 1 + delay 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 1 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + clearmonbg ANIM_TARGET + waitbgfadein + call UnsetPsychicBg + waitforvisualfinish + end +TeraBlastPoison: + loadspritegfx ANIM_TAG_POISON_BUBBLE + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_PURPLE + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + delay 2 + createsprite sPoisonSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_GUNK_SHOT + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 + waitbgfadein + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20 + playsewithpan SE_M_DIG, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 50, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB_PURPLE + call PoisonBubblesEffect + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20 + playsewithpan SE_M_DIG, SOUND_PAN_TARGET + call PoisonBubblesEffect + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20 + createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20 + playsewithpan SE_M_DIG, SOUND_PAN_TARGET + delay 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + blendoff + delay 0 + call UnsetSkyBg + end +TeraBlastFlying: + loadspritegfx ANIM_TAG_AIR_WAVE_2 + loadspritegfx ANIM_TAG_METAL_SOUND_WAVES + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_METAL_SOUND_WAVES, 0, 12, 12, RGB_WHITE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_WHITE + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + delay 2 + createsprite gAirWaveSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_BLIZZARD2, SOUND_PAN_ATTACKER + waitforvisualfinish + call SetSkyBg + splitbgprio ANIM_TARGET + setalpha 12, 8 + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + call TeraBlastFlyingBeam + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 50, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 2, 0, 12, RGB_WHITE + call TeraBlastFlyingBeam + call TeraBlastFlyingBeam + delay 8 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + blendoff + delay 0 + call UnsetSkyBg + end +TeraBlastRock: + loadspritegfx ANIM_TAG_ROCKS + loadspritegfx ANIM_TAG_FIRE_PLUME + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_FIRE_PLUME, 0, 12, 12, RGB(29, 24, 2) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(29, 24, 2) + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sRockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_ROCK_WRECKER + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0xF000, 0, 0, -1 + waitbgfadein + playsewithpan SE_FALL, SOUND_PAN_TARGET + call TeraBlastRock1 + delay 3 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + call TeraBlastRock2 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 16 @; For Meteor 1 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 + delay 3 + call TeraBlastRock3 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 16 @; For Meteor 2 + delay 3 + call TeraBlastRock4 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 16 @; For Meteor 3 + delay 3 + call TeraBlastRock1 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 16 @; For Meteor 4 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 + delay 3 + call TeraBlastRock2 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 16 @; For Meteor 1 + delay 3 + call TeraBlastRock3 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 16 @; For Meteor 3 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastBug: + loadspritegfx ANIM_TAG_HOLLOW_ORB + loadspritegfx ANIM_TAG_SPARKLE_6 + loadspritegfx ANIM_TAG_IMPACT + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_GREEN + createvisualtask AnimTask_BlendPalInAndOutByTag, 5, ANIM_TAG_HOLLOW_ORB, RGB_GREEN, 14, 0, 3 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + delay 2 + createsprite gDragonDanceOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER + waitforvisualfinish + monbg ANIM_DEF_PARTNER + call SetBugBg + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 50, 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, 30 + delay 1 + createsprite gMaxFlutterbyButterflySpriteTemplate, ANIM_ATTACKER, 2, 3, 0, -20 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 66, 0, 0, 4 + waitforvisualfinish + clearmonbg ANIM_DEF_PARTNER + call UnsetBugBg + end +TeraBlastGround: + loadspritegfx ANIM_TAG_MUD_SAND + loadspritegfx ANIM_TAG_FIRE_PLUME + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(29, 24, 2) + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + delay 2 + createsprite sMudSandSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_ROCK_THROW, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_FISSURE + waitbgfadeout + createvisualtask AnimTask_PositionFissureBgOnBattler, 5, ANIM_TARGET, 5, -1 + waitbgfadein + createvisualtask AnimTask_HorizontalShake, 3, ANIM_TARGET, 10, 50 + playsewithpan SE_M_EARTHQUAKE, SOUND_PAN_TARGET + delay 40 + loopsewithpan SE_M_FLAME_WHEEL2, SOUND_PAN_TARGET 11, 3 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 3, 25, 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 5, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -10, -15 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 0, 25 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 15, 5 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -25, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 30, 30 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, -27, 25 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 0, 8 + delay 1 + loopsewithpan SE_M_FLAME_WHEEL2, SOUND_PAN_TARGET 11, 3 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 5, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -10, -15 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 0, 25 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 15, 5 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -25, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 30, 30 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, -27, 25 + delay 1 + loopsewithpan SE_M_FLAME_WHEEL2, SOUND_PAN_TARGET 11, 3 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 0, 8 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 5, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -10, -15 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 0, 25 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 15, 5 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, -25, 0 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, 30, 30 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 2, 1, -27, 25 + delay 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 66, 1, 0, 8 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 66, 0, 0, 4 + waitforvisualfinish + restorebg + waitbgfadeout + setarg 7, -1 + waitbgfadein + end +TeraBlastGhost: + loadspritegfx ANIM_TAG_PURPLE_FLAME + loadspritegfx ANIM_TAG_EXPLOSION + loadspritegfx ANIM_TAG_GHOSTLY_SPIRIT + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_PURPLE + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_NIGHTMARE, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_GHOST + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 2, 46, 1 + delay 6 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 40, 40, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -40, -40, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 0, 40, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB_PURPLE + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 0, -40, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 40, -20, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 40, 20, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -40, -20, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -40, 20, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -20, 30, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 20, -30, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -20, -30, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 20, 30, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, -40, 0, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 2 + createsprite gGhostProjectileSpriteTemplate, ANIM_TARGET, 2, 40, 0, 16 + playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET + delay 6 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastSteel: + loadspritegfx ANIM_TAG_METAL_BALL + loadspritegfx ANIM_TAG_ROCKS + loadspritegfx ANIM_TAG_REALLY_BIG_ROCK + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_ROCKS, 0, 12, 12, RGB(25, 25, 25) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_REALLY_BIG_ROCK, 0, 12, 12, RGB(25, 25, 25) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(25, 25, 25) + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite sMetalBallSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + waitforvisualfinish + call SetSteelBeamBackground + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER + call ContinentalCrushStockpileRocks + createsprite gContinentalCrushGrowingRockSpriteTemplate, ANIM_ATTACKER, 41, 0, 0, 0, 0 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_ATTACKER + call ContinentalCrushStockpileRocks + delay 30 + loopsewithpan SE_M_HARDEN, SOUND_PAN_ATTACKER, 28, 2 + createvisualtask AnimTask_MetallicShine, 5, 0, 0, RGB_BLACK + waitforvisualfinish + playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER + createsprite gReallyBigRockBlastRockSpriteTemplate, ANIM_TARGET, 2, 16, 0, 0, 0, 25, 257 + waitforvisualfinish + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastFire: + loadspritegfx ANIM_TAG_SMALL_EMBER + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(31, 0, 0) + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + waitforvisualfinish + monbg ANIM_ATTACKER + setalpha 14, 8 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 12, 0 + waitforvisualfinish + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + createvisualtask AnimTask_GetAttackerSide, 2 + jumprettrue TeraBlastFireOnPlayer + goto TeraBlastFireOnOpponent +TeraBlastFireOnOpponent: + panse SE_M_FLAMETHROWER, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0 + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 43, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB(31, 0, 0) + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 12, 0, 0 + waitforvisualfinish + blendoff + clearmonbg ANIM_ATTACKER + end +TeraBlastFireOnPlayer: + panse SE_M_FLAMETHROWER, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0 + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 43, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB(31, 0, 0) + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 12, 0, 0 + waitforvisualfinish + blendoff + clearmonbg ANIM_ATTACKER + end +TeraBlastWater: + loadspritegfx ANIM_TAG_HYDRO_PUMP + loadspritegfx ANIM_TAG_FIRE_PLUME + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_FIRE_PLUME, 0, 12, 12, RGB_BLUE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_BLUE + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_HYDRO_PUMP, SOUND_PAN_ATTACKER + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + delay 2 + createsprite gHydroPumpSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + waitforvisualfinish + fadetobg BG_WATER + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 + waitbgfadein + playsewithpan SE_FALL, SOUND_PAN_TARGET + call TeraBlastWater1 + delay 3 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + call TeraBlastWater2 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 16 @; For Meteor 1 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 + delay 3 + call TeraBlastWater3 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 16 @; For Meteor 2 + delay 3 + call TeraBlastWater4 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 16 @; For Meteor 3 + delay 3 + call TeraBlastWater1 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 16 @; For Meteor 4 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 + delay 3 + call TeraBlastWater2 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 16 @; For Meteor 1 + delay 3 + call TeraBlastWater3 + playsewithpan SE_M_WATERFALL, SOUND_PAN_TARGET + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 16 @; For Meteor 3 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastGrass: + loadspritegfx ANIM_TAG_LEAF + loadspritegfx ANIM_TAG_FLOWER + loadspritegfx ANIM_TAG_EXPLOSION + loadspritegfx ANIM_TAG_AIR_WAVE_2 + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(0, 31, 0) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_AIR_WAVE_2, 0, 12, 12, RGB_GREEN + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite gBloomDoomPetalSpinSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_LEAF_STORM + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + call AeroblastBeam + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 5, 0, 50, 1 + call AeroblastBeam + call AeroblastBeam + call AeroblastBeam + call AeroblastBeam + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastElectric: + loadspritegfx ANIM_TAG_SHOCK + loadspritegfx ANIM_TAG_SPARK + loadspritegfx ANIM_TAG_SHOCK_3 + loadspritegfx ANIM_TAG_SPARK_2 + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_YELLOW + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + delay 2 + createsprite sCirclingShockSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_THUNDER + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0xff00, 0, 1, -1 + waitbgfadein + loopsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_TARGET, 3, 10 + createsprite gThunderboltOrbSpriteTemplate, ANIM_TARGET, 3, 44, 0, 0, 3 + createsprite gThunderboltOrbSpriteTemplate, ANIM_TARGET, 3, 44, 0, 0, 3 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 0, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 64, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 128, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 192, 40, 2, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 32, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 96, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 160, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 224, 40, 2, -32765 + delay 0 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + createsprite gThunderboltOrbSpriteTemplate, ANIM_TARGET, 3, 44, 0, 0, 3 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 0, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 64, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 128, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 192, 40, 2, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 32, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 96, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 160, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 224, 40, 2, -32765 + delay 0 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + createsprite gThunderboltOrbSpriteTemplate, ANIM_TARGET, 3, 44, 0, 0, 3 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 0, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 64, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 128, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 32, 44, 192, 40, 2, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 32, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 96, 40, 1, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 160, 40, 0, -32765 + createsprite gSparkElectricityFlashingSpriteTemplate, ANIM_TARGET, 4, 0, 0, 16, 44, 224, 40, 2, -32765 + delay 0 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 2, 2, RGB_BLACK + delay 6 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 6, RGB_BLACK + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 0, 6, 0, RGB_BLACK + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastPsychic: + loadspritegfx ANIM_TAG_PINKVIO_ORB + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_PINKVIO_ORB, 0, 12, 12, RGB_PURPLE + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_PURPLE + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + delay 2 + createsprite gPinkVioletOrbSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_REVERSAL, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_PSYCHIC + waitbgfadeout + createvisualtask AnimTask_SetPsychicBackground, 5 + waitbgfadein + createvisualtask AnimTask_InvertScreenColor, 2, 0x1 | 0x2 | 0x4 + loopsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET, 10, 3 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 8, 8, 30, 1 + createvisualtask AnimTask_ScaleMonAndRestore, 5, -4, -4, 30, ANIM_TARGET, 1 + waitforvisualfinish + createvisualtask AnimTask_InvertScreenColor, 2, 0x1 | 0x2 | 0x4 + waitforvisualfinish + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastIce: + loadspritegfx ANIM_TAG_ICE_CRYSTALS + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(12, 26, 31) @ light blue + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 2 + createsprite sIceCrystalSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_ICE + waitbgfadein + createvisualtask AnimTask_BlendBattleAnimPal, 10, 4, 2, 0, 9, RGB(12, 26, 31) + playsewithpan SE_M_STRING_SHOT, SOUND_PAN_TARGET + createsprite gIceCrystalSpiralInwardSmall, ANIM_ATTACKER, 2, 0 + createsprite gIceCrystalSpiralInwardSmall, ANIM_ATTACKER, 2, 64 + createsprite gIceCrystalSpiralInwardSmall, ANIM_ATTACKER, 2, 128 + createsprite gIceCrystalSpiralInwardSmall, ANIM_ATTACKER, 2, 192 + delay 5 + createsprite gIceCrystalSpiralInwardLarge, ANIM_ATTACKER, 2, 32 + createsprite gIceCrystalSpiralInwardLarge, ANIM_ATTACKER, 2, 96 + createsprite gIceCrystalSpiralInwardLarge, ANIM_ATTACKER, 2, 160 + createsprite gIceCrystalSpiralInwardLarge, ANIM_ATTACKER, 2, 224 + delay 17 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 5, 3, 1 + waitforvisualfinish + delay 15 + call IceCrystalEffectShort + delay 5 + call IceCrystalEffectShort + delay 5 + call IceCrystalEffectShort + delay 5 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + createvisualtask AnimTask_BlendBattleAnimPal, 10, 4, 2, 9, 0, RGB(12, 26, 31) + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastDragon: + loadspritegfx ANIM_TAG_SMALL_EMBER + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_SMALL_EMBER, 0, 12, 12, RGB(10, 25, 31) + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB(10, 25, 31) + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + delay 2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_FIRE_2 + waitbgfadeout + createvisualtask AnimTask_StartSlidingBg, 5, 0x1000, 0, 0, -1 + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + createvisualtask AnimTask_GetAttackerSide, 2 + jumprettrue TeraBlastDragonOnPlayer + goto TeraBlastDragonOnOpponent +TeraBlastDragonOnOpponent: + panse SE_M_FLAMETHROWER, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0 + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 43, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB(31, 0, 0) + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + call FireSpreadBlast + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastDragonOnPlayer: + panse SE_M_FLAMETHROWER, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, +2, 0 + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 43, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB(31, 0, 0) + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + call FireSpreadBlastOpponent + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastDark: + loadspritegfx ANIM_TAG_PURPLE_FLAME + loadspritegfx ANIM_TAG_METAL_SOUND_WAVES + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_PURPLE_FLAME, 0, 12, 12, RGB_BLACK + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_METAL_SOUND_WAVES, 0, 12, 12, RGB_BLACK + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_BLACK + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + delay 2 + createsprite gPurpleFlameSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_PSYBEAM, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_DARK + waitbgfadein + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 46, 1 + delay 6 + call TeraBlastFlyingBeam + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 3, 0, 50, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 2, 0, 12, RGB_BLACK + call TeraBlastFlyingBeam + call TeraBlastFlyingBeam + delay 8 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastFairy: + loadspritegfx ANIM_TAG_PINK_HEART + loadspritegfx ANIM_TAG_RED_HEART + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_MAGENTA + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + delay 2 + createsprite sPinkHeartSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_M_ATTRACT, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_TWINKLE_TACKLE + waitbgfadein + loopsewithpan SE_M_SUPERSONIC, SOUND_PAN_TARGET, 10, 3 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 4, 4, 0, 12, RGB_MAGENTA + call TeraBlastFairyHearts + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 8, 8, 15, 1 + createvisualtask AnimTask_ScaleMonAndRestore, 5, -4, -4, 15, ANIM_TARGET, 1 + delay 32 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_TARGET + call TeraBlastFairyHearts + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 8, 8, 15, 1 + createvisualtask AnimTask_ScaleMonAndRestore, 5, -4, -4, 15, ANIM_TARGET, 1 + delay 32 + playsewithpan SE_M_MEGA_KICK, SOUND_PAN_TARGET + call TeraBlastFairyHearts + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 8, 8, 15, 1 + createvisualtask AnimTask_ScaleMonAndRestore, 5, -4, -4, 15, ANIM_TARGET, 1 + delay 32 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call TeraBlastFairyHearts + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + blendoff + call UnsetPsychicBg + end +TeraBlastStellar: + loadspritegfx ANIM_TAG_YELLOW_STAR + loadspritegfx ANIM_TAG_EXPLOSION + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_EXPLOSION, 0, 12, 12, RGB_WHITE + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 0 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 4 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 8 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 12 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 16 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 20 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + delay 2 + createsprite gYellowStarSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 56, 24 + playsewithpan SE_SHINY, SOUND_PAN_ATTACKER + waitforvisualfinish + fadetobg BG_COSMIC + waitbgfadein + playsewithpan SE_M_DETECT, SOUND_PAN_ATTACKER + delay 20 + playsewithpan SE_FALL, SOUND_PAN_ATTACKER + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, 0, 30, 0, 1 + delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 + delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 0, 30, 0, 1 + delay 3 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 + delay 2 + playsewithpan SE_M_SWIFT, SOUND_PAN_TARGET + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 0, 1 + delay 3 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 + delay 2 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 10, -5, 30, 0, 1 + delay 3 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 0, 0, 30, 0, 1 + delay 2 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -10, 5, 30, 0, 1 + delay 3 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, -5, 30, 0, 1 + delay 2 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, 5, 5, 30, 0, 1 + delay 3 + createsprite gTeraStarSpriteTemplate, ANIM_BATTLER, 3, 0, 0, -5, 5, 30, 0, 1 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + delay 5 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 5, 1, 1 + delay 5 + playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 50, 1 + call EternabeamGeyser + delay 5 + call EternabeamGeyser + delay 5 + waitforvisualfinish + restorebg + waitbgfadeout + end + +FireSpreadBlast: + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 0, 0, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 10, 5, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, -10, -5, 45 + delay 2 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 20, 10, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, -20, -10, 45 + delay 2 + return +FireSpreadBlastOpponent: + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 0, 0, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5, 10, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, -5, -10, 45 + delay 2 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 10, 20, 45 + createsprite gFireSpreadBlastSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, -10, -20, 45 + delay 2 + return + +TeraBlastFlyingBeam: + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + delay 2 + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_TARGET + createsprite gTeraBlastFlyingSpriteTemplate, ANIM_TARGET, 2, 0, 0, 16 + return + +TeraBlastWater1: + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -48, -64, 40, 32, 25 + delay 2 + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -48, -64, 40, 32, 25 + delay 2 + return +TeraBlastWater2: + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -112, -64, -8, 32, 25 + delay 2 + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -112, -64, -8, 32, 25 + delay 2 + return +TeraBlastWater3: + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, 24, 32, 25 + delay 2 + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, 24, 32, 25 + delay 2 + return +TeraBlastWater4: + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, -8, 32, 25 + delay 2 + createsprite gTeraBlastWaterSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, -8, 32, 25 + delay 2 + return + +TeraBlastRock1: + createsprite gTeraBlastRockSpriteTemplate, ANIM_ATTACKER, 3, -48, -64, 40, 32, 25 + delay 4 + return +TeraBlastRock2: + createsprite gTeraBlastRockSpriteTemplate, ANIM_ATTACKER, 3, -112, -64, -8, 32, 25 + delay 4 + return +TeraBlastRock3: + createsprite gTeraBlastRockSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, 24, 32, 25 + delay 4 + return +TeraBlastRock4: + createsprite gTeraBlastRockSpriteTemplate, ANIM_ATTACKER, 3, -80, -64, -8, 32, 25 + delay 4 + return + +TeraBlastFairyHearts: + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 160, -32 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -256, -40 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 128, -16 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 416, -38 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -128, -22 + createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -384, -31 + return + +gBattleAnimMove_OrderUp:: loadspritegfx ANIM_TAG_IMPACT - loadspritegfx ANIM_TAG_POISON_BUBBLE - loadspritegfx ANIM_TAG_THIN_RING - fadetobg BG_DARK - waitbgfadein - playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER - createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 - waitforvisualfinish - delay 10 - playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 - createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 - waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 - delay 3 - waitforvisualfinish - playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - createvisualtask AnimTask_BlendBattleAnimPal, 10, (F_PAL_BG | F_PAL_BATTLERS_2), 3, 10, 0, 0 - createsprite gFoulPlayRingTemplate, ANIM_ATTACKER, 3, 0, 0, 256, 0 + playsewithpan SE_M_ENCORE, SOUND_PAN_ATTACKER + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 + createvisualtask AnimTask_GetCommanderType, 2 + delay 25 + jumpreteq ANIM_ORDER_UP_NONE, OrderUpNone + jumpreteq ANIM_ORDER_UP_CURLY, OrderUpCurly + jumpreteq ANIM_ORDER_UP_DROOPY, OrderUpDroopy + jumpreteq ANIM_ORDER_UP_STRETCHY, OrderUpStretchy +OrderUpNone: + loadspritegfx ANIM_TAG_TATSUGIRI_CURLY + loadspritegfx ANIM_TAG_TATSUGIRI_DROOPY + loadspritegfx ANIM_TAG_TATSUGIRI_STRETCHY + createsprite gOrderUpTatsugiriCurlySpriteTemplate, ANIM_TARGET, 2, -20, 12, 64, 50, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, -10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET delay 2 - createvisualtask AnimTask_BlendBattleAnimPal, 10, (F_PAL_BG | F_PAL_BATTLERS_2), 3, 10, 0, 0 - createsprite gFoulPlayRingTemplate, ANIM_ATTACKER, 3, 0, 0, 256, 0 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 + createsprite gOrderUpTatsugiriDroopySpriteTemplate, ANIM_TARGET, 2, 0, 12, 64, 46, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriStretchySpriteTemplate, ANIM_TARGET, 2, 20, 12, 64, 42, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + end +OrderUpCurly: + loadspritegfx ANIM_TAG_TATSUGIRI_CURLY + createsprite gOrderUpTatsugiriCurlySpriteTemplate, ANIM_TARGET, 2, -20, 12, 64, 50, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, -10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriCurlySpriteTemplate, ANIM_TARGET, 2, 0, 12, 64, 46, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriCurlySpriteTemplate, ANIM_TARGET, 2, 20, 12, 64, 42, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + end +OrderUpDroopy: + loadspritegfx ANIM_TAG_TATSUGIRI_DROOPY + createsprite gOrderUpTatsugiriDroopySpriteTemplate, ANIM_TARGET, 2, -20, 12, 64, 50, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, -10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriDroopySpriteTemplate, ANIM_TARGET, 2, 0, 12, 64, 46, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriDroopySpriteTemplate, ANIM_TARGET, 2, 20, 12, 64, 42, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 - delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + end +OrderUpStretchy: + loadspritegfx ANIM_TAG_TATSUGIRI_STRETCHY + createsprite gOrderUpTatsugiriStretchySpriteTemplate, ANIM_TARGET, 2, -20, 12, 64, 50, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, -10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriStretchySpriteTemplate, ANIM_TARGET, 2, 0, 12, 64, 46, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET + delay 2 + createsprite gOrderUpTatsugiriStretchySpriteTemplate, ANIM_TARGET, 2, 20, 12, 64, 42, 0 + delay 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 10, 0, ANIM_TARGET, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET waitforvisualfinish - blendoff - call UnsetPsychicBg end - -gBattleAnimMove_NoxiousTorque:: - loadspritegfx ANIM_TAG_IMPACT + +gBattleAnimMove_MatchaGotcha:: loadspritegfx ANIM_TAG_POISON_BUBBLE - fadetobg BG_GUNK_SHOT - waitbgfadeout - createvisualtask AnimTask_StartSlidingBg, 5, 0x0A00, 0, 1, -1 - waitbgfadein playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 waitforvisualfinish delay 10 - playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 - createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 - waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 - delay 3 - waitforvisualfinish - playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 1, 2, 0, 12, RGB(30, 0, 31) - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 27, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -27, 44, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 39, -28, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -42, -42, 20 - delay 5 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 0, 40, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -8, -44, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -46, -28, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 46, 9, 20 - delay 5 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 42, 0, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -43, -12, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, 16, -46, 20 - createsprite gSludgeBombHitParticleSpriteTemplate, ANIM_TARGET, 2, -16, 44, 20 - delay 0 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 - waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE + loopsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER, 27, 2 + createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_POISON_BUBBLE, 0, 12, 12, RGB_GREEN + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 24, 6, 2, 3 waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 + loopsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER, 18, 2 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 28, 10, 2, 4 waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 - delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + loopsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER, 9, 4 + createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 32, 10, 4, 5 waitforvisualfinish - blendoff - call UnsetPsychicBg - end + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, ANIM_ATTACKER, 20, 0, 0, 4 + jumpifdoublebattle MatchaGotchaDouble + goto MatchaGotchaSingle -gBattleAnimMove_CombatTorque:: - loadspritegfx ANIM_TAG_IMPACT - loadspritegfx ANIM_TAG_METEOR - fadetobg BG_IN_AIR - waitbgfadeout - createvisualtask AnimTask_StartSlidingBg, 5, 0, 0x1000, 0, -1 - waitbgfadein - playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER - createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 - waitforvisualfinish +MatchaGotchaSingle: + call MatchaGotchaProjectile + call MatchaGotchaProjectile + loopsewithpan SE_FALL, SOUND_PAN_ATTACKER, 8, 2 + call MatchaGotchaProjectile + call MatchaGotchaProjectile delay 10 - playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 - createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 - waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 7 + delay 28 + playsewithpan SE_M_DIVE, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 2, 0, 10, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 2, 2, 0, 12, RGB(31, 0, 0) + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 10, 15, 55, FALSE + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -20, 15, 55, FALSE delay 3 - waitforvisualfinish - playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - createsprite gSuperpowerFireballSpriteTemplate, ANIM_TARGET, 3, ANIM_ATTACKER - delay 4 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 - waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE - waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 - waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 5, 15, 55, FALSE + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -10, 15, 55, FALSE delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 30, 15, 55, FALSE + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -30, 15, 55, FALSE + delay 3 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 2, 15, 55, FALSE + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -5, 15, 55, FALSE + delay 3 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 20, 15, 55, FALSE waitforvisualfinish - clearmonbg ANIM_DEF_PARTNER - blendoff - call UnsetPsychicBg end -gBattleAnimMove_MagicalTorque:: - loadspritegfx ANIM_TAG_IMPACT - loadspritegfx ANIM_TAG_PINK_HEART - loadspritegfx ANIM_TAG_DUCK - loadspritegfx ANIM_TAG_RED_HEART - fadetobg BG_TWINKLE_TACKLE - waitbgfadeout - playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER - createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_ATTACKER, 4, 2, RGB_WHITE, 10, RGB_BLACK, 0 - waitforvisualfinish +MatchaGotchaDouble: + playsewithpan SE_M_BUBBLE3, SOUND_PAN_ATTACKER + call MatchaGotchaDoubleProjectile + call MatchaGotchaDoubleProjectile + loopsewithpan SE_FALL, SOUND_PAN_ATTACKER, 8, 2 + call MatchaGotchaDoubleProjectile + call MatchaGotchaDoubleProjectile delay 10 - playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 - createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 7 waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 0, 16, 16, RGB_WHITE - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + playsewithpan SE_M_DIVE, SOUND_PAN_TARGET + createvisualtask AnimTask_ShakeMon2, 5, ANIM_TARGET, 2, 0, 10, 1 + createvisualtask AnimTask_ShakeMon2, 5, ANIM_DEF_PARTNER, 2, 0, 10, 1 + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 2, 2, 0, 12, RGB(31, 0, 0) + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 10, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -20, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 10, 15, 55, 2 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -20, 15, 55, 2 delay 3 - waitforvisualfinish - playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 160, -32 - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -256, -40 - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 128, -16 - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, 416, -38 - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -128, -22 - createsprite gRedHeartBurstSpriteTemplate, ANIM_TARGET, 3, -384, -31 - delay 0 - createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, ANIM_TARGET, 0 - createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 1, -32, 0, 0, 3 - waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 - createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 - createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, F_PAL_BG, 2, 16, 0, RGB_WHITE - waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 - waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 5, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -10, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 5, 15, 55, 2 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -10, 15, 55, 2 delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 1, 0, 7 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 30, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -30, 15, 55, 0 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, 30, 15, 55, 2 + createsprite gAcidPoisonDropletSpriteTemplate, ANIM_TARGET, 2, 0, -10, -30, 15, 55, 2 waitforvisualfinish - blendoff - call UnsetPsychicBg end -gBattleAnimMove_TeraBlast:: -gBattleAnimMove_OrderUp:: -gBattleAnimMove_MatchaGotcha:: - end @to do +MatchaGotchaProjectile: + createsprite gSludgeProjectileSpriteTemplate, ANIM_TARGET, 2, 20, 0, 60, 0 + delay 3 + return + +MatchaGotchaDoubleProjectile: + createsprite gSludgeProjectileSpriteTemplate, ANIM_TARGET, 2, 20, 0, 60, 0, 0 + createsprite gSludgeProjectileSpriteTemplate, ANIM_TARGET, 2, 20, 0, 60, 0, TRUE + delay 3 + return @@@@@@@@@@@@@@@@@@@@@@@ GEN 1-3 @@@@@@@@@@@@@@@@@@@@@@@ gBattleAnimMove_None:: @@ -29761,7 +31619,6 @@ gBattleAnimGeneral_TeraCharge:: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 1, 0 call TeraChargeParticles playsewithpan SE_M_BRICK_BREAK, SOUND_PAN_ATTACKER clearmonbg ANIM_ATK_PARTNER @@ -29778,14 +31635,36 @@ TeraChargeParticles: return gBattleAnimGeneral_TeraActivate:: + loadspritegfx ANIM_TAG_TERA_SYMBOL + loadspritegfx ANIM_TAG_SPARKLE_6 + createvisualtask AnimTask_HideSwapSprite, 2, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 - waitforvisualfinish createvisualtask SoundTask_PlayNormalCry, 0 + createsprite gTeraSymbolSpriteTemplate ANIM_ATTACKER, 41, 0, 0, ANIM_ATTACKER + delay 2 + call TeraSpinEffect + call TeraSpinEffect + waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff end +TeraSpinEffect: + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 12, 528, 30, 13, 50, 0 + delay 2 + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 0, 480, 20, 16, -46, 0 + delay 2 + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 1, 576, 20, 8, 42, 0 + delay 2 + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 15, 400, 25, 11, -42, 0 + delay 2 + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 12, 512, 25, 16, 46, 0 + delay 2 + createsprite gTeraSmokeSpriteTemplate ANIM_ATTACKER, 7, 0, 1, 464, 30, 15, -50, 0 + delay 2 + return + gBattleAnimGeneral_RestoreBg:: restorebg waitbgfadein diff --git a/graphics/battle_anims/sprites/tatsugiri_curly.png b/graphics/battle_anims/sprites/tatsugiri_curly.png new file mode 100644 index 0000000000000000000000000000000000000000..8642833f8f44cdfb156c4c9ea43ca6fe472fe45e GIT binary patch literal 1045 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuIw+_*x96+Z|^#t2ow@8 zag8Vm&QB{TPb^AhaQATm8lzB_TBKmCXHwX@!lvNA9*GX(gAxE3E>0+cFKm;axszd6A8aAoR?7eD^5YU%MZPf96VyMD)? zKYu`GjDpb+7>*%OcFRT_=r6`3Z+DmfOW8ji1#&VyT^vIy=DfY&D0D!9!#R*?V@CD= z-(oS%dmaA2(8`a|`1HM;@5hZ^b;cUT&CCI!z2a62v!=1jsCMMCUsEVIdM{zBP-yuw z?mg3YhKp;y>puD@x#(VMqWRq|jOE)>wmmp`?cX}Ll(W~qGd*-<3M$#RqZJggp00i_ I>zopr09Ar<7ytkO literal 0 HcmV?d00001 diff --git a/graphics/battle_anims/sprites/tatsugiri_droopy.png b/graphics/battle_anims/sprites/tatsugiri_droopy.png new file mode 100644 index 0000000000000000000000000000000000000000..ae478dec5c8dd7024cb0b92047700f343eb8b783 GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuIw+_*x6(xGiNTj0~8W3 zag8Vm&QB{TPb^AhaQATm8lzB_TBKmCXHwX@!lvNA9*GX(gAxE3E>0+dQhDg5*2Pp-20A;;9WdDC9J__22V4v^MSFd72G zIs_^Y{kH{rkTJ>I-R1vM_D@HFoCHr7$B>FSZzmWEH5hQP>}+=V|38UwYv6`$C;0B> zawu$y_#gWootIs|&{Wuq_sUp51)yC~6`}TwbnKsc1_xSQt9=UyFpLipr?ZdoD q)eeU7TVjs*FQ{z&7REDc&2xr*TudyfN_^`;A?xYt=d#Wzp$P!>*k>F7 literal 0 HcmV?d00001 diff --git a/graphics/battle_anims/sprites/tatsugiri_stretchy.png b/graphics/battle_anims/sprites/tatsugiri_stretchy.png new file mode 100644 index 0000000000000000000000000000000000000000..650807db0e540e4b674f35b95c9dabfe9340242b GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuIw+_*x6(y*jtx!1BJv( zTq8~zxRIPgaA x(VHsOqgy+)XB~Qfgf;hrir(w>852#`J!cJJW!w~y7nKAGT2EI$mvv4FO#s?ySw~f%Kqsnkdxx+;uumfXKA1#-vI@VX8DM^ zg#Z6fJe=eA^vJa%6GSeF3BJ6bWNjx9wz*}}dX7^HB73FVdQ I&MBb@0Ktxb-T(jq literal 0 HcmV?d00001 diff --git a/include/battle_anim.h b/include/battle_anim.h index e62c170cc0..7cef5445da 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -93,6 +93,7 @@ void AnimWeatherBallUp(struct Sprite *sprite); void AnimWeatherBallDown(struct Sprite *sprite); void AnimSpinningSparkle(struct Sprite *sprite); void SetAverageBattlerPositions(u8 battler, bool8 respectMonPicOffsets, s16 *x, s16 *y); +void SetToPartnerPositions(u8 battler, bool8 respectMonPicOffsets, s16 *x, s16 *y); void DestroySpriteAndMatrix(struct Sprite *sprite); void TranslateSpriteLinearFixedPoint(struct Sprite *sprite); void InitSpritePosToAnimAttacker(struct Sprite *sprite, bool8 respectMonPicOffsets); @@ -230,6 +231,8 @@ void AnimMudSportDirt(struct Sprite *sprite); void AnimDirtScatter(struct Sprite *sprite); void AnimMudSportDirtRising(struct Sprite *sprite); void AnimDirtPlumeParticle(struct Sprite *); +void AnimBoneHitProjectile(struct Sprite *sprite); +extern const union AnimCmd *const sAnims_MudSlapMud[]; extern const union AffineAnimCmd *const gAffineAnims_SpinningBone[]; // battle_anim_throw.c @@ -268,6 +271,7 @@ void AnimTranslateLinearSingleSineWave(struct Sprite *sprite); void AnimTeraStarstormStars(struct Sprite *sprite); void AnimGrantingStars(struct Sprite *sprite); void AnimFollowMeFinger(struct Sprite *sprite); +void AnimPoisonJabProjectile(struct Sprite *sprite); extern const union AnimCmd *const gRazorLeafParticleAnimTable[]; extern const union AnimCmd *const gPowerAbsorptionOrbAnimTable[]; extern const union AffineAnimCmd *const gPowerAbsorptionOrbAffineAnimTable[]; @@ -466,6 +470,7 @@ void AnimElectricity(struct Sprite *); void AnimTask_VoltSwitch(struct Sprite* sprite); extern const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb[]; extern const union AffineAnimCmd *const gAffineAnims_FlashingSpark[]; +extern const union AnimCmd *const sAnims_CirclingElectricShock[]; extern const union AnimCmd *const gAnims_ThunderboltOrb[]; extern const union AnimCmd *const gAnims_ElectricPuff[]; extern const union AnimCmd *const gAnims_ElectricChargingParticles[]; @@ -490,6 +495,8 @@ extern const union AnimCmd *const gAnims_FlyingRock[]; extern const union AffineAnimCmd *const gAffineAnims_Whirlpool[]; extern const union AffineAnimCmd *const gAffineAnims_BasicRock[]; extern const union AnimCmd *const gAnims_FlyingRock[]; +extern const union AnimCmd *const sAnims_BasicRock[]; +void AnimRockTomb(struct Sprite *sprite); void AnimParticleInVortex(struct Sprite *sprite); void AnimFallingRock(struct Sprite *sprite); void AnimRaiseSprite(struct Sprite *sprite); @@ -557,6 +564,9 @@ void InitSpritePosToAnimTargetsCentre(struct Sprite *sprite, bool32 respectMonPi extern const union AffineAnimCmd *const gSpriteAffineAnimTable_PrimalSymbol[]; extern const union AffineAnimCmd *const gSpriteAffineAnimTable_MegaSymbol[]; +// battle_anim_ice.c +void AnimIceBeamParticle(struct Sprite *sprite); + // battle_anim_bug.c void AnimTranslateStinger(struct Sprite *sprite); diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index c85dcc9fe7..3d514b1936 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -419,6 +419,10 @@ #define ANIM_TAG_PINKVIO_ORB (ANIM_SPRITES_START + 405) #define ANIM_TAG_STARSTORM (ANIM_SPRITES_START + 406) #define ANIM_TAG_SALT_PARTICLE (ANIM_SPRITES_START + 407) +#define ANIM_TAG_TERA_SYMBOL (ANIM_SPRITES_START + 408) +#define ANIM_TAG_TATSUGIRI_CURLY (ANIM_SPRITES_START + 409) +#define ANIM_TAG_TATSUGIRI_DROOPY (ANIM_SPRITES_START + 410) +#define ANIM_TAG_TATSUGIRI_STRETCHY (ANIM_SPRITES_START + 411) // battlers #define ANIM_ATTACKER 0 @@ -657,6 +661,12 @@ #define ANIM_SURF_PAL_MUDDY_WATER 1 #define ANIM_SURF_PAL_SLUDGE_WAVE 2 +// Order Up palettes for Commander +#define ANIM_ORDER_UP_NONE 0 +#define ANIM_ORDER_UP_CURLY 1 +#define ANIM_ORDER_UP_DROOPY 2 +#define ANIM_ORDER_UP_STRETCHY 3 + // Flags given to various functions to indicate which palettes to consider. // Handled by UnpackSelectedBattlePalettes #define F_PAL_BG (1 << 0) diff --git a/include/graphics.h b/include/graphics.h index 262afd5337..82bf2691eb 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2700,6 +2700,8 @@ extern const u32 gBattleAnimSpriteGfx_MegaParticles[]; extern const u16 gBattleAnimSpritePal_MegaParticles[]; extern const u32 gBattleAnimSpriteGfx_MegaSymbol[]; extern const u16 gBattleAnimSpritePal_MegaSymbol[]; +extern const u32 gBattleAnimSpriteGfx_TeraSymbol[]; +extern const u16 gBattleAnimSpritePal_TeraSymbol[]; extern const u32 gBattleAnimSpriteGfx_FlashCannonBall[]; extern const u16 gBattleAnimSpritePal_FlashCannonBall[]; extern const u32 gBattleAnimSpriteGfx_WaterGun[]; @@ -2712,6 +2714,12 @@ extern const u32 gBattleAnimSpriteGfx_TeraCrystal[]; extern const u16 gBattleAnimSpritePal_TeraCrystal[]; extern const u32 gBattleAnimSpriteGfx_TeraShatter[]; extern const u16 gBattleAnimSpritePal_TeraShatter[]; +extern const u32 gBattleAnimSpriteGfx_TatsugiriCurly[]; +extern const u16 gBattleAnimSpritePal_TatsugiriCurly[]; +extern const u32 gBattleAnimSpriteGfx_TatsugiriDroopy[]; +extern const u16 gBattleAnimSpritePal_TatsugiriDroopy[]; +extern const u32 gBattleAnimSpriteGfx_TatsugiriStretchy[]; +extern const u16 gBattleAnimSpritePal_TatsugiriStretchy[]; // New Battle Anim Particles extern const u32 gBattleAnimSpriteGfx_AlphaStone[]; diff --git a/src/battle_anim_dark.c b/src/battle_anim_dark.c index 12a75efa31..f8f2dcd0d0 100644 --- a/src/battle_anim_dark.c +++ b/src/battle_anim_dark.c @@ -257,6 +257,21 @@ const struct SpriteTemplate gPunishmentImpactSpriteTemplate = .callback = AnimPunishment, }; +// See AnimShadowBall in battle_anim_ghost.c for more specifics +// arg 0: duration step 1 (attacker -> center) +// arg 1: duration step 2 (spin center) +// arg 2: duration step 3 (center -> target) +const struct SpriteTemplate gDarkPulseSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_RING, + .paletteTag = ANIM_TAG_PURPLE_RING, + .oam = &gOamData_AffineDouble_ObjNormal_16x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_SpinningBone, + .callback = AnimShadowBall, +}; + // arg 0: x pixel offset // arg 1: y pixel offset // arg 2: Something diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index bc3b4a2c44..98530b4f0a 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -154,7 +154,6 @@ static void AnimDoubleTeam(struct Sprite *); static void AnimNightSlash(struct Sprite *); static void AnimRockPolishStreak(struct Sprite *); static void AnimRockPolishSparkle(struct Sprite *); -static void AnimPoisonJabProjectile(struct Sprite *); static void AnimNightSlash(struct Sprite *); static void AnimPluck(struct Sprite *); static void AnimAcrobaticsSlashes(struct Sprite *); @@ -5190,7 +5189,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) { if (gBattleAnimArgs[0] == 0) { - if (IsDoubleBattle()) + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimAttacker, TRUE, &a, &b); } @@ -5202,7 +5201,7 @@ void AnimNeedleArmSpike(struct Sprite *sprite) } else { - if (IsDoubleBattle()) + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) { SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &a, &b); } @@ -7450,7 +7449,7 @@ static void AnimRockPolishSparkle(struct Sprite *sprite) // arg 0: initial x pixel offset // arg 1: initial y pixel offset // arg 2: duration -static void AnimPoisonJabProjectile(struct Sprite *sprite) +void AnimPoisonJabProjectile(struct Sprite *sprite) { s16 targetXPos; s16 targetYPos; diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 409244ccac..6efac4c79b 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -1325,6 +1325,41 @@ const struct SpriteTemplate gTeraCrystalSpreadSpriteTemplate = .callback = AnimTask_TeraCrystalShatter, }; +// See AnimSpriteOnMonPos in battle_anim_mons.c for more specifics +// Reuses the Mega Symbol affine animation seen in Mega Evolution +// gBattleAnimArgs 0-3 used +// 0, 1 used for position +// 2, 3 as some control variables +const struct SpriteTemplate gTeraSymbolSpriteTemplate = +{ + .tileTag = ANIM_TAG_TERA_SYMBOL, + .paletteTag = ANIM_TAG_TERA_SYMBOL, + .oam = &gOamData_AffineDouble_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_MegaSymbol, + .callback = AnimSpriteOnMonPos, +}; + +// Swirls particle in vortex. Used for moves like Fire Spin or Sand Tomb +// args[0] - initial x offset +// args[1] - initial y offset +// args[2] - y increment +// args[3] - duration +// args[4] - increments some sin parameter +// args[5] - fixed sin parameter +// args[6] - attacker or target +const struct SpriteTemplate gTeraSmokeSpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_6, + .paletteTag = ANIM_TAG_SPARKLE_6, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimParticleInVortex, +}; + const struct SpriteTemplate gPinkPetalVortexTemplate = { .tileTag = ANIM_TAG_PINK_PETAL, diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c index 593f3830ba..269d582f3b 100644 --- a/src/battle_anim_electric.c +++ b/src/battle_anim_electric.c @@ -10,7 +10,7 @@ static void AnimLightning(struct Sprite *); static void AnimLightning_Step(struct Sprite *); static void AnimUnusedSpinningFist(struct Sprite *); static void AnimUnusedSpinningFist_Step(struct Sprite *); -static void AnimUnusedCirclingShock(struct Sprite *); +static void AnimCirclingElectricShock(struct Sprite *); static void AnimZapCannonSpark_Step(struct Sprite *); static void AnimThunderboltOrb(struct Sprite *); static void AnimThunderboltOrb_Step(struct Sprite *); @@ -83,7 +83,9 @@ static const struct SpriteTemplate sUnusedSpinningFistSpriteTemplate = .callback = AnimUnusedSpinningFist, }; -static const union AnimCmd sAnim_UnusedCirclingShock[] = +// Previously an unused function named sAnim_CirclingElectricShock +// Now used for Tera Blast Electric +static const union AnimCmd sAnim_CirclingElectricShock[] = { ANIMCMD_FRAME(0, 5), ANIMCMD_FRAME(16, 5), @@ -94,21 +96,24 @@ static const union AnimCmd sAnim_UnusedCirclingShock[] = ANIMCMD_JUMP(0), }; -static const union AnimCmd *const sAnims_UnusedCirclingShock[] = +// Previously an unused function named sAnims_UnusedCirclingShock +// Now used for Tera Blast Electric +const union AnimCmd *const sAnims_CirclingElectricShock[] = { - sAnim_UnusedCirclingShock, + sAnim_CirclingElectricShock, }; -// Unused -static const struct SpriteTemplate sUnusedCirclingShockSpriteTemplate = +// Previously named sUnusedCirclingShockSpriteTemplate +// Still unused, but renamed for consistency +static const struct SpriteTemplate sCirclingElectricShockSpriteTemplate = { .tileTag = ANIM_TAG_SHOCK, .paletteTag = ANIM_TAG_SHOCK, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_UnusedCirclingShock, + .anims = sAnims_CirclingElectricShock, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = AnimUnusedCirclingShock, + .callback = AnimCirclingElectricShock, }; const struct SpriteTemplate gSparkElectricitySpriteTemplate = @@ -675,7 +680,7 @@ static void AnimUnusedSpinningFist_Step(struct Sprite *sprite) DestroySpriteAndMatrix(sprite); } -static void AnimUnusedCirclingShock(struct Sprite *sprite) +static void AnimCirclingElectricShock(struct Sprite *sprite) { sprite->x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); diff --git a/src/battle_anim_fire.c b/src/battle_anim_fire.c index 276b8c8c07..5d34d47661 100644 --- a/src/battle_anim_fire.c +++ b/src/battle_anim_fire.c @@ -1296,6 +1296,12 @@ static void AnimWillOWispFire(struct Sprite *sprite) sprite->data[3] += 0xC0 * 2; sprite->data[4] += 0xA0; + if (IsDoubleBattle() + && !IsContest() + && IsBattlerAlive(BATTLE_PARTNER(gBattleAnimTarget)) + && GetMoveTarget(gAnimMoveIndex) == MOVE_TARGET_BOTH) + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y); + sprite->x2 = Sin(sprite->data[1], sprite->data[3] >> 8); sprite->y2 = Cos(sprite->data[1], sprite->data[4] >> 8); diff --git a/src/battle_anim_ground.c b/src/battle_anim_ground.c index eb96414b55..1ba6fc0b62 100644 --- a/src/battle_anim_ground.c +++ b/src/battle_anim_ground.c @@ -7,7 +7,6 @@ #include "constants/rgb.h" static void AnimBonemerangProjectile(struct Sprite *); -static void AnimBoneHitProjectile(struct Sprite *); static void AnimDirtPlumeParticle_Step(struct Sprite *); static void AnimDigDirtMound(struct Sprite *); static void AnimBonemerangProjectile_Step(struct Sprite *); @@ -84,7 +83,7 @@ static const union AnimCmd sAnim_MudSlapMud[] = ANIMCMD_END, }; -static const union AnimCmd *const sAnims_MudSlapMud[] = +const union AnimCmd *const sAnims_MudSlapMud[] = { sAnim_MudSlapMud, }; @@ -199,7 +198,7 @@ static void AnimBonemerangProjectile_End(struct Sprite *sprite) // arg 2: target x pixel offset // arg 3: target y pixel offset // arg 4: duration -static void AnimBoneHitProjectile(struct Sprite *sprite) +void AnimBoneHitProjectile(struct Sprite *sprite) { InitSpritePosToAnimTarget(sprite, TRUE); if (!IsOnPlayerSide(gBattleAnimAttacker)) diff --git a/src/battle_anim_ice.c b/src/battle_anim_ice.c index 8aa4ae2563..5b8c599c84 100644 --- a/src/battle_anim_ice.c +++ b/src/battle_anim_ice.c @@ -28,7 +28,6 @@ struct HailStruct { static void AnimUnusedIceCrystalThrow(struct Sprite *); static void AnimUnusedIceCrystalThrow_Step(struct Sprite *); static void AnimIcePunchSwirlingParticle(struct Sprite *); -static void AnimIceBeamParticle(struct Sprite *); static void AnimFlickerIceEffectParticle(struct Sprite *); static void AnimSwirlingSnowball(struct Sprite *); static void AnimSwirlingSnowball_Step2(struct Sprite *); @@ -703,7 +702,7 @@ static void AnimIcePunchSwirlingParticle(struct Sprite *sprite) // arg 2: target x offset // arg 3: target y offset // arg 4: duration -static void AnimIceBeamParticle(struct Sprite *sprite) +void AnimIceBeamParticle(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 879f41f715..5b734e3926 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -777,6 +777,24 @@ void InitSpritePosToAnimAttackerPartner(struct Sprite *sprite, bool8 respectMonP sprite->y += gBattleAnimArgs[1]; } +void InitSpritePosToAnimBothTargets(struct Sprite *sprite, bool8 respectMonPicOffsets) +{ + if (!respectMonPicOffsets) + { + sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X) + GetBattlerSpriteCoord2(BATTLE_PARTNER(gBattleAnimTarget), BATTLER_COORD_X); + sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y) + GetBattlerSpriteCoord2(BATTLE_PARTNER(gBattleAnimTarget), BATTLER_COORD_Y); + } + else + { + sprite->x = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_X_2) + GetBattlerSpriteCoord2(BATTLE_PARTNER(gBattleAnimTarget), BATTLER_COORD_X_2); + sprite->y = GetBattlerSpriteCoord2(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + GetBattlerSpriteCoord2(BATTLE_PARTNER(gBattleAnimTarget), BATTLER_COORD_Y_PIC_OFFSET); + } + sprite->x = sprite->x / 2; + sprite->y = sprite->y / 2; + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->y += gBattleAnimArgs[1]; +} + bool32 InitSpritePosToAnimBattler(u32 animBattlerId, struct Sprite *sprite, bool8 respectMonPicOffsets) { u32 battler = GetAnimBattlerId(animBattlerId); @@ -1445,12 +1463,24 @@ void AnimSpriteOnMonPos(struct Sprite *sprite) else respectMonPicOffsets = FALSE; - if (gBattleAnimArgs[2] == 0) - InitSpritePosToAnimAttacker(sprite, respectMonPicOffsets); - else if (gBattleAnimArgs[2] == 1) - InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); - else if (gBattleAnimArgs[2] == 2) - InitSpritePosToAnimAttackerPartner(sprite, respectMonPicOffsets); + switch(gBattleAnimArgs[2]) + { + case 0: + InitSpritePosToAnimAttacker(sprite, respectMonPicOffsets); + break; + case 1: + InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); + break; + case 2: + InitSpritePosToAnimAttackerPartner(sprite, respectMonPicOffsets); + break; + case 3: + if(IsDoubleBattle()) + InitSpritePosToAnimBothTargets(sprite, respectMonPicOffsets); + else + InitSpritePosToAnimTarget(sprite, respectMonPicOffsets); + break; + } sprite->data[0]++; @@ -2180,6 +2210,37 @@ void SetAverageBattlerPositions(u8 battler, bool8 respectMonPicOffsets, s16 *x, *y = (battlerY + partnerY) / 2; } +void SetToPartnerPositions(u8 battler, bool8 respectMonPicOffsets, s16 *x, s16 *y) +{ + u8 xCoordType, yCoordType; + s16 returnX, returnY; + + if (!respectMonPicOffsets) + { + xCoordType = BATTLER_COORD_X; + yCoordType = BATTLER_COORD_Y; + } + else + { + xCoordType = BATTLER_COORD_X_2; + yCoordType = BATTLER_COORD_Y_PIC_OFFSET; + } + + if (IsDoubleBattle() && !IsContest() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + returnX = GetBattlerSpriteCoord(BATTLE_PARTNER(battler), xCoordType); + returnY = GetBattlerSpriteCoord(BATTLE_PARTNER(battler), yCoordType); + } + else + { + returnX = GetBattlerSpriteCoord(battler, xCoordType); + returnY = GetBattlerSpriteCoord(battler, yCoordType); + } + + *x = returnX; + *y = returnY; +} + u8 CreateInvisibleSpriteCopy(int battler, u8 spriteId, int species) { u8 newSpriteId = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy); diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 7a7d847d09..00281253fa 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -4740,7 +4740,7 @@ static const union AffineAnimCmd* const sSpriteAffineAnimTable_Flutterby[] = { const struct SpriteTemplate gSpriteTemplate_InfernalParadeFlame = { .tileTag = ANIM_TAG_PURPLE_FLAME, .paletteTag = ANIM_TAG_PURPLE_FLAME, - .oam = &gOamData_AffineDouble_ObjBlend_32x16, + .oam = &gOamData_AffineDouble_ObjNormal_16x32, .anims = gAnims_GrudgeFlame, .images = NULL, .affineAnims = sSpriteAffineAnimTable_Flutterby, @@ -5695,7 +5695,7 @@ const struct SpriteTemplate gBlackHoleEclipseBlueRingSpriteTemplate = const struct SpriteTemplate gBlackHoleEclipseBlackRingSpriteTemplate = { .tileTag = ANIM_TAG_THIN_RING, - .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_SHADOW_BALL, .oam = &gOamData_AffineDouble_ObjNormal_64x64, .anims = gDummySpriteAnimTable, .images = NULL, @@ -7312,6 +7312,287 @@ const struct SpriteTemplate gOmegaGeyserSpriteTemplate = .callback = SpriteCB_Geyser, }; +// Moves objects (ice crystals) in a wave-like behavior. Seen in Max Flutterby +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: wave amplitude +const struct SpriteTemplate gIceShardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineDouble_ObjBlend_8x8, + .anims = gAnims_IceCrystalSmall, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_Flutterby, + .callback = SpriteCB_MaxFlutterby +}; + +const struct SpriteTemplate gSpinningVineSpriteTemplate = +{ + .tileTag = ANIM_TAG_PUNISHMENT_BLADES, + .paletteTag = ANIM_TAG_LEAF, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_SpinningBone, + .callback = AnimBoneHitProjectile, +}; + +const struct SpriteTemplate gMaxFlutterbyButterflySpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARKLE_6, + .paletteTag = ANIM_TAG_SPARKLE_6, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_Flutterby, + .callback = SpriteCB_MaxFlutterby +}; + +const struct SpriteTemplate gReallyBigRockBlastRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_REALLY_BIG_ROCK, + .paletteTag = ANIM_TAG_REALLY_BIG_ROCK, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockBlastRock, +}; + +const struct SpriteTemplate gOrderUpTatsugiriCurlySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_CURLY, + .paletteTag = ANIM_TAG_TATSUGIRI_CURLY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +const struct SpriteTemplate gOrderUpTatsugiriDroopySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_DROOPY, + .paletteTag = ANIM_TAG_TATSUGIRI_DROOPY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +const struct SpriteTemplate gOrderUpTatsugiriStretchySpriteTemplate = +{ + .tileTag = ANIM_TAG_TATSUGIRI_STRETCHY, + .paletteTag = ANIM_TAG_TATSUGIRI_STRETCHY, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_DreepyMissilePlayer, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimRockTomb, +}; + +// Start of Tera Blast sprite templates +const struct SpriteTemplate gFireSpreadBlastSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_BasicFire, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIceBeamParticle, +}; + +const struct SpriteTemplate gPurpleFlameSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PURPLE_FLAME, + .paletteTag = ANIM_TAG_PURPLE_FLAME, + .oam = &gOamData_AffineOff_ObjBlend_16x32, + .anims = gAnims_GrudgeFlame, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gAirWaveSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_AIR_WAVE_2, + .paletteTag = ANIM_TAG_AIR_WAVE_2, + .oam = &gOamData_AffineOff_ObjNormal_32x16, + .anims = gAffineAnims_AirWaveCrescent, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gPinkVioletOrbSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PINKVIO_ORB, + .paletteTag = ANIM_TAG_PINKVIO_ORB, + .oam = &gOamData_AffineNormal_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gHydroPumpSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineOff_ObjBlend_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sCirclingShockSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHOCK, + .paletteTag = ANIM_TAG_SHOCK, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_CirclingElectricShock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sIceCrystalSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_AffineDouble_ObjBlend_8x16, + .anims = gAnims_IceCrystalLarge, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sMudSandSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_MUD_SAND, + .paletteTag = ANIM_TAG_MUD_SAND, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = sAnims_MudSlapMud, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sPoisonSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = &gAnims_PoisonProjectile[0], + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sRockSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = gAnims_FlyingRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sMetalBallSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_METAL_BALL, + .paletteTag = ANIM_TAG_METAL_BALL, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate sPinkHeartSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_PINK_HEART, + .paletteTag = ANIM_TAG_PINK_HEART, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gDragonDanceOrbSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_HOLLOW_ORB, + .paletteTag = ANIM_TAG_HOLLOW_ORB, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gYellowStarSpiralOutwardSpriteTemplate = +{ + .tileTag = ANIM_TAG_YELLOW_STAR, + .paletteTag = ANIM_TAG_YELLOW_STAR, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireSpiralOutward, +}; + +const struct SpriteTemplate gTeraBlastFlyingSpriteTemplate = +{ + .tileTag = ANIM_TAG_METAL_SOUND_WAVES, + .paletteTag = ANIM_TAG_METAL_SOUND_WAVES, + .oam = &gOamData_AffineDouble_ObjNormal_32x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_SpinningBone, + .callback = AnimShadowBall, +}; + +const struct SpriteTemplate gTeraBlastWaterSpriteTemplate = +{ + .tileTag = ANIM_TAG_HYDRO_PUMP, + .paletteTag = ANIM_TAG_HYDRO_PUMP, + .oam = &gOamData_AffineDouble_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDracoMeteorRock, +}; + +const struct SpriteTemplate gTeraBlastRockSpriteTemplate = +{ + .tileTag = ANIM_TAG_ROCKS, + .paletteTag = ANIM_TAG_ROCKS, + .oam = &gOamData_AffineOff_ObjNormal_32x32, + .anims = sAnims_BasicRock, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimDracoMeteorRock, +}; + +const struct SpriteTemplate gGhostProjectileSpriteTemplate = +{ + .tileTag = ANIM_TAG_GHOSTLY_SPIRIT, + .paletteTag = ANIM_TAG_GHOSTLY_SPIRIT, + .oam = &gOamData_AffineOff_ObjBlend_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimPoisonJabProjectile, +}; +// End of Tera Blast sprite templates + const union AnimCmd gSproutAnimCmds[] = { ANIMCMD_FRAME(96, 5), @@ -9148,6 +9429,18 @@ static void SpriteCB_DragonEnergyShot(struct Sprite* sprite) //arg 2: wave amplitude static void SpriteCB_MaxFlutterby(struct Sprite* sprite) { + s16 target_x; + s16 target_y; + if (gMovesInfo[gAnimMoveIndex].target == MOVE_TARGET_BOTH) + { + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &target_x, &target_y); + } + else + { + target_x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + target_y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + InitSpritePosToAnimAttacker(sprite, FALSE); sprite->data[0] = 0x10; //Speed delay @@ -9163,7 +9456,8 @@ static void SpriteCB_MaxFlutterbyStep1(struct Sprite* sprite) { if (!FuncIsActiveTask(AnimTask_DynamaxGrowthStep)) { - if (gAnimMoveIndex != MOVE_INFERNAL_PARADE) + if (gAnimMoveIndex != MOVE_INFERNAL_PARADE + && gAnimMoveIndex != MOVE_ASTRAL_BARRAGE) PlaySE(SE_M_SAND_ATTACK); StartSpriteAffineAnim(sprite, 1); @@ -9381,3 +9675,25 @@ const union AffineAnimCmd* const gSpriteAffineAnimTable_MegaSymbol[] = { sSpriteAffineAnim_MegaSymbol, }; + +// Used for determining which animation to use for Order Up +void AnimTask_GetCommanderType(u8 taskId) +{ + switch (gBattleStruct->commanderActive[gEffectBattler]) + { + case SPECIES_TATSUGIRI_CURLY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_CURLY; + break; + case SPECIES_TATSUGIRI_DROOPY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_DROOPY; + break; + case SPECIES_TATSUGIRI_STRETCHY: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_STRETCHY; + break; + default: + gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_NONE; + break; + } + + DestroyAnimVisualTask(taskId); +} diff --git a/src/battle_anim_poison.c b/src/battle_anim_poison.c index 39f30708c4..e47f032169 100644 --- a/src/battle_anim_poison.c +++ b/src/battle_anim_poison.c @@ -520,12 +520,44 @@ static void AnimSludgeProjectile(struct Sprite *sprite) { if (!gBattleAnimArgs[3]) StartSpriteAnim(sprite, 2); + if (gBattleAnimArgs[4] && IsDoubleBattle()) + { + u32 targetPartner; + if (IsOnPlayerSide(gBattleAnimTarget)) + { + if (gBattleAnimTarget == 0) + targetPartner = 2; + else + targetPartner = 0; + } + else + { + if (gBattleAnimTarget == 1) + targetPartner = 3; + else + targetPartner = 1; + } + + if (IsBattlerAlive(gBattleAnimTarget) && !IsBattlerAlive(targetPartner)) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + sprite->data[2] = GetBattlerSpriteCoord(targetPartner, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(targetPartner, BATTLER_COORD_Y_PIC_OFFSET); + } + } + else + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } InitSpritePosToAnimAttacker(sprite, TRUE); sprite->data[0] = gBattleAnimArgs[2]; - sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); - sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); sprite->data[5] = -30; InitAnimArcTranslation(sprite); @@ -600,7 +632,12 @@ static void AnimSludgeBombHitParticle_Step(struct Sprite *sprite) static void AnimAcidPoisonDroplet(struct Sprite *sprite) { if (gBattleAnimArgs[5]) - SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y); + { + if (gBattleAnimArgs[5] == 1) + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y); + if (gBattleAnimArgs[5] == 2) + SetToPartnerPositions(gBattleAnimTarget, TRUE, &sprite->x, &sprite->y); + } if (!IsOnPlayerSide(gBattleAnimAttacker)) gBattleAnimArgs[0] = -gBattleAnimArgs[0]; diff --git a/src/battle_anim_rock.c b/src/battle_anim_rock.c index 3408e797fc..23b244957c 100644 --- a/src/battle_anim_rock.c +++ b/src/battle_anim_rock.c @@ -11,7 +11,6 @@ static void AnimTask_Rollout_Step(u8 taskId); static void AnimRolloutParticle(struct Sprite *); -static void AnimRockTomb(struct Sprite *); static void AnimRockTomb_Step(struct Sprite *sprite); static void AnimRockScatter(struct Sprite *); static void AnimRockScatter_Step(struct Sprite *sprite); @@ -174,7 +173,7 @@ static const union AnimCmd sAnim_Rock_Smallest[] = ANIMCMD_END, }; -static const union AnimCmd *const sAnims_BasicRock[] = +const union AnimCmd *const sAnims_BasicRock[] = { sAnim_Rock_Biggest, sAnim_Rock_Bigger, @@ -935,7 +934,7 @@ static u8 GetRolloutCounter(void) return retVal; } -static void AnimRockTomb(struct Sprite *sprite) +void AnimRockTomb(struct Sprite *sprite) { StartSpriteAnim(sprite, gBattleAnimArgs[4]); diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index 038f338cb2..236c7f6dfd 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -1468,6 +1468,10 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] = {gBattleAnimSpriteGfx_PinkVioletOrb, 0x0080, ANIM_TAG_PINKVIO_ORB}, {gBattleAnimSpriteGfx_TeraStarstormBeam, 0x200, ANIM_TAG_STARSTORM}, {gBattleAnimSpriteGfx_SaltParticle, 0x400, ANIM_TAG_SALT_PARTICLE}, + {gBattleAnimSpriteGfx_TeraSymbol, 0x0200, ANIM_TAG_TERA_SYMBOL}, + {gBattleAnimSpriteGfx_TatsugiriCurly, 0x200, ANIM_TAG_TATSUGIRI_CURLY}, + {gBattleAnimSpriteGfx_TatsugiriDroopy, 0x200, ANIM_TAG_TATSUGIRI_DROOPY}, + {gBattleAnimSpriteGfx_TatsugiriStretchy, 0x200, ANIM_TAG_TATSUGIRI_STRETCHY}, }; const struct SpritePalette gBattleAnimPaletteTable[] = @@ -1937,6 +1941,10 @@ const struct SpritePalette gBattleAnimPaletteTable[] = {gBattleAnimSpritePal_PinkVioletOrb, ANIM_TAG_PINKVIO_ORB}, {gBattleAnimSpritePal_TeraStarstormBeam, ANIM_TAG_STARSTORM}, {gBattleAnimSpritePal_SaltParticle, ANIM_TAG_SALT_PARTICLE}, + {gBattleAnimSpritePal_TeraSymbol, ANIM_TAG_TERA_SYMBOL}, + {gBattleAnimSpritePal_TatsugiriCurly, ANIM_TAG_TATSUGIRI_CURLY}, + {gBattleAnimSpritePal_TatsugiriDroopy, ANIM_TAG_TATSUGIRI_DROOPY}, + {gBattleAnimSpritePal_TatsugiriStretchy, ANIM_TAG_TATSUGIRI_STRETCHY}, }; const struct BattleAnimBackground gBattleAnimBackgroundTable[] = diff --git a/src/graphics.c b/src/graphics.c index 41aad50431..925e232dbe 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -43,6 +43,9 @@ const u16 gBattleAnimSpritePal_AlphaSymbol[] = INCBIN_U16("graphics/battle_anims const u32 gBattleAnimSpriteGfx_OmegaSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/omega_symbol.4bpp.smol"); const u16 gBattleAnimSpritePal_OmegaSymbol[] = INCBIN_U16("graphics/battle_anims/sprites/omega_symbol.gbapal"); +const u32 gBattleAnimSpriteGfx_TeraSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/tera_symbol.4bpp.smol"); +const u16 gBattleAnimSpritePal_TeraSymbol[] = INCBIN_U16("graphics/battle_anims/sprites/tera_symbol.gbapal"); + const u32 gBattleAnimSpriteGfx_FlashCannonBall[] = INCBIN_U32("graphics/battle_anims/sprites/flash_cannon_ball.4bpp.smol"); const u16 gBattleAnimSpritePal_FlashCannonBall[] = INCBIN_U16("graphics/battle_anims/sprites/flash_cannon_ball.gbapal"); @@ -782,6 +785,15 @@ const u16 gBattleAnimSpritePal_BlueFlames[] = INCBIN_U16("graphics/battle_anims/ const u32 gBattleAnimSpriteGfx_BlueFlames2[] = INCBIN_U32("graphics/battle_anims/sprites/blue_flames_2.4bpp.smol"); +const u32 gBattleAnimSpriteGfx_TatsugiriCurly[] = INCBIN_U32("graphics/battle_anims/sprites/tatsugiri_curly.4bpp.smol"); +const u16 gBattleAnimSpritePal_TatsugiriCurly[] = INCBIN_U16("graphics/battle_anims/sprites/tatsugiri_curly.gbapal"); + +const u32 gBattleAnimSpriteGfx_TatsugiriDroopy[] = INCBIN_U32("graphics/battle_anims/sprites/tatsugiri_droopy.4bpp.smol"); +const u16 gBattleAnimSpritePal_TatsugiriDroopy[] = INCBIN_U16("graphics/battle_anims/sprites/tatsugiri_droopy.gbapal"); + +const u32 gBattleAnimSpriteGfx_TatsugiriStretchy[] = INCBIN_U32("graphics/battle_anims/sprites/tatsugiri_stretchy.4bpp.smol"); +const u16 gBattleAnimSpritePal_TatsugiriStretchy[] = INCBIN_U16("graphics/battle_anims/sprites/tatsugiri_stretchy.gbapal"); + // Contest const u32 gJPContestGfx1[] = INCBIN_U32("graphics/contest/japanese/composite_1.4bpp.smol"); const u16 gJPContestPal[] = INCBIN_U16("graphics/contest/japanese/palette.gbapal"); diff --git a/test/battle/move_animations/all_anims.c b/test/battle/move_animations/all_anims.c index 7bf0cabe2e..c929921d3f 100644 --- a/test/battle/move_animations/all_anims.c +++ b/test/battle/move_animations/all_anims.c @@ -1550,4 +1550,261 @@ DOUBLE_BATTLE_TEST("Z-Moves don't leak when used - Doubles (opponentRight to pla // Max Moves +// Tera Blast and all type variants +#define TERA_BLAST_PARAMETERS PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_NORMAL; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_FIGHTING; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_FLYING; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_POISON; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_GROUND; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_ROCK; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_BUG; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_GHOST; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_STEEL; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_WATER; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_FIRE; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_GRASS; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_ELECTRIC; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_PSYCHIC; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_ICE; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_DRAGON; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_DARK; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_FAIRY; } \ + PARAMETRIZE { species = SPECIES_WOBBUFFET; move = MOVE_TERA_BLAST; type = TYPE_STELLAR; } + +SINGLE_BATTLE_TEST("Tera Blast doesn't leak when used - Singles (player to opponent)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { TeraType(type); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(player, move, gimmick: GIMMICK_TERA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, player); + ANIMATION(ANIM_TYPE_MOVE, move, player); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +SINGLE_BATTLE_TEST("Tera Blast doesn't leak when used - Singles (opponent to player)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + OPPONENT(species) { TeraType(type); } + } WHEN { + TURN { MOVE(opponent, move, gimmick: GIMMICK_TERA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerLeft to opponentLeft)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { TeraType(type); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(playerLeft, move, gimmick: GIMMICK_TERA, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerLeft to opponentRight)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { TeraType(type); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(playerLeft, move, gimmick: GIMMICK_TERA, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerRight to opponentLeft)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(species) { TeraType(type); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(playerRight, move, gimmick: GIMMICK_TERA, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerRight); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (playerRight to opponentRight)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(species) { TeraType(type); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(playerRight, move, gimmick: GIMMICK_TERA, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerRight); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentLeft to playerLeft)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { Item(ITEM_FOCUS_SASH); } + PLAYER(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WOBBUFFET) { TeraType(type); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, move, gimmick: GIMMICK_TERA, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentLeft to playerRight)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { Item(ITEM_FOCUS_SASH); } + PLAYER(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WOBBUFFET) { TeraType(type); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponentLeft, move, gimmick: GIMMICK_TERA, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, move, opponentLeft); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentRight to playerLeft)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { Item(ITEM_FOCUS_SASH); } + PLAYER(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { TeraType(type); } + } WHEN { + TURN { MOVE(opponentRight, move, gimmick: GIMMICK_TERA, target: playerLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, opponentRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, move, opponentRight); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + +DOUBLE_BATTLE_TEST("Tera Blast doesn't leak when used - Doubles (opponentRight to playerRight)") +{ + FORCE_MOVE_ANIM(TRUE); + u32 species, move, type; + TERA_BLAST_PARAMETERS; + GIVEN { + PLAYER(species) { Item(ITEM_FOCUS_SASH); } + PLAYER(SPECIES_WYNAUT) { Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { TeraType(type); } + } WHEN { + TURN { MOVE(opponentRight, move, gimmick: GIMMICK_TERA, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_CHARGE, opponentRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, move, opponentRight); + } THEN { + FORCE_MOVE_ANIM(FALSE); + if (gLoadFail) + DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move); + EXPECT_EQ(gLoadFail, FALSE); + } +} + #endif From a1e67572b60e72c951ac87337bcd56c8472a2e8d Mon Sep 17 00:00:00 2001 From: Nephrite Date: Fri, 11 Jul 2025 23:53:49 +0300 Subject: [PATCH 083/283] Replaces STATUS2 usage with volatiles in code (#7262) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- asm/macros/battle_script.inc | 44 +-- data/battle_scripts_1.s | 38 +- .../how_to_battle_script_command_macro.md | 2 +- include/battle.h | 2 +- include/battle_controllers.h | 4 +- include/battle_gfx_sfx_util.h | 2 +- include/battle_main.h | 2 +- include/battle_util.h | 5 +- include/constants/battle.h | 28 +- include/constants/battle_script_commands.h | 1 - include/item.h | 3 +- include/metaprogram.h | 84 +++-- include/pokemon.h | 4 +- src/battle_ai_main.c | 56 +-- src/battle_ai_switch_items.c | 21 +- src/battle_ai_util.c | 38 +- src/battle_controller_player.c | 2 +- src/battle_controllers.c | 20 +- src/battle_debug.c | 10 +- src/battle_dynamax.c | 4 +- src/battle_end_turn.c | 34 +- src/battle_gfx_sfx_util.c | 12 +- src/battle_main.c | 82 ++--- src/battle_message.c | 5 - src/battle_script_commands.c | 348 ++++++++---------- src/battle_terastal.c | 2 +- src/battle_util.c | 220 ++++++----- src/battle_util2.c | 4 +- src/battle_z_move.c | 4 +- src/data/moves_info.h | 2 +- src/item.c | 19 +- src/item_use.c | 25 +- src/pokemon.c | 2 +- src/recorded_battle.c | 2 +- test/battle/ability/shield_dust.c | 6 +- test/battle/gimmick/dynamax.c | 4 +- test/battle/hold_effect/berserk_gene.c | 6 +- test/battle/hold_effect/covert_cloak.c | 6 +- test/battle/item_effect/cure_status.c | 2 +- test/battle/move_effect/attract.c | 12 +- test/battle/move_effect/baton_pass.c | 2 +- test/battle/move_effect/captivate.c | 4 +- test/battle/move_effect_secondary/thrash.c | 2 +- test/battle/move_effect_secondary/trap_both.c | 4 +- .../battle/{status2 => volatiles}/confusion.c | 0 45 files changed, 582 insertions(+), 597 deletions(-) rename test/battle/{status2 => volatiles}/confusion.c (100%) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index d9a7ca5fed..ba4b4619aa 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -596,27 +596,15 @@ .byte \notChosenMove .endm - .macro statusanimation battler:req + .macro statusanimation battler:req, status=0, isVolatile=FALSE .byte 0x64 .byte \battler + .4byte \status + .byte \isVolatile .endm - .macro status2animation battler:req, status2:req - .byte 0x65 - .byte \battler - .4byte \status2 - .endm - - .macro setmoveeffect effect:req - sethword sMOVE_EFFECT, \effect - sethword sSAVED_MOVE_EFFECT, \effect - .endm - - .macro chosenstatusanimation battler:req, isStatus2:req, status:req - .byte 0x66 - .byte \battler - .byte \isStatus2 - .4byte \status + .macro volatileanimation battler:req, volatile:req + statusanimation \battler, \volatile, TRUE .endm .macro yesnobox @@ -979,8 +967,11 @@ .4byte \failInstr .endm - .macro setforesight + .macro setvolatile battler:req, volatile:req, value=TRUE .byte 0xb1 + .byte \battler + .byte \volatile + .byte \value .endm .macro trysetperishsong failInstr:req @@ -1041,10 +1032,6 @@ .byte 0xbe .endm - .macro setdefensecurlbit - .byte 0xbf - .endm - .macro recoverbasedonsunlight failInstr:req .byte 0xc0 .4byte \failInstr @@ -2094,10 +2081,6 @@ .4byte \failInstr .endm - .macro setpowder battler:req - various \battler, VARIOUS_SET_POWDER - .endm - .macro bringdownairbornebattler battler:req various \battler, VARIOUS_GRAVITY_ON_AIRBORNE_MONS .endm @@ -2353,12 +2336,9 @@ setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7 .endm - .macro chosenstatus1animation battler:req, status:req - chosenstatusanimation \battler, 0x0, \status - .endm - - .macro chosenstatus2animation battler:req, status:req - chosenstatusanimation \battler, 0x1, \status + .macro setmoveeffect effect:req + sethword sMOVE_EFFECT, \effect + sethword sSAVED_MOVE_EFFECT, \effect .endm .macro sethword dst:req, value:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f7d988026d..b51fe1ee26 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1329,7 +1329,7 @@ BattleScript_EffectPowder:: attackstring ppreduce jumpifvolatile BS_TARGET, VOLATILE_POWDER, BattleScript_ButItFailed - setpowder BS_TARGET + setvolatile BS_TARGET, VOLATILE_POWDER attackanimation waitanimation printstring STRINGID_COVEREDINPOWDER @@ -3929,7 +3929,7 @@ BattleScript_EffectForesight:: ppreduce accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifvolatile BS_TARGET, VOLATILE_FORESIGHT, BattleScript_ButItFailed - setforesight + setvolatile BS_TARGET, VOLATILE_FORESIGHT BattleScript_IdentifiedFoe: attackanimation waitanimation @@ -4026,7 +4026,7 @@ BattleScript_TryDestinyKnotTarget: infatuatewithbattler BS_TARGET, BS_ATTACKER playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT waitanimation - status2animation BS_TARGET, STATUS2_INFATUATION + volatileanimation BS_TARGET, VOLATILE_INFATUATION waitanimation printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG @@ -4038,7 +4038,7 @@ BattleScript_TryDestinyKnotAttacker: infatuatewithbattler BS_ATTACKER, BS_TARGET playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT waitanimation - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION waitanimation printstring STRINGID_DESTINYKNOTACTIVATES waitmessage B_WAIT_TIME_LONG @@ -4332,7 +4332,7 @@ BattleScript_EffectDefenseCurl:: attackcanceler attackstring ppreduce - setdefensecurlbit + setvolatile BS_TARGET, VOLATILE_DEFENSE_CURL setstatchanger STAT_DEF, 1, FALSE statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_ONLY_CHECKING, BattleScript_DefenseCurlDoStatUpAnim jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StatUpPrintString @@ -6866,7 +6866,7 @@ BattleScript_PrintUproarOverTurns:: end2 BattleScript_ThrashConfuses:: - chosenstatus2animation BS_ATTACKER, STATUS2_CONFUSION + volatileanimation BS_ATTACKER, VOLATILE_CONFUSION printstring STRINGID_PKMNFATIGUECONFUSION waitmessage B_WAIT_TIME_LONG end2 @@ -6874,7 +6874,7 @@ BattleScript_ThrashConfuses:: BattleScript_MoveUsedIsConfused:: printstring STRINGID_PKMNISCONFUSED waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_CONFUSION + volatileanimation BS_ATTACKER, VOLATILE_CONFUSION jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, FALSE, BattleScript_MoveUsedIsConfusedRet BattleScript_DoSelfConfusionDmg:: cancelmultiturnmoves BS_ATTACKER @@ -6900,7 +6900,7 @@ BattleScript_MoveUsedPowder:: ppreduce pause B_WAIT_TIME_SHORT cancelmultiturnmoves BS_ATTACKER - status2animation BS_ATTACKER, STATUS2_POWDER + volatileanimation BS_ATTACKER, VOLATILE_POWDER waitanimation effectivenesssound hitanimation BS_ATTACKER @@ -6938,7 +6938,7 @@ BattleScript_WrapEnds:: BattleScript_MoveUsedIsInLove:: printstring STRINGID_PKMNINLOVE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION return BattleScript_MoveUsedIsInLoveCantAttack:: @@ -6949,13 +6949,13 @@ BattleScript_MoveUsedIsInLoveCantAttack:: BattleScript_NightmareTurnDmg:: printstring STRINGID_PKMNLOCKEDINNIGHTMARE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_NIGHTMARE + volatileanimation BS_ATTACKER, VOLATILE_NIGHTMARE goto BattleScript_DoTurnDmg BattleScript_CurseTurnDmg:: printstring STRINGID_PKMNAFFLICTEDBYCURSE waitmessage B_WAIT_TIME_LONG - status2animation BS_ATTACKER, STATUS2_CURSED + volatileanimation BS_ATTACKER, VOLATILE_CURSED goto BattleScript_DoTurnDmg BattleScript_TargetPRLZHeal:: @@ -7085,7 +7085,7 @@ BattleScript_MoveEffectWrap:: return BattleScript_MoveEffectConfusion:: - chosenstatus2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_CONFUSION printstring STRINGID_PKMNWASCONFUSED waitmessage B_WAIT_TIME_LONG return @@ -8195,7 +8195,7 @@ BattleScript_BanefulBunkerEffect:: BattleScript_CuteCharmActivates:: call BattleScript_AbilityPopUp - status2animation BS_ATTACKER, STATUS2_INFATUATION + volatileanimation BS_ATTACKER, VOLATILE_INFATUATION printstring STRINGID_PKMNSXINFATUATEDY waitmessage B_WAIT_TIME_LONG call BattleScript_TryDestinyKnotTarget @@ -9455,9 +9455,9 @@ BattleScript_EffectConfuseSide:: BattleScript_ConfuseSideLoop: jumpifabsent BS_TARGET, BattleScript_ConfuseSideIncrement trysetconfusion BattleScript_ConfuseSideIncrement - status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_CONFUSION BattleScript_ConfuseSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNWASCONFUSED waitmessage B_WAIT_TIME_LONG BattleScript_ConfuseSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ConfuseSideEnd @@ -9477,9 +9477,9 @@ BattleScript_EffectInfatuateSide:: BattleScript_InfatuateSideLoop: jumpifabsent BS_TARGET, BattleScript_InfatuateSideIncrement trysetinfatuation BattleScript_InfatuateSideIncrement - status2animation BS_EFFECT_BATTLER, STATUS2_INFATUATION + volatileanimation BS_EFFECT_BATTLER, VOLATILE_INFATUATION BattleScript_InfatuateSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNFELLINLOVE waitmessage B_WAIT_TIME_LONG BattleScript_InfatuateSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_InfatuateSideEnd @@ -9495,7 +9495,7 @@ BattleScript_TormentSideLoop: jumpifabsent BS_TARGET, BattleScript_TormentSideIncrement trysettorment BattleScript_TormentSideIncrement BattleScript_TormentSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_PKMNSUBJECTEDTOTORMENT waitmessage B_WAIT_TIME_LONG BattleScript_TormentSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_TormentSideEnd @@ -9516,7 +9516,7 @@ BattleScript_MeanLookSideLoop: jumpifabsent BS_TARGET, BattleScript_MeanLookSideIncrement trysetescapeprevention BattleScript_MeanLookSideIncrement BattleScript_MeanLookSidePrintMessage: - printfromtable gStatus2StringIds + printstring STRINGID_TARGETCANTESCAPENOW waitmessage B_WAIT_TIME_LONG BattleScript_MeanLookSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_MeanLookSideEnd diff --git a/docs/tutorials/how_to_battle_script_command_macro.md b/docs/tutorials/how_to_battle_script_command_macro.md index 2bbf503fbe..afb9a15e89 100644 --- a/docs/tutorials/how_to_battle_script_command_macro.md +++ b/docs/tutorials/how_to_battle_script_command_macro.md @@ -35,7 +35,7 @@ void BS_TrySetOctolock(void) else { gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[battler].volatiles.escapePrevention = TRUE; gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/include/battle.h b/include/battle.h index cdeac89719..b537f779af 100644 --- a/include/battle.h +++ b/include/battle.h @@ -44,7 +44,7 @@ // Used to exclude moves learned temporarily by Transform or Mimic #define MOVE_IS_PERMANENT(battler, moveSlot) \ - (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) \ + (!(gBattleMons[battler].volatiles.transformed) \ && !(gDisableStructs[battler].mimickedMoves & (1u << moveSlot))) // Battle Actions diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 80c8c6ee38..d5166ce6f8 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -301,8 +301,8 @@ void BtlController_EmitChooseItem(u32 battler, u32 bufferId, u8 *battlePartyOrde void BtlController_EmitChoosePokemon(u32 battler, u32 bufferId, u8 caseId, u8 slotId, u16 abilityId, u8 battlerPreventingSwitchout, u8 *data); void BtlController_EmitHealthBarUpdate(u32 battler, u32 bufferId, u16 hpValue); void BtlController_EmitExpUpdate(u32 battler, u32 bufferId, u8 partyId, s32 expPoints); -void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status1, u32 status2); -void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 status2, u32 status); +void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status); +void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 isVolatile, u32 status); void BtlController_EmitDataTransfer(u32 battler, u32 bufferId, u16 size, void *data); void BtlController_EmitTwoReturnValues(u32 battler, u32 bufferId, u8 ret8, u32 ret32); void BtlController_EmitChosenMonReturnValue(u32 battler, u32 bufferId, u8 partyId, u8 *battlePartyOrder); diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index c2cc901171..ae71eb5b50 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -7,7 +7,7 @@ u16 ChooseMoveAndTargetInBattlePalace(u32 battler); void SpriteCB_WaitForBattlerBallReleaseAnim(struct Sprite *sprite); void SpriteCB_TrainerSlideIn(struct Sprite *sprite); void SpriteCB_TrainerSpawn(struct Sprite *sprite); -void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 status); +void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isVolatile, u32 status); bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattlerId, u8 attacker, u8 target, u8 tableId, u16 argument); void InitAndLaunchSpecialAnimation(u8 activeBattlerId, u8 attacker, u8 target, u8 tableId); bool8 IsBattleSEPlaying(u8 battler); diff --git a/include/battle_main.h b/include/battle_main.h index 23e030f6d3..6367f7e0f4 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -89,7 +89,7 @@ void SpriteCB_TrainerThrowObject(struct Sprite *sprite); void AnimSetCenterToCornerVecX(struct Sprite *sprite); void BeginBattleIntroDummy(void); void BeginBattleIntro(void); -void SwitchInClearSetData(u32 battler); +void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy); const u8* FaintClearSetData(u32 battler); void BattleTurnPassed(void); u8 IsRunningFromBattleImpossible(u32 battler); diff --git a/include/battle_util.h b/include/battle_util.h index 9eca2dacd7..8161e8d2d2 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -392,9 +392,10 @@ bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); void UpdateStallMons(void); bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId); bool32 TrySwitchInEjectPack(enum ItemCaseId caseID); -u32 GetMonVolatile(u32 battler, enum Volatile volatile); -void SetMonVolatile(u32 battler, enum Volatile volatile, u32 newValue); +u32 GetMonVolatile(u32 battler, enum Volatile _volatile); +void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue); u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); +bool32 ItemHealMonVolatile(u32 battler, u16 itemId); void PushHazardTypeToQueue(u32 side, enum Hazards hazardType); bool32 IsHazardOnSide(u32 side, enum Hazards hazardType); bool32 AreAnyHazardsOnSide(u32 side); diff --git a/include/constants/battle.h b/include/constants/battle.h index f0861ad43a..b87176ff7a 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -142,23 +142,21 @@ enum VolatileFlags V_BATON_PASSABLE = (1 << 0), }; -// Volatile status ailments -// These are removed after exiting the battle or switching -/* Definitions with names e.g. "Confusion" are accessible in the debug menu - * Enum, Type, (Field name, (optional)bitSize), Flags, (optional)(Debug menu header, (optional)max. value) - */ +/* Volatile status ailments + * These are removed after exiting the battle or switching + * Enum, Type Type, max value, flags */ #define VOLATILE_DEFINITIONS(F) \ - F(VOLATILE_CONFUSION, confusionTurns, (u32, 3), V_BATON_PASSABLE) \ + F(VOLATILE_CONFUSION, confusionTurns, (u32, 6), V_BATON_PASSABLE) \ F(VOLATILE_FLINCHED, flinched, (u32, 1)) \ - F(VOLATILE_UPROAR, uproarTurns, (u32, 3)) \ + F(VOLATILE_UPROAR, uproarTurns, (u32, 5)) \ F(VOLATILE_TORMENT, torment, (u32, 1)) \ - F(VOLATILE_BIDE, bideTurns, (u32, 2)) \ - F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 2)) \ + F(VOLATILE_BIDE, bideTurns, (u32, 3)) \ + F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 3)) \ F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ F(VOLATILE_POWDER, powder, (u32, 1)) \ F(VOLATILE_UNUSED, padding, (u32, 1)) \ - F(VOLATILE_INFATUATION, infatuation, (u32, 4)) \ + F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ @@ -174,18 +172,22 @@ enum VolatileFlags F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) -/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeBitSize and debug parameters as input. */ -#define GET_VOLATILE_MAXIMUM(_typeBitSize, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeBitSize) -#define GET_VOLATILE_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(MAX_BITS(FIRST(__VA_ARGS__)),) MAX_BITS((sizeof(_type) * 8))) +/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ +#define GET_VOLATILE_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeMaxValue) +#define GET_VOLATILE_MAXIMUM_(_type, ...) FIRST(__VA_OPT__(FIRST(__VA_ARGS__),) MAX_BITS((sizeof(_type) * 8))) #define UNPACK_VOLATILE_ENUMS(_enum, ...) _enum, enum Volatile { + VOLATILE_NONE, VOLATILE_DEFINITIONS(UNPACK_VOLATILE_ENUMS) /* Expands to VOLATILE_CONFUSION, VOLATILE_FLINCHED, etc. */ }; +// Helper macros +#define INFATUATED_WITH(battler) (battler + 1) + // Old flags #define STATUS2_CONFUSION (1 << 0 | 1 << 1 | 1 << 2) #define STATUS2_CONFUSION_TURN(num) ((num) << 0) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 34497fc52e..b38d1cb9a6 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -149,7 +149,6 @@ enum CmdVarious VARIOUS_SET_AURORA_VEIL, VARIOUS_TRY_THIRD_TYPE, VARIOUS_ACUPRESSURE, - VARIOUS_SET_POWDER, VARIOUS_GRAVITY_ON_AIRBORNE_MONS, VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, VARIOUS_JUMP_IF_ROAR_FAILS, diff --git a/include/item.h b/include/item.h index 565784c85a..5fbb12ec43 100644 --- a/include/item.h +++ b/include/item.h @@ -2,6 +2,7 @@ #define GUARD_ITEM_H #include "constants/item.h" +#include "constants/item_effects.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/tms_hms.h" @@ -187,7 +188,7 @@ u8 GetItemBattleUsage(u16 itemId); u32 GetItemSecondaryId(u32 itemId); u32 GetItemFlingPower(u32 itemId); u32 GetItemStatus1Mask(u16 itemId); -u32 GetItemStatus2Mask(u16 itemId); +bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile volatile); u32 GetItemSellPrice(u32 itemId); #endif // GUARD_ITEM_H diff --git a/include/metaprogram.h b/include/metaprogram.h index 47fa99af72..197ed0b756 100644 --- a/include/metaprogram.h +++ b/include/metaprogram.h @@ -120,42 +120,51 @@ #define DEFAULT_3(_default, ...) DEFAULT(_default __VA_OPT__(, THIRD(__VA_ARGS__))) #define DEFAULT_4(_default, ...) DEFAULT(_default __VA_OPT__(, FOURTH(__VA_ARGS__))) +/* Simply a lists numbers 0-31, allows for word-spanning macros */ +#define BITS_32(F, ...) \ + F(0, __VA_ARGS__) \ + F(1, __VA_ARGS__) \ + F(2, __VA_ARGS__) \ + F(3, __VA_ARGS__) \ + F(4, __VA_ARGS__) \ + F(5, __VA_ARGS__) \ + F(6, __VA_ARGS__) \ + F(7, __VA_ARGS__) \ + F(8, __VA_ARGS__) \ + F(9, __VA_ARGS__) \ + F(10, __VA_ARGS__) \ + F(11, __VA_ARGS__) \ + F(12, __VA_ARGS__) \ + F(13, __VA_ARGS__) \ + F(14, __VA_ARGS__) \ + F(15, __VA_ARGS__) \ + F(16, __VA_ARGS__) \ + F(17, __VA_ARGS__) \ + F(18, __VA_ARGS__) \ + F(19, __VA_ARGS__) \ + F(20, __VA_ARGS__) \ + F(21, __VA_ARGS__) \ + F(22, __VA_ARGS__) \ + F(23, __VA_ARGS__) \ + F(24, __VA_ARGS__) \ + F(25, __VA_ARGS__) \ + F(26, __VA_ARGS__) \ + F(27, __VA_ARGS__) \ + F(28, __VA_ARGS__) \ + F(29, __VA_ARGS__) \ + F(30, __VA_ARGS__) \ + F(31, __VA_ARGS__) + +/* Compares _n to 1 shifted by _b by _operation (==, <, > etc) */ +#define OP_BIT_SHIFT(_b, _n, _operation) (_n) _operation (1 << _b) ? _b : + /* (Credit to MGriffin) A rather monstrous way of finding the set bit in a word. Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1hm7B */ -#define BIT_INDEX(n) \ - (n) == (1 << 0) ? 0 : \ - (n) == (1 << 1) ? 1 : \ - (n) == (1 << 2) ? 2 : \ - (n) == (1 << 3) ? 3 : \ - (n) == (1 << 4) ? 4 : \ - (n) == (1 << 5) ? 5 : \ - (n) == (1 << 6) ? 6 : \ - (n) == (1 << 7) ? 7 : \ - (n) == (1 << 8) ? 8 : \ - (n) == (1 << 9) ? 9 : \ - (n) == (1 << 10) ? 10 : \ - (n) == (1 << 11) ? 11 : \ - (n) == (1 << 12) ? 12 : \ - (n) == (1 << 13) ? 13 : \ - (n) == (1 << 14) ? 14 : \ - (n) == (1 << 15) ? 15 : \ - (n) == (1 << 16) ? 16 : \ - (n) == (1 << 17) ? 17 : \ - (n) == (1 << 18) ? 18 : \ - (n) == (1 << 19) ? 19 : \ - (n) == (1 << 20) ? 20 : \ - (n) == (1 << 21) ? 21 : \ - (n) == (1 << 22) ? 22 : \ - (n) == (1 << 23) ? 23 : \ - (n) == (1 << 24) ? 24 : \ - (n) == (1 << 25) ? 25 : \ - (n) == (1 << 26) ? 26 : \ - (n) == (1 << 27) ? 27 : \ - (n) == (1 << 28) ? 28 : \ - (n) == (1 << 29) ? 29 : \ - (n) == (1 << 30) ? 30 : \ - (n) == (1 << 31) ? 31 : \ - *(u32 *)NULL +#define BIT_INDEX(_n) BITS_32(OP_BIT_SHIFT, _n, ==) *(u32 *)NULL + +/* (Credit to MGriffin) A way to find the minimum required number of bits to +store a number (max: 32). Sample: https://godbolt.org/z/xb4KdPMhT */ +#define BIT_SIZE(_n) (BITS_32(OP_BIT_SHIFT, _n, <) 32) #define COMPRESS_BITS_0 0, 1 #define COMPRESS_BITS_1 1, 1 @@ -167,11 +176,10 @@ Invalid input causes a compiler error. Sample: https://cexplore.karathan.at/z/x1 #define COMPRESS_BITS_7 7, 1 /* Will try and compress a set bit (or up to three sequential bits) into a single byte -Input must be of the form (upper << lower) where upper can be up to 3, lower up to 31 */ +Input must be of the form (upper << lower) where upper can be up to 7, lower up to 31 */ #define COMPRESS_BITS(_val) COMPRESS_BITS_STEP_2 _val -#define COMPRESS_BITS_STEP_2(_unpacked) COMPRESS_BITS_STEP_3(COMPRESS_BITS_## _unpacked) -#define COMPRESS_BITS_STEP_3(...) COMPRESS_BITS_STEP_4(__VA_ARGS__) -#define COMPRESS_BITS_STEP_4(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower))) +#define COMPRESS_BITS_STEP_2(_unpacked) INVOKE(COMPRESS_BITS_STEP_3, COMPRESS_BITS_## _unpacked) +#define COMPRESS_BITS_STEP_3(upper, lower) (((upper % 8) << 5) + (BIT_INDEX(lower))) /* Will read a compressed bit stored by COMPRESS_BIT into a single byte */ #define UNCOMPRESS_BITS(compressed) ((compressed >> 5) << (compressed & 0x1F)) diff --git a/include/pokemon.h b/include/pokemon.h index 1a6bb8c696..ac525624cc 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -310,8 +310,8 @@ enum { MON_SPR_GFX_MANAGERS_COUNT }; -#define UNPACK_VOLATILE_STRUCT(_enum, _fieldName, _typeBitSize, ...) INVOKE(UNPACK_VOLATILE_STRUCT_, _fieldName, UNPACK_B(_typeBitSize)); -#define UNPACK_VOLATILE_STRUCT_(_fieldName, _type, ...) _type FIRST(__VA_OPT__(_fieldName:FIRST(__VA_ARGS__),) _fieldName) +#define UNPACK_VOLATILE_STRUCT(_enum, _fieldName, _typeMaxValue, ...) INVOKE(UNPACK_VOLATILE_STRUCT_, _fieldName, UNPACK_B(_typeMaxValue)); +#define UNPACK_VOLATILE_STRUCT_(_fieldName, _type, ...) _type FIRST(__VA_OPT__(_fieldName:BIT_SIZE(FIRST(__VA_ARGS__)),) _fieldName) struct Volatiles { diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 43d01dfa2e..3c582e3072 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1653,19 +1653,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // AI_CBM_HighRiskForDamage if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(-10); - if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + if (HasDamagingMove(battlerDef) && !(gBattleMons[battlerAtk].volatiles.substitute || IsBattlerIncapacitated(battlerDef, abilityDef) || gBattleMons[battlerDef].volatiles.infatuation || gBattleMons[battlerDef].volatiles.confusionTurns)) ADJUST_SCORE(-10); - if (HasMoveWithEffect(battlerAtk, EFFECT_SUBSTITUTE) && !(gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)) + if (HasMoveWithEffect(battlerAtk, EFFECT_SUBSTITUTE) && !gBattleMons[battlerAtk].volatiles.substitute) ADJUST_SCORE(-10); if (HasNonVolatileMoveEffect(battlerAtk, MOVE_EFFECT_SLEEP) && ! (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)) ADJUST_SCORE(-10); break; case EFFECT_COUNTER: case EFFECT_MIRROR_COAT: - if (IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION)) + if (IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) ADJUST_SCORE(-1); if ((predictedMove == MOVE_NONE || GetBattleMoveCategory(predictedMove) == DAMAGE_CATEGORY_STATUS || DoesSubstituteBlockMove(battlerAtk, BATTLE_PARTNER(battlerDef), predictedMove)) @@ -1717,7 +1719,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_FOCUS_ENERGY: - if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (gBattleMons[battlerAtk].volatiles.dragonCheer || gBattleMons[battlerAtk].volatiles.focusEnergy) ADJUST_SCORE(-10); break; case EFFECT_CONFUSE: @@ -1727,7 +1729,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_SUBSTITUTE: - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) + if (gBattleMons[battlerAtk].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) ADJUST_SCORE(-8); else if (aiData->hpPercents[battlerAtk] <= 25) ADJUST_SCORE(-10); @@ -1737,7 +1739,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_SHED_TAIL: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) + if (gBattleMons[battlerAtk].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_INFILTRATOR) ADJUST_SCORE(-8); else if (aiData->hpPercents[battlerAtk] <= 50) ADJUST_SCORE(-10); @@ -1808,7 +1810,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NIGHTMARE: - if (gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) + if (gBattleMons[battlerDef].volatiles.nightmare) ADJUST_SCORE(-10); else if (!AI_IsBattlerAsleepOrComatose(battlerDef)) ADJUST_SCORE(-8); @@ -1818,7 +1820,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CURSE: if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GHOST)) { - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED + if (gBattleMons[battlerDef].volatiles.cursed || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] <= 50) @@ -1857,7 +1859,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: - if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT) + if (gBattleMons[battlerDef].volatiles.foresight) ADJUST_SCORE(-10); else if (gBattleMons[battlerDef].statStages[STAT_EVASION] <= 4 || !(IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST)) @@ -1945,7 +1947,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_BATON_PASS: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE + else if (gBattleMons[battlerAtk].volatiles.substitute || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) || AnyStatIsRaised(battlerAtk)) break; @@ -2005,7 +2007,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TORMENT: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); - else if (gBattleMons[battlerDef].status2 & STATUS2_TORMENT + else if (gBattleMons[battlerDef].volatiles.torment || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); @@ -2162,8 +2164,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-6); break; case EFFECT_TRANSFORM: - if (gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED - || (gBattleMons[battlerDef].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE))) //Leave out Illusion b/c AI is supposed to be fooled + if (gBattleMons[battlerAtk].volatiles.transformed + || gBattleMons[battlerDef].volatiles.transformed + || gBattleMons[battlerDef].volatiles.substitute) //Leave out Illusion b/c AI is supposed to be fooled ADJUST_SCORE(-10); break; case EFFECT_SPITE: @@ -2206,7 +2209,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_DESTINY_BOND: if (DoesDestinyBondFail(battlerAtk)) ADJUST_SCORE(-10); - if (gBattleMons[battlerDef].status2 & STATUS2_DESTINY_BOND) + if (gBattleMons[battlerDef].volatiles.destinyBond) ADJUST_SCORE(-10); else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); @@ -2703,7 +2706,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || MoveHasAdditionalEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE) || IsZMove(instructedMove) || (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF) - || gBattleMons[battlerDef].status2 & STATUS2_MULTIPLETURNS + || gBattleMons[battlerDef].volatiles.multipleTurns || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); @@ -2975,7 +2978,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-7); break; case EFFECT_PERISH_SONG: - if (!(gBattleMons[battlerDef].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED))) + if (!(gBattleMons[battlerDef].volatiles.escapePrevention || gBattleMons[battlerDef].volatiles.wrapped)) { if (IsTrappingMove(aiData->partnerMove) || predictedMove == MOVE_INGRAIN) ADJUST_SCORE(WEAK_EFFECT); @@ -3038,7 +3041,9 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_DRAGON_CHEER: - if (gBattleMons[battlerAtkPartner].status2 & STATUS2_FOCUS_ENERGY_ANY || !HasDamagingMove(battlerAtkPartner)) + if (gBattleMons[battlerAtkPartner].volatiles.dragonCheer + || gBattleMons[battlerAtkPartner].volatiles.focusEnergy + || !HasDamagingMove(battlerAtkPartner)) ADJUST_SCORE(-5); else if (atkPartnerHoldEffect == HOLD_EFFECT_SCOPE_LENS || IS_BATTLER_OF_TYPE(battlerAtkPartner, TYPE_DRAGON) @@ -4147,7 +4152,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_BATON_PASS: - if ((gAiLogicData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE + if ((gAiLogicData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].volatiles.substitute || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) || AnyStatIsRaised(battlerAtk))) ADJUST_SCORE(BEST_EFFECT); @@ -4411,7 +4416,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_DEFENSE_CURL: - if (HasMoveWithEffect(battlerAtk, EFFECT_ROLLOUT) && !(gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL)) + if (HasMoveWithEffect(battlerAtk, EFFECT_ROLLOUT) && !gBattleMons[battlerAtk].volatiles.defenseCurl) ADJUST_SCORE(DECENT_EFFECT); ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; @@ -4456,7 +4461,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) && BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef])) break; // Don't use if the attract won't have a change to activate if (gBattleMons[battlerDef].status1 & STATUS1_ANY - || (gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + || gBattleMons[battlerDef].volatiles.confusionTurns > 0 || (!AI_CanBattlerEscape(battlerDef) && IsBattlerTrapped(battlerAtk, battlerDef))) ADJUST_SCORE(GOOD_EFFECT); else @@ -5049,7 +5054,7 @@ case EFFECT_GUARD_SPLIT: break; case EFFECT_RAPID_SPIN: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) - || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)) + || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].volatiles.wrapped)) ADJUST_SCORE(GOOD_EFFECT); case EFFECT_SPECTRAL_THIEF: ADJUST_SCORE(AI_ShouldCopyStatChanges(battlerAtk, battlerDef)); @@ -5204,13 +5209,13 @@ case EFFECT_GUARD_SPLIT: score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); break; case MOVE_EFFECT_BUG_BITE: // And pluck - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES) ADJUST_SCORE(DECENT_EFFECT); break; case MOVE_EFFECT_INCINERATE: - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) ADJUST_SCORE(DECENT_EFFECT); @@ -5949,9 +5954,10 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < UQ_4_12(2.0)) ADJUST_SCORE(10); - if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + if (HasDamagingMove(battlerDef) && !(gBattleMons[battlerAtk].volatiles.substitute || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION))) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0)) ADJUST_SCORE(10); } break; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 587b085500..ae01363a42 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -692,7 +692,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && gAiLogicData->abilities[opposingBattler] != ABILITY_KEEN_EYE && gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE && (B_ILLUMINATE_EFFECT >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) - && !(gBattleMons[battler].status2 & STATUS2_FORESIGHT) + && !gBattleMons[battler].volatiles.foresight && !(gStatuses3[battler] & STATUS3_MIRACLE_EYED)) switchMon = FALSE; @@ -713,12 +713,12 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Cursed - if (gBattleMons[battler].status2 & STATUS2_CURSED + if (gBattleMons[battler].volatiles.cursed && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Nightmare - if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE + if (gBattleMons[battler].volatiles.nightmare && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); @@ -729,7 +729,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) } // Infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION + if (gBattleMons[battler].volatiles.infatuation && !AiExpectsToFaintPlayer(battler) && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_INFATUATION, GetSwitchChance(SHOULD_SWITCH_INFATUATION))) @@ -1079,7 +1079,9 @@ bool32 ShouldSwitch(u32 battler) s32 i; s32 availableToSwitch; - if (gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + if (gBattleMons[battler].volatiles.wrapped) + return FALSE; + if (gBattleMons[battler].volatiles.escapePrevention) return FALSE; if (gStatuses3[battler] & STATUS3_ROOTED) return FALSE; @@ -1228,7 +1230,9 @@ void ModifySwitchAfterMoveScoring(u32 battler) s32 i; s32 availableToSwitch; - if (gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) + if (gBattleMons[battler].volatiles.wrapped) + return; + if (gBattleMons[battler].volatiles.escapePrevention) return; if (gStatuses3[battler] & STATUS3_ROOTED) return; @@ -2405,7 +2409,7 @@ static bool32 ShouldUseItem(u32 battler) shouldUse = TRUE; if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[battler].status1 & STATUS1_PARALYSIS) shouldUse = TRUE; - if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[battler].volatiles.confusionTurns > 0) shouldUse = TRUE; break; case EFFECT_ITEM_INCREASE_STAT: @@ -2417,7 +2421,8 @@ static bool32 ShouldUseItem(u32 battler) break; case EFFECT_ITEM_SET_FOCUS_ENERGY: if (!gDisableStructs[battler].isFirstTurn - || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY + || gBattleMons[battler].volatiles.dragonCheer + || gBattleMons[battler].volatiles.focusEnergy || AI_OpponentCanFaintAiWithMod(battler, 0)) break; shouldUse = TRUE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 48403d4e11..c9fb43c143 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -373,7 +373,9 @@ bool32 AI_CanBattlerEscape(u32 battler) bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) { - if (gBattleMons[battlerDef].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) + if (gBattleMons[battlerDef].volatiles.wrapped) + return TRUE; + if (gBattleMons[battlerDef].volatiles.escapePrevention) return TRUE; if (gStatuses3[battlerDef] & (STATUS3_ROOTED | STATUS3_SKY_DROPPED)) return TRUE; @@ -1880,7 +1882,9 @@ bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) bool32 IsBattlerDamagedByStatus(u32 battler) { return gBattleMons[battler].status1 & STATUS1_DAMAGING - || gBattleMons[battler].status2 & (STATUS2_WRAPPED | STATUS2_NIGHTMARE | STATUS2_CURSED) + || gBattleMons[battler].volatiles.wrapped + || gBattleMons[battler].volatiles.nightmare + || gBattleMons[battler].volatiles.cursed || gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED) || gStatuses4[battler] & (STATUS4_SALT_CURE) || gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_DAMAGE_NON_TYPES); @@ -2028,7 +2032,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += WEAK_EFFECT; if (gStatuses3[battlerDef] & STATUS3_ROOTED) tempScore += WEAK_EFFECT; - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED) + if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; case STAT_EVASION: @@ -2038,7 +2042,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += WEAK_EFFECT; if (gStatuses3[battlerDef] & STATUS3_ROOTED) tempScore += WEAK_EFFECT; - if (gBattleMons[battlerDef].status2 & STATUS2_CURSED) + if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; break; } @@ -2801,7 +2805,7 @@ static u32 GetLeechSeedDamage(u32 battlerId) static u32 GetNightmareDamage(u32 battlerId) { u32 damage = 0; - if ((gBattleMons[battlerId].status2 & STATUS2_NIGHTMARE) && gBattleMons[battlerId].status1 & STATUS1_SLEEP) + if (gBattleMons[battlerId].volatiles.nightmare && gBattleMons[battlerId].status1 & STATUS1_SLEEP) { damage = GetNonDynamaxMaxHP(battlerId) / 4; if (damage == 0) @@ -2813,7 +2817,7 @@ static u32 GetNightmareDamage(u32 battlerId) static u32 GetCurseDamage(u32 battlerId) { u32 damage = 0; - if (gBattleMons[battlerId].status2 & STATUS2_CURSED) + if (gBattleMons[battlerId].volatiles.cursed) { damage = GetNonDynamaxMaxHP(battlerId) / 4; if (damage == 0) @@ -2827,7 +2831,7 @@ static u32 GetTrapDamage(u32 battlerId) // ai has no knowledge about turns remaining u32 damage = 0; enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[gBattleStruct->wrappedBy[battlerId]]; - if (gBattleMons[battlerId].status2 & STATUS2_WRAPPED) + if (gBattleMons[battlerId].volatiles.wrapped) { if (holdEffect == HOLD_EFFECT_BINDING_BAND) damage = GetNonDynamaxMaxHP(battlerId) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); @@ -3233,7 +3237,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !HasMoveWithEffect(battler, EFFECT_SLEEP_TALK)) return TRUE; - if (gBattleMons[battler].status2 & STATUS2_RECHARGE || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) + if (gBattleMons[battler].volatiles.recharge || (ability == ABILITY_TRUANT && gDisableStructs[battler].truantCounter != 0)) return TRUE; return FALSE; @@ -3372,7 +3376,7 @@ bool32 AI_CanParalyze(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, bool32 AI_CanBeConfused(u32 battlerAtk, u32 battlerDef, u32 move, u32 ability) { - if ((gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + if (gBattleMons[battlerDef].volatiles.confusionTurns > 0 || (ability == ABILITY_OWN_TEMPO && !DoesBattlerIgnoreAbilityChecks(battlerAtk, gAiLogicData->abilities[battlerAtk], move)) || IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) || gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD @@ -3421,7 +3425,7 @@ bool32 AI_CanGiveFrostbite(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 b bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) { - if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) + if (gBattleMons[battlerDef].volatiles.infatuation || gAiLogicData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex] == UQ_4_12(0.0) || defAbility == ABILITY_OBLIVIOUS || !AreBattlersOfOppositeGender(battlerAtk, battlerDef) @@ -3441,8 +3445,8 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi } else if ((atkAbility == ABILITY_SERENE_GRACE || gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION - || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) || ((AI_IsFaster(battlerAtk, battlerDef, move)) && CanTargetFaintAi(battlerDef, battlerAtk))) { return 2; // good idea to flinch @@ -4357,8 +4361,8 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe || IsPowerBasedOnStatus(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS) || (HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FIRST_TURN_ONLY)) // filter out Fake Out - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION - || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + || gBattleMons[battlerDef].volatiles.infatuation + || gBattleMons[battlerDef].volatiles.confusionTurns > 0) ADJUST_SCORE_PTR(GOOD_EFFECT); else ADJUST_SCORE_PTR(DECENT_EFFECT); @@ -4396,7 +4400,7 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score && gAiLogicData->holdEffects[battlerDef] != HOLD_EFFECT_CURE_STATUS) { if (gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS - || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION + || gBattleMons[battlerDef].volatiles.infatuation || (gAiLogicData->abilities[battlerAtk] == ABILITY_SERENE_GRACE && HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FIRST_TURN_ONLY))) ADJUST_SCORE_PTR(GOOD_EFFECT); else @@ -4801,9 +4805,9 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerDef) != 0) ADJUST_SCORE_PTR(-2); - if (gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE && AI_IsFaster(battlerAtk, battlerDef, move)) + if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move)) ADJUST_SCORE_PTR(-10); - if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[battlerDef].volatiles.substitute) ADJUST_SCORE_PTR(GOOD_EFFECT); if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 0147875995..751a2eca46 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1025,7 +1025,7 @@ void HandleMoveSwitching(u32 battler) gBattleMons[battler].pp[i] = moveInfo->currentPp[i]; } - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battler].volatiles.transformed)) { for (i = 0; i < MAX_MON_MOVES; i++) { diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 51f7e75d37..14b39bbb1f 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1043,24 +1043,20 @@ void BtlController_EmitExpUpdate(u32 battler, u32 bufferId, u8 partyId, s32 expP PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 6); } -void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status1, u32 status2) +void BtlController_EmitStatusIconUpdate(u32 battler, u32 bufferId, u32 status) { gBattleResources->transferBuffer[0] = CONTROLLER_STATUSICONUPDATE; - gBattleResources->transferBuffer[1] = status1; - gBattleResources->transferBuffer[2] = (status1 & 0x0000FF00) >> 8; - gBattleResources->transferBuffer[3] = (status1 & 0x00FF0000) >> 16; - gBattleResources->transferBuffer[4] = (status1 & 0xFF000000) >> 24; - gBattleResources->transferBuffer[5] = status2; - gBattleResources->transferBuffer[6] = (status2 & 0x0000FF00) >> 8; - gBattleResources->transferBuffer[7] = (status2 & 0x00FF0000) >> 16; - gBattleResources->transferBuffer[8] = (status2 & 0xFF000000) >> 24; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 9); + gBattleResources->transferBuffer[1] = status; + gBattleResources->transferBuffer[2] = (status & 0x0000FF00) >> 8; + gBattleResources->transferBuffer[3] = (status & 0x00FF0000) >> 16; + gBattleResources->transferBuffer[4] = (status & 0xFF000000) >> 24; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 5); } -void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 status2, u32 status) +void BtlController_EmitStatusAnimation(u32 battler, u32 bufferId, bool8 isVolatile, u32 status) { gBattleResources->transferBuffer[0] = CONTROLLER_STATUSANIMATION; - gBattleResources->transferBuffer[1] = status2; + gBattleResources->transferBuffer[1] = isVolatile; gBattleResources->transferBuffer[2] = status; gBattleResources->transferBuffer[3] = (status & 0x0000FF00) >> 8; gBattleResources->transferBuffer[4] = (status & 0x00FF0000) >> 16; diff --git a/src/battle_debug.c b/src/battle_debug.c index 30f3d6766b..cd3b3cd253 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -1668,13 +1668,13 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data) if (data->modifyArrows.currValue) { if (IsBattlerAlive(BATTLE_OPPOSITE(data->battlerId))) - gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId)); + gBattleMons[data->battlerId].volatiles.infatuation = INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId)); else - gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId))); + gBattleMons[data->battlerId].volatiles.infatuation = INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId))); } else { - gBattleMons[data->battlerId].status2 &= ~STATUS2_INFATUATION; + gBattleMons[data->battlerId].volatiles.infatuation = 0; } break; } @@ -2034,7 +2034,7 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.maxDigits = 1; data->modifyArrows.modifiedValPtr = NULL; data->modifyArrows.typeOfVal = VAR_IN_LOVE; - data->modifyArrows.currValue = (gBattleMons[data->battlerId].status2 & STATUS2_INFATUATION) != 0; + data->modifyArrows.currValue = gBattleMons[data->battlerId].volatiles.infatuation; } break; case LIST_ITEM_STATUS1: @@ -2046,7 +2046,7 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.currValue = GetMonVolatile(data->battlerId, data->currentSecondaryListItemId); data->modifyArrows.typeOfVal = VAL_VOLATILE; data->modifyArrows.minValue = 0; -#define UNPACK_VOLATILE_MAX_SIZE(_enum, _fieldName, _typeBitSize, ...) case _enum: data->modifyArrows.maxValue = min(MAX_u16, GET_VOLATILE_MAXIMUM(_typeBitSize)); break; +#define UNPACK_VOLATILE_MAX_SIZE(_enum, _fieldName, _typeMaxValue, ...) case _enum: data->modifyArrows.maxValue = min(MAX_u16, GET_VOLATILE_MAXIMUM(_typeMaxValue)); break; switch (data->currentSecondaryListItemId) { VOLATILE_DEFINITIONS(UNPACK_VOLATILE_MAX_SIZE) diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index a34ecc21b3..c6e91742e8 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -181,14 +181,14 @@ void ActivateDynamax(u32 battler) gBattleStruct->dynamax.dynamaxTurns[battler] = gBattleTurnCounter + DYNAMAX_TURNS_COUNT; // Substitute is removed upon Dynamaxing. - gBattleMons[battler].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[battler].volatiles.substitute = FALSE; ClearBehindSubstituteBit(battler); // Choiced Moves are reset upon Dynamaxing. gBattleStruct->choicedMove[battler] = MOVE_NONE; // Try Gigantamax form change. - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) // Ditto cannot Gigantamax. + if (!gBattleMons[battler].volatiles.transformed) // Ditto cannot Gigantamax. TryBattleFormChange(battler, FORM_CHANGE_BATTLE_GIGANTAMAX); BattleScriptExecute(BattleScript_DynamaxBegins); diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index b63fd3938f..e56b383ba1 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -458,21 +458,21 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_THRASH: - if (gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + if (gBattleMons[battler].volatiles.lockConfusionTurns && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) { - gBattleMons[battler].status2 -= STATUS2_LOCK_CONFUSE_TURN(1); + gBattleMons[battler].volatiles.lockConfusionTurns--; if (WasUnableToUseMove(battler)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); } - else if (!(gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) && (gBattleMons[battler].status2 & STATUS2_MULTIPLETURNS)) + else if (!gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.multipleTurns) { - gBattleMons[battler].status2 &= ~STATUS2_MULTIPLETURNS; - if (!(gBattleMons[battler].status2 & STATUS2_CONFUSION)) + gBattleMons[battler].volatiles.multipleTurns = FALSE; + if (!gBattleMons[battler].volatiles.confusionTurns) { gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; SetMoveEffect(battler, battler, TRUE, FALSE); - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns) BattleScriptExecute(BattleScript_ThrashConfuses); effect = TRUE; } @@ -705,7 +705,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE + if (gBattleMons[battler].volatiles.nightmare && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -719,7 +719,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) } else { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; } } @@ -732,7 +732,7 @@ static bool32 HandleEndTurnCurse(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_CURSED + if (gBattleMons[battler].volatiles.cursed && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -752,7 +752,7 @@ static bool32 HandleEndTurnWrap(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gBattleMons[battler].status2 & STATUS2_WRAPPED && IsBattlerAlive(battler)) + if (gBattleMons[battler].volatiles.wrapped && IsBattlerAlive(battler)) { if (--gDisableStructs[battler].wrapTurns != 0) { @@ -773,7 +773,7 @@ static bool32 HandleEndTurnWrap(u32 battler) } else // broke free { - gBattleMons[battler].status2 &= ~STATUS2_WRAPPED; + gBattleMons[battler].volatiles.wrapped = FALSE; PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); BattleScriptExecute(BattleScript_WrapEnds); } @@ -867,7 +867,7 @@ static bool32 HandleEndTurnTorment(u32 battler) if (gDisableStructs[battler].tormentTimer == gBattleTurnCounter) { - gBattleMons[battler].status2 &= ~STATUS2_TORMENT; + gBattleMons[battler].volatiles.torment = FALSE; BattleScriptExecute(BattleScript_TormentEnds); effect = TRUE; } @@ -1349,7 +1349,7 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) switch (gBattleStruct->eventBlockCounter) { case THIRD_EVENT_BLOCK_UPROAR: - if (gBattleMons[battler].status2 & STATUS2_UPROAR) + if (gBattleMons[battler].volatiles.uproarTurns) { for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { @@ -1357,7 +1357,7 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) && GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) { gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = 1; BattleScriptExecute(BattleScript_MonWokeUpInUproar); BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); @@ -1372,16 +1372,16 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) else { gBattlerAttacker = battler; - gBattleMons[battler].status2 -= STATUS2_UPROAR_TURN(1); // uproar timer goes down + gBattleMons[battler].volatiles.uproarTurns--; // uproar timer goes down if (WasUnableToUseMove(battler)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_ENDS; } - else if (gBattleMons[battler].status2 & STATUS2_UPROAR) + else if (gBattleMons[battler].volatiles.uproarTurns) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_CONTINUES; - gBattleMons[battler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[battler].volatiles.multipleTurns = TRUE; } else { diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index ca1b8fcb02..930419e3d9 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -459,10 +459,10 @@ static void SpriteCB_TrainerSlideVertical(struct Sprite *sprite) #undef sSpeedX -void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 status) +void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isVolatile, u32 status) { gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 1; - if (!isStatus2) + if (!isVolatile) { if (status == STATUS1_FREEZE || status == STATUS1_FROSTBITE) LaunchStatusAnimation(battler, B_ANIM_STATUS_FRZ); @@ -479,13 +479,13 @@ void InitAndLaunchChosenStatusAnimation(u32 battler, bool32 isStatus2, u32 statu } else { - if (status & STATUS2_INFATUATION) + if (status == VOLATILE_INFATUATION) LaunchStatusAnimation(battler, B_ANIM_STATUS_INFATUATION); - else if (status & STATUS2_CONFUSION) + else if (status == VOLATILE_CONFUSION) LaunchStatusAnimation(battler, B_ANIM_STATUS_CONFUSION); - else if (status & STATUS2_CURSED) + else if (status == VOLATILE_CURSED) LaunchStatusAnimation(battler, B_ANIM_STATUS_CURSED); - else if (status & STATUS2_NIGHTMARE) + else if (status == VOLATILE_NIGHTMARE) LaunchStatusAnimation(battler, B_ANIM_STATUS_NIGHTMARE); else // no animation gBattleSpritesDataPtr->healthBoxesData[battler].statusAnimActive = 0; diff --git a/src/battle_main.c b/src/battle_main.c index 869720c680..22c27ea460 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3117,14 +3117,13 @@ static void BattleStartClearSetData(void) } } -#define UNPACK_VOLATILE_BATON_PASSABLES(_enum, _fieldName, _typeBitSize, ...) __VA_OPT__(if ((FIRST(__VA_ARGS__)) & V_BATON_PASSABLE) gBattleMons[battler].volatiles._fieldName = volatilesCopy._fieldName;) +#define UNPACK_VOLATILE_BATON_PASSABLES(_enum, _fieldName, _typeMaxValue, ...) __VA_OPT__(if ((FIRST(__VA_ARGS__)) & V_BATON_PASSABLE) gBattleMons[battler].volatiles._fieldName = volatilesCopy->_fieldName;) -void SwitchInClearSetData(u32 battler) +void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) { s32 i; enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); struct DisableStruct disableStructCopy = gDisableStructs[battler]; - struct Volatiles volatilesCopy = gBattleMons[battler].volatiles; ClearIllusionMon(battler); if (effect != EFFECT_BATON_PASS) @@ -3133,8 +3132,8 @@ void SwitchInClearSetData(u32 battler) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == battler) - gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION; + if (gBattleMons[i].volatiles.escapePrevention && gDisableStructs[i].battlerPreventingEscape == battler) + gBattleMons[i].volatiles.escapePrevention = FALSE; if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].battlerWithSureHit == battler) { gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; @@ -3142,15 +3141,17 @@ void SwitchInClearSetData(u32 battler) } } } + + // Clear volatiles - reapply some if Baton Pass was used + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); if (effect == EFFECT_BATON_PASS) { // Transfer Baton Passable volatile statuses - memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); VOLATILE_DEFINITIONS(UNPACK_VOLATILE_BATON_PASSABLES) /* Expands to the following (compiler removes `if` statements): - * gBattleMons[battler].volatiles.confusionTurns = volatilesCopy.confusionTurns; - * gBattleMons[battler].volatiles.substitute = volatilesCopy.substitute; - * gBattleMons[battler].volatiles.escapePrevention = volatilesCopy.escapePrevention; + * gBattleMons[battler].volatiles.confusionTurns = volatilesCopy->confusionTurns; + * gBattleMons[battler].volatiles.substitute = volatilesCopy->substitute; + * gBattleMons[battler].volatiles.escapePrevention = volatilesCopy->escapePrevention; * ...etc */ gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED @@ -3172,17 +3173,16 @@ void SwitchInClearSetData(u32 battler) } else { - gBattleMons[battler].status2 = 0; gStatuses3[battler] = 0; gStatuses4[battler] = 0; } for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler)) - gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler); - if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler) - gBattleMons[i].status2 &= ~STATUS2_WRAPPED; + if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) + gBattleMons[i].volatiles.infatuation = 0; + if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + gBattleMons[i].volatiles.wrapped = FALSE; if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; } @@ -3203,7 +3203,7 @@ void SwitchInClearSetData(u32 battler) } else if (effect == EFFECT_SHED_TAIL) { - gBattleMons[battler].status2 |= STATUS2_SUBSTITUTE; + gBattleMons[battler].volatiles.substitute = TRUE; gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP; } @@ -3289,18 +3289,18 @@ const u8* FaintClearSetData(u32 battler) for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - gBattleMons[battler].status2 = 0; + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); gStatuses3[battler] &= STATUS3_GASTRO_ACID; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. gStatuses4[battler] = 0; for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == battler) - gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION; - if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(battler)) - gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battler); - if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && gBattleStruct->wrappedBy[i] == battler) - gBattleMons[i].status2 &= ~STATUS2_WRAPPED; + if (gBattleMons[i].volatiles.escapePrevention && gDisableStructs[i].battlerPreventingEscape == battler) + gBattleMons[i].volatiles.escapePrevention = FALSE; + if (gBattleMons[i].volatiles.infatuation == INFATUATED_WITH(battler)) + gBattleMons[i].volatiles.infatuation = 0; + if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) + gBattleMons[i].volatiles.wrapped = FALSE; if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; } @@ -3403,17 +3403,17 @@ const u8* FaintClearSetData(u32 battler) // If the target was sky dropped in the middle of using Outrage/Petal Dance/Thrash, // confuse them upon release and print "confused via fatigue" message and animation. - if (gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) + if (gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns) { - gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns = 0; // If the released mon can be confused, do so. // Don't use CanBeConfused here, since it can cause issues in edge cases. if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO - || gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION + || gBattleMons[otherSkyDropper].volatiles.confusionTurns || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) { - gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattlerAttacker = otherSkyDropper; result = BattleScript_ThrashConfuses; } @@ -3476,7 +3476,7 @@ static void DoBattleIntro(void) gBattleMons[battler].types[2] = TYPE_MYSTERY; gBattleMons[battler].ability = GetAbilityBySpecies(gBattleMons[battler].species, gBattleMons[battler].abilityNum); gBattleStruct->hpOnSwitchout[GetBattlerSide(battler)] = gBattleMons[battler].hp; - gBattleMons[battler].status2 = 0; + memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; #if TESTING @@ -3905,7 +3905,7 @@ static void TryDoEventsBeforeFirstTurn(void) for (i = 0; i < gBattlersCount; i++) { - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; + gBattleMons[i].volatiles.flinched = FALSE; // Record party slots of player's mons that appeared in battle if (!BattlerHasAi(i)) gBattleStruct->appearedInBattle |= 1u << gBattlerPartyIndexes[i]; @@ -3945,8 +3945,8 @@ static void HandleEndTurn_ContinueBattle(void) gBattleCommunication[i] = 0; for (i = 0; i < gBattlersCount; i++) { - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; - if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].status2 & STATUS2_MULTIPLETURNS)) + gBattleMons[i].volatiles.flinched = FALSE; + if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].volatiles.multipleTurns)) CancelMultiTurnMoves(i, SKY_DROP_IGNORE); } gBattleStruct->eventBlockCounter = 0; @@ -4003,8 +4003,8 @@ void BattleTurnPassed(void) gChosenMoveByBattler[i] = MOVE_NONE; gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; gStatuses4[i] &= ~STATUS4_ELECTRIFIED; - gBattleMons[i].status2 &= ~STATUS2_FLINCHED; - gBattleMons[i].status2 &= ~STATUS2_POWDER; + gBattleMons[i].volatiles.flinched = FALSE; + gBattleMons[i].volatiles.powder = FALSE; if (gBattleStruct->battlerState[i].stompingTantrumTimer > 0) gBattleStruct->battlerState[i].stompingTantrumTimer--; @@ -4192,8 +4192,8 @@ static void HandleTurnActionSelectionState(void) } else { - if (gBattleMons[battler].status2 & STATUS2_MULTIPLETURNS - || gBattleMons[battler].status2 & STATUS2_RECHARGE) + if (gBattleMons[battler].volatiles.multipleTurns + || gBattleMons[battler].volatiles.recharge) { gChosenActionByBattler[battler] = B_ACTION_USE_MOVE; gBattleCommunication[battler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY; @@ -4347,8 +4347,8 @@ static void HandleTurnActionSelectionState(void) gBattleCommunication[battler] = STATE_WAIT_SET_BEFORE_ACTION; gBattleCommunication[GetPartnerBattler(battler)] = STATE_BEFORE_ACTION_CHOSEN; RecordedBattle_ClearBattlerAction(battler, 1); - if (gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_MULTIPLETURNS - || gBattleMons[GetPartnerBattler(battler)].status2 & STATUS2_RECHARGE) + if (gBattleMons[GetPartnerBattler(battler)].volatiles.multipleTurns + || gBattleMons[GetPartnerBattler(battler)].volatiles.recharge) { BtlController_EmitEndBounceEffect(battler, B_COMM_TO_CONTROLLER); MarkBattlerForControllerExec(battler); @@ -4740,9 +4740,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h speed *= 2; else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; - else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) + else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].volatiles.transformed) && ((gBattleWeather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; - else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) + else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].volatiles.transformed) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivated)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive) speed *= 2; @@ -4762,7 +4762,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h speed /= 2; else if (holdEffect == HOLD_EFFECT_CHOICE_SCARF && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) speed = (speed * 150) / 100; - else if (holdEffect == HOLD_EFFECT_QUICK_POWDER && gBattleMons[battler].species == SPECIES_DITTO && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + else if (holdEffect == HOLD_EFFECT_QUICK_POWDER && gBattleMons[battler].species == SPECIES_DITTO && !(gBattleMons[battler].volatiles.transformed)) speed *= 2; // various effects @@ -5108,13 +5108,13 @@ static void TurnValuesCleanUp(bool8 var0) { gDisableStructs[i].rechargeTimer--; if (gDisableStructs[i].rechargeTimer == 0) - gBattleMons[i].status2 &= ~STATUS2_RECHARGE; + gBattleMons[i].volatiles.recharge = FALSE; } gBattleStruct->battlerState[i].canPickupItem = FALSE; } if (gDisableStructs[i].substituteHP == 0) - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; if (!(gStatuses3[i] & STATUS3_COMMANDER)) gBattleStruct->battlerState[i].commandingDondozo = FALSE; diff --git a/src/battle_message.c b/src/battle_message.c index 6be243ba51..9027d5a36e 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1379,11 +1379,6 @@ const u16 gStatusConditionsStringIds[] = STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP, STRINGID_PKMNGOTFROSTBITE }; -const u16 gStatus2StringIds[] = -{ - STRINGID_PKMNWASCONFUSED, STRINGID_PKMNFELLINLOVE, STRINGID_TARGETCANTESCAPENOW, STRINGID_PKMNSUBJECTEDTOTORMENT -}; - const u16 gDamageNonTypesStartStringIds[] = { [B_MSG_TRAPPED_WITH_VINES] = STRINGID_TEAMTRAPPEDWITHVINES, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c0842af259..a50fb27956 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -449,8 +449,8 @@ static void Cmd_drawpartystatussummary(void); static void Cmd_hidepartystatussummary(void); static void Cmd_jumptocalledmove(void); static void Cmd_statusanimation(void); -static void Cmd_status2animation(void); -static void Cmd_chosenstatusanimation(void); +static void Cmd_unused_0x65(void); +static void Cmd_unused_0x66(void); static void Cmd_yesnobox(void); static void Cmd_cancelallactions(void); static void Cmd_setgravity(void); @@ -525,7 +525,7 @@ static void Cmd_tryspiteppreduce(void); static void Cmd_healpartystatus(void); static void Cmd_cursetarget(void); static void Cmd_trysetspikes(void); -static void Cmd_setforesight(void); +static void Cmd_setvolatile(void); static void Cmd_trysetperishsong(void); static void Cmd_handlerollout(void); static void Cmd_jumpifconfusedandstatmaxed(void); @@ -539,7 +539,7 @@ static void Cmd_tryrestorehpberry(void); static void Cmd_halvehp(void); static void Cmd_copyfoestats(void); static void Cmd_rapidspinfree(void); -static void Cmd_setdefensecurlbit(void); +static void Cmd_unused_0xBF(void); static void Cmd_recoverbasedonsunlight(void); static void Cmd_setstickyweb(void); static void Cmd_selectfirstvalidtarget(void); @@ -708,8 +708,8 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_hidepartystatussummary, //0x62 Cmd_jumptocalledmove, //0x63 Cmd_statusanimation, //0x64 - Cmd_status2animation, //0x65 - Cmd_chosenstatusanimation, //0x66 + Cmd_unused_0x65, //0x65 + Cmd_unused_0x66, //0x66 Cmd_yesnobox, //0x67 Cmd_cancelallactions, //0x68 Cmd_setgravity, //0x69 @@ -784,7 +784,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_healpartystatus, //0xAE Cmd_cursetarget, //0xAF Cmd_trysetspikes, //0xB0 - Cmd_setforesight, //0xB1 + Cmd_setvolatile, //0xB1 Cmd_trysetperishsong, //0xB2 Cmd_handlerollout, //0xB3 Cmd_jumpifconfusedandstatmaxed, //0xB4 @@ -798,7 +798,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_halvehp, //0xBC Cmd_copyfoestats, //0xBD Cmd_rapidspinfree, //0xBE - Cmd_setdefensecurlbit, //0xBF + Cmd_unused_0xBF, //0xBF Cmd_recoverbasedonsunlight, //0xC0 Cmd_setstickyweb, //0xC1 Cmd_selectfirstvalidtarget, //0xC2 @@ -1137,9 +1137,9 @@ u32 NumAffectedSpreadMoveTargets(void) u32 NumFaintedBattlersByAttacker(u32 battlerAtk) { - u32 numMonsFainted = 0; + u32 battler, numMonsFainted = 0; - for (u32 battler = 0; battler < gBattlersCount; battler++) + for (battler = 0; battler < gBattlersCount; battler++) { if (battler == battlerAtk) continue; @@ -1268,7 +1268,7 @@ static void Cmd_attackcanceler(void) if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & (HITMARKER_ALLOW_NO_PP | HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT)) - && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + && !(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) { gBattlescriptCurrInstr = BattleScript_NoPPForMove; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; @@ -1279,7 +1279,7 @@ static void Cmd_attackcanceler(void) // Check if no available target present on the field or if Sky Battles ban the move if ((NoTargetPresent(gBattlerAttacker, gCurrentMove) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) + && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns))) || (IsMoveNotAllowedInSkyBattles(gCurrentMove))) { gBattleStruct->noTargetPresent = TRUE; @@ -1289,7 +1289,7 @@ static void Cmd_attackcanceler(void) else gBattlescriptCurrInstr = BattleScript_FailedFromAtkString; - if (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + if (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); return; } @@ -1354,7 +1354,8 @@ static void Cmd_attackcanceler(void) return; } - for (u32 i = 0; i < gBattlersCount; i++) + u32 i; + for (i = 0; i < gBattlersCount; i++) { if ((gProtectStructs[gBattlerByTurnOrder[i]].stealMove) && MoveCanBeSnatched(gCurrentMove)) { @@ -1382,7 +1383,7 @@ static void Cmd_attackcanceler(void) } else if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) && (effect != EFFECT_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) + && (!gBattleMoveEffects[effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) && effect != EFFECT_SUCKER_PUNCH && effect != EFFECT_COUNTER && effect != EFFECT_UPPER_HAND) @@ -1504,13 +1505,14 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u } else { - u32 numTargets = 0; - u32 numMisses = 0; - u32 moveType = GetBattleMoveType(move); - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); + u32 battlerDef, + numTargets = 0, + numMisses = 0, + moveType = GetBattleMoveType(move), + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, move); bool32 calcSpreadMove = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(move); - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->calculatedSpreadMoveAccuracy) break; @@ -1624,7 +1626,7 @@ static void Cmd_ppreduce(void) if (gBattleControllerExecFlags) return; - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) + if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns) gHitMarker |= HITMARKER_NO_PPDEDUCT; if (moveTarget == MOVE_TARGET_BOTH @@ -1739,8 +1741,8 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA } else { - critChance = 2 * ((gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY) != 0) - + 1 * ((gBattleMons[battlerAtk].status2 & STATUS2_DRAGON_CHEER) != 0) + critChance = 2 * (gBattleMons[battlerAtk].volatiles.focusEnergy != 0) + + 1 * (gBattleMons[battlerAtk].volatiles.dragonCheer != 0) + GetMoveCriticalHitStage(move) + GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk) + 2 * (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) @@ -1789,9 +1791,9 @@ s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec if (bonusCritStage > 0) critChance *= bonusCritStage; - if (gBattleMons[battlerAtk].status2 & STATUS2_FOCUS_ENERGY) + if (gBattleMons[battlerAtk].volatiles.focusEnergy) critChance *= 4; - else if (gBattleMons[battlerAtk].status2 & STATUS2_DRAGON_CHEER) + else if (gBattleMons[battlerAtk].volatiles.dragonCheer) critChance *= 2; if (holdEffectCritStage > 0) @@ -1836,14 +1838,15 @@ static void Cmd_critcalc(void) { CMD_ARGS(); - u32 partySlot = gBattlerPartyIndexes[gBattlerAttacker]; - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + u32 partySlot = gBattlerPartyIndexes[gBattlerAttacker], + moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), + abilityAtk = GetBattlerAbility(gBattlerAttacker), + battlerDef; bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); - u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); gPotentialItemEffectBattler = gBattlerAttacker; - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->calculatedDamageDone) break; @@ -2120,7 +2123,7 @@ static inline bool32 DoesBattlerNegateDamage(u32 battler) u32 species = gBattleMons[battler].species; u32 ability = GetBattlerAbility(battler); - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; if (ability == ABILITY_DISGUISE && species == SPECIES_MIMIKYU) return TRUE; @@ -2307,7 +2310,7 @@ static void Cmd_attackanimation(void) if (!(moveResultFlags & MOVE_RESULT_NO_EFFECT)) { u32 multihit; - if (gBattleMons[gBattlerTarget].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[gBattlerTarget].volatiles.substitute) { multihit = gMultiHitCounter; } @@ -3138,20 +3141,20 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_CONFUSION: if (!CanBeConfused(gEffectBattler) - || gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION + || gBattleMons[gEffectBattler].volatiles.confusionTurns || (gSideStatuses[GetBattlerSide(gEffectBattler)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && !primary)) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); // 2-5 turns + gBattleMons[gEffectBattler].volatiles.confusionTurns = ((Random()) % 4) + 2; // 2-5 turns // If the confusion is activating due to being released from Sky Drop, go to "confused due to fatigue" script. // Otherwise, do normal confusion script. if (GetMoveEffect(gCurrentMove) == EFFECT_SKY_DROP) { - gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; gBattlerAttacker = gEffectBattler; gBattlescriptCurrInstr = BattleScript_ThrashConfuses; } @@ -3179,14 +3182,14 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattlescriptCurrInstr++; } } - else if (gBattleMons[gEffectBattler].status2 & STATUS2_FLINCHED) + else if (gBattleMons[gEffectBattler].volatiles.flinched) { gBattlescriptCurrInstr++; } else if (GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber && !(GetActiveGimmick(gEffectBattler) == GIMMICK_DYNAMAX)) { - gBattleMons[gEffectBattler].status2 |= STATUS2_FLINCHED; + gBattleMons[gEffectBattler].volatiles.flinched = TRUE; gBattlescriptCurrInstr++; } else @@ -3195,11 +3198,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_UPROAR: - if (!(gBattleMons[gEffectBattler].status2 & STATUS2_UPROAR)) + if (!gBattleMons[gEffectBattler].volatiles.uproarTurns) { - gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gEffectBattler].volatiles.multipleTurns = TRUE; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN(B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2); + gBattleMons[gEffectBattler].volatiles.uproarTurns = B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectUproar; @@ -3260,13 +3263,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_WRAP: - if (gBattleMons[gEffectBattler].status2 & STATUS2_WRAPPED) + if (gBattleMons[gEffectBattler].volatiles.wrapped) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED; + gBattleMons[gEffectBattler].volatiles.wrapped = TRUE; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5; else @@ -3401,13 +3404,13 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (B_SKIP_RECHARGE == GEN_1 && !IsBattlerAlive(gBattlerTarget)) // Skip recharge if gen 1 and foe is KO'd break; - gBattleMons[gEffectBattler].status2 |= STATUS2_RECHARGE; + gBattleMons[gEffectBattler].volatiles.recharge = TRUE; gDisableStructs[gEffectBattler].rechargeTimer = 2; gLockedMoves[gEffectBattler] = gCurrentMove; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_RAGE: - gBattleMons[gBattlerAttacker].status2 |= STATUS2_RAGE; + gBattleMons[gBattlerAttacker].volatiles.rage = TRUE; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_STEAL_ITEM: @@ -3440,15 +3443,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_PREVENT_ESCAPE: - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; } gBattlescriptCurrInstr++; break; case MOVE_EFFECT_NIGHTMARE: - gBattleMons[gBattlerTarget].status2 |= STATUS2_NIGHTMARE; + gBattleMons[gBattlerTarget].volatiles.nightmare = TRUE; gBattlescriptCurrInstr++; break; case MOVE_EFFECT_ALL_STATS_UP: @@ -3484,15 +3487,15 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_THRASH: // Petal Dance doesn't lock mons that copy the move with Dancer - if (gSpecialStatuses[gEffectBattler].dancerUsedMove || gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE) + if (gSpecialStatuses[gEffectBattler].dancerUsedMove || gBattleMons[gEffectBattler].volatiles.lockConfusionTurns) { gBattlescriptCurrInstr++; } else { - gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gEffectBattler].volatiles.multipleTurns = TRUE; gLockedMoves[gEffectBattler] = gCurrentMove; - gBattleMons[gEffectBattler].status2 |= STATUS2_LOCK_CONFUSE_TURN(RandomUniform(RNG_RAMPAGE_TURNS, 2, 3)); + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = RandomUniform(RNG_RAMPAGE_TURNS, 2, 3); } break; case MOVE_EFFECT_CLEAR_SMOG: @@ -3597,19 +3600,19 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_TRAP_BOTH: - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!(gBattleMons[gBattlerTarget].volatiles.escapePrevention || gBattleMons[gBattlerAttacker].volatiles.escapePrevention)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_BothCanNoLongerEscape; } - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerAttacker].volatiles.escapePrevention) gDisableStructs[gBattlerAttacker].battlerPreventingEscape = gBattlerTarget; - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; + gBattleMons[gBattlerAttacker].volatiles.escapePrevention = TRUE; break; case MOVE_EFFECT_REMOVE_ARG_TYPE: { @@ -3893,7 +3896,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) - && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[gBattlerTarget].volatiles.transformed)) { BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); MarkBattlerForControllerExec(gBattlerTarget); @@ -4128,9 +4131,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { if (!IsBattlerAlly(battler, gBattlerTarget)) continue; - if (!(gBattleMons[battler].status2 & STATUS2_WRAPPED)) + if (!gBattleMons[battler].volatiles.wrapped) { - gBattleMons[battler].status2 |= STATUS2_WRAPPED; + gBattleMons[battler].volatiles.wrapped = TRUE; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[battler].wrapTurns = (B_BINDING_TURNS >= GEN_5) ? 7 : 5; else @@ -4539,12 +4542,12 @@ static void Cmd_jumpifstatus(void) static void Cmd_jumpifvolatile(void) { - CMD_ARGS(u8 battler, u8 volatileStatus, const u8 *jumpInstr); + CMD_ARGS(u8 battler, u8 _volatile, const u8 *jumpInstr); u8 battler = GetBattlerForBattleScript(cmd->battler); const u8 *jumpInstr = cmd->jumpInstr; - if (GetMonVolatile(battler, cmd->volatileStatus) && IsBattlerAlive(battler)) + if (GetMonVolatile(battler, cmd->_volatile) && IsBattlerAlive(battler)) gBattlescriptCurrInstr = jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -6119,7 +6122,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_RAGE: // rage check - if (gBattleMons[gBattlerTarget].status2 & STATUS2_RAGE + if (gBattleMons[gBattlerTarget].volatiles.rage && IsBattlerAlive(gBattlerTarget) && gBattlerAttacker != gBattlerTarget && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) @@ -6313,7 +6316,7 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { if (gDisableStructs[i].substituteHP == 0) - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; } gBattleScripting.moveendState++; break; @@ -6348,7 +6351,7 @@ static void Cmd_moveend(void) if (!IsOnPlayerSide(gBattlerAttacker)) UpdateStallMons(); if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) - || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) + || (gBattleMons[gBattlerAttacker].volatiles.flinched) || gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility) gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2; @@ -7050,7 +7053,7 @@ static void Cmd_moveend(void) if (B_RAMPAGE_CANCELLING >= GEN_5 && MoveHasAdditionalEffectSelf(gCurrentMove, MOVE_EFFECT_THRASH) // If we're rampaging && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT // And it is unusable - && (gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE) != STATUS2_LOCK_CONFUSE_TURN(1)) // And won't end this turn + && gBattleMons[gBattlerAttacker].volatiles.lockConfusionTurns != 1) // And won't end this turn CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_IGNORE); // Cancel it if (gBattleStruct->savedAttackerCount > 0) @@ -7320,10 +7323,9 @@ static void Cmd_switchindataupdate(void) { gBattleMons[battler].statStages[i] = oldData.statStages[i]; } - gBattleMons[battler].status2 = oldData.status2; } - SwitchInClearSetData(battler); + SwitchInClearSetData(battler, &oldData.volatiles); if (gBattleTypeFlags & BATTLE_TYPE_PALACE && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp @@ -7843,7 +7845,7 @@ static void UpdateSentMonFlags(u32 battler) static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) { - gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND; + gBattleMons[battler].volatiles.destinyBond = FALSE; gHitMarker &= ~HITMARKER_DESTINYBOND; gBattleScripting.battler = battler; gBattleCommunication[MULTISTRING_CHOOSER] = multistringId; @@ -8220,7 +8222,7 @@ static void Cmd_handlelearnnewmove(void) u32 battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gBattlerPartyIndexes[battler] == monId - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { GiveMoveToBattleMon(&gBattleMons[battler], learnMove); } @@ -8228,7 +8230,7 @@ static void Cmd_handlelearnnewmove(void) { battler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); if (gBattlerPartyIndexes[battler] == monId - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { GiveMoveToBattleMon(&gBattleMons[battler], learnMove); } @@ -8643,58 +8645,29 @@ static void Cmd_jumptocalledmove(void) static void Cmd_statusanimation(void) { - CMD_ARGS(u8 battler); + CMD_ARGS(u8 battler, u32 status, bool8 isVolatile); if (gBattleControllerExecFlags == 0) { - u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 battler = GetBattlerForBattleScript(cmd->battler), + statusFlag = (cmd->isVolatile || cmd->status) ? cmd->status : gBattleMons[battler].status1; if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[battler].substituteHP == 0 && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, FALSE, gBattleMons[battler].status1); + BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, cmd->isVolatile, statusFlag); MarkBattlerForControllerExec(battler); } gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_status2animation(void) +static void Cmd_unused_0x65(void) { - CMD_ARGS(u8 battler, u32 status2); - - if (gBattleControllerExecFlags == 0) - { - u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 status2ToAnim = cmd->status2; - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && gDisableStructs[battler].substituteHP == 0 - && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) - { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, TRUE, gBattleMons[battler].status2 & status2ToAnim); - MarkBattlerForControllerExec(battler); - } - gBattlescriptCurrInstr = cmd->nextInstr; - } } -static void Cmd_chosenstatusanimation(void) +static void Cmd_unused_0x66(void) { - CMD_ARGS(u8 battler, bool8 isStatus2, u32 status); - - if (gBattleControllerExecFlags == 0) - { - u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 wantedStatus = cmd->status; - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) - && gDisableStructs[battler].substituteHP == 0 - && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) - { - BtlController_EmitStatusAnimation(battler, B_COMM_TO_CONTROLLER, cmd->isStatus2, wantedStatus); - MarkBattlerForControllerExec(battler); - } - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_yesnobox(void) @@ -9454,13 +9427,13 @@ static bool32 TryTidyUpClear(u32 battlerAtk, bool32 clear) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - if (gBattleMons[i].status2 & STATUS2_SUBSTITUTE) + if (gBattleMons[i].volatiles.substitute) { if (clear) { gBattlerTarget = i; gDisableStructs[i].substituteHP = 0; - gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; + gBattleMons[i].volatiles.substitute = FALSE; BattleScriptCall(BattleScript_SubstituteFade); } gBattlerAttacker = saveBattler; @@ -9799,7 +9772,7 @@ static void Cmd_various(void) { VARIOUS_ARGS(u8 infatuateWith); gBattleScripting.battler = battler; - gBattleMons[battler].status2 |= STATUS2_INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); + gBattleMons[battler].volatiles.infatuation = INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); gBattlescriptCurrInstr = cmd->nextInstr; return; } @@ -9939,12 +9912,6 @@ static void Cmd_various(void) gStatuses3[battler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); break; } - case VARIOUS_SET_POWDER: - { - VARIOUS_ARGS(); - gBattleMons[battler].status2 |= STATUS2_POWDER; - break; - } case VARIOUS_ACUPRESSURE: { VARIOUS_ARGS(const u8 *failInstr); @@ -10953,10 +10920,10 @@ static void Cmd_various(void) gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget; gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker; - // End any multiturn effects caused by the target except STATUS2_LOCK_CONFUSE - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_MULTIPLETURNS); - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_UPROAR); - gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_BIDE); + // End any multiturn effects caused by the target except VOLATILE_LOCK_CONFUSE + gBattleMons[gBattlerTarget].volatiles.multipleTurns = 0; + gBattleMons[gBattlerTarget].volatiles.uproarTurns= 0; + gBattleMons[gBattlerTarget].volatiles.bideTurns = 0; gDisableStructs[gBattlerTarget].rolloutTimer = 0; gDisableStructs[gBattlerTarget].furyCutterCounter = 0; @@ -10982,7 +10949,7 @@ static void Cmd_various(void) } // Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted. - if (gBattleMons[gBattlerTarget].status2 & STATUS2_LOCK_CONFUSE) + if (gBattleMons[gBattlerTarget].volatiles.lockConfusionTurns) gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; return; } @@ -10999,11 +10966,11 @@ static void Cmd_various(void) gBattleStruct->skyDropTargets[gEffectBattler] = SKY_DROP_NO_TARGET; // If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation - if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE && CanBeConfused(gEffectBattler)) + if (gBattleMons[gEffectBattler].volatiles.lockConfusionTurns && CanBeConfused(gEffectBattler)) { - gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; gBattlerAttacker = gEffectBattler; - gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattlescriptCurrInstr = BattleScript_ThrashConfuses; return; } @@ -11225,7 +11192,7 @@ static void Cmd_various(void) } else { - if (!(gBattleMons[battler].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[battler].volatiles.escapePrevention) gDisableStructs[battler].noRetreat = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -11235,9 +11202,9 @@ static void Cmd_various(void) { VARIOUS_ARGS(); // Check infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) + if (gBattleMons[battler].volatiles.infatuation) { - gBattleMons[battler].status2 &= ~(STATUS2_INFATUATION); + gBattleMons[battler].volatiles.infatuation = 0; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); } @@ -11256,9 +11223,9 @@ static void Cmd_various(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED } // Check torment - if (gBattleMons[battler].status2 & STATUS2_TORMENT) + if (gBattleMons[battler].volatiles.torment == TRUE) { - gBattleMons[battler].status2 &= ~(STATUS2_TORMENT); + gBattleMons[battler].volatiles.torment = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; } // Check heal block @@ -11673,7 +11640,7 @@ bool8 UproarWakeUpCheck(u8 battler) for (i = 0; i < gBattlersCount; i++) { - if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || hasSoundproof) + if (!(gBattleMons[i].volatiles.uproarTurns) || hasSoundproof) continue; gBattleScripting.battler = i; @@ -12317,10 +12284,10 @@ static void Cmd_setbide(void) { CMD_ARGS(); - gBattleMons[gBattlerAttacker].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; gLockedMoves[gBattlerAttacker] = gCurrentMove; gBideDmg[gBattlerAttacker] = 0; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_BIDE_TURN(2); + gBattleMons[gBattlerAttacker].volatiles.bideTurns = 2; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12838,14 +12805,14 @@ static void Cmd_tryinfatuating(void) } else { - if (gBattleMons[gBattlerTarget].status2 & STATUS2_INFATUATION + if (gBattleMons[gBattlerTarget].volatiles.infatuation || !AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_INFATUATED_WITH(gBattlerAttacker); + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12865,7 +12832,7 @@ static void Cmd_updatestatusicon(void) { if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } } @@ -12876,7 +12843,7 @@ static void Cmd_updatestatusicon(void) battler = gBattlerAttacker; if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } if ((IsDoubleBattle())) @@ -12884,7 +12851,7 @@ static void Cmd_updatestatusicon(void) battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); if (!(gAbsentBattlerFlags & (1u << battler))) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); } } @@ -12893,7 +12860,7 @@ static void Cmd_updatestatusicon(void) else { battler = GetBattlerForBattleScript(cmd->battler); - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1, gBattleMons[battler].status2); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12924,22 +12891,22 @@ static void Cmd_setfocusenergy(void) enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); if ((effect == EFFECT_DRAGON_CHEER && (!(IsDoubleBattle()) || (gAbsentBattlerFlags & (1u << battler)))) - || gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + || gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED; } else if (effect == EFFECT_DRAGON_CHEER && !IS_BATTLER_OF_TYPE(battler, TYPE_DRAGON)) { - gBattleMons[battler].status2 |= STATUS2_DRAGON_CHEER; + gBattleMons[battler].volatiles.dragonCheer = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } else { if (GetGenConfig(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3) - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; else - gBattleMons[battler].status2 |= STATUS2_DRAGON_CHEER; + gBattleMons[battler].volatiles.dragonCheer = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -12951,7 +12918,7 @@ static void Cmd_transformdataexecution(void) gChosenMove = MOVE_UNAVAILABLE; gBattlescriptCurrInstr = cmd->nextInstr; - if (gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED + if (gBattleMons[gBattlerTarget].volatiles.transformed || gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER) { @@ -12964,7 +12931,7 @@ static void Cmd_transformdataexecution(void) u8 *battleMonAttacker, *battleMonTarget; u8 timesGotHit; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_TRANSFORMED; + gBattleMons[gBattlerAttacker].volatiles.transformed = TRUE; gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; @@ -13029,8 +12996,8 @@ static void Cmd_setsubstitute(void) if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_SUBSTITUTE; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED; + gBattleMons[gBattlerAttacker].volatiles.substitute = TRUE; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; if (factor == 2) gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker] / 2; else @@ -13047,7 +13014,7 @@ static void Cmd_mimicattackcopy(void) CMD_ARGS(const u8 *failInstr); if ((IsMoveMimicBanned(gLastMoves[gBattlerTarget])) - || (gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED) + || (gBattleMons[gBattlerAttacker].volatiles.transformed) || gLastMoves[gBattlerTarget] == MOVE_NONE || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) { @@ -13296,7 +13263,7 @@ static void Cmd_settypetorandomresistance(void) gBattlescriptCurrInstr = cmd->failInstr; } else if (gBattleMoveEffects[GetMoveEffect(gLastLandedMoves[gBattlerAttacker])].twoTurnEffect - && gBattleMons[gLastHitBy[gBattlerAttacker]].status2 & STATUS2_MULTIPLETURNS) + && gBattleMons[gLastHitBy[gBattlerAttacker]].volatiles.multipleTurns) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13422,7 +13389,7 @@ static void Cmd_copymovepermanently(void) gChosenMove = MOVE_UNAVAILABLE; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED) + if (!(gBattleMons[gBattlerAttacker].volatiles.transformed) && gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE && !IsMoveSketchBanned(gLastPrintedMoves[gBattlerTarget])) { @@ -13541,14 +13508,14 @@ static void Cmd_trysetdestinybond(void) } else { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND; + gBattleMons[gBattlerAttacker].volatiles.destinyBond = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } static void TrySetDestinyBondToHappen(void) { - if (gBattleMons[gBattlerTarget].status2 & STATUS2_DESTINY_BOND + if (gBattleMons[gBattlerTarget].volatiles.destinyBond && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && !(gHitMarker & HITMARKER_GRUDGE)) { @@ -13629,7 +13596,7 @@ static void Cmd_tryspiteppreduce(void) // if (MOVE_IS_PERMANENT(gBattlerTarget, i)), but backwards if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) - && !(gBattleMons[gBattlerTarget].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[gBattlerTarget].volatiles.transformed)) { BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); MarkBattlerForControllerExec(gBattlerTarget); @@ -13672,7 +13639,7 @@ static void Cmd_healpartystatus(void) else gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA; gBattleMons[gBattlerAttacker].status1 = 0; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; } else { @@ -13688,7 +13655,7 @@ static void Cmd_healpartystatus(void) || !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF)) { gBattleMons[partner].status1 = 0; - gBattleMons[partner].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[partner].volatiles.nightmare = FALSE; } else { @@ -13753,13 +13720,13 @@ static void Cmd_cursetarget(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_CURSED) + if (gBattleMons[gBattlerTarget].volatiles.cursed) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_CURSED; + gBattleMons[gBattlerTarget].volatiles.cursed = TRUE; gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) gBattleStruct->moveDamage[gBattlerAttacker] = 1; @@ -13787,11 +13754,11 @@ static void Cmd_trysetspikes(void) } } -static void Cmd_setforesight(void) +static void Cmd_setvolatile(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler, u8 _volatile, u8 value); - gBattleMons[gBattlerTarget].status2 |= STATUS2_FORESIGHT; + SetMonVolatile(GetBattlerForBattleScript(cmd->battler), cmd->_volatile, cmd->value); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -13835,16 +13802,16 @@ static void Cmd_handlerollout(void) } else { - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) // First hit. + if (!(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) // First hit. { gDisableStructs[gBattlerAttacker].rolloutTimer = 5; gDisableStructs[gBattlerAttacker].rolloutTimerStartValue = 5; - gBattleMons[gBattlerAttacker].status2 |= STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; gLockedMoves[gBattlerAttacker] = gCurrentMove; } if (--gDisableStructs[gBattlerAttacker].rolloutTimer == 0) // Last hit. { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -13855,7 +13822,7 @@ static void Cmd_jumpifconfusedandstatmaxed(void) { CMD_ARGS(u8 stat, const u8 *jumpInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION + if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0 && !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN)) gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised else @@ -14130,10 +14097,10 @@ static void Cmd_rapidspinfree(void) u8 atkSide = GetBattlerSide(gBattlerAttacker); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_WRAPPED) + if (gBattleMons[gBattlerAttacker].volatiles.wrapped) { gBattleScripting.battler = gBattlerTarget; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_WRAPPED; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker]; PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); BattleScriptCall(BattleScript_WrapFree); @@ -14163,12 +14130,8 @@ static void Cmd_rapidspinfree(void) } } -static void Cmd_setdefensecurlbit(void) +static void Cmd_unused_0xBF(void) { - CMD_ARGS(); - - gBattleMons[gBattlerAttacker].status2 |= STATUS2_DEFENSE_CURL; - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_recoverbasedonsunlight(void) @@ -14536,14 +14499,14 @@ static void Cmd_settorment(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT + if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].status2 |= STATUS2_TORMENT; + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -15300,7 +15263,7 @@ static void Cmd_settypebasedhalvers(void) bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) { - if (!(gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)) + if (!gBattleMons[battlerDef].volatiles.substitute) return FALSE; else if (MoveIgnoresSubstitute(move)) return FALSE; @@ -15313,7 +15276,7 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) bool32 DoesDisguiseBlockMove(u32 battler, u32 move) { if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) - || gBattleMons[battler].status2 & STATUS2_TRANSFORMED + || gBattleMons[battler].volatiles.transformed || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE)) || gHitMarker & HITMARKER_IGNORE_DISGUISE || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) @@ -16881,34 +16844,23 @@ void BS_ItemCureStatus(void) { NATIVE_ARGS(const u8 *noStatusInstr); u32 battler = gBattlerAttacker; - u32 previousStatus2 = 0; bool32 statusChanged = FALSE; struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - // Heal Status2 conditions if battler is active. + // Heal volatile conditions if battler is active. if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - { - previousStatus2 = gBattleMons[battler].status2; - gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem); - } + statusChanged = ItemHealMonVolatile(battler, gLastUsedItem); else if (IsDoubleBattle() - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) - { - battler = BATTLE_PARTNER(gBattlerAttacker); - previousStatus2 = gBattleMons[battler].status2; - gBattleMons[battler].status2 &= ~GetItemStatus2Mask(gLastUsedItem); - } - - if (previousStatus2 != gBattleMons[battler].status2) - statusChanged = TRUE; + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem); // Heal Status1 conditions. if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler)) { statusChanged = TRUE; if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; - if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION) + gBattleMons[battler].volatiles.nightmare = FALSE; + if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; } @@ -17168,7 +17120,7 @@ void BS_TrySetOctolock(void) else { gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[battler].volatiles.escapePrevention = TRUE; gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -17962,7 +17914,7 @@ void BS_CheckPokeFlute(void) if (GetBattlerAbility(i) != ABILITY_SOUNDPROOF) { gBattleMons[i].status1 &= ~STATUS1_SLEEP; - gBattleMons[i].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[i].volatiles.nightmare = FALSE; } } @@ -18243,8 +18195,7 @@ void BS_TrySetConfusion(void) if (CanBeConfused(gBattlerTarget)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; gBattleCommunication[MULTIUSE_STATE] = 1; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18259,13 +18210,12 @@ void BS_TrySetInfatuation(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_INFATUATION) + if (!gBattleMons[gBattlerTarget].volatiles.infatuation && gBattleMons[gBattlerTarget].ability != ABILITY_OBLIVIOUS && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_INFATUATED_WITH(gBattlerAttacker); - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); gBattleCommunication[MULTIUSE_STATE] = 2; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18280,11 +18230,10 @@ void BS_TrySetEscapePrevention(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION)) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; - gBattleCommunication[MULTISTRING_CHOOSER] = 2; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18298,12 +18247,11 @@ void BS_TrySetTorment(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT) + if (!(gBattleMons[gBattlerTarget].volatiles.torment == TRUE) && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)) { - gBattleMons[gBattlerTarget].status2 |= STATUS2_TORMENT; + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; gDisableStructs[gBattlerTarget].tormentTimer = gBattleTurnCounter + 3; // 3 turns excluding current turn - gBattleCommunication[MULTISTRING_CHOOSER] = 3; gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/battle_terastal.c b/src/battle_terastal.c index 6984f3fc6c..8799dc7ab2 100644 --- a/src/battle_terastal.c +++ b/src/battle_terastal.c @@ -64,7 +64,7 @@ bool32 CanTerastallize(u32 battler) { enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, FALSE); - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED && GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_TERAPAGOS) + if (gBattleMons[battler].volatiles.transformed && GET_BASE_SPECIES_ID(gBattleMons[battler].species) == SPECIES_TERAPAGOS) return FALSE; // Prevents Zigzagoon from terastalizing in vanilla. diff --git a/src/battle_util.c b/src/battle_util.c index d882f28fa4..088436c4c1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -412,7 +412,7 @@ void HandleAction_UseMove(void) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattleStruct->moveTarget[gBattlerAttacker] = GetBattleMoveTarget(MOVE_STRUGGLE, NO_TARGET_OVERRIDE); } - else if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS || gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) + else if (gBattleMons[gBattlerAttacker].volatiles.multipleTurns || gBattleMons[gBattlerAttacker].volatiles.recharge) { gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker]; } @@ -1056,18 +1056,18 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) // If target was sky dropped in the middle of Outrage/Thrash/Petal Dance, // confuse them upon release and display "confused by fatigue" message & animation. // Don't do this if this CancelMultiTurnMoves is caused by falling asleep via Yawn. - if (gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE && skyDropState != SKY_DROP_STATUS_YAWN) + if (gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns && skyDropState != SKY_DROP_STATUS_YAWN) { - gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns = 0; // If the target can be confused, confuse them. // Don't use CanBeConfused, can cause issues in edge cases. - if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION + if (!(gBattleMons[otherSkyDropper].volatiles.confusionTurns > 0 || IsAbilityAndRecord(otherSkyDropper, GetBattlerAbility(otherSkyDropper), ABILITY_OWN_TEMPO) || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) { // Set confused status - gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); + gBattleMons[otherSkyDropper].volatiles.confusionTurns = ((Random()) % 4) + 2; if (skyDropState == SKY_DROP_ATTACKCANCELLER_CHECK) { @@ -1094,7 +1094,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) } // Clear skyDropTargets data, unless this CancelMultiTurnMoves is caused by Yawn, attackcanceler, or VARIOUS_GRAVITY_ON_AIRBORNE_MONS - if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[battler] < 4) + if (!(gBattleMons[otherSkyDropper].volatiles.lockConfusionTurns) && gBattleStruct->skyDropTargets[battler] < 4) { gBattleStruct->skyDropTargets[battler] = SKY_DROP_NO_TARGET; gBattleStruct->skyDropTargets[otherSkyDropper] = SKY_DROP_NO_TARGET; @@ -1106,18 +1106,18 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState) { const u8 *result = NULL; - gBattleMons[battler].status2 &= ~(STATUS2_UPROAR); - gBattleMons[battler].status2 &= ~(STATUS2_BIDE); + gBattleMons[battler].volatiles.uproarTurns = 0; + gBattleMons[battler].volatiles.bideTurns = 0; if (B_RAMPAGE_CANCELLING < GEN_5) { - gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); - gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[battler].volatiles.multipleTurns = 0; + gBattleMons[battler].volatiles.lockConfusionTurns = 0; } - else if (!(gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) - || ((gBattleMons[battler].status2 & STATUS2_LOCK_CONFUSE) > STATUS2_LOCK_CONFUSE_TURN(1))) + else if (!gBattleMons[battler].volatiles.lockConfusionTurns + || gBattleMons[battler].volatiles.lockConfusionTurns > 1) { - gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); + gBattleMons[battler].volatiles.multipleTurns = 0; } // Clear battler's semi-invulnerable bits if they are not held by Sky Drop. @@ -1341,7 +1341,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } } - if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT)) + if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].volatiles.torment == TRUE)) { CancelMultiTurnMoves(battler, SKY_DROP_IGNORE); if (gBattleTypeFlags & BATTLE_TYPE_PALACE) @@ -1588,7 +1588,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) else if (check & MOVE_LIMITATION_DISABLED && move == gDisableStructs[battler].disabledMove) unusableMoves |= 1u << i; // Torment - else if (check & MOVE_LIMITATION_TORMENTED && move == gLastMoves[battler] && gBattleMons[battler].status2 & STATUS2_TORMENT) + else if (check & MOVE_LIMITATION_TORMENTED && move == gLastMoves[battler] && gBattleMons[battler].volatiles.torment == TRUE) unusableMoves |= 1u << i; // Taunt else if (check & MOVE_LIMITATION_TAUNT && gDisableStructs[battler].tauntTimer && IsBattleMoveStatus(move)) @@ -1849,8 +1849,8 @@ void TryClearRageAndFuryCutter(void) s32 i; for (i = 0; i < gBattlersCount; i++) { - if ((gBattleMons[i].status2 & STATUS2_RAGE) && gChosenMoveByBattler[i] != MOVE_RAGE) - gBattleMons[i].status2 &= ~STATUS2_RAGE; + if (gBattleMons[i].volatiles.rage && gChosenMoveByBattler[i] != MOVE_RAGE) + gBattleMons[i].volatiles.rage = FALSE; if (gDisableStructs[i].furyCutterCounter != 0 && gChosenMoveByBattler[i] != MOVE_FURY_CUTTER) gDisableStructs[i].furyCutterCounter = 0; } @@ -1871,7 +1871,7 @@ static inline bool32 TryFormChangeBeforeMove(void) static inline bool32 TryActivatePowderStatus(u32 move) { u32 partnerMove = gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].moves[gBattleStruct->chosenMovePositions[BATTLE_PARTNER(gBattlerAttacker)]]; - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)) + if (!gBattleMons[gBattlerAttacker].volatiles.powder) return FALSE; if (GetBattleMoveType(move) == TYPE_FIRE && !gBattleStruct->pledgeMove) return TRUE; @@ -1890,7 +1890,7 @@ void SetAtkCancellerForCalledMove(void) static enum MoveCanceller CancellerFlags(void) { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND; + gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE; gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH; return MOVE_STEP_SUCCESS; @@ -1917,9 +1917,9 @@ static enum MoveCanceller CancellerSkyDrop(void) static enum MoveCanceller CancellerRecharge(void) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE) + if (gBattleMons[gBattlerAttacker].volatiles.recharge) { - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RECHARGE; + gBattleMons[gBattlerAttacker].volatiles.recharge = TRUE; gDisableStructs[gBattlerAttacker].rechargeTimer = 0; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; @@ -1937,7 +1937,7 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void) { TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; @@ -1967,7 +1967,7 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void) else { TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; @@ -2067,7 +2067,7 @@ static enum MoveCanceller CancellerTruant(void) static enum MoveCanceller CancellerFlinch(void) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED) + if (gBattleMons[gBattlerAttacker].volatiles.flinched) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); @@ -2154,11 +2154,11 @@ static enum MoveCanceller CancellerConfused(void) if (gBattleStruct->isAtkCancelerForCalledMove) return MOVE_STEP_SUCCESS; - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) { if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) - gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) + gBattleMons[gBattlerAttacker].volatiles.confusionTurns--; + if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) { // confusion dmg if (RandomPercentage(RNG_CONFUSION, (GetGenConfig(GEN_CONFIG_CONFUSION_SELF_DMG_CHANCE) >= GEN_7 ? 33 : 50))) @@ -2212,9 +2212,9 @@ static enum MoveCanceller CancellerParalysed(void) static enum MoveCanceller CancellerInfatuation(void) { - if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) + if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].volatiles.infatuation) { - gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10); + gBattleScripting.battler = gBattleMons[gBattlerAttacker].volatiles.infatuation - 1; if (!RandomPercentage(RNG_INFATUATION, 50)) { BattleScriptCall(BattleScript_MoveUsedIsInLove); @@ -2234,17 +2234,16 @@ static enum MoveCanceller CancellerInfatuation(void) static enum MoveCanceller CancellerBide(void) { - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + if (gBattleMons[gBattlerAttacker].volatiles.bideTurns) { - gBattleMons[gBattlerAttacker].status2 -= STATUS2_BIDE_TURN(1); - if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE) + if (--gBattleMons[gBattlerAttacker].volatiles.bideTurns) { gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; } else { // This is removed in FRLG and Emerald for some reason - //gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_MULTIPLETURNS; + //gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; if (gBideDmg[gBattlerAttacker]) { gCurrentMove = MOVE_BIDE; @@ -2978,7 +2977,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a case ABILITY_SOUNDPROOF: if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER)) { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) + if (gBattleMons[battlerAtk].volatiles.multipleTurns) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; } @@ -2986,7 +2985,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a case ABILITY_BULLETPROOF: if (IsBallisticMove(move)) { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) + if (gBattleMons[battlerAtk].volatiles.multipleTurns) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_SoundproofProtected; } @@ -2996,7 +2995,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a case ABILITY_ARMOR_TAIL: if (atkPriority > 0 && !IsBattlerAlly(battlerAtk, battlerDef)) { - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) + if (gBattleMons[battlerAtk].volatiles.multipleTurns) gHitMarker |= HITMARKER_NO_PPDEDUCT; battleScriptBlocksMove = BattleScript_DazzlingProtected; } @@ -3041,7 +3040,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a case ABILITY_DAZZLING: case ABILITY_QUEENLY_MAJESTY: case ABILITY_ARMOR_TAIL: - if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS) + if (gBattleMons[battlerAtk].volatiles.multipleTurns) gHitMarker |= HITMARKER_NO_PPDEDUCT; battlerAbility = partnerDef; battleScriptBlocksMove = BattleScript_DazzlingProtected; @@ -3549,8 +3548,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gDisableStructs[battler].isFirstTurn == 2 && !gDisableStructs[battler].overwrittenAbility && IsBattlerAlive(diagonalBattler) - && !(gBattleMons[diagonalBattler].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE)) - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[diagonalBattler].volatiles.substitute + && !gBattleMons[diagonalBattler].volatiles.transformed + && !gBattleMons[battler].volatiles.transformed && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON && !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER)) { @@ -4124,7 +4124,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ICE_FACE: if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) && gBattleMons[battler].species == SPECIES_EISCUE_NOICE - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { // TODO: Convert this to a proper FORM_CHANGE type. gBattleMons[battler].species = SPECIES_EISCUE_ICE; @@ -4147,9 +4147,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleStruct->battlerState[battler].commandingDondozo = TRUE; gBattleStruct->commanderActive[partner] = gBattleMons[battler].species; gStatuses3[battler] |= STATUS3_COMMANDER; - if (gBattleMons[battler].status2 & STATUS2_CONFUSION + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !(gStatuses4[battler] & STATUS4_INFINITE_CONFUSION)) - gBattleMons[battler].status2 -= STATUS2_CONFUSION_TURN(1); + gBattleMons[battler].volatiles.confusionTurns--; BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); MarkBattlerForControllerExec(battler); BattleScriptPushCursorAndCallback(BattleScript_CommanderActivates); @@ -4245,7 +4245,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); gBattleMons[battler].status1 = 0; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_ShedSkinActivates); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); @@ -4363,7 +4363,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_HUNGER_SWITCH: - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (!gBattleMons[battler].volatiles.transformed && GetActiveGimmick(battler) != GIMMICK_TERA && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { @@ -4728,13 +4728,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3)) - && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) + && !(gBattleMons[gBattlerAttacker].volatiles.infatuation) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget) && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS) && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)) { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_INFATUATED_WITH(gBattlerTarget); + gBattleMons[gBattlerAttacker].volatiles.infatuation = INFATUATED_WITH(gBattlerTarget); BattleScriptCall(BattleScript_CuteCharmActivates); effect++; } @@ -5034,7 +5034,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_OWN_TEMPO: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) { StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); effect = 2; @@ -5052,7 +5052,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gBattleMons[battler].status1 & STATUS1_SLEEP) { TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); effect = 1; } @@ -5074,7 +5074,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_OBLIVIOUS: - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) + if (gBattleMons[battler].volatiles.infatuation) effect = 3; else if (gDisableStructs[battler].tauntTimer != 0) effect = 4; @@ -5094,7 +5094,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptCall(BattleScript_AbilityCuredStatus); break; case 3: // get rid of infatuation - gBattleMons[battler].status2 &= ~STATUS2_INFATUATION; + gBattleMons[battler].volatiles.infatuation = 0; BattleScriptCall(BattleScript_BattlerGotOverItsInfatuation); break; case 4: // get rid of taunt @@ -5215,7 +5215,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].weatherAbilityDone && battlerWeatherAffected && gBattleMons[battler].species == SPECIES_EISCUE_NOICE - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battler].volatiles.transformed)) { // TODO: Convert this to a proper FORM_CHANGE type. gBattleScripting.battler = battler; @@ -5229,7 +5229,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_PROTOSYNTHESIS: if (!gDisableStructs[battler].weatherAbilityDone && (gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect() - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[battler].volatiles.transformed && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].weatherAbilityDone = TRUE; @@ -5258,7 +5258,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_QUARK_DRIVE: if (!gDisableStructs[battler].terrainAbilityDone && gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN - && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && !gBattleMons[battler].volatiles.transformed && !gDisableStructs[battler].boosterEnergyActivated) { gDisableStructs[battler].terrainAbilityDone = TRUE; @@ -5358,7 +5358,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS if (abilityCantBeSuppressed) { // Edge case: pokemon under the effect of gastro acid transforms into a pokemon with Comatose (Todo: verify how other unsuppressable abilities behave) - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED + if (gBattleMons[battler].volatiles.transformed && gStatuses3[battler] & STATUS3_GASTRO_ACID && gBattleMons[battler].ability == ABILITY_COMATOSE) return ABILITY_NONE; @@ -5457,7 +5457,9 @@ bool32 CanBattlerEscape(u32 battler) // no ability check return TRUE; else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return TRUE; - else if (gBattleMons[battler].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) + else if (gBattleMons[battler].volatiles.escapePrevention) + return FALSE; + else if (gBattleMons[battler].volatiles.wrapped) return FALSE; else if (gStatuses3[battler] & STATUS3_ROOTED) return FALSE; @@ -5793,7 +5795,7 @@ static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum Func bool32 CanBeConfused(u32 battler) { - if (gBattleMons[battler].status2 & STATUS2_CONFUSION + if (gBattleMons[battler].volatiles.confusionTurns > 0 || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) || IsAbilityAndRecord(battler, GetBattlerAbility(battler),ABILITY_OWN_TEMPO)) return FALSE; @@ -6137,9 +6139,9 @@ static bool32 GetMentalHerbEffect(u32 battler) bool32 ret = FALSE; // Check infatuation - if (gBattleMons[battler].status2 & STATUS2_INFATUATION) + if (gBattleMons[battler].volatiles.infatuation) { - gBattleMons[battler].status2 &= ~STATUS2_INFATUATION; + gBattleMons[battler].volatiles.infatuation = 0; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; @@ -6163,9 +6165,9 @@ static bool32 GetMentalHerbEffect(u32 battler) ret = TRUE; } // Check torment - if (gBattleMons[battler].status2 & STATUS2_TORMENT) + if (gBattleMons[battler].volatiles.torment == TRUE) { - gBattleMons[battler].status2 &= ~STATUS2_TORMENT; + gBattleMons[battler].volatiles.torment = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; ret = TRUE; } @@ -6209,7 +6211,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemCaseId caseID) u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID) { - if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gDisableStructs[battler].boosterEnergyActivated || gBattleMons[battler].volatiles.transformed) return ITEM_NO_EFFECT; if (((ability == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && HasWeatherEffect())) @@ -6368,14 +6370,14 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptCall(BattleScript_BerryCureSlpRet); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION && !UnnerveOn(battler, gLastUsedItem)) + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) { RemoveConfusionStatus(battler); BattleScriptCall(BattleScript_BerryCureConfusionRet); @@ -6392,14 +6394,14 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) } break; case HOLD_EFFECT_CURE_STATUS: - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem)) + if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) { if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn); if (gBattleMons[battler].status1 & STATUS1_SLEEP) { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } @@ -6413,7 +6415,7 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) if (gBattleMons[battler].status1 & STATUS1_FREEZE || gBattleMons[battler].status1 & STATUS1_FROSTBITE) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); gBattleMons[battler].status1 = 0; @@ -6425,10 +6427,10 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) break; case HOLD_EFFECT_CRITICAL_UP: // lansat berry if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; gPotentialItemEffectBattler = battler; BattleScriptCall(BattleScript_BerryFocusEnergyRet); @@ -6453,7 +6455,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) u32 effect = ITEM_NO_EFFECT; u32 string = 0; - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem)) + if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].volatiles.confusionTurns > 0) && !UnnerveOn(battler, gLastUsedItem)) { if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) { @@ -6462,7 +6464,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) } if (gBattleMons[battler].status1 & STATUS1_SLEEP) { - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn); string++; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); @@ -6482,7 +6484,7 @@ static inline bool32 TryCureStatus(u32 battler, enum ItemCaseId caseId) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); string++; } - if (gBattleMons[battler].status2 & STATUS2_CONFUSION) + if (gBattleMons[battler].volatiles.confusionTurns > 0) { StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn); string++; @@ -6585,10 +6587,10 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; case HOLD_EFFECT_CRITICAL_UP: if (B_BERRIES_INSTANT >= GEN_4 - && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + && !(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); effect = ITEM_EFFECT_OTHER; @@ -6652,7 +6654,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); @@ -6808,10 +6810,10 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, caseID); break; case HOLD_EFFECT_CRITICAL_UP: - if (!(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (!(gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { - gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleScripting.battler = battler; BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2); effect = ITEM_EFFECT_OTHER; @@ -6862,14 +6864,14 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; - gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; + gBattleMons[battler].volatiles.nightmare = FALSE; BattleScriptExecute(BattleScript_BerryCureSlpEnd2); effect = ITEM_STATUS_CHANGE; TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); } break; case HOLD_EFFECT_CURE_CONFUSION: - if (gBattleMons[battler].status2 & STATUS2_CONFUSION && !UnnerveOn(battler, gLastUsedItem)) + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !UnnerveOn(battler, gLastUsedItem)) { RemoveConfusionStatus(battler); BattleScriptExecute(BattleScript_BerryCureConfusionEnd2); @@ -7270,7 +7272,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) void ClearVariousBattlerFlags(u32 battler) { gDisableStructs[battler].furyCutterCounter = 0; - gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND; + gBattleMons[battler].volatiles.destinyBond = FALSE; gStatuses3[battler] &= ~STATUS3_GRUDGE; gStatuses4[battler] &= ~ STATUS4_GLAIVE_RUSH; } @@ -7459,7 +7461,7 @@ u8 GetAttackerObedienceForAction() // is not obedient enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); if (moveEffect == EFFECT_RAGE) - gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_RAGE; + gBattleMons[gBattlerAttacker].volatiles.rage = FALSE; if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP && (moveEffect == EFFECT_SNORE || moveEffect == EFFECT_SLEEP_TALK)) return DISOBEYS_WHILE_ASLEEP; @@ -7485,7 +7487,7 @@ u8 GetAttackerObedienceForAction() // try putting asleep int i; for (i = 0; i < gBattlersCount; i++) - if (gBattleMons[i].status2 & STATUS2_UPROAR) + if (gBattleMons[i].volatiles.uproarTurns) break; if (i == gBattlersCount) return DISOBEYS_FALL_ASLEEP; @@ -7895,7 +7897,7 @@ u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer) u32 i; for (i = 1; i < (5 - rolloutTimer); i++) basePower *= 2; - if (gBattleMons[battlerAtk].status2 & STATUS2_DEFENSE_CURL) + if (gBattleMons[battlerAtk].volatiles.defenseCurl) basePower *= 2; return basePower; } @@ -8431,7 +8433,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) u8 defHighestStat = GetHighestStatId(battlerDef); if (((ctx->weather & B_WEATHER_SUN && HasWeatherEffect()) || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) - && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; @@ -8440,7 +8442,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) u8 defHighestStat = GetHighestStatId(battlerDef); if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivated) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) - && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); } break; @@ -8683,7 +8685,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PROTOSYNTHESIS: - if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battlerAtk].volatiles.transformed)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); if (((ctx->weather & B_WEATHER_SUN) && HasWeatherEffect()) || gDisableStructs[battlerAtk].boosterEnergyActivated) @@ -8694,7 +8696,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) } break; case ABILITY_QUARK_DRIVE: - if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battlerAtk].volatiles.transformed)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivated) @@ -8919,7 +8921,7 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_METAL_POWDER: - if (gBattleMons[battlerDef].species == SPECIES_DITTO && usesDefStat && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) + if (gBattleMons[battlerDef].species == SPECIES_DITTO && usesDefStat && !(gBattleMons[battlerDef].volatiles.transformed)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_EVIOLITE: @@ -9521,7 +9523,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m if (ctx->updateFlags) RecordItemEffectBattle(ctx->battlerDef, HOLD_EFFECT_RING_TARGET); } - else if ((ctx->moveType == TYPE_FIGHTING || ctx->moveType == TYPE_NORMAL) && defType == TYPE_GHOST && gBattleMons[ctx->battlerDef].status2 & STATUS2_FORESIGHT && mod == UQ_4_12(0.0)) + else if ((ctx->moveType == TYPE_FIGHTING || ctx->moveType == TYPE_NORMAL) && defType == TYPE_GHOST && gBattleMons[ctx->battlerDef].volatiles.foresight && mod == UQ_4_12(0.0)) { mod = UQ_4_12(1.0); } @@ -9964,7 +9966,7 @@ void ActivateUltraBurst(u32 battler) bool32 IsBattlerMegaEvolved(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isMegaEvolution); } @@ -9972,7 +9974,7 @@ bool32 IsBattlerMegaEvolved(u32 battler) bool32 IsBattlerPrimalReverted(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isPrimalReversion); } @@ -9980,7 +9982,7 @@ bool32 IsBattlerPrimalReverted(u32 battler) bool32 IsBattlerUltraBursted(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as true Ultra Burst. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isUltraBurst); } @@ -9988,7 +9990,7 @@ bool32 IsBattlerUltraBursted(u32 battler) bool32 IsBattlerInTeraForm(u32 battler) { // While Transform does copy stats and visuals, it shouldn't be counted as a true Tera Form. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gBattleMons[battler].volatiles.transformed) return FALSE; return (gSpeciesInfo[gBattleMons[battler].species].isTeraForm); } @@ -10106,7 +10108,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, enum FormChanges method) bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) { // Can't change form if transformed. - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED + if (gBattleMons[battler].volatiles.transformed && B_TRANSFORM_FORM_CHANGES >= GEN_5) return FALSE; // Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle. @@ -10856,7 +10858,7 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing) void RemoveConfusionStatus(u32 battler) { - gBattleMons[battler].status2 &= ~STATUS2_CONFUSION; + gBattleMons[battler].volatiles.confusionTurns = 0; gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; } @@ -11415,7 +11417,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) return FALSE; } -#define UNPACK_VOLATILE_GETTERS(_enum, _fieldName, _typeBitSize, ...) case _enum: return gBattleMons[battler].volatiles._fieldName; +#define UNPACK_VOLATILE_GETTERS(_enum, _fieldName, _typeMaxValue, ...) case _enum: return gBattleMons[battler].volatiles._fieldName; // Gets the value of a volatile status flag for a certain battler // Primarily used for the debug menu and scripts. Outside of it explicit references are preferred @@ -11433,7 +11435,7 @@ u32 GetMonVolatile(u32 battler, enum Volatile _volatile) } } -#define UNPACK_VOLATILE_SETTERS(_enum, _fieldName, _typeBitSize, ...) case _enum: gBattleMons[battler].volatiles._fieldName = min(GET_VOLATILE_MAXIMUM(_typeBitSize), newValue); break; +#define UNPACK_VOLATILE_SETTERS(_enum, _fieldName, _typeMaxValue, ...) case _enum: gBattleMons[battler].volatiles._fieldName = min(GET_VOLATILE_MAXIMUM(_typeMaxValue), newValue); break; // Sets the value of a volatile status flag for a certain battler // Primarily used for the debug menu and scripts. Outside of it explicit references are preferred @@ -11452,6 +11454,30 @@ void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue) } } +bool32 ItemHealMonVolatile(u32 battler, u16 itemId) +{ + bool32 statusChanged = FALSE; + const u8 *effect = GetItemEffect(itemId); + if (effect[3] & ITEM3_STATUS_ALL) + { + statusChanged = (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0); + gBattleMons[battler].volatiles.infatuation = 0; + gBattleMons[battler].volatiles.confusionTurns = 0; + } + else if (effect[0] & ITEM0_INFATUATION) + { + statusChanged = !!gBattleMons[battler].volatiles.infatuation; + gBattleMons[battler].volatiles.infatuation = 0; + } + else if (effect[3] & ITEM3_CONFUSION) + { + statusChanged = gBattleMons[battler].volatiles.confusionTurns > 0; + gBattleMons[battler].volatiles.confusionTurns = 0; + } + + return statusChanged; +} + // Hazards are added to a queue and applied based in order (FIFO) void PushHazardTypeToQueue(u32 side, enum Hazards hazardType) { @@ -11634,7 +11660,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (defAbility == ABILITY_UNAWARE) accStage = DEFAULT_STAT_STAGE; - if (gBattleMons[battlerDef].status2 & STATUS2_FORESIGHT || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) + if (gBattleMons[battlerDef].volatiles.foresight || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) buff = accStage; else buff = accStage + DEFAULT_STAT_STAGE - evasionStage; diff --git a/src/battle_util2.c b/src/battle_util2.c index ba8db66f5d..3a05e5ac13 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -133,7 +133,7 @@ u32 BattlePalace_TryEscapeStatus(u8 battler) { // Wake up from Uproar gBattleMons[battler].status1 &= ~(STATUS1_SLEEP); - gBattleMons[battler].status2 &= ~(STATUS2_NIGHTMARE); + gBattleMons[battler].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; BattleScriptCall(BattleScript_MoveUsedWokeUp); effect = 2; @@ -162,7 +162,7 @@ u32 BattlePalace_TryEscapeStatus(u8 battler) else { // Wake up - gBattleMons[battler].status2 &= ~(STATUS2_NIGHTMARE); + gBattleMons[battler].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP; BattleScriptCall(BattleScript_MoveUsedWokeUp); effect = 2; diff --git a/src/battle_z_move.c b/src/battle_z_move.c index 4f33ff5a17..638e9ef901 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -486,9 +486,9 @@ void SetZEffect(void) break; } case Z_EFFECT_BOOST_CRITS: - if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY_ANY)) + if (!(gBattleMons[gBattlerAttacker].volatiles.dragonCheer || gBattleMons[gBattlerAttacker].volatiles.focusEnergy)) { - gBattleMons[gBattlerAttacker].status2 |= STATUS2_FOCUS_ENERGY; + gBattleMons[gBattlerAttacker].volatiles.focusEnergy = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_BOOST_CRITS; BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH); gBattlescriptCurrInstr = BattleScript_ZEffectPrintString; diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 465d3c0153..5dba4cb657 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -3108,7 +3108,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_ACC_UP_1 }, - .argument = { .status = STATUS2_FOCUS_ENERGY }, + .argument = { .status = VOLATILE_FOCUS_ENERGY }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .snatchAffected = TRUE, diff --git a/src/item.c b/src/item.c index 45a3dfe421..52d52923ca 100644 --- a/src/item.c +++ b/src/item.c @@ -958,17 +958,18 @@ u32 GetItemStatus1Mask(u16 itemId) return 0; } -u32 GetItemStatus2Mask(u16 itemId) +bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile _volatile) { const u8 *effect = GetItemEffect(itemId); - if (effect[3] & ITEM3_STATUS_ALL) - return STATUS2_INFATUATION | STATUS2_CONFUSION; - else if (effect[0] & ITEM0_INFATUATION) - return STATUS2_INFATUATION; - else if (effect[3] & ITEM3_CONFUSION) - return STATUS2_CONFUSION; - else - return 0; + switch (_volatile) + { + case VOLATILE_CONFUSION: + return (effect[3] & ITEM3_STATUS_ALL) || (effect[3] & ITEM3_CONFUSION); + case VOLATILE_INFATUATION: + return (effect[3] & ITEM3_STATUS_ALL) || (effect[0] & ITEM0_INFATUATION); + default: + return FALSE; + } } u32 GetItemSellPrice(u32 itemId) diff --git a/src/item_use.c b/src/item_use.c index 9df366e595..ace6aaccf6 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1191,12 +1191,25 @@ void ItemUseInBattle_PartyMenuChooseMove(u8 taskId) ItemUseInBattle_ShowPartyMenu(taskId); } -static bool32 SelectedMonHasStatus2(u16 itemId) +static bool32 IteamHealsMonVolatile(u32 battler, u16 itemId) +{ + const u8 *effect = GetItemEffect(itemId); + if (effect[3] & ITEM3_STATUS_ALL) + return (gBattleMons[battler].volatiles.infatuation || gBattleMons[battler].volatiles.confusionTurns > 0); + else if (effect[0] & ITEM0_INFATUATION) + return gBattleMons[battler].volatiles.infatuation; + else if (effect[3] & ITEM3_CONFUSION) + return gBattleMons[battler].volatiles.confusionTurns > 0; + + return FALSE; +} + +static bool32 SelectedMonHasVolatile(u16 itemId) { if (gPartyMenu.slotId == 0) - return gBattleMons[0].status2 & GetItemStatus2Mask(itemId); + return IteamHealsMonVolatile(0, itemId); else if (gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI) && gPartyMenu.slotId == 1) - return gBattleMons[2].status2 & GetItemStatus2Mask(itemId); + return IteamHealsMonVolatile(2, itemId); return FALSE; } @@ -1224,7 +1237,7 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) cannotUse = TRUE; break; case EFFECT_ITEM_SET_FOCUS_ENERGY: - if (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY_ANY) + if (gBattleMons[gBattlerInMenuId].volatiles.dragonCheer || gBattleMons[gBattlerInMenuId].volatiles.focusEnergy) cannotUse = TRUE; break; case EFFECT_ITEM_SET_MIST: @@ -1272,13 +1285,13 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) break; case EFFECT_ITEM_CURE_STATUS: if (!((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || SelectedMonHasStatus2(itemId))) + || SelectedMonHasVolatile(itemId))) cannotUse = TRUE; break; case EFFECT_ITEM_HEAL_AND_CURE_STATUS: if ((hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)) && !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId)) - || SelectedMonHasStatus2(itemId))) + || SelectedMonHasVolatile(itemId))) cannotUse = TRUE; break; case EFFECT_ITEM_REVIVE: diff --git a/src/pokemon.c b/src/pokemon.c index 91524ae97d..85ef8a2fc9 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3693,7 +3693,7 @@ void PokemonToBattleMon(struct Pokemon *src, struct BattlePokemon *dst) for (i = 0; i < NUM_BATTLE_STATS; i++) dst->statStages[i] = DEFAULT_STAT_STAGE; - dst->status2 = 0; + memset(&dst->volatiles, 0, sizeof(struct Volatiles)); } void CopyPartyMonToBattleData(u32 battler, u32 partyIndex) diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 2d9556311f..500a83e888 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -756,7 +756,7 @@ void RecordedBattle_CheckMovesetChanges(u8 mode) gDisableStructs[battler].mimickedMoves |= mimickedMoveSlots[j] << j; } - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (!(gBattleMons[battler].volatiles.transformed)) { struct Pokemon *mon = GetBattlerMon(battler); for (j = 0; j < MAX_MON_MOVES; j++) diff --git a/test/battle/ability/shield_dust.c b/test/battle/ability/shield_dust.c index da6bbf87df..828e596525 100644 --- a/test/battle/ability/shield_dust.c +++ b/test/battle/ability/shield_dust.c @@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Shield Dust blocks secondary effects") MESSAGE("The opposing Vivillon was prevented from healing!"); } } THEN { // Can't find good way to test trapping - EXPECT(!(opponent->status2 & STATUS2_ESCAPE_PREVENTION)); + EXPECT(!opponent->volatiles.escapePrevention); } } @@ -78,8 +78,8 @@ SINGLE_BATTLE_TEST("Shield Dust does not block primary effects") } } THEN { // Can't find good way to test trapping if (move == MOVE_JAW_LOCK) { - EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION); - EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(opponent->volatiles.escapePrevention); + EXPECT(player->volatiles.escapePrevention); } } } diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index 220eaa362c..f9fb2e0081 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -1221,7 +1221,7 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Terror traps both opponents") MESSAGE("The opposing Wobbuffet can no longer escape!"); MESSAGE("The opposing Wobbuffet can no longer escape!"); } THEN { // Can't find good way to test trapping - EXPECT(opponentLeft->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(opponentLeft->volatiles.escapePrevention); } } @@ -1238,7 +1238,7 @@ SINGLE_BATTLE_TEST("Dynamax: Baton Pass passes G-Max Terror's escape prevention ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_TERROR, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_BATON_PASS, opponent); } THEN { - EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(opponent->volatiles.escapePrevention); } } diff --git a/test/battle/hold_effect/berserk_gene.c b/test/battle/hold_effect/berserk_gene.c index 640198c992..bbeb356701 100644 --- a/test/battle/hold_effect/berserk_gene.c +++ b/test/battle/hold_effect/berserk_gene.c @@ -217,7 +217,7 @@ SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is } } -SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 status2) +SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 confusionTurns) { u32 turns; PARAMETRIZE { turns = 1; } @@ -231,9 +231,9 @@ SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 s TURN {} } } THEN { - results[i].status2 = player->status2; + results[i].confusionTurns = player->volatiles.confusionTurns; } FINALLY { - EXPECT_EQ(results[0].status2, results[1].status2); + EXPECT_EQ(results[0].confusionTurns, results[1].confusionTurns); } } diff --git a/test/battle/hold_effect/covert_cloak.c b/test/battle/hold_effect/covert_cloak.c index 90593e7cc5..0b3d0c2ed6 100644 --- a/test/battle/hold_effect/covert_cloak.c +++ b/test/battle/hold_effect/covert_cloak.c @@ -41,7 +41,7 @@ SINGLE_BATTLE_TEST("Covert Cloak blocks secondary effects") MESSAGE("The opposing Wobbuffet was prevented from healing!"); } } THEN { // Can't find good way to test trapping - EXPECT(!(opponent->status2 & STATUS2_ESCAPE_PREVENTION)); + EXPECT(!opponent->volatiles.escapePrevention); } } @@ -82,8 +82,8 @@ SINGLE_BATTLE_TEST("Covert Cloak does not block primary effects") } } THEN { // Can't find good way to test trapping if (move == MOVE_JAW_LOCK) { - EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION); - EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(opponent->volatiles.escapePrevention); + EXPECT(player->volatiles.escapePrevention); } } } diff --git a/test/battle/item_effect/cure_status.c b/test/battle/item_effect/cure_status.c index 6f7d403c43..919b4539af 100644 --- a/test/battle/item_effect/cure_status.c +++ b/test/battle/item_effect/cure_status.c @@ -389,6 +389,6 @@ SINGLE_BATTLE_TEST("Full Heal, Heal Powder and Local Specialties heal a battler } SCENE { MESSAGE("Wobbuffet had its status healed!"); } THEN { - EXPECT_EQ(player->status2, STATUS1_NONE); // because we dont have STATUS2_NONE + EXPECT(player->volatiles.confusionTurns == 0); } } diff --git a/test/battle/move_effect/attract.c b/test/battle/move_effect/attract.c index be30483358..2964b7b611 100644 --- a/test/battle/move_effect/attract.c +++ b/test/battle/move_effect/attract.c @@ -19,7 +19,7 @@ SINGLE_BATTLE_TEST("Attract causes the target to become infatuated with the user ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); MESSAGE("The opposing Nidoking fell in love!"); } THEN { - EXPECT(opponent->status2 & STATUS2_INFATUATION); + EXPECT(opponent->volatiles.infatuation); } } @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Attract ignores type immunity") ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); MESSAGE("The opposing Misdreavus fell in love!"); } THEN { - EXPECT(opponent->status2 & STATUS2_INFATUATION); + EXPECT(opponent->volatiles.infatuation); } } @@ -51,7 +51,7 @@ SINGLE_BATTLE_TEST("Attract bypasses Substitute") ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); MESSAGE("The opposing Nidoking fell in love!"); } THEN { - EXPECT(opponent->status2 & STATUS2_INFATUATION); + EXPECT(opponent->volatiles.infatuation); } } @@ -69,7 +69,7 @@ SINGLE_BATTLE_TEST("Attract fails if the target is already infatuated") MESSAGE("Nidoqueen used Attract!"); MESSAGE("But it failed!"); } THEN { - EXPECT(opponent->status2 & STATUS2_INFATUATION); + EXPECT(opponent->volatiles.infatuation); } } @@ -84,7 +84,7 @@ SINGLE_BATTLE_TEST("Attract fails when used on a Pokémon of the same gender") MESSAGE("Nidoqueen used Attract!"); MESSAGE("But it failed!"); } THEN { - EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + EXPECT(!(opponent->volatiles.infatuation)); } } @@ -100,6 +100,6 @@ SINGLE_BATTLE_TEST("Attract fails when used on a genderless Pokémon") MESSAGE("Nidoqueen used Attract!"); MESSAGE("But it failed!"); } THEN { - EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + EXPECT(!(opponent->volatiles.infatuation)); } } diff --git a/test/battle/move_effect/baton_pass.c b/test/battle/move_effect/baton_pass.c index cb6530ae89..5cb1ac4c05 100644 --- a/test/battle/move_effect/baton_pass.c +++ b/test/battle/move_effect/baton_pass.c @@ -37,7 +37,7 @@ TO_DO_BATTLE_TEST("Baton Pass doesn't pass ability changes"); // // Move these to the corresponding effect files. // -TO_DO_BATTLE_TEST("Baton Pass passes confusion status"); // test/battle/status2/confusion.c +TO_DO_BATTLE_TEST("Baton Pass passes confusion status"); // test/battle/volatiles/confusion.c TO_DO_BATTLE_TEST("Baton Pass passes Fairy lock's escape prevention effect"); // test/battle/move_effect/fairy_lock.c TO_DO_BATTLE_TEST("Baton Pass passes Focus Energy's effect"); // test/battle/move_effect/focus_energy.c diff --git a/test/battle/move_effect/captivate.c b/test/battle/move_effect/captivate.c index 224e6bef07..27790b8461 100644 --- a/test/battle/move_effect/captivate.c +++ b/test/battle/move_effect/captivate.c @@ -92,7 +92,7 @@ SINGLE_BATTLE_TEST("Attract fails when used by a genderless Pokémon") MESSAGE("Starmie used Attract!"); MESSAGE("But it failed!"); } THEN { - EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + EXPECT(!(opponent->volatiles.infatuation)); } } @@ -107,6 +107,6 @@ SINGLE_BATTLE_TEST("Attract fails if both the user and the target are genderless MESSAGE("Starmie used Attract!"); MESSAGE("But it failed!"); } THEN { - EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + EXPECT(!(opponent->volatiles.infatuation)); } } diff --git a/test/battle/move_effect_secondary/thrash.c b/test/battle/move_effect_secondary/thrash.c index 83a49554d7..e7f573d1ed 100644 --- a/test/battle/move_effect_secondary/thrash.c +++ b/test/battle/move_effect_secondary/thrash.c @@ -114,6 +114,6 @@ SINGLE_BATTLE_TEST("Petal Dance does not lock mons that copy the move with Dance ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent); // How do you actually test locking? - EXPECT(!(opponent->status2 & STATUS2_MULTIPLETURNS)); + EXPECT(!(opponent->volatiles.multipleTurns)); } } diff --git a/test/battle/move_effect_secondary/trap_both.c b/test/battle/move_effect_secondary/trap_both.c index ec06b25c30..76d572dad9 100644 --- a/test/battle/move_effect_secondary/trap_both.c +++ b/test/battle/move_effect_secondary/trap_both.c @@ -17,7 +17,7 @@ SINGLE_BATTLE_TEST("Jaw Lock traps both opponents") ANIMATION(ANIM_TYPE_MOVE, MOVE_JAW_LOCK, player); MESSAGE("Neither Pokémon can run away!"); } THEN { // Can't find good way to test trapping - EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION); - EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION); + EXPECT(opponent->volatiles.escapePrevention); + EXPECT(player->volatiles.escapePrevention); } } diff --git a/test/battle/status2/confusion.c b/test/battle/volatiles/confusion.c similarity index 100% rename from test/battle/status2/confusion.c rename to test/battle/volatiles/confusion.c From 4e0a8167be5bfd9ef2d96a3ca34db27f4edf503b Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 00:37:11 -0400 Subject: [PATCH 084/283] Test works? I think? --- test/battle/ai/ai_assume_powerful_status.c | 36 ++++++---------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/test/battle/ai/ai_assume_powerful_status.c b/test/battle/ai/ai_assume_powerful_status.c index 7c1f08f352..1fd16adcf4 100644 --- a/test/battle/ai/ai_assume_powerful_status.c +++ b/test/battle/ai/ai_assume_powerful_status.c @@ -8,11 +8,8 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_POWERFUL_STATUS correctly records assumed PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS); PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_LOW_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS); - u32 aiFlag = 0; - PARAMETRIZE { aiFlag = AI_FLAG_ASSUME_POWERFUL_STATUS; } - PARAMETRIZE { aiFlag = 0; } GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiFlag); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ASSUME_POWERFUL_STATUS); PLAYER(SPECIES_TYPHLOSION) { Moves(MOVE_TACKLE, MOVE_COURT_CHANGE, MOVE_FAKE_OUT); } PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_HAIL, MOVE_SHED_TAIL, MOVE_THUNDERBOLT); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } @@ -20,29 +17,14 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_POWERFUL_STATUS correctly records assumed } WHEN { TURN { MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(playerRight, MOVE_THUNDERBOLT, target:opponentRight); } } THEN { - if (aiFlag == AI_FLAG_ASSUME_POWERFUL_STATUS) - { - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_COURT_CHANGE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_FAKE_OUT); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_COURT_CHANGE); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_FAKE_OUT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_HAIL); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_SHED_TAIL); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); - } - else if (aiFlag == 0) - { - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][0], MOVE_TACKLE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][1], MOVE_NONE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][2], MOVE_NONE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_LEFT][3], MOVE_NONE); - - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_NONE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_NONE); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); - EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); - } + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][0], MOVE_HAIL); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][1], MOVE_SHED_TAIL); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][2], MOVE_THUNDERBOLT); + EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); } } From 3defa242826df1e8b35bbf81efab194b0f1cfda6 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 00:41:14 -0400 Subject: [PATCH 085/283] Adding other healing move effects. --- src/battle_ai_util.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index f09fe2d132..9f8d6c94ea 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -290,12 +290,18 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_HEALING_WISH: case EFFECT_LIFE_DEW: case EFFECT_MEMENTO: + case EFFECT_MOONLIGHT: + case EFFECT_MORNING_SUN: case EFFECT_PARTING_SHOT: case EFFECT_PROTECT: case EFFECT_REST: case EFFECT_RESTORE_HP: case EFFECT_ROAR: + case EFFECT_ROOST: + case EFFECT_SHORE_UP: case EFFECT_SLEEP_TALK: + case EFFECT_SOFTBOILED: + case EFFECT_SYNTHESIS: case EFFECT_TAUNT: case EFFECT_TAILWIND: case EFFECT_TELEPORT: From 96274c772d8c446cd399b38bf96a26eb5d79da10 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 00:42:46 -0400 Subject: [PATCH 086/283] Also adding Helping Hand. --- src/battle_ai_util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 9f8d6c94ea..2c7c850d1e 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -288,6 +288,7 @@ bool32 ShouldRecordStatusMove(u32 move) case EFFECT_HAZE: case EFFECT_HEAL_BELL: case EFFECT_HEALING_WISH: + case EFFECT_HELPING_HAND: case EFFECT_LIFE_DEW: case EFFECT_MEMENTO: case EFFECT_MOONLIGHT: From c7b8787f59738d6d887cb4f81495cd0a3fc1d42a Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 00:55:52 -0400 Subject: [PATCH 087/283] Better description in the documentation. --- docs/tutorials/ai_flags.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 9f39090b65..6b8a2e941f 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -148,8 +148,9 @@ AI has full knowledge of player moves, abilities, and hold items, and can use th A significantly more restricted version of `AI_FLAG_OMNISCIENT`, the AI only knows the player's STAB moves, as their existence would be reasonable to assume in almost any case. ## `AI_FLAG_ASSUME_POWERFUL_STATUS` -A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know if the player has certain iconic status moves, plus also Fake Out and fixed percentage moves like Super Fang. +A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know if the player has certain strong status moves, plus also Fake Out and fixed percentage moves like Super Fang. The intention is so that if the AI has a counterplay implemented, it will seem to have guessed if the player's pokemon has a move, without giving the AI perfect information. For example, with Omniscient set, the AI will not put a pokemon to sleep if it has Sleep Talk; with neither Assume Powerful Status nor Omniscient set, the AI will always assume the pokemon does not have Sleep Talk. +Percentages for the three groupings (high odds, medium odds, and low odds) are defined in `include/config/ai.h` under `ASSUME_POWERFUL_STATUS_HIGH_ODDS`, `ASSUME_POWERFUL_STATUS_MEDIUM_ODDS`, and `ASSUME_POWERFUL_STATUS_LOW_ODDS`. Moves are sorted in `src/battle_ai_util.c` within `ShouldRecordStatusMove()` ## `AI_FLAG_SMART_MON_CHOICES` Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled. From 9ccb1fbc3a528b001a8f79394e5642d8fb3a8089 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 01:01:18 -0400 Subject: [PATCH 088/283] Lowering the default odds to 90%, 70%, and 40%. --- include/config/ai.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/config/ai.h b/include/config/ai.h index be091649af..8a97430d4b 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -77,9 +77,9 @@ #define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience. // AI_FLAG_ASSUME_POWERFUL_STATUS settings -#define ASSUME_POWERFUL_STATUS_HIGH_ODDS 95 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore -#define ASSUME_POWERFUL_STATUS_MEDIUM_ODDS 75 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect -#define ASSUME_POWERFUL_STATUS_LOW_ODDS 50 // Chance for AI to see niche moves a pokemon may have but probably won't, like Trick Room or Speed Swap +#define ASSUME_POWERFUL_STATUS_HIGH_ODDS 90 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore +#define ASSUME_POWERFUL_STATUS_MEDIUM_ODDS 70 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect +#define ASSUME_POWERFUL_STATUS_LOW_ODDS 40 // Chance for AI to see niche moves a pokemon may have but probably won't, like Trick Room or Speed Swap // AI_FLAG_SMART_SWITCHING settings #define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise From c9ec896312f60274254e0610002ae26fd2c15045 Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:38:06 -0400 Subject: [PATCH 089/283] Refactor battle environment (#4891) --- data/battle_anim_scripts.s | 2 +- include/battle_environment.h | 17 + include/battle_setup.h | 2 +- include/config/battle.h | 2 +- include/constants/battle.h | 15 +- include/constants/form_change_types.h | 4 +- include/pokemon_sprite_visualizer.h | 2 +- src/battle_bg.c | 463 ++++--------------------- src/battle_script_commands.c | 166 +-------- src/battle_setup.c | 2 +- src/data/battle_environment.h | 434 +++++++++++++++++++++++ src/data/graphics/battle_environment.h | 38 -- src/debug.c | 24 +- src/pokemon_sprite_visualizer.c | 32 +- 14 files changed, 584 insertions(+), 619 deletions(-) create mode 100644 include/battle_environment.h create mode 100644 src/data/battle_environment.h diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 8b504a37f9..08753aac8a 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -27586,7 +27586,7 @@ gBattleAnimMove_RazorLeaf:: end gBattleAnimMove_NaturePower:: - @ No actual animation, uses the animation of a move from sNaturePowerMoves instead + @ No actual animation, uses the animation of a move from gBattleEnvironmentInfo.naturePower instead gBattleAnimMove_AncientPower:: loadspritegfx ANIM_TAG_ROCKS diff --git a/include/battle_environment.h b/include/battle_environment.h new file mode 100644 index 0000000000..e9435aa454 --- /dev/null +++ b/include/battle_environment.h @@ -0,0 +1,17 @@ +#ifndef GUARD_BATTLE_ENVIRONMENT_H +#define GUARD_BATTLE_ENVIRONMENT_H + +#include "constants/battle.h" +#include "battle_bg.h" + +struct BattleEnvironment { + u8 name[26]; + u16 naturePower; + u16 secretPowerEffect; + u8 camouflageType; + struct BattleBackground background; +}; + +extern const struct BattleEnvironment gBattleEnvironmentInfo[BATTLE_ENVIRONMENT_COUNT]; + +#endif // GUARD_BATTLE_ENVIRONMENT_H diff --git a/include/battle_setup.h b/include/battle_setup.h index 7cddc06725..aa01178d8d 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -60,7 +60,7 @@ void BattleSetup_StartLatiBattle(void); void BattleSetup_StartLegendaryBattle(void); void StartGroudonKyogreBattle(void); void StartRegiBattle(void); -enum BattleEnvironment BattleSetup_GetEnvironmentId(void); +enum BattleEnvironments BattleSetup_GetEnvironmentId(void); u8 GetWildBattleTransition(void); u8 GetTrainerBattleTransition(void); u8 GetSpecialBattleTransition(s32 id); diff --git a/include/config/battle.h b/include/config/battle.h index 06373f2c19..a58b174b46 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -262,7 +262,7 @@ #define B_TERRAIN_TYPE_BOOST GEN_LATEST // In Gen8, damage is boosted by 30% instead of 50%. #define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See MOVE_EFFECT_SECRET_POWER's case in `SetMoveEffect`. #define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation. -#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves. +#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See gBattleEnvironmentInfo. #define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType. #define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain. diff --git a/include/constants/battle.h b/include/constants/battle.h index b87176ff7a..28b39117ff 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -531,7 +531,7 @@ enum MoveEffects #define MOVE_EFFECT_CONTINUE 0x8000 // Battle environment defines for gBattleEnvironment. -enum BattleEnvironment +enum BattleEnvironments { BATTLE_ENVIRONMENT_GRASS, BATTLE_ENVIRONMENT_LONG_GRASS, @@ -543,6 +543,19 @@ enum BattleEnvironment BATTLE_ENVIRONMENT_CAVE, BATTLE_ENVIRONMENT_BUILDING, BATTLE_ENVIRONMENT_PLAIN, + BATTLE_ENVIRONMENT_FRONTIER, + BATTLE_ENVIRONMENT_GYM, + BATTLE_ENVIRONMENT_LEADER, + BATTLE_ENVIRONMENT_MAGMA, + BATTLE_ENVIRONMENT_AQUA, + BATTLE_ENVIRONMENT_SIDNEY, + BATTLE_ENVIRONMENT_PHOEBE, + BATTLE_ENVIRONMENT_GLACIA, + BATTLE_ENVIRONMENT_DRAKE, + BATTLE_ENVIRONMENT_CHAMPION, + BATTLE_ENVIRONMENT_GROUDON, + BATTLE_ENVIRONMENT_KYOGRE, + BATTLE_ENVIRONMENT_RAYQUAZA, // New battle environments are used for Secret Power but not fully implemented. BATTLE_ENVIRONMENT_SOARING, BATTLE_ENVIRONMENT_SKY_PILLAR, diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index a1c4c5bc45..10de5f785f 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -61,8 +61,8 @@ enum FormChanges // param2: a move that will be replaced, optional // param3: a new move to replace it with, optional FORM_CHANGE_END_BATTLE, - // Form change that activates at the end of a battle based on the terrain if it participated in the battle and hasn't fainted. Takes priority over FORM_CHANGE_END_BATTLE. - // param1: battle terrain to check. + // Form change that activates at the end of a battle based on the environment if it participated in the battle and hasn't fainted. Takes priority over FORM_CHANGE_END_BATTLE. + // param1: battle environment to check. FORM_CHANGE_END_BATTLE_ENVIRONMENT, // Form change that activates when the Pokémon is switched out in battle. // param1: ability to check, optional diff --git a/include/pokemon_sprite_visualizer.h b/include/pokemon_sprite_visualizer.h index fdd53d2ce8..4205c6dc20 100644 --- a/include/pokemon_sprite_visualizer.h +++ b/include/pokemon_sprite_visualizer.h @@ -81,7 +81,7 @@ struct PokemonSpriteVisualizer u8 animIdBack; u8 animIdFront; u8 battleBgType; - u8 battleTerrain; + u8 battleEnvironment; u8 currentSubmenu; u8 submenuYpos[3]; }; diff --git a/src/battle_bg.c b/src/battle_bg.c index 6de96168f7..11a28ea2fa 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -5,6 +5,7 @@ #include "battle_main.h" #include "battle_message.h" #include "battle_setup.h" +#include "battle_environment.h" #include "bg.h" #include "data.h" #include "decompress.h" @@ -26,6 +27,7 @@ #include "constants/trainers.h" #include "constants/battle_anim.h" #include "constants/battle_partner.h" +#include "data/battle_environment.h" // .rodata @@ -609,98 +611,75 @@ const struct WindowTemplate *const gBattleWindowTemplates[] = [B_WIN_TYPE_ARENA] = sBattleArenaWindowTemplates, }; -const struct BattleBackground sBattleEnvironmentTable[] = +// If current map scene equals any of the values in sMapBattleSceneMapping, +// use its battle terrain value. Otherwise, use the default. +static u8 GetBattleEnvironmentByMapScene(u8 mapBattleScene) { - [BATTLE_ENVIRONMENT_GRASS] = + int i; + for (i = 0; i < NELEMS(sMapBattleSceneMapping); i++) { - .tileset = gBattleEnvironmentTiles_TallGrass, - .tilemap = gBattleEnvironmentTilemap_TallGrass, - .entryTileset = gBattleEnvironmentAnimTiles_TallGrass, - .entryTilemap = gBattleEnvironmentAnimTilemap_TallGrass, - .palette = gBattleEnvironmentPalette_TallGrass, - }, - - [BATTLE_ENVIRONMENT_LONG_GRASS] = - { - .tileset = gBattleEnvironmentTiles_LongGrass, - .tilemap = gBattleEnvironmentTilemap_LongGrass, - .entryTileset = gBattleEnvironmentAnimTiles_LongGrass, - .entryTilemap = gBattleEnvironmentAnimTilemap_LongGrass, - .palette = gBattleEnvironmentPalette_LongGrass, - }, - - [BATTLE_ENVIRONMENT_SAND] = - { - .tileset = gBattleEnvironmentTiles_Sand, - .tilemap = gBattleEnvironmentTilemap_Sand, - .entryTileset = gBattleEnvironmentAnimTiles_Sand, - .entryTilemap = gBattleEnvironmentAnimTilemap_Sand, - .palette = gBattleEnvironmentPalette_Sand, - }, + if (mapBattleScene == sMapBattleSceneMapping[i].mapScene) + return sMapBattleSceneMapping[i].battleEnvironment; + } + return BATTLE_ENVIRONMENT_PLAIN; +} - [BATTLE_ENVIRONMENT_UNDERWATER] = - { - .tileset = gBattleEnvironmentTiles_Underwater, - .tilemap = gBattleEnvironmentTilemap_Underwater, - .entryTileset = gBattleEnvironmentAnimTiles_Underwater, - .entryTilemap = gBattleEnvironmentAnimTilemap_Underwater, - .palette = gBattleEnvironmentPalette_Underwater, - }, +// Loads the initial battle terrain. +static void LoadBattleEnvironmentGfx(u16 terrain) +{ + if (terrain >= NELEMS(gBattleEnvironmentInfo)) + terrain = BATTLE_ENVIRONMENT_PLAIN; // If higher than the number of entries in gBattleEnvironmentInfo, use the default. + // Copy to bg3 + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[terrain].background.tileset, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[terrain].background.tilemap, (void *)(BG_SCREEN_ADDR(26))); + LoadPalette(gBattleEnvironmentInfo[terrain].background.palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); +} - [BATTLE_ENVIRONMENT_WATER] = - { - .tileset = gBattleEnvironmentTiles_Water, - .tilemap = gBattleEnvironmentTilemap_Water, - .entryTileset = gBattleEnvironmentAnimTiles_Water, - .entryTilemap = gBattleEnvironmentAnimTilemap_Water, - .palette = gBattleEnvironmentPalette_Water, - }, +// Loads the entry associated with the battle terrain. +// This can be the grass moving on the screen at the start of a wild encounter in tall grass. +static void LoadBattleEnvironmentEntryGfx(u16 terrain) +{ + if (terrain >= NELEMS(gBattleEnvironmentInfo)) + terrain = BATTLE_ENVIRONMENT_PLAIN; + // Copy to bg1 + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[terrain].background.entryTileset, (void *)BG_CHAR_ADDR(1)); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[terrain].background.entryTilemap, (void *)BG_SCREEN_ADDR(28)); +} - [BATTLE_ENVIRONMENT_POND] = - { - .tileset = gBattleEnvironmentTiles_PondWater, - .tilemap = gBattleEnvironmentTilemap_PondWater, - .entryTileset = gBattleEnvironmentAnimTiles_PondWater, - .entryTilemap = gBattleEnvironmentAnimTilemap_PondWater, - .palette = gBattleEnvironmentPalette_PondWater, - }, +static u8 GetBattleEnvironmentOverride(void) +{ + u8 battleScene = GetCurrentMapBattleScene(); - [BATTLE_ENVIRONMENT_MOUNTAIN] = + if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) + return BATTLE_ENVIRONMENT_FRONTIER; + else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) { - .tileset = gBattleEnvironmentTiles_Rock, - .tilemap = gBattleEnvironmentTilemap_Rock, - .entryTileset = gBattleEnvironmentAnimTiles_Rock, - .entryTilemap = gBattleEnvironmentAnimTilemap_Rock, - .palette = gBattleEnvironmentPalette_Rock, - }, - - [BATTLE_ENVIRONMENT_CAVE] = + switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) + { + case SPECIES_GROUDON: + return BATTLE_ENVIRONMENT_GROUDON; + case SPECIES_KYOGRE: + return BATTLE_ENVIRONMENT_KYOGRE; + case SPECIES_RAYQUAZA: + return BATTLE_ENVIRONMENT_RAYQUAZA; + default: + return gBattleEnvironment; + } + } + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - .tileset = gBattleEnvironmentTiles_Cave, - .tilemap = gBattleEnvironmentTilemap_Cave, - .entryTileset = gBattleEnvironmentAnimTiles_Cave, - .entryTilemap = gBattleEnvironmentAnimTilemap_Cave, - .palette = gBattleEnvironmentPalette_Cave, - }, + u32 trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); + if (trainerClass == TRAINER_CLASS_LEADER) + return BATTLE_ENVIRONMENT_LEADER; + else if (trainerClass == TRAINER_CLASS_CHAMPION) + return BATTLE_ENVIRONMENT_CHAMPION; + } - [BATTLE_ENVIRONMENT_BUILDING] = - { - .tileset = gBattleEnvironmentTiles_Building, - .tilemap = gBattleEnvironmentTilemap_Building, - .entryTileset = gBattleEnvironmentAnimTiles_Building, - .entryTilemap = gBattleEnvironmentAnimTilemap_Building, - .palette = gBattleEnvironmentPalette_Building, - }, + if (battleScene == MAP_BATTLE_SCENE_NORMAL) + return gBattleEnvironment; - [BATTLE_ENVIRONMENT_PLAIN] = - { - .tileset = gBattleEnvironmentTiles_Building, - .tilemap = gBattleEnvironmentTilemap_Building, - .entryTileset = gBattleEnvironmentAnimTiles_Building, - .entryTilemap = gBattleEnvironmentAnimTilemap_Building, - .palette = gBattleEnvironmentPalette_Plain, - }, -}; + return GetBattleEnvironmentByMapScene(battleScene); +} void BattleInitBgsAndWindows(void) { @@ -751,109 +730,7 @@ void LoadBattleMenuWindowGfx(void) void DrawMainBattleBackground(void) { - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK)) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - } - else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) - { - switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) - { - case SPECIES_GROUDON: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Cave, (void*)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_Groudon, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case SPECIES_KYOGRE: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Water, (void*)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_Kyogre, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case SPECIES_RAYQUAZA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_Rayquaza, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - default: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tileset, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tilemap, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(sBattleEnvironmentTable[gBattleEnvironment].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - } - } - else - { - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - enum TrainerClassID trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); - if (trainerClass == TRAINER_CLASS_LEADER) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_BuildingLeader, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - return; - } - else if (trainerClass == TRAINER_CLASS_CHAMPION) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumWallace, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - return; - } - } - - switch (GetCurrentMapBattleScene()) - { - default: - case MAP_BATTLE_SCENE_NORMAL: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tileset, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tilemap, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(sBattleEnvironmentTable[gBattleEnvironment].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_GYM: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_BuildingGym, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_MAGMA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumMagma, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_AQUA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumAqua, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_SIDNEY: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumSidney, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_PHOEBE: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumPhoebe, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_GLACIA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumGlacia, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_DRAKE: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_StadiumDrake, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_FRONTIER: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - LoadPalette(gBattleEnvironmentPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - } - } + LoadBattleEnvironmentGfx(GetBattleEnvironmentOverride()); } void LoadBattleTextboxAndBackground(void) @@ -1147,8 +1024,7 @@ void DrawBattleEntryBackground(void) { if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_BUILDING); } else { @@ -1167,20 +1043,17 @@ void DrawBattleEntryBackground(void) switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) { case SPECIES_GROUDON: - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Cave, (void*)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Cave, (void*)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_CAVE); break; case SPECIES_KYOGRE: - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Underwater, (void*)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Underwater, (void*)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_UNDERWATER); break; case SPECIES_RAYQUAZA: - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Rayquaza, (void*)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_RAYQUAZA); break; default: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].entryTileset, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[gBattleEnvironment].background.entryTileset, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[gBattleEnvironment].background.entryTilemap, (void *)(BG_SCREEN_ADDR(28))); break; } } @@ -1191,27 +1064,23 @@ void DrawBattleEntryBackground(void) enum TrainerClassID trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); if (trainerClass == TRAINER_CLASS_LEADER) { - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_BUILDING); return; } else if (trainerClass == TRAINER_CLASS_CHAMPION) { - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(BATTLE_ENVIRONMENT_BUILDING); return; } } if (GetCurrentMapBattleScene() == MAP_BATTLE_SCENE_NORMAL) { - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].entryTileset, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(gBattleEnvironment); } else { - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - DecompressDataWithHeaderVram(gBattleEnvironmentAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + LoadBattleEnvironmentEntryGfx(gBattleEnvironment); } } } @@ -1233,195 +1102,13 @@ bool8 LoadChosenBattleElement(u8 caseId) LoadPalette(gBattleTextboxPalette, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); break; case 3: - if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - } - else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) - { - switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) - { - case SPECIES_GROUDON: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Cave, (void*)(BG_CHAR_ADDR(2))); - break; - case SPECIES_KYOGRE: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Water, (void*)(BG_SCREEN_ADDR(2))); - break; - } - } - else - { - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - enum TrainerClassID trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); - if (trainerClass == TRAINER_CLASS_LEADER) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - break; - } - else if (trainerClass == TRAINER_CLASS_CHAMPION) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - } - } - - switch (GetCurrentMapBattleScene()) - { - default: - case MAP_BATTLE_SCENE_NORMAL: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tileset, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_GYM: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_MAGMA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_AQUA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_SIDNEY: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_PHOEBE: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_GLACIA: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_DRAKE: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - break; - case MAP_BATTLE_SCENE_FRONTIER: - DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void *)(BG_CHAR_ADDR(2))); - break; - } - } + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[GetBattleEnvironmentOverride()].background.tileset, (void *)(BG_CHAR_ADDR(2))); break; case 4: - if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - } - else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) - { - if (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL) == SPECIES_GROUDON) - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); - else - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Water, (void *)(BG_SCREEN_ADDR(26))); - } - else - { - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - enum TrainerClassID trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); - if (trainerClass == TRAINER_CLASS_LEADER) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - break; - } - else if (trainerClass == TRAINER_CLASS_CHAMPION) - { - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - } - } - - switch (GetCurrentMapBattleScene()) - { - default: - case MAP_BATTLE_SCENE_NORMAL: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[gBattleEnvironment].tilemap, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_GYM: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_MAGMA: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_AQUA: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_SIDNEY: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_PHOEBE: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_GLACIA: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_DRAKE: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); - break; - case MAP_BATTLE_SCENE_FRONTIER: - DecompressDataWithHeaderVram(gBattleEnvironmentTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); - break; - } - } + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[GetBattleEnvironmentOverride()].background.tilemap, (void *)(BG_SCREEN_ADDR(26))); break; case 5: - if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) - { - LoadPalette(gBattleEnvironmentPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - } - else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) - { - if (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL) == SPECIES_GROUDON) - LoadPalette(gBattleEnvironmentPalette_Groudon, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - else - LoadPalette(gBattleEnvironmentPalette_Kyogre, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - } - else - { - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - enum TrainerClassID trainerClass = GetTrainerClassFromId(TRAINER_BATTLE_PARAM.opponentA); - if (trainerClass == TRAINER_CLASS_LEADER) - { - LoadPalette(gBattleEnvironmentPalette_BuildingLeader, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - } - else if (trainerClass == TRAINER_CLASS_CHAMPION) - { - LoadPalette(gBattleEnvironmentPalette_StadiumWallace, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - } - } - - switch (GetCurrentMapBattleScene()) - { - default: - case MAP_BATTLE_SCENE_NORMAL: - LoadPalette(sBattleEnvironmentTable[gBattleEnvironment].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_GYM: - LoadPalette(gBattleEnvironmentPalette_BuildingGym, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_MAGMA: - LoadPalette(gBattleEnvironmentPalette_StadiumMagma, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_AQUA: - LoadPalette(gBattleEnvironmentPalette_StadiumAqua, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_SIDNEY: - LoadPalette(gBattleEnvironmentPalette_StadiumSidney, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_PHOEBE: - LoadPalette(gBattleEnvironmentPalette_StadiumPhoebe, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_GLACIA: - LoadPalette(gBattleEnvironmentPalette_StadiumGlacia, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_DRAKE: - LoadPalette(gBattleEnvironmentPalette_StadiumDrake, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - case MAP_BATTLE_SCENE_FRONTIER: - LoadPalette(gBattleEnvironmentPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); - break; - } - } + LoadPalette(gBattleEnvironmentInfo[GetBattleEnvironmentOverride()].background.palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case 6: LoadBattleMenuWindowGfx(); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7824a354bf..26144cecd1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5,6 +5,7 @@ #include "battle_ai_main.h" #include "battle_ai_util.h" #include "battle_scripts.h" +#include "battle_environment.h" #include "battle_z_move.h" #include "item.h" #include "util.h" @@ -938,78 +939,6 @@ static const u16 sFinalStrikeOnlyEffects[] = MOVE_EFFECT_WRAP, }; -static const u16 sNaturePowerMoves[BATTLE_ENVIRONMENT_COUNT] = -{ -#if B_NATURE_POWER_MOVES >= GEN_7 - [BATTLE_ENVIRONMENT_GRASS] = MOVE_ENERGY_BALL, - [BATTLE_ENVIRONMENT_LONG_GRASS] = MOVE_ENERGY_BALL, - [BATTLE_ENVIRONMENT_SAND] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_WATER] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_POND] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_MOUNTAIN] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_CAVE] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_BUILDING] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_PLAIN] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_SNOW] = MOVE_ICE_BEAM, -#elif B_NATURE_POWER_MOVES == GEN_6 - [BATTLE_ENVIRONMENT_GRASS] = MOVE_ENERGY_BALL, - [BATTLE_ENVIRONMENT_LONG_GRASS] = MOVE_ENERGY_BALL, - [BATTLE_ENVIRONMENT_SAND] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_WATER] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_POND] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_MOUNTAIN] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_CAVE] = MOVE_EARTH_POWER, - [BATTLE_ENVIRONMENT_BUILDING] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_PLAIN] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_SNOW] = MOVE_FROST_BREATH, -#elif B_NATURE_POWER_MOVES == GEN_5 - [BATTLE_ENVIRONMENT_GRASS] = MOVE_SEED_BOMB, - [BATTLE_ENVIRONMENT_LONG_GRASS] = MOVE_SEED_BOMB, - [BATTLE_ENVIRONMENT_SAND] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_WATER] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_POND] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_MOUNTAIN] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_CAVE] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_BUILDING] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_PLAIN] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_SNOW] = MOVE_BLIZZARD, -#elif B_NATURE_POWER_MOVES == GEN_4 - [BATTLE_ENVIRONMENT_GRASS] = MOVE_SEED_BOMB, - [BATTLE_ENVIRONMENT_LONG_GRASS] = MOVE_SEED_BOMB, - [BATTLE_ENVIRONMENT_SAND] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_WATER] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_POND] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_MOUNTAIN] = MOVE_ROCK_SLIDE, - [BATTLE_ENVIRONMENT_CAVE] = MOVE_ROCK_SLIDE, - [BATTLE_ENVIRONMENT_BUILDING] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_PLAIN] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_SNOW] = MOVE_BLIZZARD, -#else // Gen 1-3 - [BATTLE_ENVIRONMENT_GRASS] = MOVE_STUN_SPORE, - [BATTLE_ENVIRONMENT_LONG_GRASS] = MOVE_RAZOR_LEAF, - [BATTLE_ENVIRONMENT_SAND] = MOVE_EARTHQUAKE, - [BATTLE_ENVIRONMENT_WATER] = MOVE_SURF, - [BATTLE_ENVIRONMENT_POND] = MOVE_BUBBLE_BEAM, - [BATTLE_ENVIRONMENT_MOUNTAIN] = MOVE_ROCK_SLIDE, - [BATTLE_ENVIRONMENT_CAVE] = MOVE_SHADOW_BALL, - [BATTLE_ENVIRONMENT_BUILDING] = MOVE_SWIFT, - [BATTLE_ENVIRONMENT_PLAIN] = MOVE_SWIFT, - [BATTLE_ENVIRONMENT_SNOW] = MOVE_BLIZZARD, -#endif - [BATTLE_ENVIRONMENT_UNDERWATER] = MOVE_HYDRO_PUMP, - [BATTLE_ENVIRONMENT_SOARING] = MOVE_AIR_SLASH, - [BATTLE_ENVIRONMENT_SKY_PILLAR] = MOVE_AIR_SLASH, - [BATTLE_ENVIRONMENT_BURIAL_GROUND] = MOVE_SHADOW_BALL, - [BATTLE_ENVIRONMENT_PUDDLE] = MOVE_MUD_BOMB, - [BATTLE_ENVIRONMENT_MARSH] = MOVE_MUD_BOMB, - [BATTLE_ENVIRONMENT_SWAMP] = MOVE_MUD_BOMB, - [BATTLE_ENVIRONMENT_ICE] = MOVE_ICE_BEAM, - [BATTLE_ENVIRONMENT_VOLCANO] = MOVE_LAVA_PLUME, - [BATTLE_ENVIRONMENT_DISTORTION_WORLD] = MOVE_TRI_ATTACK, - [BATTLE_ENVIRONMENT_SPACE] = MOVE_DRACO_METEOR, - [BATTLE_ENVIRONMENT_ULTRA_SPACE] = MOVE_PSYSHOCK, -}; - #define _ 0 static const struct PickupItem sPickupTable[] = @@ -1048,32 +977,6 @@ static const struct PickupItem sPickupTable[] = #undef _ -static const u8 sEnvironmentToType[BATTLE_ENVIRONMENT_COUNT] = -{ - [BATTLE_ENVIRONMENT_GRASS] = TYPE_GRASS, - [BATTLE_ENVIRONMENT_LONG_GRASS] = TYPE_GRASS, - [BATTLE_ENVIRONMENT_SAND] = TYPE_GROUND, - [BATTLE_ENVIRONMENT_UNDERWATER] = TYPE_WATER, - [BATTLE_ENVIRONMENT_WATER] = TYPE_WATER, - [BATTLE_ENVIRONMENT_POND] = TYPE_WATER, - [BATTLE_ENVIRONMENT_CAVE] = TYPE_ROCK, - [BATTLE_ENVIRONMENT_BUILDING] = TYPE_NORMAL, - [BATTLE_ENVIRONMENT_SOARING] = TYPE_FLYING, - [BATTLE_ENVIRONMENT_SKY_PILLAR] = TYPE_FLYING, - [BATTLE_ENVIRONMENT_BURIAL_GROUND] = TYPE_GHOST, - [BATTLE_ENVIRONMENT_PUDDLE] = TYPE_GROUND, - [BATTLE_ENVIRONMENT_MARSH] = TYPE_GROUND, - [BATTLE_ENVIRONMENT_SWAMP] = TYPE_GROUND, - [BATTLE_ENVIRONMENT_SNOW] = TYPE_ICE, - [BATTLE_ENVIRONMENT_ICE] = TYPE_ICE, - [BATTLE_ENVIRONMENT_VOLCANO] = TYPE_FIRE, - [BATTLE_ENVIRONMENT_DISTORTION_WORLD] = TYPE_NORMAL, - [BATTLE_ENVIRONMENT_SPACE] = TYPE_DRAGON, - [BATTLE_ENVIRONMENT_ULTRA_SPACE] = TYPE_PSYCHIC, - [BATTLE_ENVIRONMENT_MOUNTAIN] = (B_CAMOUFLAGE_TYPES >= GEN_5 ? TYPE_GROUND : TYPE_ROCK), - [BATTLE_ENVIRONMENT_PLAIN] = (B_CAMOUFLAGE_TYPES >= GEN_4 ? TYPE_GROUND : TYPE_NORMAL), -}; - static bool32 NoTargetPresent(u8 battler, u32 move) { if (!IsBattlerAlive(gBattlerTarget)) @@ -3703,64 +3606,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } } else - { - switch (gBattleEnvironment) - { - case BATTLE_ENVIRONMENT_GRASS: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON); - break; - case BATTLE_ENVIRONMENT_UNDERWATER: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1); - break; - case BATTLE_ENVIRONMENT_POND: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1); - break; - case BATTLE_ENVIRONMENT_MOUNTAIN: - if (B_SECRET_POWER_EFFECT >= GEN_5) - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; - else if (B_SECRET_POWER_EFFECT >= GEN_4) - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - else - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; - break; - case BATTLE_ENVIRONMENT_PUDDLE: - gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1); - break; - case BATTLE_ENVIRONMENT_LONG_GRASS: - gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP; - break; - case BATTLE_ENVIRONMENT_SAND: - gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1; - break; - case BATTLE_ENVIRONMENT_WATER: - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; - break; - case BATTLE_ENVIRONMENT_CAVE: - case BATTLE_ENVIRONMENT_BURIAL_GROUND: - case BATTLE_ENVIRONMENT_SPACE: - gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; - break; - case BATTLE_ENVIRONMENT_SOARING: - case BATTLE_ENVIRONMENT_SKY_PILLAR: - case BATTLE_ENVIRONMENT_MARSH: - case BATTLE_ENVIRONMENT_SWAMP: - gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; - break; - case BATTLE_ENVIRONMENT_SNOW: - case BATTLE_ENVIRONMENT_ICE: - gBattleScripting.moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE; - break; - case BATTLE_ENVIRONMENT_VOLCANO: - gBattleScripting.moveEffect = MOVE_EFFECT_BURN; - break; - case BATTLE_ENVIRONMENT_ULTRA_SPACE: - gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_1; - break; - default: - gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; - break; - } - } + gBattleScripting.moveEffect = gBattleEnvironmentInfo[gBattleEnvironment].secretPowerEffect; SetMoveEffect(battler, effectBattler, primary, certain); break; case MOVE_EFFECT_PSYCHIC_NOISE: @@ -14483,7 +14329,7 @@ static void Cmd_callenvironmentattack(void) u32 GetNaturePowerMove(u32 battler) { - u32 move = sNaturePowerMoves[gBattleEnvironment]; + u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) move = MOVE_MOONBLAST; else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) @@ -14492,7 +14338,7 @@ u32 GetNaturePowerMove(u32 battler) move = MOVE_ENERGY_BALL; else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) move = MOVE_PSYCHIC; - else if (sNaturePowerMoves[gBattleEnvironment] == MOVE_NONE) + else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) move = MOVE_TRI_ATTACK; if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE) @@ -15359,7 +15205,7 @@ static void Cmd_tryrecycleitem(void) bool32 CanCamouflage(u8 battler) { - if (IS_BATTLER_OF_TYPE(battler, sEnvironmentToType[gBattleEnvironment])) + if (IS_BATTLER_OF_TYPE(battler, gBattleEnvironmentInfo[gBattleEnvironment].camouflageType)) return FALSE; return TRUE; } @@ -15384,7 +15230,7 @@ static void Cmd_settypetoenvironment(void) environmentType = TYPE_PSYCHIC; break; default: - environmentType = sEnvironmentToType[gBattleEnvironment]; + environmentType = gBattleEnvironmentInfo[gBattleEnvironment].camouflageType; break; } diff --git a/src/battle_setup.c b/src/battle_setup.c index 0074eebf38..0860d5511a 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -621,7 +621,7 @@ static void CB2_EndScriptedWildBattle(void) } } -enum BattleEnvironment BattleSetup_GetEnvironmentId(void) +enum BattleEnvironments BattleSetup_GetEnvironmentId(void) { u16 tileBehavior; s16 x, y; diff --git a/src/data/battle_environment.h b/src/data/battle_environment.h new file mode 100644 index 0000000000..1773e6ced3 --- /dev/null +++ b/src/data/battle_environment.h @@ -0,0 +1,434 @@ +const u32 gBattleEnvironmentTiles_TallGrass[] = INCBIN_U32("graphics/battle_environment/tall_grass/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_TallGrass[] = INCBIN_U16("graphics/battle_environment/tall_grass/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_TallGrass[] = INCBIN_U32("graphics/battle_environment/tall_grass/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_LongGrass[] = INCBIN_U32("graphics/battle_environment/long_grass/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_LongGrass[] = INCBIN_U16("graphics/battle_environment/long_grass/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_LongGrass[] = INCBIN_U32("graphics/battle_environment/long_grass/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_Sand[] = INCBIN_U32("graphics/battle_environment/sand/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Sand[] = INCBIN_U16("graphics/battle_environment/sand/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_Sand[] = INCBIN_U32("graphics/battle_environment/sand/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_Underwater[] = INCBIN_U32("graphics/battle_environment/underwater/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Underwater[] = INCBIN_U16("graphics/battle_environment/underwater/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_Underwater[] = INCBIN_U32("graphics/battle_environment/underwater/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_Water[] = INCBIN_U32("graphics/battle_environment/water/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Water[] = INCBIN_U16("graphics/battle_environment/water/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_Water[] = INCBIN_U32("graphics/battle_environment/water/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_PondWater[] = INCBIN_U32("graphics/battle_environment/pond_water/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_PondWater[] = INCBIN_U16("graphics/battle_environment/pond_water/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_PondWater[] = INCBIN_U32("graphics/battle_environment/pond_water/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_Rock[] = INCBIN_U32("graphics/battle_environment/rock/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Rock[] = INCBIN_U16("graphics/battle_environment/rock/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_Rock[] = INCBIN_U32("graphics/battle_environment/rock/map.bin.smolTM"); + +const u32 gBattleEnvironmentTiles_Cave[] = INCBIN_U32("graphics/battle_environment/cave/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Cave[] = INCBIN_U16("graphics/battle_environment/cave/palette.gbapal"); +const u32 gBattleEnvironmentTilemap_Cave[] = INCBIN_U32("graphics/battle_environment/cave/map.bin.smolTM"); + +const u16 gBattleEnvironmentPalette_Plain[] = INCBIN_U16("graphics/battle_environment/plain/palette.gbapal"); + +const u32 gBattleEnvironmentTiles_Building[] = INCBIN_U32("graphics/battle_environment/building/tiles.4bpp.smol"); +const u16 gBattleEnvironmentPalette_Frontier[] = INCBIN_U16("graphics/battle_environment/stadium/battle_frontier.gbapal"); // this is also used for link battles +const u32 gBattleEnvironmentTilemap_Building[] = INCBIN_U32("graphics/battle_environment/building/map.bin.smolTM"); + +#define ENVIRONMENT_BACKGROUND(background) \ +{ \ + .tileset = gBattleEnvironmentTiles_##background, \ + .tilemap = gBattleEnvironmentTilemap_##background, \ + .entryTileset = gBattleEnvironmentAnimTiles_##background, \ + .entryTilemap = gBattleEnvironmentAnimTilemap_##background, \ + .palette = gBattleEnvironmentPalette_##background, \ +} + +const struct BattleEnvironment gBattleEnvironmentInfo[BATTLE_ENVIRONMENT_COUNT] = +{ + [BATTLE_ENVIRONMENT_GRASS] = + { + #if B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_ENERGY_BALL, + #elif B_NATURE_POWER_MOVES >= GEN_4 + .naturePower = MOVE_SEED_BOMB, + #else + .naturePower = MOVE_STUN_SPORE, + #endif + .secretPowerEffect = B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON, + .camouflageType = TYPE_GRASS, + .background = ENVIRONMENT_BACKGROUND(TallGrass), + }, + + [BATTLE_ENVIRONMENT_LONG_GRASS] = + { + #if B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_ENERGY_BALL, + #elif B_NATURE_POWER_MOVES >= GEN_4 + .naturePower = MOVE_SEED_BOMB, + #else + .naturePower = MOVE_RAZOR_LEAF, + #endif + .secretPowerEffect = MOVE_EFFECT_SLEEP, + .camouflageType = TYPE_GRASS, + .background = ENVIRONMENT_BACKGROUND(LongGrass), + }, + + [BATTLE_ENVIRONMENT_SAND] = + { + .naturePower = B_NATURE_POWER_MOVES >= GEN_6 ? MOVE_EARTH_POWER : MOVE_EARTHQUAKE, + .secretPowerEffect = MOVE_EFFECT_ACC_MINUS_1, + .camouflageType = TYPE_GROUND, + .background = ENVIRONMENT_BACKGROUND(Sand), + }, + + [BATTLE_ENVIRONMENT_UNDERWATER] = + { + .naturePower = MOVE_HYDRO_PUMP, + .secretPowerEffect = B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1, + .camouflageType = TYPE_WATER, + .background = ENVIRONMENT_BACKGROUND(Underwater), + }, + + [BATTLE_ENVIRONMENT_WATER] = + { + .naturePower = B_NATURE_POWER_MOVES >= GEN_4 ? MOVE_HYDRO_PUMP : MOVE_SURF, + .secretPowerEffect = MOVE_EFFECT_ATK_MINUS_1, + .camouflageType = TYPE_WATER, + .background = ENVIRONMENT_BACKGROUND(Water), + }, + + [BATTLE_ENVIRONMENT_POND] = + { + .naturePower = B_NATURE_POWER_MOVES >= GEN_4 ? MOVE_HYDRO_PUMP : MOVE_BUBBLE_BEAM, + .secretPowerEffect = B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1, + .camouflageType = TYPE_WATER, + .background = ENVIRONMENT_BACKGROUND(PondWater), + }, + + [BATTLE_ENVIRONMENT_MOUNTAIN] = + { + #if B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_EARTH_POWER, + #elif B_NATURE_POWER_MOVES >= GEN_5 + .naturePower = MOVE_EARTHQUAKE, + #else + .naturePower = MOVE_ROCK_SLIDE, + #endif + #if B_SECRET_POWER_EFFECT >= GEN_5 + .secretPowerEffect = MOVE_EFFECT_ACC_MINUS_1, + #elif B_SECRET_POWER_EFFECT >= GEN_4 + .secretPowerEffect = MOVE_EFFECT_FLINCH, + #else + .secretPowerEffect = MOVE_EFFECT_CONFUSION, + #endif + .camouflageType = B_CAMOUFLAGE_TYPES >= GEN_5 ? TYPE_GROUND : TYPE_ROCK, + .background = ENVIRONMENT_BACKGROUND(Rock), + }, + + [BATTLE_ENVIRONMENT_CAVE] = + { + #if B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_EARTH_POWER, + #elif B_NATURE_POWER_MOVES >= GEN_5 + .naturePower = MOVE_EARTHQUAKE, + #elif B_NATURE_POWER_MOVES >= GEN_4 + .naturePower = MOVE_ROCK_SLIDE, + #else + .naturePower = MOVE_SHADOW_BALL, + #endif + .secretPowerEffect = MOVE_EFFECT_FLINCH, + .camouflageType = TYPE_ROCK, + .background = ENVIRONMENT_BACKGROUND(Cave), + }, + + [BATTLE_ENVIRONMENT_BUILDING] = + { + .naturePower = B_NATURE_POWER_MOVES >= GEN_4 ? MOVE_TRI_ATTACK : MOVE_SWIFT, + .secretPowerEffect = MOVE_EFFECT_PARALYSIS, + .camouflageType = TYPE_NORMAL, + .background = ENVIRONMENT_BACKGROUND(Building), + }, + + [BATTLE_ENVIRONMENT_PLAIN] = + { + #if B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_TRI_ATTACK, + #elif B_NATURE_POWER_MOVES >= GEN_4 + .naturePower = MOVE_EARTHQUAKE, + #else + .naturePower = MOVE_SWIFT, + #endif + .secretPowerEffect = MOVE_EFFECT_PARALYSIS, + .camouflageType = B_CAMOUFLAGE_TYPES >= GEN_4 ? TYPE_GROUND : TYPE_NORMAL, + .background = + { + .tileset = gBattleEnvironmentTiles_Building, + .tilemap = gBattleEnvironmentTilemap_Building, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_Plain, + }, + }, + + [BATTLE_ENVIRONMENT_FRONTIER] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Building, + .tilemap = gBattleEnvironmentTilemap_Building, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_Frontier, + }, + }, + + [BATTLE_ENVIRONMENT_GYM] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Building, + .tilemap = gBattleEnvironmentTilemap_Building, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_BuildingGym, + }, + }, + + [BATTLE_ENVIRONMENT_LEADER] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Building, + .tilemap = gBattleEnvironmentTilemap_Building, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_BuildingLeader, + }, + }, + + [BATTLE_ENVIRONMENT_MAGMA] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumMagma, + }, + }, + + [BATTLE_ENVIRONMENT_AQUA] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumAqua, + }, + }, + + [BATTLE_ENVIRONMENT_SIDNEY] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumSidney, + }, + }, + + [BATTLE_ENVIRONMENT_PHOEBE] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumPhoebe, + }, + }, + + [BATTLE_ENVIRONMENT_GLACIA] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumGlacia, + }, + }, + + [BATTLE_ENVIRONMENT_DRAKE] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumDrake, + }, + }, + + [BATTLE_ENVIRONMENT_CHAMPION] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Stadium, + .tilemap = gBattleEnvironmentTilemap_Stadium, + .entryTileset = gBattleEnvironmentAnimTiles_Building, + .entryTilemap = gBattleEnvironmentAnimTilemap_Building, + .palette = gBattleEnvironmentPalette_StadiumWallace, + }, + }, + + [BATTLE_ENVIRONMENT_GROUDON] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Cave, + .tilemap = gBattleEnvironmentTilemap_Cave, + .entryTileset = gBattleEnvironmentAnimTiles_Cave, + .entryTilemap = gBattleEnvironmentAnimTilemap_Cave, + .palette = gBattleEnvironmentPalette_Groudon, + }, + }, + + [BATTLE_ENVIRONMENT_KYOGRE] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Water, + .tilemap = gBattleEnvironmentTilemap_Water, + .entryTileset = gBattleEnvironmentAnimTiles_Underwater, + .entryTilemap = gBattleEnvironmentAnimTilemap_Underwater, + .palette = gBattleEnvironmentPalette_Kyogre, + }, + }, + + [BATTLE_ENVIRONMENT_RAYQUAZA] = + { + .background = + { + .tileset = gBattleEnvironmentTiles_Rayquaza, + .tilemap = gBattleEnvironmentTilemap_Rayquaza, + .entryTileset = gBattleEnvironmentAnimTiles_Rayquaza, + .entryTilemap = gBattleEnvironmentAnimTilemap_Rayquaza, + .palette = gBattleEnvironmentPalette_Rayquaza, + }, + }, + + [BATTLE_ENVIRONMENT_SOARING] = + { + .naturePower = MOVE_AIR_SLASH, + .secretPowerEffect = MOVE_EFFECT_SPD_MINUS_1, + .camouflageType = TYPE_FLYING, + }, + + [BATTLE_ENVIRONMENT_SKY_PILLAR] = + { + .naturePower = MOVE_AIR_SLASH, + .secretPowerEffect = MOVE_EFFECT_SPD_MINUS_1, + .camouflageType = TYPE_FLYING, + }, + + [BATTLE_ENVIRONMENT_BURIAL_GROUND] = + { + .naturePower = MOVE_SHADOW_BALL, + .secretPowerEffect = MOVE_EFFECT_FLINCH, + .camouflageType = TYPE_GHOST, + }, + + [BATTLE_ENVIRONMENT_PUDDLE] = + { + .naturePower = MOVE_MUD_BOMB, + .secretPowerEffect = B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1, + .camouflageType = TYPE_GROUND, + }, + + [BATTLE_ENVIRONMENT_MARSH] = + { + .naturePower = MOVE_MUD_BOMB, + .secretPowerEffect = MOVE_EFFECT_SPD_MINUS_1, + .camouflageType = TYPE_GROUND, + }, + + [BATTLE_ENVIRONMENT_SWAMP] = + { + .naturePower = MOVE_MUD_BOMB, + .secretPowerEffect = MOVE_EFFECT_SPD_MINUS_1, + .camouflageType = TYPE_GROUND, + }, + + [BATTLE_ENVIRONMENT_SNOW] = + { + #if B_NATURE_POWER_MOVES >= GEN_7 + .naturePower = MOVE_ICE_BEAM, + #elif B_NATURE_POWER_MOVES >= GEN_6 + .naturePower = MOVE_FROST_BREATH, + #else + .naturePower = MOVE_BLIZZARD, + #endif + .secretPowerEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, + .camouflageType = TYPE_ICE, + }, + + [BATTLE_ENVIRONMENT_ICE] = + { + .naturePower = MOVE_ICE_BEAM, + .secretPowerEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE, + .camouflageType = TYPE_ICE, + }, + + [BATTLE_ENVIRONMENT_VOLCANO] = + { + .naturePower = MOVE_LAVA_PLUME, + .secretPowerEffect = MOVE_EFFECT_BURN, + .camouflageType = TYPE_FIRE, + }, + + [BATTLE_ENVIRONMENT_DISTORTION_WORLD] = + { + .naturePower = MOVE_TRI_ATTACK, + .secretPowerEffect = MOVE_EFFECT_PARALYSIS, + .camouflageType = TYPE_NORMAL, + }, + + [BATTLE_ENVIRONMENT_SPACE] = + { + .naturePower = MOVE_DRACO_METEOR, + .secretPowerEffect = MOVE_EFFECT_FLINCH, + .camouflageType = TYPE_DRAGON, + }, + + [BATTLE_ENVIRONMENT_ULTRA_SPACE] = + { + .naturePower = MOVE_PSYSHOCK, + .secretPowerEffect = MOVE_EFFECT_DEF_MINUS_1, + .camouflageType = TYPE_PSYCHIC, + }, +}; + +static const struct { + u8 mapScene; + u8 battleEnvironment; +} sMapBattleSceneMapping[] = { + {MAP_BATTLE_SCENE_GYM, BATTLE_ENVIRONMENT_GYM}, + {MAP_BATTLE_SCENE_MAGMA, BATTLE_ENVIRONMENT_MAGMA}, + {MAP_BATTLE_SCENE_AQUA, BATTLE_ENVIRONMENT_AQUA}, + {MAP_BATTLE_SCENE_SIDNEY, BATTLE_ENVIRONMENT_SIDNEY}, + {MAP_BATTLE_SCENE_PHOEBE, BATTLE_ENVIRONMENT_PHOEBE}, + {MAP_BATTLE_SCENE_GLACIA, BATTLE_ENVIRONMENT_GLACIA}, + {MAP_BATTLE_SCENE_DRAKE, BATTLE_ENVIRONMENT_DRAKE}, + {MAP_BATTLE_SCENE_FRONTIER, BATTLE_ENVIRONMENT_FRONTIER} +}; diff --git a/src/data/graphics/battle_environment.h b/src/data/graphics/battle_environment.h index d220611c6d..4d271ea82d 100644 --- a/src/data/graphics/battle_environment.h +++ b/src/data/graphics/battle_environment.h @@ -1,41 +1,3 @@ -const u32 gBattleEnvironmentTiles_TallGrass[] = INCBIN_U32("graphics/battle_environment/tall_grass/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_TallGrass[] = INCBIN_U16("graphics/battle_environment/tall_grass/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_TallGrass[] = INCBIN_U32("graphics/battle_environment/tall_grass/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_LongGrass[] = INCBIN_U32("graphics/battle_environment/long_grass/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_LongGrass[] = INCBIN_U16("graphics/battle_environment/long_grass/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_LongGrass[] = INCBIN_U32("graphics/battle_environment/long_grass/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_Sand[] = INCBIN_U32("graphics/battle_environment/sand/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Sand[] = INCBIN_U16("graphics/battle_environment/sand/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_Sand[] = INCBIN_U32("graphics/battle_environment/sand/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_Underwater[] = INCBIN_U32("graphics/battle_environment/underwater/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Underwater[] = INCBIN_U16("graphics/battle_environment/underwater/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_Underwater[] = INCBIN_U32("graphics/battle_environment/underwater/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_Water[] = INCBIN_U32("graphics/battle_environment/water/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Water[] = INCBIN_U16("graphics/battle_environment/water/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_Water[] = INCBIN_U32("graphics/battle_environment/water/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_PondWater[] = INCBIN_U32("graphics/battle_environment/pond_water/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_PondWater[] = INCBIN_U16("graphics/battle_environment/pond_water/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_PondWater[] = INCBIN_U32("graphics/battle_environment/pond_water/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_Rock[] = INCBIN_U32("graphics/battle_environment/rock/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Rock[] = INCBIN_U16("graphics/battle_environment/rock/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_Rock[] = INCBIN_U32("graphics/battle_environment/rock/map.bin.smolTM"); - -const u32 gBattleEnvironmentTiles_Cave[] = INCBIN_U32("graphics/battle_environment/cave/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Cave[] = INCBIN_U16("graphics/battle_environment/cave/palette.gbapal"); -const u32 gBattleEnvironmentTilemap_Cave[] = INCBIN_U32("graphics/battle_environment/cave/map.bin.smolTM"); - -const u16 gBattleEnvironmentPalette_Plain[] = INCBIN_U16("graphics/battle_environment/plain/palette.gbapal"); - -const u32 gBattleEnvironmentTiles_Building[] = INCBIN_U32("graphics/battle_environment/building/tiles.4bpp.smol"); -const u16 gBattleEnvironmentPalette_Frontier[] = INCBIN_U16("graphics/battle_environment/stadium/battle_frontier.gbapal"); // this is also used for link battles -const u32 gBattleEnvironmentTilemap_Building[] = INCBIN_U32("graphics/battle_environment/building/map.bin.smolTM"); - const u32 gBattleEnvironmentTiles_Stadium[] = INCBIN_U32("graphics/battle_environment/stadium/tiles.4bpp.smol"); const u32 gBattleEnvironmentTilemap_Stadium[] = INCBIN_U32("graphics/battle_environment/stadium/map.bin.smolTM"); diff --git a/src/debug.c b/src/debug.c index ba91351b98..a14b0ebe53 100644 --- a/src/debug.c +++ b/src/debug.c @@ -141,18 +141,18 @@ enum DebugBattleAIFlags DEBUG_BATTLE_1_MENU_ITEM_CONTINUE, }; -enum DebugBattleTerrain -{ - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9, +enum DebugBattleEnvironment +{ + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_0, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_1, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_2, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_3, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_4, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_5, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_6, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_7, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_8, + DEBUG_BATTLE_2_MENU_ITEM_ENVIRONMENT_9, }; // ******************************* diff --git a/src/pokemon_sprite_visualizer.c b/src/pokemon_sprite_visualizer.c index 6984290f13..a5f36a0db6 100644 --- a/src/pokemon_sprite_visualizer.c +++ b/src/pokemon_sprite_visualizer.c @@ -3,6 +3,7 @@ #include "battle.h" #include "battle_anim.h" #include "battle_gfx_sfx_util.h" +#include "battle_environment.h" #include "bg.h" #include "data.h" #include "decompress.h" @@ -42,7 +43,7 @@ #include "constants/rgb.h" #include "constants/songs.h" -extern const struct BattleBackground sBattleEnvironmentTable[]; +extern const struct BattleEnvironment gBattleEnvironmentInfo[BATTLE_ENVIRONMENT_COUNT]; extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow; extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadowsSized; extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow; @@ -385,6 +386,7 @@ const u8 gBattleBackgroundNames[][30] = [MAP_BATTLE_SCENE_KYOGRE] = _("KYOGRE "), [MAP_BATTLE_SCENE_RAYQUAZA] = _("RAYQUAZA "), }; + const u8 gBattleBackgroundTerrainNames[][26] = { [BATTLE_ENVIRONMENT_GRASS] = _("NORMAL - GRASS "), @@ -398,6 +400,7 @@ const u8 gBattleBackgroundTerrainNames[][26] = [BATTLE_ENVIRONMENT_BUILDING] = _("NORMAL - BUILDING "), [BATTLE_ENVIRONMENT_PLAIN] = _("NORMAL - PLAIN "), }; + const u8 sShadowSizeLabels[][4] = { [SHADOW_SIZE_S] = _(" S"), @@ -405,6 +408,7 @@ const u8 sShadowSizeLabels[][4] = [SHADOW_SIZE_L] = _(" L"), [SHADOW_SIZE_XL_BATTLE_ONLY] = _(" XL"), }; + //Function declarations static void PrintDigitChars(struct PokemonSpriteVisualizer *data); static void SetUpModifyArrows(struct PokemonSpriteVisualizer *data); @@ -921,15 +925,15 @@ static void LoadAndCreateEnemyShadowSpriteCustom(struct PokemonSpriteVisualizer } //Battle background functions -static void LoadBattleBg(u8 battleBgType, enum BattleEnvironment battleEnvironment) +static void LoadBattleBg(u8 battleBgType, enum BattleEnvironments battleEnvironment) { switch (battleBgType) { default: case MAP_BATTLE_SCENE_NORMAL: - DecompressDataWithHeaderVram(sBattleEnvironmentTable[battleEnvironment].tileset, (void*)(BG_CHAR_ADDR(2))); - DecompressDataWithHeaderVram(sBattleEnvironmentTable[battleEnvironment].tilemap, (void*)(BG_SCREEN_ADDR(26))); - LoadPalette(sBattleEnvironmentTable[battleEnvironment].palette, 0x20, 0x60); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[battleEnvironment].background.tileset, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleEnvironmentInfo[battleEnvironment].background.tilemap, (void*)(BG_SCREEN_ADDR(26))); + LoadPalette(gBattleEnvironmentInfo[battleEnvironment].background.palette, 0x20, 0x60); break; case MAP_BATTLE_SCENE_GYM: DecompressDataWithHeaderVram(gBattleEnvironmentTiles_Building, (void*)(BG_CHAR_ADDR(2))); @@ -998,6 +1002,7 @@ static void LoadBattleBg(u8 battleBgType, enum BattleEnvironment battleEnvironme break; } } + static void PrintBattleBgName(u8 taskId) { struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); @@ -1005,11 +1010,12 @@ static void PrintBattleBgName(u8 taskId) u8 text[30+1]; if (data->battleBgType == 0) - StringCopy(text, gBattleBackgroundTerrainNames[data->battleTerrain]); + StringCopy(text, gBattleBackgroundTerrainNames[data->battleEnvironment]); else StringCopy(text, gBattleBackgroundNames[data->battleBgType]); AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, 0, 24, 0, NULL); } + static void UpdateBattleBg(u8 taskId, bool8 increment) { struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); @@ -1018,17 +1024,17 @@ static void UpdateBattleBg(u8 taskId, bool8 increment) { if (increment) { - if (data->battleTerrain == BATTLE_ENVIRONMENT_PLAIN) + if (data->battleEnvironment == BATTLE_ENVIRONMENT_PLAIN) data->battleBgType += 1; else - data->battleTerrain += 1; + data->battleEnvironment += 1; } else { - if (data->battleTerrain == BATTLE_ENVIRONMENT_GRASS) + if (data->battleEnvironment == BATTLE_ENVIRONMENT_GRASS) data->battleBgType = MAP_BATTLE_SCENE_RAYQUAZA; else - data->battleTerrain -= 1; + data->battleEnvironment -= 1; } } else if (data->battleBgType == MAP_BATTLE_SCENE_GYM) @@ -1038,7 +1044,7 @@ static void UpdateBattleBg(u8 taskId, bool8 increment) else { data->battleBgType = MAP_BATTLE_SCENE_NORMAL; - data->battleTerrain = BATTLE_ENVIRONMENT_PLAIN; + data->battleEnvironment = BATTLE_ENVIRONMENT_PLAIN; } } else if (data->battleBgType == MAP_BATTLE_SCENE_RAYQUAZA) @@ -1046,7 +1052,7 @@ static void UpdateBattleBg(u8 taskId, bool8 increment) if (increment) { data->battleBgType = MAP_BATTLE_SCENE_NORMAL; - data->battleTerrain = BATTLE_ENVIRONMENT_GRASS; + data->battleEnvironment = BATTLE_ENVIRONMENT_GRASS; } else data->battleBgType -= 1; @@ -1061,7 +1067,7 @@ static void UpdateBattleBg(u8 taskId, bool8 increment) PrintBattleBgName(taskId); - LoadBattleBg(data->battleBgType, data->battleTerrain); + LoadBattleBg(data->battleBgType, data->battleEnvironment); } // ******************************* From b55ee2288b66ccc4614026a9e129ab17f2025ccc Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 12 Jul 2025 15:28:05 -0400 Subject: [PATCH 090/283] Fix AI seeing switchin abilities wrong in tests (#7328) --- src/battle_controllers.c | 2 +- src/battle_main.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index ec3dfa7426..d189c67215 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1652,7 +1652,7 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 * u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif break; diff --git a/src/battle_main.c b/src/battle_main.c index fc7304b1a3..8bab8fd1ef 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3263,7 +3263,7 @@ void SwitchInClearSetData(u32 battler) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif // TESTING @@ -3474,7 +3474,7 @@ static void DoBattleIntro(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif } @@ -3770,7 +3770,7 @@ static void TryDoEventsBeforeFirstTurn(void) u32 side = GetBattlerSide(i); u32 partyIndex = gBattlerPartyIndexes[i]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } } #endif // TESTING From 14dbbf63d454073dbb198b941cc3566168c89f11 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 12 Jul 2025 22:03:36 +0200 Subject: [PATCH 091/283] Remove competitive syntax config (#7154) Co-authored-by: Hedara --- .gitignore | 4 + Makefile | 6 +- include/config/general.h | 1 - src/data/battle_partners.h | 105 - src/data/debug_trainers.h | 132 - src/data/trainers.h | 42180 -------------------------------- test/battle/trainer_control.h | 792 - trainer_rules.mk | 10 + 8 files changed, 15 insertions(+), 43215 deletions(-) delete mode 100644 src/data/battle_partners.h delete mode 100644 src/data/debug_trainers.h delete mode 100644 src/data/trainers.h delete mode 100644 test/battle/trainer_control.h create mode 100644 trainer_rules.mk diff --git a/.gitignore b/.gitignore index 8cc8ba9ed9..2d699f8e98 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,10 @@ prefabs.json src/data/map_group_count.h include/constants/heal_locations.h tools/trainerproc/trainerproc +src/data/battle_partners.h +src/data/trainers.h +src/data/debug_trainers.h +test/battle/trainer_control.h tools/compresSmol/compresSmol tools/compresSmol/compresSmolTilemap *.Identifier diff --git a/Makefile b/Makefile index 7456a9073b..dd1c0f2c92 100644 --- a/Makefile +++ b/Makefile @@ -351,6 +351,7 @@ include map_data_rules.mk include spritesheet_rules.mk include json_data_rules.mk include audio_rules.mk +include trainer_rules.mk # NOTE: Tools must have been built prior (FIXME) # so you can't really call this rule directly @@ -380,11 +381,6 @@ clean-generated: @rm -f $(ALL_LEARNABLES_JSON) @echo "rm -f " -COMPETITIVE_PARTY_SYNTAX := $(shell PATH="$(PATH)"; echo 'COMPETITIVE_PARTY_SYNTAX' | $(CPP) $(CPPFLAGS) -imacros include/gba/defines.h -imacros include/config/general.h | tail -n1) -ifeq ($(COMPETITIVE_PARTY_SYNTAX),1) -%.h: %.party ; $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< - -endif - $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast $(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member $(C_BUILDDIR)/agb_flash.o: override CFLAGS += -fno-toplevel-reorder diff --git a/include/config/general.h b/include/config/general.h index db01fd22f9..7eabc2e26f 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -70,7 +70,6 @@ #define EXPANSION_INTRO TRUE // If TRUE, a custom RHH intro will play after the vanilla copyright screen. #define SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. #define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG. -#define COMPETITIVE_PARTY_SYNTAX TRUE // If TRUE, parties are defined in "competitive syntax". #define AUTO_SCROLL_TEXT FALSE // If TRUE, text will automatically scroll to the next line after NUM_FRAMES_AUTO_SCROLL_DELAY. Players can still press A_BUTTON or B_BUTTON to scroll on their own. #define NUM_FRAMES_AUTO_SCROLL_DELAY 49 #define PHONEMES_SHARED FALSE // If TRUE, bard phonemes all reference the same sound (sound/direct_sound_samples/phonemes/shared.bin) to save ROM space. diff --git a/src/data/battle_partners.h b/src/data/battle_partners.h deleted file mode 100644 index 34e30ea083..0000000000 --- a/src/data/battle_partners.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// DO NOT MODIFY THIS FILE! It is auto-generated from src/data/battle_partners.party -// -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'src/data/battle_partners.h' to remove #line markers. -// - -#line 1 "src/data/battle_partners.party" - -#line 1 - [DIFFICULTY_NORMAL][PARTNER_NONE] = - { -#line 3 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 4 - .trainerPic = TRAINER_BACK_PIC_BRENDAN, - .encounterMusic_gender = -#line 6 - TRAINER_ENCOUNTER_MUSIC_MALE, - .partySize = 0, - .party = (const struct TrainerMon[]) - { - }, - }, -#line 8 - [DIFFICULTY_NORMAL][PARTNER_STEVEN] = - { -#line 9 - .trainerName = _("STEVEN"), -#line 10 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 11 - .trainerPic = TRAINER_BACK_PIC_STEVEN, - .encounterMusic_gender = -#line 13 - TRAINER_ENCOUNTER_MUSIC_MALE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 15 - .species = SPECIES_METANG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 19 - .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), -#line 18 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 17 - .lvl = 42, -#line 16 - .nature = NATURE_BRAVE, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 20 - MOVE_LIGHT_SCREEN, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_METAL_CLAW, - }, - }, - { -#line 25 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 29 - .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), -#line 28 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 27 - .lvl = 43, -#line 26 - .nature = NATURE_IMPISH, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 30 - MOVE_TOXIC, - MOVE_AERIAL_ACE, - MOVE_PROTECT, - MOVE_STEEL_WING, - }, - }, - { -#line 35 - .species = SPECIES_AGGRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 39 - .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), -#line 38 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 37 - .lvl = 44, -#line 36 - .nature = NATURE_ADAMANT, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 40 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_SOLAR_BEAM, - MOVE_DRAGON_CLAW, - }, - }, - }, - }, diff --git a/src/data/debug_trainers.h b/src/data/debug_trainers.h deleted file mode 100644 index 0ec683e296..0000000000 --- a/src/data/debug_trainers.h +++ /dev/null @@ -1,132 +0,0 @@ -// -// DO NOT MODIFY THIS FILE! It is auto-generated from src/data/debug_trainers.party -// -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'src/data/debug_trainers.h' to remove #line markers. -// - -#line 1 "src/data/debug_trainers.party" - -#line 14 - [DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER] = - { -#line 15 - .trainerName = _("Player"), -#line 16 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 17 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 19 - TRAINER_ENCOUNTER_MUSIC_MALE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 21 - .nickname = COMPOUND_STRING("Buffie"), -#line 21 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 25 - .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), -#line 24 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 23 - .lvl = 100, -#line 22 - .nature = NATURE_BRAVE, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 26 - MOVE_EARTHQUAKE, - MOVE_FLAMETHROWER, - MOVE_CELEBRATE, - MOVE_CELEBRATE, - }, - }, - }, - }, -#line 31 - [DIFFICULTY_NORMAL][DEBUG_TRAINER_AI] = - { -#line 32 - .trainerName = _("Debugger"), -#line 33 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 35 - .trainerPic = TRAINER_PIC_STEVEN, - .encounterMusic_gender = -#line 37 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 34 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 39 - .species = SPECIES_METANG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 43 - .ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0), -#line 42 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 41 - .lvl = 42, -#line 40 - .nature = NATURE_BRAVE, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 44 - MOVE_LIGHT_SCREEN, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_METAL_CLAW, - }, - }, - { -#line 49 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 53 - .ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252), -#line 52 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 51 - .lvl = 43, -#line 50 - .nature = NATURE_IMPISH, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 54 - MOVE_TOXIC, - MOVE_AERIAL_ACE, - MOVE_PROTECT, - MOVE_STEEL_WING, - }, - }, - { -#line 59 - .species = SPECIES_AGGRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 63 - .ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6), -#line 62 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 61 - .lvl = 44, -#line 60 - .nature = NATURE_ADAMANT, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 64 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_SOLAR_BEAM, - MOVE_DRAGON_CLAW, - }, - }, - }, - }, diff --git a/src/data/trainers.h b/src/data/trainers.h deleted file mode 100644 index 44cb25be75..0000000000 --- a/src/data/trainers.h +++ /dev/null @@ -1,42180 +0,0 @@ -// -// DO NOT MODIFY THIS FILE! It is auto-generated from src/data/trainers.party -// -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'src/data/trainers.h' to remove #line markers. -// - -#line 1 "src/data/trainers.party" - -#line 76 - [DIFFICULTY_NORMAL][TRAINER_NONE] = - { -#line 78 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 79 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 81 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 82 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 0, - .party = (const struct TrainerMon[]) - { - }, - }, -#line 84 - [DIFFICULTY_NORMAL][TRAINER_SAWYER_1] = - { -#line 85 - .trainerName = _("SAWYER"), -#line 86 - .trainerClass = TRAINER_CLASS_HIKER, -#line 87 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 89 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 90 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 91 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 93 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 95 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 94 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 97 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_1] = - { -#line 98 - .trainerName = _("GRUNT"), -#line 99 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 100 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 102 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 103 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 104 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 106 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 108 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 107 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 110 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_2] = - { -#line 111 - .trainerName = _("GRUNT"), -#line 112 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 113 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 115 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 116 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 117 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 119 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 121 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 120 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 123 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 125 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 124 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 127 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_3] = - { -#line 128 - .trainerName = _("GRUNT"), -#line 129 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 130 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 132 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 133 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 134 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 136 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 138 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 137 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 140 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_4] = - { -#line 141 - .trainerName = _("GRUNT"), -#line 142 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 143 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 145 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 146 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 147 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 149 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 151 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 150 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 153 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_1] = - { -#line 154 - .trainerName = _("GRUNT"), -#line 155 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 156 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 158 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 159 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 160 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 162 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 164 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 163 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 166 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_2] = - { -#line 167 - .trainerName = _("GRUNT"), -#line 168 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 169 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 171 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 172 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 173 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 175 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 177 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 176 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 179 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_3] = - { -#line 180 - .trainerName = _("GRUNT"), -#line 181 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 182 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 184 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 185 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 186 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 188 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 190 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 189 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 192 - [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_1] = - { -#line 193 - .trainerName = _("GABRIELLE"), -#line 194 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 195 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 196 -F_TRAINER_FEMALE | -#line 197 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 198 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 199 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 201 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 203 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 202 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 205 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 207 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 206 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 209 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 211 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 210 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 213 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 215 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 214 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 217 - .species = SPECIES_SEEDOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 219 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 218 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 221 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 223 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 222 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 225 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_PETALBURG_WOODS] = - { -#line 226 - .trainerName = _("GRUNT"), -#line 227 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 228 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 230 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 231 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 232 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 234 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 236 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 235 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 238 - [DIFFICULTY_NORMAL][TRAINER_MARCEL] = - { -#line 239 - .trainerName = _("MARCEL"), -#line 240 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 241 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 243 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 244 - .items = { ITEM_HYPER_POTION }, -#line 245 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 246 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 248 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 250 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 249 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 252 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 254 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 253 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 256 - [DIFFICULTY_NORMAL][TRAINER_ALBERTO] = - { -#line 257 - .trainerName = _("ALBERTO"), -#line 258 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 259 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 261 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 262 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 263 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 265 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 267 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 266 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 269 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 271 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 270 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 273 - [DIFFICULTY_NORMAL][TRAINER_ED] = - { -#line 274 - .trainerName = _("ED"), -#line 275 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 276 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 278 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 279 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 280 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 282 - .species = SPECIES_ZANGOOSE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 284 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 283 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 286 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 288 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 287 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 290 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_4] = - { -#line 291 - .trainerName = _("GRUNT"), -#line 292 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 293 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 294 -F_TRAINER_FEMALE | -#line 295 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 296 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 297 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 299 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 301 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 300 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 303 - [DIFFICULTY_NORMAL][TRAINER_DECLAN] = - { -#line 304 - .trainerName = _("DECLAN"), -#line 305 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 306 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 308 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 309 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 310 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 312 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 314 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 313 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 316 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_RUSTURF_TUNNEL] = - { -#line 317 - .trainerName = _("GRUNT"), -#line 318 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 319 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 321 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 322 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 323 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 325 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 327 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 326 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 329 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_1] = - { -#line 330 - .trainerName = _("GRUNT"), -#line 331 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 332 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 334 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 335 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 336 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 338 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 340 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 339 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 342 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 344 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 343 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 346 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_2] = - { -#line 347 - .trainerName = _("GRUNT"), -#line 348 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 349 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 351 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 352 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 353 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 355 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 357 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 356 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 359 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 361 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 360 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 363 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_3] = - { -#line 364 - .trainerName = _("GRUNT"), -#line 365 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 366 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 368 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 369 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 370 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 372 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 374 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 373 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 376 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 378 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 377 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 380 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 382 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 381 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 384 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MUSEUM_1] = - { -#line 385 - .trainerName = _("GRUNT"), -#line 386 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 387 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 389 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 390 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 391 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 393 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 395 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 394 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 397 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MUSEUM_2] = - { -#line 398 - .trainerName = _("GRUNT"), -#line 399 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 400 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 402 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 403 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 404 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 406 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 408 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 407 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 410 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 412 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 411 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 414 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_1] = - { -#line 415 - .trainerName = _("GRUNT"), -#line 416 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 417 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 419 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 420 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 421 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 423 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 425 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 424 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 427 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_1] = - { -#line 428 - .trainerName = _("GRUNT"), -#line 429 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 430 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 432 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 433 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 434 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 436 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 438 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 437 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 440 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_2] = - { -#line 441 - .trainerName = _("GRUNT"), -#line 442 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 443 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 445 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 446 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 447 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 449 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 451 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 450 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 453 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_3] = - { -#line 454 - .trainerName = _("GRUNT"), -#line 455 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 456 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 458 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 459 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 460 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 462 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 464 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 463 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 466 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 468 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 467 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 470 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_4] = - { -#line 471 - .trainerName = _("GRUNT"), -#line 472 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 473 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 474 -F_TRAINER_FEMALE | -#line 475 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 476 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 477 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 479 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 481 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 480 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 483 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_5] = - { -#line 484 - .trainerName = _("GRUNT"), -#line 485 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 486 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 487 -F_TRAINER_FEMALE | -#line 488 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 489 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 490 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 492 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 494 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 493 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 496 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_6] = - { -#line 497 - .trainerName = _("GRUNT"), -#line 498 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 499 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 500 -F_TRAINER_FEMALE | -#line 501 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 502 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 503 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 505 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 507 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 506 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 509 - [DIFFICULTY_NORMAL][TRAINER_FREDRICK] = - { -#line 510 - .trainerName = _("FREDRICK"), -#line 511 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 512 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 514 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 515 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 516 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 518 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 520 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 519 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 522 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 524 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 523 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 526 - [DIFFICULTY_NORMAL][TRAINER_MATT] = - { -#line 527 - .trainerName = _("MATT"), -#line 528 - .trainerClass = TRAINER_CLASS_AQUA_ADMIN, -#line 529 - .trainerPic = TRAINER_PIC_AQUA_ADMIN_M, - .encounterMusic_gender = -#line 531 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 532 - .items = { ITEM_SUPER_POTION }, -#line 533 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 534 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 536 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 538 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 537 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 540 - .species = SPECIES_GOLBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 542 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 541 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 544 - [DIFFICULTY_NORMAL][TRAINER_ZANDER] = - { -#line 545 - .trainerName = _("ZANDER"), -#line 546 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 547 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 549 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 550 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 551 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 553 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 555 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 554 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 557 - [DIFFICULTY_NORMAL][TRAINER_SHELLY_WEATHER_INSTITUTE] = - { -#line 558 - .trainerName = _("SHELLY"), -#line 559 - .trainerClass = TRAINER_CLASS_AQUA_ADMIN, -#line 560 - .trainerPic = TRAINER_PIC_AQUA_ADMIN_F, - .encounterMusic_gender = -#line 561 -F_TRAINER_FEMALE | -#line 562 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 563 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 564 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 566 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 568 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 567 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 570 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 572 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 571 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 574 - [DIFFICULTY_NORMAL][TRAINER_SHELLY_SEAFLOOR_CAVERN] = - { -#line 575 - .trainerName = _("SHELLY"), -#line 576 - .trainerClass = TRAINER_CLASS_AQUA_ADMIN, -#line 577 - .trainerPic = TRAINER_PIC_AQUA_ADMIN_F, - .encounterMusic_gender = -#line 578 -F_TRAINER_FEMALE | -#line 579 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 580 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 581 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 583 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 585 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 584 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 587 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 589 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 588 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 591 - [DIFFICULTY_NORMAL][TRAINER_ARCHIE] = - { -#line 592 - .trainerName = _("ARCHIE"), -#line 593 - .trainerClass = TRAINER_CLASS_AQUA_LEADER, -#line 594 - .trainerPic = TRAINER_PIC_AQUA_LEADER_ARCHIE, - .encounterMusic_gender = -#line 596 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 597 - .items = { ITEM_SUPER_POTION, ITEM_SUPER_POTION }, -#line 598 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 599 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 601 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 603 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 602 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 605 - .species = SPECIES_CROBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 607 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 606 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 609 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 611 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 610 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 613 - [DIFFICULTY_NORMAL][TRAINER_LEAH] = - { -#line 614 - .trainerName = _("LEAH"), -#line 615 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 616 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 617 -F_TRAINER_FEMALE | -#line 618 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 619 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 620 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 622 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 624 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 623 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 626 - [DIFFICULTY_NORMAL][TRAINER_DAISY] = - { -#line 627 - .trainerName = _("DAISY"), -#line 628 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 629 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 630 -F_TRAINER_FEMALE | -#line 631 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 632 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 633 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 635 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 637 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 636 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 639 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 641 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 640 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 643 - [DIFFICULTY_NORMAL][TRAINER_ROSE_1] = - { -#line 644 - .trainerName = _("ROSE"), -#line 645 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 646 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 647 -F_TRAINER_FEMALE | -#line 648 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 649 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 650 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 652 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 654 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 653 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 656 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 658 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 657 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 660 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 662 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 661 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 664 - [DIFFICULTY_NORMAL][TRAINER_FELIX] = - { -#line 665 - .trainerName = _("FELIX"), -#line 666 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 667 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 669 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 670 - .items = { ITEM_FULL_RESTORE }, -#line 671 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 672 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 674 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 676 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 675 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 677 - MOVE_PSYCHIC, - }, - }, - { -#line 679 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 681 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 680 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 682 - MOVE_SKILL_SWAP, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 685 - [DIFFICULTY_NORMAL][TRAINER_VIOLET] = - { -#line 686 - .trainerName = _("VIOLET"), -#line 687 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 688 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 689 -F_TRAINER_FEMALE | -#line 690 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 691 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 692 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 694 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 696 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 695 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 698 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 700 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 699 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 702 - [DIFFICULTY_NORMAL][TRAINER_ROSE_2] = - { -#line 703 - .trainerName = _("ROSE"), -#line 704 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 705 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 706 -F_TRAINER_FEMALE | -#line 707 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 708 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 709 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 711 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 713 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 712 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 715 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 717 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 716 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 719 - [DIFFICULTY_NORMAL][TRAINER_ROSE_3] = - { -#line 720 - .trainerName = _("ROSE"), -#line 721 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 722 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 723 -F_TRAINER_FEMALE | -#line 724 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 725 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 726 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 728 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 730 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 729 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 732 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 734 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 733 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 736 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 738 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 737 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 740 - [DIFFICULTY_NORMAL][TRAINER_ROSE_4] = - { -#line 741 - .trainerName = _("ROSE"), -#line 742 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 743 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 744 -F_TRAINER_FEMALE | -#line 745 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 746 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 747 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 749 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 751 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 750 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 753 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 755 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 754 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 757 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 759 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 758 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 761 - [DIFFICULTY_NORMAL][TRAINER_ROSE_5] = - { -#line 762 - .trainerName = _("ROSE"), -#line 763 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 764 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 765 -F_TRAINER_FEMALE | -#line 766 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 767 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 768 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 770 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 772 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 771 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 774 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 776 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 775 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 778 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 780 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 779 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 782 - [DIFFICULTY_NORMAL][TRAINER_DUSTY_1] = - { -#line 783 - .trainerName = _("DUSTY"), -#line 784 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 785 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 787 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 788 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 789 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 791 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 793 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 792 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 794 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 799 - [DIFFICULTY_NORMAL][TRAINER_CHIP] = - { -#line 800 - .trainerName = _("CHIP"), -#line 801 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 802 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 804 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 805 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 806 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 808 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 810 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 809 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 811 - MOVE_PSYBEAM, - MOVE_SELF_DESTRUCT, - MOVE_SANDSTORM, - MOVE_ANCIENT_POWER, - }, - }, - { -#line 816 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 818 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 817 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 819 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - { -#line 824 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 826 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 825 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 827 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 832 - [DIFFICULTY_NORMAL][TRAINER_FOSTER] = - { -#line 833 - .trainerName = _("FOSTER"), -#line 834 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 835 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 837 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 838 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 839 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 841 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 843 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 842 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 844 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - { -#line 849 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 851 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 850 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 852 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 857 - [DIFFICULTY_NORMAL][TRAINER_DUSTY_2] = - { -#line 858 - .trainerName = _("DUSTY"), -#line 859 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 860 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 862 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 863 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 864 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 866 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 868 - .iv = TRAINER_PARTY_IVS(7, 7, 7, 7, 7, 7), -#line 867 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 869 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 874 - [DIFFICULTY_NORMAL][TRAINER_DUSTY_3] = - { -#line 875 - .trainerName = _("DUSTY"), -#line 876 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 877 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 879 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 880 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 881 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 883 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 885 - .iv = TRAINER_PARTY_IVS(8, 8, 8, 8, 8, 8), -#line 884 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 886 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 891 - [DIFFICULTY_NORMAL][TRAINER_DUSTY_4] = - { -#line 892 - .trainerName = _("DUSTY"), -#line 893 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 894 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 896 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 897 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 898 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 900 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 902 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 901 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 903 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 908 - [DIFFICULTY_NORMAL][TRAINER_DUSTY_5] = - { -#line 909 - .trainerName = _("DUSTY"), -#line 910 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 911 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 913 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 914 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 915 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 917 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 919 - .iv = TRAINER_PARTY_IVS(10, 10, 10, 10, 10, 10), -#line 918 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 920 - MOVE_DIG, - MOVE_SLASH, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - }, - }, - }, - }, -#line 925 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_1] = - { -#line 926 - .trainerName = _("GABBY & TY"), -#line 927 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 928 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 930 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 931 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 932 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 934 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 936 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 935 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 938 - .species = SPECIES_WHISMUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 940 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 939 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 942 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_2] = - { -#line 943 - .trainerName = _("GABBY & TY"), -#line 944 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 945 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 947 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 948 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 949 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 951 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 953 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 952 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 955 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 957 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 956 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 959 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_3] = - { -#line 960 - .trainerName = _("GABBY & TY"), -#line 961 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 962 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 964 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 965 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 966 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 968 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 970 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 969 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 972 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 974 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 973 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 976 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_4] = - { -#line 977 - .trainerName = _("GABBY & TY"), -#line 978 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 979 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 981 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 982 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 983 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 985 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 987 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 986 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 989 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 991 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 990 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 993 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_5] = - { -#line 994 - .trainerName = _("GABBY & TY"), -#line 995 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 996 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 998 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 999 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 1000 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1002 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1004 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 1003 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1006 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1008 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 1007 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1010 - [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_6] = - { -#line 1011 - .trainerName = _("GABBY & TY"), -#line 1012 - .trainerClass = TRAINER_CLASS_INTERVIEWER, -#line 1013 - .trainerPic = TRAINER_PIC_INTERVIEWER, - .encounterMusic_gender = -#line 1015 - TRAINER_ENCOUNTER_MUSIC_INTERVIEWER, -#line 1016 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 1017 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1019 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1021 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 1020 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1022 - MOVE_SONIC_BOOM, - MOVE_THUNDER_WAVE, - MOVE_METAL_SOUND, - MOVE_THUNDERBOLT, - }, - }, - { -#line 1027 - .species = SPECIES_EXPLOUD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1029 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 1028 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1030 - MOVE_ASTONISH, - MOVE_STOMP, - MOVE_SUPERSONIC, - MOVE_HYPER_VOICE, - }, - }, - }, - }, -#line 1035 - [DIFFICULTY_NORMAL][TRAINER_LOLA_1] = - { -#line 1036 - .trainerName = _("LOLA"), -#line 1037 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1038 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1039 -F_TRAINER_FEMALE | -#line 1040 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1041 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1042 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1044 - .species = SPECIES_AZURILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1046 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1045 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1048 - .species = SPECIES_AZURILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1050 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1049 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1052 - [DIFFICULTY_NORMAL][TRAINER_AUSTINA] = - { -#line 1053 - .trainerName = _("AUSTINA"), -#line 1054 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1055 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1056 -F_TRAINER_FEMALE | -#line 1057 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1058 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1059 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1061 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1063 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1062 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1065 - [DIFFICULTY_NORMAL][TRAINER_GWEN] = - { -#line 1066 - .trainerName = _("GWEN"), -#line 1067 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1068 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1069 -F_TRAINER_FEMALE | -#line 1070 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1071 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1072 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1074 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1076 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1075 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1078 - [DIFFICULTY_NORMAL][TRAINER_LOLA_2] = - { -#line 1079 - .trainerName = _("LOLA"), -#line 1080 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1081 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1082 -F_TRAINER_FEMALE | -#line 1083 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1084 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1085 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1087 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1089 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1088 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1091 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1093 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1092 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1095 - [DIFFICULTY_NORMAL][TRAINER_LOLA_3] = - { -#line 1096 - .trainerName = _("LOLA"), -#line 1097 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1098 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1099 -F_TRAINER_FEMALE | -#line 1100 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1101 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1102 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1104 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1106 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 1105 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1108 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1110 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 1109 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1112 - [DIFFICULTY_NORMAL][TRAINER_LOLA_4] = - { -#line 1113 - .trainerName = _("LOLA"), -#line 1114 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1115 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1116 -F_TRAINER_FEMALE | -#line 1117 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1118 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1119 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1121 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1123 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 1122 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1125 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1127 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 1126 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1129 - [DIFFICULTY_NORMAL][TRAINER_LOLA_5] = - { -#line 1130 - .trainerName = _("LOLA"), -#line 1131 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 1132 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 1133 -F_TRAINER_FEMALE | -#line 1134 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1135 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1136 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1138 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1140 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 1139 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1142 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1144 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 1143 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1146 - [DIFFICULTY_NORMAL][TRAINER_RICKY_1] = - { -#line 1147 - .trainerName = _("RICKY"), -#line 1148 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1149 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1151 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1152 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1153 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1155 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1157 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1156 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1158 - MOVE_SAND_ATTACK, - MOVE_HEADBUTT, - MOVE_TAIL_WHIP, - MOVE_SURF, - }, - }, - }, - }, -#line 1163 - [DIFFICULTY_NORMAL][TRAINER_SIMON] = - { -#line 1164 - .trainerName = _("SIMON"), -#line 1165 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1166 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1168 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1169 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1170 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1172 - .species = SPECIES_AZURILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1174 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1173 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1176 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1178 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1177 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1180 - [DIFFICULTY_NORMAL][TRAINER_CHARLIE] = - { -#line 1181 - .trainerName = _("CHARLIE"), -#line 1182 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1183 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1185 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1186 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1187 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1189 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1191 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1190 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1193 - [DIFFICULTY_NORMAL][TRAINER_RICKY_2] = - { -#line 1194 - .trainerName = _("RICKY"), -#line 1195 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1196 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1198 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1199 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1200 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1202 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1204 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 1203 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1205 - MOVE_SAND_ATTACK, - MOVE_PIN_MISSILE, - MOVE_TAIL_WHIP, - MOVE_SURF, - }, - }, - }, - }, -#line 1210 - [DIFFICULTY_NORMAL][TRAINER_RICKY_3] = - { -#line 1211 - .trainerName = _("RICKY"), -#line 1212 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1213 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1215 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1216 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1217 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1219 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1221 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 1220 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1222 - MOVE_SAND_ATTACK, - MOVE_PIN_MISSILE, - MOVE_TAIL_WHIP, - MOVE_SURF, - }, - }, - }, - }, -#line 1227 - [DIFFICULTY_NORMAL][TRAINER_RICKY_4] = - { -#line 1228 - .trainerName = _("RICKY"), -#line 1229 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1230 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1232 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1233 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1234 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1236 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1238 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 1237 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1239 - MOVE_SAND_ATTACK, - MOVE_PIN_MISSILE, - MOVE_TAIL_WHIP, - MOVE_SURF, - }, - }, - }, - }, -#line 1244 - [DIFFICULTY_NORMAL][TRAINER_RICKY_5] = - { -#line 1245 - .trainerName = _("RICKY"), -#line 1246 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 1247 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 1249 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 1250 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1251 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1253 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1255 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 1254 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1256 - MOVE_SAND_ATTACK, - MOVE_PIN_MISSILE, - MOVE_TAIL_WHIP, - MOVE_SURF, - }, - }, - }, - }, -#line 1261 - [DIFFICULTY_NORMAL][TRAINER_RANDALL] = - { -#line 1262 - .trainerName = _("RANDALL"), -#line 1263 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1264 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1266 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1267 - .items = { ITEM_HYPER_POTION }, -#line 1268 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1269 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1271 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1273 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1272 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1274 - MOVE_QUICK_ATTACK, - MOVE_AGILITY, - MOVE_WING_ATTACK, - }, - }, - }, - }, -#line 1278 - [DIFFICULTY_NORMAL][TRAINER_PARKER] = - { -#line 1279 - .trainerName = _("PARKER"), -#line 1280 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1281 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1283 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1284 - .items = { ITEM_HYPER_POTION }, -#line 1285 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1286 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1288 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1290 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1289 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1291 - MOVE_TEETER_DANCE, - MOVE_DIZZY_PUNCH, - MOVE_FOCUS_PUNCH, - }, - }, - }, - }, -#line 1295 - [DIFFICULTY_NORMAL][TRAINER_GEORGE] = - { -#line 1296 - .trainerName = _("GEORGE"), -#line 1297 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1298 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1300 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1301 - .items = { ITEM_HYPER_POTION }, -#line 1302 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1303 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1305 - .species = SPECIES_SLAKOTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1305 - .heldItem = ITEM_SITRUS_BERRY, -#line 1307 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1306 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1308 - MOVE_SLACK_OFF, - MOVE_COUNTER, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 1312 - [DIFFICULTY_NORMAL][TRAINER_BERKE] = - { -#line 1313 - .trainerName = _("BERKE"), -#line 1314 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1315 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1317 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1318 - .items = { ITEM_HYPER_POTION }, -#line 1319 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1320 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1322 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1324 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1323 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1325 - MOVE_FOCUS_ENERGY, - MOVE_SLASH, - }, - }, - }, - }, -#line 1328 - [DIFFICULTY_NORMAL][TRAINER_BRAXTON] = - { -#line 1329 - .trainerName = _("BRAXTON"), -#line 1330 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1331 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1333 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1334 - .items = { ITEM_HYPER_POTION }, -#line 1335 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1336 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 1338 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1340 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1339 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1341 - MOVE_FOCUS_ENERGY, - MOVE_QUICK_ATTACK, - MOVE_WING_ATTACK, - MOVE_ENDEAVOR, - }, - }, - { -#line 1346 - .species = SPECIES_TRAPINCH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1348 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1347 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1349 - MOVE_BITE, - MOVE_DIG, - MOVE_FEINT_ATTACK, - MOVE_SAND_TOMB, - }, - }, - { -#line 1354 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1356 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1355 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1357 - MOVE_ROLLOUT, - MOVE_WHIRLPOOL, - MOVE_ASTONISH, - MOVE_WATER_PULSE, - }, - }, - { -#line 1362 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1364 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1363 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1365 - MOVE_THUNDERBOLT, - MOVE_SUPERSONIC, - MOVE_THUNDER_WAVE, - MOVE_SONIC_BOOM, - }, - }, - { -#line 1370 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1372 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1371 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1373 - MOVE_GIGA_DRAIN, - MOVE_FEINT_ATTACK, - MOVE_DOUBLE_TEAM, - MOVE_SWAGGER, - }, - }, - }, - }, -#line 1378 - [DIFFICULTY_NORMAL][TRAINER_VINCENT] = - { -#line 1379 - .trainerName = _("VINCENT"), -#line 1380 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1381 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1383 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1384 - .items = { ITEM_FULL_RESTORE }, -#line 1385 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1386 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1388 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1390 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1389 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1392 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1394 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1393 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1396 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1398 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1397 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1400 - [DIFFICULTY_NORMAL][TRAINER_LEROY] = - { -#line 1401 - .trainerName = _("LEROY"), -#line 1402 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1403 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1405 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1406 - .items = { ITEM_FULL_RESTORE }, -#line 1407 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1408 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1410 - .species = SPECIES_MAWILE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1412 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1411 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1414 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1416 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1415 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1418 - [DIFFICULTY_NORMAL][TRAINER_WILTON_1] = - { -#line 1419 - .trainerName = _("WILTON"), -#line 1420 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1421 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1423 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1424 - .items = { ITEM_SUPER_POTION }, -#line 1425 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1426 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1428 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1430 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1429 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1432 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1434 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1433 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1436 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1438 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1437 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1440 - [DIFFICULTY_NORMAL][TRAINER_EDGAR] = - { -#line 1441 - .trainerName = _("EDGAR"), -#line 1442 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1443 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1445 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1446 - .items = { ITEM_FULL_RESTORE }, -#line 1447 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1448 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1450 - .species = SPECIES_CACTURNE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1452 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1451 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1454 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1456 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1455 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1458 - [DIFFICULTY_NORMAL][TRAINER_ALBERT] = - { -#line 1459 - .trainerName = _("ALBERT"), -#line 1460 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1461 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1463 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1464 - .items = { ITEM_FULL_RESTORE }, -#line 1465 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1466 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1468 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1470 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1469 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1472 - .species = SPECIES_MUK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1474 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1473 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1476 - [DIFFICULTY_NORMAL][TRAINER_SAMUEL] = - { -#line 1477 - .trainerName = _("SAMUEL"), -#line 1478 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1479 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1481 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1482 - .items = { ITEM_FULL_RESTORE }, -#line 1483 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1484 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1486 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1488 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1487 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1490 - .species = SPECIES_MAWILE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1492 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1491 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1494 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1496 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1495 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1498 - [DIFFICULTY_NORMAL][TRAINER_VITO] = - { -#line 1499 - .trainerName = _("VITO"), -#line 1500 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1501 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1503 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1504 - .items = { ITEM_FULL_RESTORE }, -#line 1505 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1506 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 1508 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1510 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1509 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1512 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1514 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1513 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1516 - .species = SPECIES_ELECTRODE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1518 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1517 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1520 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1522 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1521 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1524 - [DIFFICULTY_NORMAL][TRAINER_OWEN] = - { -#line 1525 - .trainerName = _("OWEN"), -#line 1526 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1527 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1529 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1530 - .items = { ITEM_FULL_RESTORE }, -#line 1531 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1532 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1534 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1536 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1535 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1538 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1540 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1539 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1542 - .species = SPECIES_WAILORD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1544 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1543 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1546 - [DIFFICULTY_NORMAL][TRAINER_WILTON_2] = - { -#line 1547 - .trainerName = _("WILTON"), -#line 1548 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1549 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1551 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1552 - .items = { ITEM_HYPER_POTION }, -#line 1553 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1554 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1556 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1558 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1557 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1560 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1562 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1561 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1564 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1566 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1565 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1568 - [DIFFICULTY_NORMAL][TRAINER_WILTON_3] = - { -#line 1569 - .trainerName = _("WILTON"), -#line 1570 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1571 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1573 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1574 - .items = { ITEM_HYPER_POTION }, -#line 1575 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1576 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1578 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1580 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1579 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1582 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1584 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1583 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1586 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1588 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1587 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1590 - [DIFFICULTY_NORMAL][TRAINER_WILTON_4] = - { -#line 1591 - .trainerName = _("WILTON"), -#line 1592 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1593 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1595 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1596 - .items = { ITEM_FULL_RESTORE }, -#line 1597 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1598 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1600 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1602 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1601 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1604 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1606 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1605 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1608 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1610 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1609 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1612 - [DIFFICULTY_NORMAL][TRAINER_WILTON_5] = - { -#line 1613 - .trainerName = _("WILTON"), -#line 1614 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1615 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1617 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1618 - .items = { ITEM_FULL_RESTORE }, -#line 1619 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1620 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1622 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1624 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1623 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1626 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1628 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1627 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1630 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1632 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1631 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1634 - [DIFFICULTY_NORMAL][TRAINER_WARREN] = - { -#line 1635 - .trainerName = _("WARREN"), -#line 1636 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1637 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 1639 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1640 - .items = { ITEM_FULL_RESTORE }, -#line 1641 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1642 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1644 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1646 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1645 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1648 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1650 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1649 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1652 - [DIFFICULTY_NORMAL][TRAINER_MARY] = - { -#line 1653 - .trainerName = _("MARY"), -#line 1654 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1655 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1656 -F_TRAINER_FEMALE | -#line 1657 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1658 - .items = { ITEM_HYPER_POTION }, -#line 1659 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1660 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1662 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1664 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1663 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1665 - MOVE_FEINT_ATTACK, - MOVE_SHOCK_WAVE, - }, - }, - }, - }, -#line 1668 - [DIFFICULTY_NORMAL][TRAINER_ALEXIA] = - { -#line 1669 - .trainerName = _("ALEXIA"), -#line 1670 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1671 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1672 -F_TRAINER_FEMALE | -#line 1673 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1674 - .items = { ITEM_HYPER_POTION }, -#line 1675 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1676 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1678 - .species = SPECIES_WIGGLYTUFF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1680 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1679 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1681 - MOVE_DEFENSE_CURL, - MOVE_DOUBLE_EDGE, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 1685 - [DIFFICULTY_NORMAL][TRAINER_JODY] = - { -#line 1686 - .trainerName = _("JODY"), -#line 1687 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1688 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1689 -F_TRAINER_FEMALE | -#line 1690 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1691 - .items = { ITEM_HYPER_POTION }, -#line 1692 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1693 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1695 - .species = SPECIES_ZANGOOSE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1697 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 1696 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1698 - MOVE_SWORDS_DANCE, - MOVE_SLASH, - }, - }, - }, - }, -#line 1701 - [DIFFICULTY_NORMAL][TRAINER_WENDY] = - { -#line 1702 - .trainerName = _("WENDY"), -#line 1703 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1704 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1705 -F_TRAINER_FEMALE | -#line 1706 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1707 - .items = { ITEM_FULL_RESTORE }, -#line 1708 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1709 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1711 - .species = SPECIES_MAWILE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1713 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1712 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1714 - MOVE_BATON_PASS, - MOVE_FEINT_ATTACK, - MOVE_FAKE_TEARS, - MOVE_BITE, - }, - }, - { -#line 1719 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1721 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1720 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1722 - MOVE_MEGA_DRAIN, - MOVE_MAGICAL_LEAF, - MOVE_GRASS_WHISTLE, - MOVE_LEECH_SEED, - }, - }, - { -#line 1727 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1729 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1728 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 1730 - MOVE_FLY, - MOVE_WATER_GUN, - MOVE_MIST, - MOVE_PROTECT, - }, - }, - }, - }, -#line 1735 - [DIFFICULTY_NORMAL][TRAINER_KEIRA] = - { -#line 1736 - .trainerName = _("KEIRA"), -#line 1737 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1738 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1739 -F_TRAINER_FEMALE | -#line 1740 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1741 - .items = { ITEM_FULL_RESTORE }, -#line 1742 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1743 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1745 - .species = SPECIES_LAIRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1747 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1746 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1749 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1751 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1750 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1753 - [DIFFICULTY_NORMAL][TRAINER_BROOKE_1] = - { -#line 1754 - .trainerName = _("BROOKE"), -#line 1755 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1756 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1757 -F_TRAINER_FEMALE | -#line 1758 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1759 - .items = { ITEM_SUPER_POTION }, -#line 1760 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1761 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1763 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1765 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1764 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1767 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1769 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1768 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1771 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1773 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1772 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1775 - [DIFFICULTY_NORMAL][TRAINER_JENNIFER] = - { -#line 1776 - .trainerName = _("JENNIFER"), -#line 1777 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1778 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1779 -F_TRAINER_FEMALE | -#line 1780 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1781 - .items = { ITEM_FULL_RESTORE }, -#line 1782 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1783 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1785 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1787 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 1786 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1789 - [DIFFICULTY_NORMAL][TRAINER_HOPE] = - { -#line 1790 - .trainerName = _("HOPE"), -#line 1791 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1792 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1793 -F_TRAINER_FEMALE | -#line 1794 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1795 - .items = { ITEM_FULL_RESTORE }, -#line 1796 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1797 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1799 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1801 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1800 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1803 - [DIFFICULTY_NORMAL][TRAINER_SHANNON] = - { -#line 1804 - .trainerName = _("SHANNON"), -#line 1805 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1806 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1807 -F_TRAINER_FEMALE | -#line 1808 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1809 - .items = { ITEM_FULL_RESTORE }, -#line 1810 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1811 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 1813 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1815 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1814 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1817 - [DIFFICULTY_NORMAL][TRAINER_MICHELLE] = - { -#line 1818 - .trainerName = _("MICHELLE"), -#line 1819 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1820 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1821 -F_TRAINER_FEMALE | -#line 1822 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1823 - .items = { ITEM_FULL_RESTORE }, -#line 1824 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1825 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1827 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1829 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1828 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1831 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1833 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1832 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1835 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1837 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1836 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1839 - [DIFFICULTY_NORMAL][TRAINER_CAROLINE] = - { -#line 1840 - .trainerName = _("CAROLINE"), -#line 1841 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1842 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1843 -F_TRAINER_FEMALE | -#line 1844 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1845 - .items = { ITEM_FULL_RESTORE }, -#line 1846 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1847 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1849 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1851 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1850 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1853 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1855 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1854 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1857 - [DIFFICULTY_NORMAL][TRAINER_JULIE] = - { -#line 1858 - .trainerName = _("JULIE"), -#line 1859 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1860 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1861 -F_TRAINER_FEMALE | -#line 1862 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1863 - .items = { ITEM_FULL_RESTORE }, -#line 1864 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1865 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1867 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1869 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1868 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1871 - .species = SPECIES_NINETALES, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1873 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1872 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1875 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1877 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 1876 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1879 - [DIFFICULTY_NORMAL][TRAINER_BROOKE_2] = - { -#line 1880 - .trainerName = _("BROOKE"), -#line 1881 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1882 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1883 -F_TRAINER_FEMALE | -#line 1884 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1885 - .items = { ITEM_HYPER_POTION }, -#line 1886 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1887 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1889 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1891 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1890 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1893 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1895 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1894 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1897 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1899 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 1898 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1901 - [DIFFICULTY_NORMAL][TRAINER_BROOKE_3] = - { -#line 1902 - .trainerName = _("BROOKE"), -#line 1903 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1904 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1905 -F_TRAINER_FEMALE | -#line 1906 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1907 - .items = { ITEM_HYPER_POTION }, -#line 1908 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1909 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1911 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1913 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1912 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1915 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1917 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1916 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1919 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1921 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 1920 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1923 - [DIFFICULTY_NORMAL][TRAINER_BROOKE_4] = - { -#line 1924 - .trainerName = _("BROOKE"), -#line 1925 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1926 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1927 -F_TRAINER_FEMALE | -#line 1928 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1929 - .items = { ITEM_FULL_RESTORE }, -#line 1930 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1931 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1933 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1935 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1934 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1937 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1939 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1938 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1941 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1943 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 1942 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1945 - [DIFFICULTY_NORMAL][TRAINER_BROOKE_5] = - { -#line 1946 - .trainerName = _("BROOKE"), -#line 1947 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 1948 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 1949 -F_TRAINER_FEMALE | -#line 1950 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 1951 - .items = { ITEM_FULL_RESTORE }, -#line 1952 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1953 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 1955 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1957 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1956 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1959 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1961 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1960 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1963 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1965 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 1964 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1967 - [DIFFICULTY_NORMAL][TRAINER_PATRICIA] = - { -#line 1968 - .trainerName = _("PATRICIA"), -#line 1969 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 1970 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 1971 -F_TRAINER_FEMALE | -#line 1972 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 1973 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1974 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1976 - .species = SPECIES_BANETTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1978 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1977 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1980 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1982 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1981 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 1984 - [DIFFICULTY_NORMAL][TRAINER_KINDRA] = - { -#line 1985 - .trainerName = _("KINDRA"), -#line 1986 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 1987 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 1988 -F_TRAINER_FEMALE | -#line 1989 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 1990 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 1991 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 1993 - .species = SPECIES_DUSKULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1995 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1994 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 1997 - .species = SPECIES_SHUPPET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 1999 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 1998 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2001 - [DIFFICULTY_NORMAL][TRAINER_TAMMY] = - { -#line 2002 - .trainerName = _("TAMMY"), -#line 2003 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2004 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2005 -F_TRAINER_FEMALE | -#line 2006 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2007 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2008 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2010 - .species = SPECIES_DUSKULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2012 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2011 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2014 - .species = SPECIES_SHUPPET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2016 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2015 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2018 - [DIFFICULTY_NORMAL][TRAINER_VALERIE_1] = - { -#line 2019 - .trainerName = _("VALERIE"), -#line 2020 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2021 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2022 -F_TRAINER_FEMALE | -#line 2023 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2024 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2025 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2027 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2029 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2028 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2031 - [DIFFICULTY_NORMAL][TRAINER_TASHA] = - { -#line 2032 - .trainerName = _("TASHA"), -#line 2033 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2034 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2035 -F_TRAINER_FEMALE | -#line 2036 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2037 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2038 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2040 - .species = SPECIES_SHUPPET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2042 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 2041 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2044 - [DIFFICULTY_NORMAL][TRAINER_VALERIE_2] = - { -#line 2045 - .trainerName = _("VALERIE"), -#line 2046 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2047 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2048 -F_TRAINER_FEMALE | -#line 2049 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2050 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2051 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2053 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2055 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2054 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2057 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2059 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2058 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2061 - [DIFFICULTY_NORMAL][TRAINER_VALERIE_3] = - { -#line 2062 - .trainerName = _("VALERIE"), -#line 2063 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2064 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2065 -F_TRAINER_FEMALE | -#line 2066 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2067 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2068 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2070 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2072 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2071 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2074 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2076 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2075 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2078 - [DIFFICULTY_NORMAL][TRAINER_VALERIE_4] = - { -#line 2079 - .trainerName = _("VALERIE"), -#line 2080 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2081 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2082 -F_TRAINER_FEMALE | -#line 2083 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2084 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2085 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2087 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2089 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2088 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2091 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2093 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2092 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2095 - [DIFFICULTY_NORMAL][TRAINER_VALERIE_5] = - { -#line 2096 - .trainerName = _("VALERIE"), -#line 2097 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 2098 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 2099 -F_TRAINER_FEMALE | -#line 2100 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2101 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2102 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 2104 - .species = SPECIES_DUSKULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2106 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2105 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2108 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2110 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2109 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2112 - .species = SPECIES_GRUMPIG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2114 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2113 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2116 - [DIFFICULTY_NORMAL][TRAINER_CINDY_1] = - { -#line 2117 - .trainerName = _("CINDY"), -#line 2118 - .trainerClass = TRAINER_CLASS_LADY, -#line 2119 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2120 -F_TRAINER_FEMALE | -#line 2121 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2122 - .items = { ITEM_FULL_RESTORE }, -#line 2123 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2124 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2126 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2126 - .heldItem = ITEM_NUGGET, -#line 2128 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2127 - .lvl = 7, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2130 - [DIFFICULTY_NORMAL][TRAINER_DAPHNE] = - { -#line 2131 - .trainerName = _("DAPHNE"), -#line 2132 - .trainerClass = TRAINER_CLASS_LADY, -#line 2133 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2134 -F_TRAINER_FEMALE | -#line 2135 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2136 - .items = { ITEM_FULL_RESTORE }, -#line 2137 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2138 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2140 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2140 - .heldItem = ITEM_NUGGET, -#line 2142 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2141 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2143 - MOVE_ATTRACT, - MOVE_SWEET_KISS, - MOVE_FLAIL, - MOVE_WATER_PULSE, - }, - }, - { -#line 2148 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2148 - .heldItem = ITEM_NUGGET, -#line 2150 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2149 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2151 - MOVE_ATTRACT, - MOVE_SAFEGUARD, - MOVE_TAKE_DOWN, - MOVE_WATER_PULSE, - }, - }, - }, - }, -#line 2156 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_2] = - { -#line 2157 - .trainerName = _("GRUNT"), -#line 2158 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 2159 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 2161 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 2162 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2163 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 2165 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2167 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2166 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2169 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2171 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2170 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2173 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2175 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2174 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2177 - [DIFFICULTY_NORMAL][TRAINER_CINDY_2] = - { -#line 2178 - .trainerName = _("CINDY"), -#line 2179 - .trainerClass = TRAINER_CLASS_LADY, -#line 2180 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2181 -F_TRAINER_FEMALE | -#line 2182 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2183 - .items = { ITEM_FULL_RESTORE }, -#line 2184 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2185 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2187 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2187 - .heldItem = ITEM_NUGGET, -#line 2189 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2188 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2190 - MOVE_TACKLE, - MOVE_TAIL_WHIP, - }, - }, - }, - }, -#line 2193 - [DIFFICULTY_NORMAL][TRAINER_BRIANNA] = - { -#line 2194 - .trainerName = _("BRIANNA"), -#line 2195 - .trainerClass = TRAINER_CLASS_LADY, -#line 2196 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2197 -F_TRAINER_FEMALE | -#line 2198 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2199 - .items = { ITEM_FULL_RESTORE }, -#line 2200 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2201 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2203 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2203 - .heldItem = ITEM_NUGGET, -#line 2205 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 2204 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2207 - [DIFFICULTY_NORMAL][TRAINER_NAOMI] = - { -#line 2208 - .trainerName = _("NAOMI"), -#line 2209 - .trainerClass = TRAINER_CLASS_LADY, -#line 2210 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2211 -F_TRAINER_FEMALE | -#line 2212 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2213 - .items = { ITEM_FULL_RESTORE }, -#line 2214 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2215 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2217 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2217 - .heldItem = ITEM_NUGGET, -#line 2219 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2218 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2221 - [DIFFICULTY_NORMAL][TRAINER_CINDY_3] = - { -#line 2222 - .trainerName = _("CINDY"), -#line 2223 - .trainerClass = TRAINER_CLASS_LADY, -#line 2224 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2225 -F_TRAINER_FEMALE | -#line 2226 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2227 - .items = { ITEM_FULL_RESTORE }, -#line 2228 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2229 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2231 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2231 - .heldItem = ITEM_NUGGET, -#line 2233 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2232 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2235 - [DIFFICULTY_NORMAL][TRAINER_CINDY_4] = - { -#line 2236 - .trainerName = _("CINDY"), -#line 2237 - .trainerClass = TRAINER_CLASS_LADY, -#line 2238 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2239 -F_TRAINER_FEMALE | -#line 2240 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2241 - .items = { ITEM_FULL_RESTORE }, -#line 2242 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2243 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2245 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2245 - .heldItem = ITEM_NUGGET, -#line 2247 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2246 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2249 - [DIFFICULTY_NORMAL][TRAINER_CINDY_5] = - { -#line 2250 - .trainerName = _("CINDY"), -#line 2251 - .trainerClass = TRAINER_CLASS_LADY, -#line 2252 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2253 -F_TRAINER_FEMALE | -#line 2254 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2255 - .items = { ITEM_FULL_RESTORE }, -#line 2256 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2257 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2259 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2259 - .heldItem = ITEM_NUGGET, -#line 2261 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2260 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2263 - [DIFFICULTY_NORMAL][TRAINER_CINDY_6] = - { -#line 2264 - .trainerName = _("CINDY"), -#line 2265 - .trainerClass = TRAINER_CLASS_LADY, -#line 2266 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 2267 -F_TRAINER_FEMALE | -#line 2268 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2269 - .items = { ITEM_FULL_RESTORE }, -#line 2270 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2271 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2273 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2273 - .heldItem = ITEM_NUGGET, -#line 2275 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2274 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2276 - MOVE_FURY_SWIPES, - MOVE_MUD_SPORT, - MOVE_ODOR_SLEUTH, - MOVE_SAND_ATTACK, - }, - }, - }, - }, -#line 2281 - [DIFFICULTY_NORMAL][TRAINER_MELISSA] = - { -#line 2282 - .trainerName = _("MELISSA"), -#line 2283 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2284 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2285 -F_TRAINER_FEMALE | -#line 2286 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2287 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2288 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2290 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2292 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2291 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2294 - [DIFFICULTY_NORMAL][TRAINER_SHEILA] = - { -#line 2295 - .trainerName = _("SHEILA"), -#line 2296 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2297 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2298 -F_TRAINER_FEMALE | -#line 2299 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2300 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2301 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2303 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2305 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2304 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2307 - [DIFFICULTY_NORMAL][TRAINER_SHIRLEY] = - { -#line 2308 - .trainerName = _("SHIRLEY"), -#line 2309 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2310 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2311 -F_TRAINER_FEMALE | -#line 2312 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2313 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2314 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2316 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2318 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2317 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2320 - [DIFFICULTY_NORMAL][TRAINER_JESSICA_1] = - { -#line 2321 - .trainerName = _("JESSICA"), -#line 2322 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2323 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2324 -F_TRAINER_FEMALE | -#line 2325 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2326 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2327 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2329 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2331 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2330 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2332 - MOVE_BIND, - MOVE_LICK, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 2337 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2339 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2338 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2340 - MOVE_POISON_TAIL, - MOVE_SCREECH, - MOVE_GLARE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 2345 - [DIFFICULTY_NORMAL][TRAINER_CONNIE] = - { -#line 2346 - .trainerName = _("CONNIE"), -#line 2347 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2348 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2349 -F_TRAINER_FEMALE | -#line 2350 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2351 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2352 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2354 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2356 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2355 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2358 - [DIFFICULTY_NORMAL][TRAINER_BRIDGET] = - { -#line 2359 - .trainerName = _("BRIDGET"), -#line 2360 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2361 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2362 -F_TRAINER_FEMALE | -#line 2363 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2364 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2365 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2367 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2369 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 2368 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2371 - [DIFFICULTY_NORMAL][TRAINER_OLIVIA] = - { -#line 2372 - .trainerName = _("OLIVIA"), -#line 2373 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2374 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2375 -F_TRAINER_FEMALE | -#line 2376 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2377 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2378 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 2380 - .species = SPECIES_CLAMPERL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2382 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2381 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2383 - MOVE_IRON_DEFENSE, - MOVE_WHIRLPOOL, - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - }, - }, - { -#line 2388 - .species = SPECIES_CORPHISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2390 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2389 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2391 - MOVE_TAUNT, - MOVE_CRABHAMMER, - MOVE_WATER_PULSE, - }, - }, - { -#line 2395 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2397 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2396 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2398 - MOVE_UPROAR, - MOVE_FURY_SWIPES, - MOVE_FAKE_OUT, - MOVE_WATER_PULSE, - }, - }, - }, - }, -#line 2403 - [DIFFICULTY_NORMAL][TRAINER_TIFFANY] = - { -#line 2404 - .trainerName = _("TIFFANY"), -#line 2405 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2406 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2407 -F_TRAINER_FEMALE | -#line 2408 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2409 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2410 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2412 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2414 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2413 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2416 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2418 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 2417 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2420 - [DIFFICULTY_NORMAL][TRAINER_JESSICA_2] = - { -#line 2421 - .trainerName = _("JESSICA"), -#line 2422 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2423 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2424 -F_TRAINER_FEMALE | -#line 2425 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2426 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2427 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2429 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2431 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2430 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2432 - MOVE_BIND, - MOVE_LICK, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 2437 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2439 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2438 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2440 - MOVE_POISON_TAIL, - MOVE_SCREECH, - MOVE_GLARE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 2445 - [DIFFICULTY_NORMAL][TRAINER_JESSICA_3] = - { -#line 2446 - .trainerName = _("JESSICA"), -#line 2447 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2448 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2449 -F_TRAINER_FEMALE | -#line 2450 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2451 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2452 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2454 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2456 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2455 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2457 - MOVE_BIND, - MOVE_LICK, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 2462 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2464 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2463 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2465 - MOVE_POISON_TAIL, - MOVE_SCREECH, - MOVE_GLARE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 2470 - [DIFFICULTY_NORMAL][TRAINER_JESSICA_4] = - { -#line 2471 - .trainerName = _("JESSICA"), -#line 2472 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2473 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2474 -F_TRAINER_FEMALE | -#line 2475 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2476 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2477 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2479 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2481 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2480 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2482 - MOVE_BIND, - MOVE_LICK, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 2487 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2489 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2488 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2490 - MOVE_POISON_TAIL, - MOVE_SCREECH, - MOVE_GLARE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 2495 - [DIFFICULTY_NORMAL][TRAINER_JESSICA_5] = - { -#line 2496 - .trainerName = _("JESSICA"), -#line 2497 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2498 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2499 -F_TRAINER_FEMALE | -#line 2500 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2501 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2502 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2504 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2506 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2505 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2507 - MOVE_BIND, - MOVE_LICK, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 2512 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2514 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2513 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2515 - MOVE_POISON_TAIL, - MOVE_SCREECH, - MOVE_GLARE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 2520 - [DIFFICULTY_NORMAL][TRAINER_WINSTON_1] = - { -#line 2521 - .trainerName = _("WINSTON"), -#line 2522 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2523 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2525 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2526 - .items = { ITEM_FULL_RESTORE }, -#line 2527 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2528 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2530 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2530 - .heldItem = ITEM_NUGGET, -#line 2532 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2531 - .lvl = 7, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2534 - [DIFFICULTY_NORMAL][TRAINER_MOLLIE] = - { -#line 2535 - .trainerName = _("MOLLIE"), -#line 2536 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 2537 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 2538 -F_TRAINER_FEMALE | -#line 2539 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 2540 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2541 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2543 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2545 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2544 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2547 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2549 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 2548 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2551 - [DIFFICULTY_NORMAL][TRAINER_GARRET] = - { -#line 2552 - .trainerName = _("GARRET"), -#line 2553 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2554 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2556 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2557 - .items = { ITEM_FULL_RESTORE }, -#line 2558 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2559 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2561 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2561 - .heldItem = ITEM_NUGGET, -#line 2563 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2562 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2565 - [DIFFICULTY_NORMAL][TRAINER_WINSTON_2] = - { -#line 2566 - .trainerName = _("WINSTON"), -#line 2567 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2568 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2570 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2571 - .items = { ITEM_FULL_RESTORE }, -#line 2572 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2573 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2575 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2575 - .heldItem = ITEM_NUGGET, -#line 2577 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2576 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2579 - [DIFFICULTY_NORMAL][TRAINER_WINSTON_3] = - { -#line 2580 - .trainerName = _("WINSTON"), -#line 2581 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2582 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2584 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2585 - .items = { ITEM_FULL_RESTORE }, -#line 2586 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2587 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2589 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2589 - .heldItem = ITEM_NUGGET, -#line 2591 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2590 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2593 - [DIFFICULTY_NORMAL][TRAINER_WINSTON_4] = - { -#line 2594 - .trainerName = _("WINSTON"), -#line 2595 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2596 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2598 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2599 - .items = { ITEM_FULL_RESTORE }, -#line 2600 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2601 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2603 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2603 - .heldItem = ITEM_NUGGET, -#line 2605 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2604 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2607 - [DIFFICULTY_NORMAL][TRAINER_WINSTON_5] = - { -#line 2608 - .trainerName = _("WINSTON"), -#line 2609 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 2610 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 2612 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 2613 - .items = { ITEM_FULL_RESTORE }, -#line 2614 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2615 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2617 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2617 - .heldItem = ITEM_NUGGET, -#line 2619 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2618 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 2620 - MOVE_FURY_SWIPES, - MOVE_MUD_SPORT, - MOVE_ODOR_SLEUTH, - MOVE_SAND_ATTACK, - }, - }, - }, - }, -#line 2625 - [DIFFICULTY_NORMAL][TRAINER_STEVE_1] = - { -#line 2626 - .trainerName = _("STEVE"), -#line 2627 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2628 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2630 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2631 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2632 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2634 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2636 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2635 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2638 - [DIFFICULTY_NORMAL][TRAINER_THALIA_1] = - { -#line 2639 - .trainerName = _("THALIA"), -#line 2640 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 2641 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 2642 -F_TRAINER_FEMALE | -#line 2643 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 2644 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2645 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2647 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2649 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2648 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2651 - .species = SPECIES_HORSEA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2653 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2652 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2655 - [DIFFICULTY_NORMAL][TRAINER_MARK] = - { -#line 2656 - .trainerName = _("MARK"), -#line 2657 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2658 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2660 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2661 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2662 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2664 - .species = SPECIES_RHYHORN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2666 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2665 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2668 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_CHIMNEY_1] = - { -#line 2669 - .trainerName = _("GRUNT"), -#line 2670 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 2671 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_F, - .encounterMusic_gender = -#line 2672 -F_TRAINER_FEMALE | -#line 2673 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 2674 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2675 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2677 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2679 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2678 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2681 - [DIFFICULTY_NORMAL][TRAINER_STEVE_2] = - { -#line 2682 - .trainerName = _("STEVE"), -#line 2683 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2684 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2686 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2687 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2688 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2690 - .species = SPECIES_LAIRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2692 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2691 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2694 - [DIFFICULTY_NORMAL][TRAINER_STEVE_3] = - { -#line 2695 - .trainerName = _("STEVE"), -#line 2696 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2697 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2699 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2700 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2701 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2703 - .species = SPECIES_LAIRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2705 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2704 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2707 - .species = SPECIES_RHYHORN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2709 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 2708 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2711 - [DIFFICULTY_NORMAL][TRAINER_STEVE_4] = - { -#line 2712 - .trainerName = _("STEVE"), -#line 2713 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2714 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2716 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2717 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2718 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2720 - .species = SPECIES_LAIRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2722 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2721 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2724 - .species = SPECIES_RHYHORN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2726 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 2725 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2728 - [DIFFICULTY_NORMAL][TRAINER_STEVE_5] = - { -#line 2729 - .trainerName = _("STEVE"), -#line 2730 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 2731 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 2733 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 2734 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2735 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2737 - .species = SPECIES_AGGRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2739 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2738 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2741 - .species = SPECIES_RHYDON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2743 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 2742 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2745 - [DIFFICULTY_NORMAL][TRAINER_LUIS] = - { -#line 2746 - .trainerName = _("LUIS"), -#line 2747 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2748 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2750 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2751 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2752 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2754 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2756 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2755 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2758 - [DIFFICULTY_NORMAL][TRAINER_DOMINIK] = - { -#line 2759 - .trainerName = _("DOMINIK"), -#line 2760 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2761 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2763 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2764 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2765 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2767 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2769 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2768 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2771 - [DIFFICULTY_NORMAL][TRAINER_DOUGLAS] = - { -#line 2772 - .trainerName = _("DOUGLAS"), -#line 2773 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2774 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2776 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2777 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2778 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2780 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2782 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2781 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2784 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2786 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2785 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2788 - [DIFFICULTY_NORMAL][TRAINER_DARRIN] = - { -#line 2789 - .trainerName = _("DARRIN"), -#line 2790 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2791 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2793 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2794 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2795 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 2797 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2799 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2798 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2801 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2803 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2802 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2805 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2807 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 2806 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2809 - [DIFFICULTY_NORMAL][TRAINER_TONY_1] = - { -#line 2810 - .trainerName = _("TONY"), -#line 2811 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2812 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2814 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2815 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2816 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2818 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2820 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2819 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2822 - [DIFFICULTY_NORMAL][TRAINER_JEROME] = - { -#line 2823 - .trainerName = _("JEROME"), -#line 2824 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2825 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2827 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2828 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2829 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2831 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2833 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2832 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2835 - [DIFFICULTY_NORMAL][TRAINER_MATTHEW] = - { -#line 2836 - .trainerName = _("MATTHEW"), -#line 2837 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2838 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2840 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2841 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2842 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2844 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2846 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2845 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2848 - [DIFFICULTY_NORMAL][TRAINER_DAVID] = - { -#line 2849 - .trainerName = _("DAVID"), -#line 2850 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2851 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2853 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2854 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2855 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2857 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2859 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2858 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2861 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2863 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2862 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2865 - [DIFFICULTY_NORMAL][TRAINER_SPENCER] = - { -#line 2866 - .trainerName = _("SPENCER"), -#line 2867 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2868 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2870 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2871 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2872 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2874 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2876 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2875 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2878 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2880 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2879 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2882 - [DIFFICULTY_NORMAL][TRAINER_ROLAND] = - { -#line 2883 - .trainerName = _("ROLAND"), -#line 2884 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2885 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2887 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2888 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2889 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2891 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2893 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2892 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2895 - [DIFFICULTY_NORMAL][TRAINER_NOLEN] = - { -#line 2896 - .trainerName = _("NOLEN"), -#line 2897 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2898 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2900 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2901 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2902 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2904 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2906 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2905 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2908 - [DIFFICULTY_NORMAL][TRAINER_STAN] = - { -#line 2909 - .trainerName = _("STAN"), -#line 2910 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2911 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2913 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2914 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2915 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2917 - .species = SPECIES_HORSEA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2919 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2918 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2921 - [DIFFICULTY_NORMAL][TRAINER_BARRY] = - { -#line 2922 - .trainerName = _("BARRY"), -#line 2923 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2924 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2926 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2927 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2928 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2930 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2932 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2931 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2934 - [DIFFICULTY_NORMAL][TRAINER_DEAN] = - { -#line 2935 - .trainerName = _("DEAN"), -#line 2936 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2937 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2939 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2940 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2941 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 2943 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2945 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2944 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2947 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2949 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2948 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2951 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2953 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2952 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2955 - [DIFFICULTY_NORMAL][TRAINER_RODNEY] = - { -#line 2956 - .trainerName = _("RODNEY"), -#line 2957 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2958 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2960 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2961 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2962 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2964 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2966 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2965 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2968 - [DIFFICULTY_NORMAL][TRAINER_RICHARD] = - { -#line 2969 - .trainerName = _("RICHARD"), -#line 2970 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2971 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2973 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2974 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2975 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 2977 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2979 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2978 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2981 - [DIFFICULTY_NORMAL][TRAINER_HERMAN] = - { -#line 2982 - .trainerName = _("HERMAN"), -#line 2983 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 2984 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 2986 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 2987 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 2988 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 2990 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2992 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2991 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 2994 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 2996 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 2995 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 2998 - [DIFFICULTY_NORMAL][TRAINER_SANTIAGO] = - { -#line 2999 - .trainerName = _("SANTIAGO"), -#line 3000 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3001 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3003 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3004 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3005 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3007 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3009 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3008 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3011 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3013 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3012 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3015 - [DIFFICULTY_NORMAL][TRAINER_GILBERT] = - { -#line 3016 - .trainerName = _("GILBERT"), -#line 3017 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3018 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3020 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3021 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3022 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3024 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3026 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3025 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3028 - [DIFFICULTY_NORMAL][TRAINER_FRANKLIN] = - { -#line 3029 - .trainerName = _("FRANKLIN"), -#line 3030 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3031 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3033 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3034 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3035 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3037 - .species = SPECIES_SEALEO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3039 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3038 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3041 - [DIFFICULTY_NORMAL][TRAINER_KEVIN] = - { -#line 3042 - .trainerName = _("KEVIN"), -#line 3043 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3044 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3046 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3047 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3048 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3050 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3052 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3051 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3054 - [DIFFICULTY_NORMAL][TRAINER_JACK] = - { -#line 3055 - .trainerName = _("JACK"), -#line 3056 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3057 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3059 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3060 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3061 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3063 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3065 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3064 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3067 - [DIFFICULTY_NORMAL][TRAINER_DUDLEY] = - { -#line 3068 - .trainerName = _("DUDLEY"), -#line 3069 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3070 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3072 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3073 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3074 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3076 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3078 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3077 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3080 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3082 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3081 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3084 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3086 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3085 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3088 - [DIFFICULTY_NORMAL][TRAINER_CHAD] = - { -#line 3089 - .trainerName = _("CHAD"), -#line 3090 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3091 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3093 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3094 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3095 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3097 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3099 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3098 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3101 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3103 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3102 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3105 - [DIFFICULTY_NORMAL][TRAINER_TONY_2] = - { -#line 3106 - .trainerName = _("TONY"), -#line 3107 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3108 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3110 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3111 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3112 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3114 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3116 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3115 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3118 - [DIFFICULTY_NORMAL][TRAINER_TONY_3] = - { -#line 3119 - .trainerName = _("TONY"), -#line 3120 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3121 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3123 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3124 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3125 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3127 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3129 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3128 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3131 - [DIFFICULTY_NORMAL][TRAINER_TONY_4] = - { -#line 3132 - .trainerName = _("TONY"), -#line 3133 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3134 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3136 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3137 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3138 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3140 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3142 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3141 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3144 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3146 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3145 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3148 - [DIFFICULTY_NORMAL][TRAINER_TONY_5] = - { -#line 3149 - .trainerName = _("TONY"), -#line 3150 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 3151 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 3153 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 3154 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3155 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3157 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3159 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3158 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3161 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3163 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3162 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3165 - [DIFFICULTY_NORMAL][TRAINER_TAKAO] = - { -#line 3166 - .trainerName = _("TAKAO"), -#line 3167 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3168 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3170 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3171 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3172 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3174 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3176 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 3175 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3178 - [DIFFICULTY_NORMAL][TRAINER_HITOSHI] = - { -#line 3179 - .trainerName = _("HITOSHI"), -#line 3180 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3181 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3183 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3184 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3185 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3187 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3189 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 3188 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3191 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3193 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 3192 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3195 - [DIFFICULTY_NORMAL][TRAINER_KIYO] = - { -#line 3196 - .trainerName = _("KIYO"), -#line 3197 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3198 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3200 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3201 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3202 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3204 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3206 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3205 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3208 - [DIFFICULTY_NORMAL][TRAINER_KOICHI] = - { -#line 3209 - .trainerName = _("KOICHI"), -#line 3210 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3211 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3213 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3214 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3215 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3217 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3219 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3218 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3221 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3223 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 3222 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3225 - [DIFFICULTY_NORMAL][TRAINER_NOB_1] = - { -#line 3226 - .trainerName = _("NOB"), -#line 3227 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3228 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3230 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3231 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3232 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3234 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3236 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3235 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3238 - [DIFFICULTY_NORMAL][TRAINER_NOB_2] = - { -#line 3239 - .trainerName = _("NOB"), -#line 3240 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3241 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3243 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3244 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3245 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3247 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3249 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 3248 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3251 - [DIFFICULTY_NORMAL][TRAINER_NOB_3] = - { -#line 3252 - .trainerName = _("NOB"), -#line 3253 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3254 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3256 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3257 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3258 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3260 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3262 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 3261 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3264 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3266 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 3265 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3268 - [DIFFICULTY_NORMAL][TRAINER_NOB_4] = - { -#line 3269 - .trainerName = _("NOB"), -#line 3270 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3271 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3273 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3274 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3275 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3277 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3279 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 3278 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3281 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3283 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 3282 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3285 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3287 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 3286 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3289 - [DIFFICULTY_NORMAL][TRAINER_NOB_5] = - { -#line 3290 - .trainerName = _("NOB"), -#line 3291 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3292 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3294 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3295 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3296 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 3298 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3300 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 3299 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3302 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3304 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 3303 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3306 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3308 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 3307 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3310 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3310 - .heldItem = ITEM_BLACK_BELT, -#line 3312 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 3311 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3314 - [DIFFICULTY_NORMAL][TRAINER_YUJI] = - { -#line 3315 - .trainerName = _("YUJI"), -#line 3316 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3317 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3319 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3320 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3321 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3323 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3325 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3324 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3327 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3329 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3328 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3331 - [DIFFICULTY_NORMAL][TRAINER_DAISUKE] = - { -#line 3332 - .trainerName = _("DAISUKE"), -#line 3333 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3334 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3336 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3337 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3338 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3340 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3342 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3341 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3344 - [DIFFICULTY_NORMAL][TRAINER_ATSUSHI] = - { -#line 3345 - .trainerName = _("ATSUSHI"), -#line 3346 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 3347 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 3349 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3350 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3353 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3355 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3354 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3357 - [DIFFICULTY_NORMAL][TRAINER_KIRK] = - { -#line 3358 - .trainerName = _("KIRK"), -#line 3359 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3360 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3362 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3363 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3364 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3366 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3368 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3367 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3369 - MOVE_QUICK_ATTACK, - MOVE_THUNDER_WAVE, - MOVE_SPARK, - MOVE_LEER, - }, - }, - { -#line 3374 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3376 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3375 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3377 - MOVE_CHARGE, - MOVE_SHOCK_WAVE, - MOVE_SCREECH, - }, - }, - }, - }, -#line 3381 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_7] = - { -#line 3382 - .trainerName = _("GRUNT"), -#line 3383 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 3384 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 3385 -F_TRAINER_FEMALE | -#line 3386 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 3387 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3388 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3390 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3392 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3391 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3394 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3396 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3395 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3398 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_8] = - { -#line 3399 - .trainerName = _("GRUNT"), -#line 3400 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 3401 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 3403 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 3404 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3405 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3407 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3409 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3408 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3411 - [DIFFICULTY_NORMAL][TRAINER_SHAWN] = - { -#line 3412 - .trainerName = _("SHAWN"), -#line 3413 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3414 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3416 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3417 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3418 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3420 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3422 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3421 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3424 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3426 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3425 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3428 - [DIFFICULTY_NORMAL][TRAINER_FERNANDO_1] = - { -#line 3429 - .trainerName = _("FERNANDO"), -#line 3430 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3431 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3433 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3434 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3435 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3437 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3439 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3438 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3441 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3443 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3442 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3445 - [DIFFICULTY_NORMAL][TRAINER_DALTON_1] = - { -#line 3446 - .trainerName = _("DALTON"), -#line 3447 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3448 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3450 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3451 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3452 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3454 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3456 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3455 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3458 - .species = SPECIES_WHISMUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3460 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3459 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3462 - [DIFFICULTY_NORMAL][TRAINER_DALTON_2] = - { -#line 3463 - .trainerName = _("DALTON"), -#line 3464 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3465 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3467 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3468 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3469 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3471 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3473 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3472 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3475 - .species = SPECIES_WHISMUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3477 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3476 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3479 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3481 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3480 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3483 - [DIFFICULTY_NORMAL][TRAINER_DALTON_3] = - { -#line 3484 - .trainerName = _("DALTON"), -#line 3485 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3486 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3488 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3489 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3490 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3492 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3494 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3493 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3496 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3498 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3497 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3500 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3502 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3501 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3504 - [DIFFICULTY_NORMAL][TRAINER_DALTON_4] = - { -#line 3505 - .trainerName = _("DALTON"), -#line 3506 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3507 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3509 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3510 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3511 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3513 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3515 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3514 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3517 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3519 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3518 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3521 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3523 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3522 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3525 - [DIFFICULTY_NORMAL][TRAINER_DALTON_5] = - { -#line 3526 - .trainerName = _("DALTON"), -#line 3527 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 3528 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 3530 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 3531 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3532 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3534 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3536 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3535 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3538 - .species = SPECIES_EXPLOUD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3540 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3539 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3542 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3544 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3543 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3546 - [DIFFICULTY_NORMAL][TRAINER_COLE] = - { -#line 3547 - .trainerName = _("COLE"), -#line 3548 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3549 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3551 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3552 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3553 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3555 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3557 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3556 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3559 - [DIFFICULTY_NORMAL][TRAINER_JEFF] = - { -#line 3560 - .trainerName = _("JEFF"), -#line 3561 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3562 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3564 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3565 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3566 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3568 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3570 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3569 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3572 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3574 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3573 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3576 - [DIFFICULTY_NORMAL][TRAINER_AXLE] = - { -#line 3577 - .trainerName = _("AXLE"), -#line 3578 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3579 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3581 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3582 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3583 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3585 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3587 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3586 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3589 - [DIFFICULTY_NORMAL][TRAINER_JACE] = - { -#line 3590 - .trainerName = _("JACE"), -#line 3591 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3592 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3594 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3595 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3596 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3598 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3600 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3599 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3602 - [DIFFICULTY_NORMAL][TRAINER_KEEGAN] = - { -#line 3603 - .trainerName = _("KEEGAN"), -#line 3604 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3605 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3607 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3608 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3609 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3611 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3613 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 3612 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3615 - [DIFFICULTY_NORMAL][TRAINER_BERNIE_1] = - { -#line 3616 - .trainerName = _("BERNIE"), -#line 3617 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3618 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3620 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3621 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3622 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3624 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3626 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3625 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3628 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3630 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3629 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3632 - [DIFFICULTY_NORMAL][TRAINER_BERNIE_2] = - { -#line 3633 - .trainerName = _("BERNIE"), -#line 3634 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3635 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3637 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3638 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3639 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3641 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3643 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3642 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3645 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3647 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3646 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3649 - [DIFFICULTY_NORMAL][TRAINER_BERNIE_3] = - { -#line 3650 - .trainerName = _("BERNIE"), -#line 3651 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3652 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3654 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3655 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3656 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3658 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3660 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3659 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3662 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3664 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3663 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3666 - [DIFFICULTY_NORMAL][TRAINER_BERNIE_4] = - { -#line 3667 - .trainerName = _("BERNIE"), -#line 3668 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3669 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3671 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3672 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3673 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3675 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3677 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3676 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3679 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3681 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3680 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3683 - [DIFFICULTY_NORMAL][TRAINER_BERNIE_5] = - { -#line 3684 - .trainerName = _("BERNIE"), -#line 3685 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 3686 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 3688 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 3689 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3690 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3692 - .species = SPECIES_MAGCARGO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3694 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3693 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3696 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3698 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3697 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3700 - [DIFFICULTY_NORMAL][TRAINER_DREW] = - { -#line 3701 - .trainerName = _("DREW"), -#line 3702 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3703 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3705 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3706 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3707 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3709 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3711 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3710 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3712 - MOVE_DIG, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - MOVE_SLASH, - }, - }, - }, - }, -#line 3717 - [DIFFICULTY_NORMAL][TRAINER_BEAU] = - { -#line 3718 - .trainerName = _("BEAU"), -#line 3719 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3720 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3722 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3723 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3724 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3726 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3728 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3727 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3729 - MOVE_RAPID_SPIN, - MOVE_MUD_SLAP, - MOVE_PSYBEAM, - MOVE_ROCK_TOMB, - }, - }, - { -#line 3734 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3736 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3735 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3737 - MOVE_POISON_STING, - MOVE_SAND_ATTACK, - MOVE_SCRATCH, - MOVE_DIG, - }, - }, - { -#line 3742 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3744 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3743 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 3745 - MOVE_RAPID_SPIN, - MOVE_MUD_SLAP, - MOVE_PSYBEAM, - MOVE_ROCK_TOMB, - }, - }, - }, - }, -#line 3750 - [DIFFICULTY_NORMAL][TRAINER_LARRY] = - { -#line 3751 - .trainerName = _("LARRY"), -#line 3752 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3753 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3755 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3756 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3757 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3759 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3761 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3760 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3763 - [DIFFICULTY_NORMAL][TRAINER_SHANE] = - { -#line 3764 - .trainerName = _("SHANE"), -#line 3765 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3766 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3768 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3769 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3770 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3772 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3774 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3773 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3776 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3778 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3777 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3780 - [DIFFICULTY_NORMAL][TRAINER_JUSTIN] = - { -#line 3781 - .trainerName = _("JUSTIN"), -#line 3782 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3783 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3785 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3786 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3787 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3789 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3791 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3790 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3793 - [DIFFICULTY_NORMAL][TRAINER_ETHAN_1] = - { -#line 3794 - .trainerName = _("ETHAN"), -#line 3795 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3796 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3798 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3799 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3800 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3802 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3804 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3803 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3806 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3808 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3807 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3810 - [DIFFICULTY_NORMAL][TRAINER_AUTUMN] = - { -#line 3811 - .trainerName = _("AUTUMN"), -#line 3812 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 3813 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 3814 -F_TRAINER_FEMALE | -#line 3815 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 3816 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3817 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3819 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3821 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3820 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3823 - [DIFFICULTY_NORMAL][TRAINER_TRAVIS] = - { -#line 3824 - .trainerName = _("TRAVIS"), -#line 3825 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3826 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3828 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3829 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3830 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3832 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3834 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3833 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3836 - [DIFFICULTY_NORMAL][TRAINER_ETHAN_2] = - { -#line 3837 - .trainerName = _("ETHAN"), -#line 3838 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3839 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3841 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3842 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3843 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3845 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3847 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3846 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3849 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3851 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 3850 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3853 - [DIFFICULTY_NORMAL][TRAINER_ETHAN_3] = - { -#line 3854 - .trainerName = _("ETHAN"), -#line 3855 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3856 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3858 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3859 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3860 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3862 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3864 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3863 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3866 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3868 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 3867 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3870 - [DIFFICULTY_NORMAL][TRAINER_ETHAN_4] = - { -#line 3871 - .trainerName = _("ETHAN"), -#line 3872 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3873 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3875 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3876 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3877 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3879 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3881 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3880 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3883 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3885 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3884 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3887 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3889 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 3888 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3891 - [DIFFICULTY_NORMAL][TRAINER_ETHAN_5] = - { -#line 3892 - .trainerName = _("ETHAN"), -#line 3893 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 3894 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 3896 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 3897 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3898 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3900 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3902 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3901 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3904 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3906 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3905 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3908 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3910 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 3909 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3912 - [DIFFICULTY_NORMAL][TRAINER_BRENT] = - { -#line 3913 - .trainerName = _("BRENT"), -#line 3914 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 3915 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 3917 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 3918 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3919 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 3921 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3923 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3922 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3925 - [DIFFICULTY_NORMAL][TRAINER_DONALD] = - { -#line 3926 - .trainerName = _("DONALD"), -#line 3927 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 3928 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 3930 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 3931 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3932 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3934 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3936 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3935 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3938 - .species = SPECIES_SILCOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3940 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3939 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3942 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3944 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3943 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3946 - [DIFFICULTY_NORMAL][TRAINER_TAYLOR] = - { -#line 3947 - .trainerName = _("TAYLOR"), -#line 3948 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 3949 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 3951 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 3952 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3953 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3955 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3957 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3956 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3959 - .species = SPECIES_CASCOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3961 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3960 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3963 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3965 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 3964 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3967 - [DIFFICULTY_NORMAL][TRAINER_JEFFREY_1] = - { -#line 3968 - .trainerName = _("JEFFREY"), -#line 3969 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 3970 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 3972 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 3973 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3974 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 3976 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3978 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3977 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3980 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3982 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3981 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 3984 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3986 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 3985 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 3988 - [DIFFICULTY_NORMAL][TRAINER_DEREK] = - { -#line 3989 - .trainerName = _("DEREK"), -#line 3990 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 3991 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 3993 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 3994 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 3995 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 3997 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 3999 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 3998 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4001 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4003 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 4002 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4005 - [DIFFICULTY_NORMAL][TRAINER_JEFFREY_2] = - { -#line 4006 - .trainerName = _("JEFFREY"), -#line 4007 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 4008 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 4010 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 4011 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4012 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4014 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4016 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4015 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4018 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4020 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4019 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4022 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4024 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4023 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4026 - [DIFFICULTY_NORMAL][TRAINER_JEFFREY_3] = - { -#line 4027 - .trainerName = _("JEFFREY"), -#line 4028 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 4029 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 4031 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 4032 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4033 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4035 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4037 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4036 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4039 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4041 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4040 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4043 - .species = SPECIES_MASQUERAIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4045 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4044 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4047 - [DIFFICULTY_NORMAL][TRAINER_JEFFREY_4] = - { -#line 4048 - .trainerName = _("JEFFREY"), -#line 4049 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 4050 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 4052 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 4053 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4054 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 4056 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4058 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4057 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4060 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4062 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4061 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4064 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4066 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4065 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4068 - .species = SPECIES_MASQUERAIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4070 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4069 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4072 - [DIFFICULTY_NORMAL][TRAINER_JEFFREY_5] = - { -#line 4073 - .trainerName = _("JEFFREY"), -#line 4074 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 4075 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 4077 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 4078 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4079 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4081 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4083 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4082 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4085 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4087 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4086 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4089 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4091 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4090 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4093 - .species = SPECIES_MASQUERAIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4093 - .heldItem = ITEM_SILVER_POWDER, -#line 4095 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4094 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4097 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4099 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4098 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4101 - [DIFFICULTY_NORMAL][TRAINER_EDWARD] = - { -#line 4102 - .trainerName = _("EDWARD"), -#line 4103 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4104 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4106 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4107 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4108 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4110 - .species = SPECIES_ABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4112 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4111 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4113 - MOVE_HIDDEN_POWER, - }, - }, - }, - }, -#line 4115 - [DIFFICULTY_NORMAL][TRAINER_PRESTON] = - { -#line 4116 - .trainerName = _("PRESTON"), -#line 4117 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4118 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4120 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4121 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4122 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4124 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4126 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4125 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4128 - [DIFFICULTY_NORMAL][TRAINER_VIRGIL] = - { -#line 4129 - .trainerName = _("VIRGIL"), -#line 4130 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4131 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4133 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4134 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4135 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4137 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4139 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4138 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4141 - [DIFFICULTY_NORMAL][TRAINER_BLAKE] = - { -#line 4142 - .trainerName = _("BLAKE"), -#line 4143 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4144 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4146 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4147 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4148 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4150 - .species = SPECIES_GIRAFARIG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4152 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4151 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4154 - [DIFFICULTY_NORMAL][TRAINER_WILLIAM] = - { -#line 4155 - .trainerName = _("WILLIAM"), -#line 4156 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4157 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4159 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4160 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4161 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4163 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4165 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4164 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4167 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4169 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4168 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4171 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4173 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4172 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4175 - [DIFFICULTY_NORMAL][TRAINER_JOSHUA] = - { -#line 4176 - .trainerName = _("JOSHUA"), -#line 4177 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4178 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4180 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4181 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4182 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4184 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4186 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4185 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4188 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4190 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4189 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4192 - [DIFFICULTY_NORMAL][TRAINER_CAMERON_1] = - { -#line 4193 - .trainerName = _("CAMERON"), -#line 4194 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4195 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4197 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4198 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4199 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4201 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4203 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4202 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4205 - [DIFFICULTY_NORMAL][TRAINER_CAMERON_2] = - { -#line 4206 - .trainerName = _("CAMERON"), -#line 4207 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4208 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4210 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4211 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4212 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4214 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4216 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4215 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4218 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4220 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4219 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4222 - [DIFFICULTY_NORMAL][TRAINER_CAMERON_3] = - { -#line 4223 - .trainerName = _("CAMERON"), -#line 4224 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4225 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4227 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4228 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4229 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4231 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4233 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4232 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4235 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4237 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4236 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4239 - [DIFFICULTY_NORMAL][TRAINER_CAMERON_4] = - { -#line 4240 - .trainerName = _("CAMERON"), -#line 4241 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4242 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4244 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4245 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4246 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4248 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4250 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4249 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4252 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4254 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4253 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4256 - [DIFFICULTY_NORMAL][TRAINER_CAMERON_5] = - { -#line 4257 - .trainerName = _("CAMERON"), -#line 4258 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4259 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 4261 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4262 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4263 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4265 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4267 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4266 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4269 - .species = SPECIES_ALAKAZAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4271 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4270 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4273 - [DIFFICULTY_NORMAL][TRAINER_JACLYN] = - { -#line 4274 - .trainerName = _("JACLYN"), -#line 4275 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4276 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4277 -F_TRAINER_FEMALE | -#line 4278 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4279 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4280 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4282 - .species = SPECIES_ABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4284 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4283 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4285 - MOVE_HIDDEN_POWER, - }, - }, - }, - }, -#line 4287 - [DIFFICULTY_NORMAL][TRAINER_HANNAH] = - { -#line 4288 - .trainerName = _("HANNAH"), -#line 4289 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4290 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4291 -F_TRAINER_FEMALE | -#line 4292 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4293 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4294 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4296 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4298 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4297 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4300 - [DIFFICULTY_NORMAL][TRAINER_SAMANTHA] = - { -#line 4301 - .trainerName = _("SAMANTHA"), -#line 4302 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4303 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4304 -F_TRAINER_FEMALE | -#line 4305 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4306 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4307 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4309 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4311 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4310 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4313 - [DIFFICULTY_NORMAL][TRAINER_MAURA] = - { -#line 4314 - .trainerName = _("MAURA"), -#line 4315 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4316 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4317 -F_TRAINER_FEMALE | -#line 4318 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4319 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4320 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4322 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4324 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4323 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4326 - [DIFFICULTY_NORMAL][TRAINER_KAYLA] = - { -#line 4327 - .trainerName = _("KAYLA"), -#line 4328 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4329 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4330 -F_TRAINER_FEMALE | -#line 4331 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4332 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4333 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4335 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4337 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4336 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4339 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4341 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4340 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4343 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4345 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4344 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4347 - [DIFFICULTY_NORMAL][TRAINER_ALEXIS] = - { -#line 4348 - .trainerName = _("ALEXIS"), -#line 4349 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4350 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4351 -F_TRAINER_FEMALE | -#line 4352 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4353 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4354 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4356 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4358 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4357 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4360 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4362 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4361 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4364 - [DIFFICULTY_NORMAL][TRAINER_JACKI_1] = - { -#line 4365 - .trainerName = _("JACKI"), -#line 4366 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4367 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4368 -F_TRAINER_FEMALE | -#line 4369 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4370 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4371 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4373 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4375 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4374 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4377 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4379 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4378 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4381 - [DIFFICULTY_NORMAL][TRAINER_JACKI_2] = - { -#line 4382 - .trainerName = _("JACKI"), -#line 4383 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4384 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4385 -F_TRAINER_FEMALE | -#line 4386 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4387 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4388 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4390 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4392 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4391 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4394 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4396 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4395 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4398 - [DIFFICULTY_NORMAL][TRAINER_JACKI_3] = - { -#line 4399 - .trainerName = _("JACKI"), -#line 4400 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4401 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4402 -F_TRAINER_FEMALE | -#line 4403 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4404 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4405 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4407 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4409 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4408 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4411 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4413 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4412 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4415 - [DIFFICULTY_NORMAL][TRAINER_JACKI_4] = - { -#line 4416 - .trainerName = _("JACKI"), -#line 4417 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4418 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4419 -F_TRAINER_FEMALE | -#line 4420 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4421 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4422 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4424 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4426 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4425 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4428 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4430 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4429 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4432 - [DIFFICULTY_NORMAL][TRAINER_JACKI_5] = - { -#line 4433 - .trainerName = _("JACKI"), -#line 4434 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 4435 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 4436 -F_TRAINER_FEMALE | -#line 4437 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 4438 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4439 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4441 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4443 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4442 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4445 - .species = SPECIES_ALAKAZAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4447 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4446 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4449 - [DIFFICULTY_NORMAL][TRAINER_WALTER_1] = - { -#line 4450 - .trainerName = _("WALTER"), -#line 4451 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4452 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4454 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4455 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4456 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4458 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4460 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4459 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4462 - [DIFFICULTY_NORMAL][TRAINER_MICAH] = - { -#line 4463 - .trainerName = _("MICAH"), -#line 4464 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4465 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4467 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4468 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4469 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4471 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4473 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4472 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 4475 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4477 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4476 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4479 - [DIFFICULTY_NORMAL][TRAINER_THOMAS] = - { -#line 4480 - .trainerName = _("THOMAS"), -#line 4481 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4482 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4484 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4485 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4486 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4488 - .species = SPECIES_ZANGOOSE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4490 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 4489 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4492 - [DIFFICULTY_NORMAL][TRAINER_WALTER_2] = - { -#line 4493 - .trainerName = _("WALTER"), -#line 4494 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4495 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4497 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4498 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4499 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 4501 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4503 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 4502 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 4505 - [DIFFICULTY_NORMAL][TRAINER_WALTER_3] = - { -#line 4506 - .trainerName = _("WALTER"), -#line 4507 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4508 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4510 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4511 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4512 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4514 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4516 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4515 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4517 - MOVE_HEADBUTT, - MOVE_SAND_ATTACK, - MOVE_ODOR_SLEUTH, - MOVE_FURY_SWIPES, - }, - }, - { -#line 4522 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4524 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 4523 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4525 - MOVE_QUICK_ATTACK, - MOVE_SPARK, - MOVE_ODOR_SLEUTH, - MOVE_ROAR, - }, - }, - }, - }, -#line 4530 - [DIFFICULTY_NORMAL][TRAINER_WALTER_4] = - { -#line 4531 - .trainerName = _("WALTER"), -#line 4532 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4533 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4535 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4536 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4537 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 4539 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4541 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4540 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4542 - MOVE_HEADBUTT, - MOVE_SAND_ATTACK, - MOVE_ODOR_SLEUTH, - MOVE_FURY_SWIPES, - }, - }, - { -#line 4547 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4549 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 4548 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4550 - MOVE_QUICK_ATTACK, - MOVE_SPARK, - MOVE_ODOR_SLEUTH, - }, - }, - }, - }, -#line 4554 - [DIFFICULTY_NORMAL][TRAINER_WALTER_5] = - { -#line 4555 - .trainerName = _("WALTER"), -#line 4556 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 4557 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 4559 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 4560 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4561 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4563 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4565 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4564 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4566 - MOVE_HEADBUTT, - MOVE_SAND_ATTACK, - MOVE_ODOR_SLEUTH, - MOVE_FURY_SWIPES, - }, - }, - { -#line 4571 - .species = SPECIES_GOLDUCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4573 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4572 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4574 - MOVE_FURY_SWIPES, - MOVE_DISABLE, - MOVE_CONFUSION, - MOVE_PSYCH_UP, - }, - }, - { -#line 4579 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4581 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 4580 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4582 - MOVE_QUICK_ATTACK, - MOVE_SPARK, - MOVE_ODOR_SLEUTH, - MOVE_ROAR, - }, - }, - }, - }, -#line 4587 - [DIFFICULTY_NORMAL][TRAINER_SIDNEY] = - { -#line 4588 - .trainerName = _("SIDNEY"), -#line 4589 - .trainerClass = TRAINER_CLASS_ELITE_FOUR, -#line 4590 - .trainerPic = TRAINER_PIC_ELITE_FOUR_SIDNEY, - .encounterMusic_gender = -#line 4592 - TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR, -#line 4593 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 4594 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4595 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_FORCE_SETUP_FIRST_TURN, -#line 4596 - .mugshotColor = MUGSHOT_COLOR_PURPLE, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4598 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4600 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4599 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4601 - MOVE_ROAR, - MOVE_DOUBLE_EDGE, - MOVE_SAND_ATTACK, - MOVE_CRUNCH, - }, - }, - { -#line 4606 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4608 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4607 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4609 - MOVE_TORMENT, - MOVE_DOUBLE_TEAM, - MOVE_SWAGGER, - MOVE_EXTRASENSORY, - }, - }, - { -#line 4614 - .species = SPECIES_CACTURNE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4616 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4615 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4617 - MOVE_LEECH_SEED, - MOVE_FEINT_ATTACK, - MOVE_NEEDLE_ARM, - MOVE_COTTON_SPORE, - }, - }, - { -#line 4622 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4624 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4623 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4625 - MOVE_SURF, - MOVE_SWORDS_DANCE, - MOVE_STRENGTH, - MOVE_FACADE, - }, - }, - { -#line 4630 - .species = SPECIES_ABSOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4630 - .heldItem = ITEM_SITRUS_BERRY, -#line 4632 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 4631 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4633 - MOVE_AERIAL_ACE, - MOVE_ROCK_SLIDE, - MOVE_SWORDS_DANCE, - MOVE_SLASH, - }, - }, - }, - }, -#line 4638 - [DIFFICULTY_NORMAL][TRAINER_PHOEBE] = - { -#line 4639 - .trainerName = _("PHOEBE"), -#line 4640 - .trainerClass = TRAINER_CLASS_ELITE_FOUR, -#line 4641 - .trainerPic = TRAINER_PIC_ELITE_FOUR_PHOEBE, - .encounterMusic_gender = -#line 4642 -F_TRAINER_FEMALE | -#line 4643 - TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR, -#line 4644 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 4645 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4646 - .aiFlags = AI_FLAG_BASIC_TRAINER, -#line 4647 - .mugshotColor = MUGSHOT_COLOR_GREEN, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4649 - .species = SPECIES_DUSCLOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4651 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4650 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4652 - MOVE_SHADOW_PUNCH, - MOVE_CONFUSE_RAY, - MOVE_CURSE, - MOVE_PROTECT, - }, - }, - { -#line 4657 - .species = SPECIES_BANETTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4659 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4658 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4660 - MOVE_SHADOW_BALL, - MOVE_GRUDGE, - MOVE_WILL_O_WISP, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 4665 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4667 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4666 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4668 - MOVE_SHADOW_BALL, - MOVE_DOUBLE_TEAM, - MOVE_NIGHT_SHADE, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 4673 - .species = SPECIES_BANETTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4675 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4674 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4676 - MOVE_SHADOW_BALL, - MOVE_PSYCHIC, - MOVE_THUNDERBOLT, - MOVE_FACADE, - }, - }, - { -#line 4681 - .species = SPECIES_DUSCLOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4681 - .heldItem = ITEM_SITRUS_BERRY, -#line 4683 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 4682 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4684 - MOVE_SHADOW_BALL, - MOVE_ICE_BEAM, - MOVE_ROCK_SLIDE, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 4689 - [DIFFICULTY_NORMAL][TRAINER_GLACIA] = - { -#line 4690 - .trainerName = _("GLACIA"), -#line 4691 - .trainerClass = TRAINER_CLASS_ELITE_FOUR, -#line 4692 - .trainerPic = TRAINER_PIC_ELITE_FOUR_GLACIA, - .encounterMusic_gender = -#line 4693 -F_TRAINER_FEMALE | -#line 4694 - TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR, -#line 4695 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 4696 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4697 - .aiFlags = AI_FLAG_BASIC_TRAINER, -#line 4698 - .mugshotColor = MUGSHOT_COLOR_PINK, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4700 - .species = SPECIES_SEALEO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4702 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4701 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4703 - MOVE_ENCORE, - MOVE_BODY_SLAM, - MOVE_HAIL, - MOVE_ICE_BALL, - }, - }, - { -#line 4708 - .species = SPECIES_GLALIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4710 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4709 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4711 - MOVE_LIGHT_SCREEN, - MOVE_CRUNCH, - MOVE_ICY_WIND, - MOVE_ICE_BEAM, - }, - }, - { -#line 4716 - .species = SPECIES_SEALEO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4718 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4717 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4719 - MOVE_ATTRACT, - MOVE_DOUBLE_EDGE, - MOVE_HAIL, - MOVE_BLIZZARD, - }, - }, - { -#line 4724 - .species = SPECIES_GLALIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4726 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4725 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4727 - MOVE_SHADOW_BALL, - MOVE_EXPLOSION, - MOVE_HAIL, - MOVE_ICE_BEAM, - }, - }, - { -#line 4732 - .species = SPECIES_WALREIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4732 - .heldItem = ITEM_SITRUS_BERRY, -#line 4734 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 4733 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4735 - MOVE_SURF, - MOVE_BODY_SLAM, - MOVE_ICE_BEAM, - MOVE_SHEER_COLD, - }, - }, - }, - }, -#line 4740 - [DIFFICULTY_NORMAL][TRAINER_DRAKE] = - { -#line 4741 - .trainerName = _("DRAKE"), -#line 4742 - .trainerClass = TRAINER_CLASS_ELITE_FOUR, -#line 4743 - .trainerPic = TRAINER_PIC_ELITE_FOUR_DRAKE, - .encounterMusic_gender = -#line 4745 - TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR, -#line 4746 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 4747 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4748 - .aiFlags = AI_FLAG_BASIC_TRAINER, -#line 4749 - .mugshotColor = MUGSHOT_COLOR_BLUE, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4751 - .species = SPECIES_SHELGON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4753 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4752 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4754 - MOVE_ROCK_TOMB, - MOVE_DRAGON_CLAW, - MOVE_PROTECT, - MOVE_DOUBLE_EDGE, - }, - }, - { -#line 4759 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4761 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4760 - .lvl = 54, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4762 - MOVE_DOUBLE_EDGE, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - MOVE_AERIAL_ACE, - }, - }, - { -#line 4767 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4769 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4768 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4770 - MOVE_SMOKESCREEN, - MOVE_DRAGON_DANCE, - MOVE_SURF, - MOVE_BODY_SLAM, - }, - }, - { -#line 4775 - .species = SPECIES_FLYGON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4777 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4776 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4778 - MOVE_FLAMETHROWER, - MOVE_CRUNCH, - MOVE_DRAGON_BREATH, - MOVE_EARTHQUAKE, - }, - }, - { -#line 4783 - .species = SPECIES_SALAMENCE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4783 - .heldItem = ITEM_SITRUS_BERRY, -#line 4785 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 4784 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4786 - MOVE_FLAMETHROWER, - MOVE_DRAGON_CLAW, - MOVE_ROCK_SLIDE, - MOVE_CRUNCH, - }, - }, - }, - }, -#line 4791 - [DIFFICULTY_NORMAL][TRAINER_ROXANNE_1] = - { -#line 4792 - .trainerName = _("ROXANNE"), -#line 4793 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4794 - .trainerPic = TRAINER_PIC_LEADER_ROXANNE, - .encounterMusic_gender = -#line 4795 -F_TRAINER_FEMALE | -#line 4796 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 4797 - .items = { ITEM_POTION, ITEM_POTION }, -#line 4798 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4799 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4801 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4803 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4802 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4804 - MOVE_TACKLE, - MOVE_DEFENSE_CURL, - MOVE_ROCK_THROW, - MOVE_ROCK_TOMB, - }, - }, - { -#line 4809 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4811 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4810 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4812 - MOVE_TACKLE, - MOVE_DEFENSE_CURL, - MOVE_ROCK_THROW, - MOVE_ROCK_TOMB, - }, - }, - { -#line 4817 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4817 - .heldItem = ITEM_ORAN_BERRY, -#line 4819 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4818 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4820 - MOVE_BLOCK, - MOVE_HARDEN, - MOVE_TACKLE, - MOVE_ROCK_TOMB, - }, - }, - }, - }, -#line 4825 - [DIFFICULTY_NORMAL][TRAINER_BRAWLY_1] = - { -#line 4826 - .trainerName = _("BRAWLY"), -#line 4827 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4828 - .trainerPic = TRAINER_PIC_LEADER_BRAWLY, - .encounterMusic_gender = -#line 4830 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 4831 - .items = { ITEM_SUPER_POTION, ITEM_SUPER_POTION }, -#line 4832 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4833 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 4835 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4837 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4836 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4838 - MOVE_KARATE_CHOP, - MOVE_LOW_KICK, - MOVE_SEISMIC_TOSS, - MOVE_BULK_UP, - }, - }, - { -#line 4843 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4845 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 4844 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4846 - MOVE_FOCUS_PUNCH, - MOVE_LIGHT_SCREEN, - MOVE_REFLECT, - MOVE_BULK_UP, - }, - }, - { -#line 4851 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4851 - .heldItem = ITEM_SITRUS_BERRY, -#line 4853 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4852 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4854 - MOVE_ARM_THRUST, - MOVE_VITAL_THROW, - MOVE_REVERSAL, - MOVE_BULK_UP, - }, - }, - }, - }, -#line 4859 - [DIFFICULTY_NORMAL][TRAINER_WATTSON_1] = - { -#line 4860 - .trainerName = _("WATTSON"), -#line 4861 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4862 - .trainerPic = TRAINER_PIC_LEADER_WATTSON, - .encounterMusic_gender = -#line 4864 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 4865 - .items = { ITEM_SUPER_POTION, ITEM_SUPER_POTION }, -#line 4866 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4867 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 4869 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4871 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4870 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4872 - MOVE_ROLLOUT, - MOVE_SPARK, - MOVE_SELF_DESTRUCT, - MOVE_SHOCK_WAVE, - }, - }, - { -#line 4877 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4879 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4878 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4880 - MOVE_SHOCK_WAVE, - MOVE_LEER, - MOVE_QUICK_ATTACK, - MOVE_HOWL, - }, - }, - { -#line 4885 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4887 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 4886 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4888 - MOVE_SUPERSONIC, - MOVE_SHOCK_WAVE, - MOVE_THUNDER_WAVE, - MOVE_SONIC_BOOM, - }, - }, - { -#line 4893 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4893 - .heldItem = ITEM_SITRUS_BERRY, -#line 4895 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4894 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4896 - MOVE_QUICK_ATTACK, - MOVE_THUNDER_WAVE, - MOVE_SHOCK_WAVE, - MOVE_HOWL, - }, - }, - }, - }, -#line 4901 - [DIFFICULTY_NORMAL][TRAINER_FLANNERY_1] = - { -#line 4902 - .trainerName = _("FLANNERY"), -#line 4903 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4904 - .trainerPic = TRAINER_PIC_LEADER_FLANNERY, - .encounterMusic_gender = -#line 4905 -F_TRAINER_FEMALE | -#line 4906 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 4907 - .items = { ITEM_HYPER_POTION, ITEM_HYPER_POTION }, -#line 4908 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4909 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 4911 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4913 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4912 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4914 - MOVE_OVERHEAT, - MOVE_TAKE_DOWN, - MOVE_MAGNITUDE, - MOVE_SUNNY_DAY, - }, - }, - { -#line 4919 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4921 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4920 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4922 - MOVE_OVERHEAT, - MOVE_SMOG, - MOVE_LIGHT_SCREEN, - MOVE_SUNNY_DAY, - }, - }, - { -#line 4927 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4929 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4928 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4930 - MOVE_OVERHEAT, - MOVE_TACKLE, - MOVE_SUNNY_DAY, - MOVE_ATTRACT, - }, - }, - { -#line 4935 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4935 - .heldItem = ITEM_WHITE_HERB, -#line 4937 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4936 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4938 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_BODY_SLAM, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 4943 - [DIFFICULTY_NORMAL][TRAINER_NORMAN_1] = - { -#line 4944 - .trainerName = _("NORMAN"), -#line 4945 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4946 - .trainerPic = TRAINER_PIC_LEADER_NORMAN, - .encounterMusic_gender = -#line 4948 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 4949 - .items = { ITEM_HYPER_POTION, ITEM_HYPER_POTION }, -#line 4950 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4951 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 4953 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4955 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4954 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4956 - MOVE_TEETER_DANCE, - MOVE_PSYBEAM, - MOVE_FACADE, - MOVE_ENCORE, - }, - }, - { -#line 4961 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4963 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4962 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4964 - MOVE_SLASH, - MOVE_FACADE, - MOVE_ENCORE, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 4969 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4971 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 4970 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4972 - MOVE_SLASH, - MOVE_BELLY_DRUM, - MOVE_FACADE, - MOVE_HEADBUTT, - }, - }, - { -#line 4977 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4977 - .heldItem = ITEM_SITRUS_BERRY, -#line 4979 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 4978 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4980 - MOVE_COUNTER, - MOVE_YAWN, - MOVE_FACADE, - MOVE_FEINT_ATTACK, - }, - }, - }, - }, -#line 4985 - [DIFFICULTY_NORMAL][TRAINER_WINONA_1] = - { -#line 4986 - .trainerName = _("WINONA"), -#line 4987 - .trainerClass = TRAINER_CLASS_LEADER, -#line 4988 - .trainerPic = TRAINER_PIC_LEADER_WINONA, - .encounterMusic_gender = -#line 4989 -F_TRAINER_FEMALE | -#line 4990 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 4991 - .items = { ITEM_HYPER_POTION, ITEM_HYPER_POTION }, -#line 4992 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 4993 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_RISKY, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 4995 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 4997 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 4996 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 4998 - MOVE_PERISH_SONG, - MOVE_MIRROR_MOVE, - MOVE_SAFEGUARD, - MOVE_AERIAL_ACE, - }, - }, - { -#line 5003 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5005 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 5004 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5006 - MOVE_SUNNY_DAY, - MOVE_AERIAL_ACE, - MOVE_SOLAR_BEAM, - MOVE_SYNTHESIS, - }, - }, - { -#line 5011 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5013 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 5012 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5014 - MOVE_WATER_GUN, - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_AERIAL_ACE, - }, - }, - { -#line 5019 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5021 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 5020 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5022 - MOVE_SAND_ATTACK, - MOVE_FURY_ATTACK, - MOVE_STEEL_WING, - MOVE_AERIAL_ACE, - }, - }, - { -#line 5027 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5027 - .heldItem = ITEM_ORAN_BERRY, -#line 5029 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 5028 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5030 - MOVE_EARTHQUAKE, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - MOVE_AERIAL_ACE, - }, - }, - }, - }, -#line 5035 - [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_1] = - { -#line 5036 - .trainerName = _("TATE&LIZA"), -#line 5037 - .trainerClass = TRAINER_CLASS_LEADER, -#line 5038 - .trainerPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, - .encounterMusic_gender = -#line 5040 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 5041 - .items = { ITEM_HYPER_POTION, ITEM_HYPER_POTION, ITEM_HYPER_POTION, ITEM_HYPER_POTION }, -#line 5042 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5043 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 5045 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5047 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 5046 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5048 - MOVE_EARTHQUAKE, - MOVE_ANCIENT_POWER, - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 5053 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5055 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 5054 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5056 - MOVE_PSYCHIC, - MOVE_SUNNY_DAY, - MOVE_CONFUSE_RAY, - MOVE_CALM_MIND, - }, - }, - { -#line 5061 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5061 - .heldItem = ITEM_SITRUS_BERRY, -#line 5063 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 5062 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5064 - MOVE_LIGHT_SCREEN, - MOVE_PSYCHIC, - MOVE_HYPNOSIS, - MOVE_CALM_MIND, - }, - }, - { -#line 5069 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5069 - .heldItem = ITEM_SITRUS_BERRY, -#line 5071 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 5070 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5072 - MOVE_SUNNY_DAY, - MOVE_SOLAR_BEAM, - MOVE_PSYCHIC, - MOVE_FLAMETHROWER, - }, - }, - }, - }, -#line 5077 - [DIFFICULTY_NORMAL][TRAINER_JUAN_1] = - { -#line 5078 - .trainerName = _("JUAN"), -#line 5079 - .trainerClass = TRAINER_CLASS_LEADER, -#line 5080 - .trainerPic = TRAINER_PIC_LEADER_JUAN, - .encounterMusic_gender = -#line 5082 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5083 - .items = { ITEM_HYPER_POTION, ITEM_HYPER_POTION }, -#line 5084 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5085 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 5087 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5089 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5088 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5090 - MOVE_WATER_PULSE, - MOVE_ATTRACT, - MOVE_SWEET_KISS, - MOVE_FLAIL, - }, - }, - { -#line 5095 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5097 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5096 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5098 - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - MOVE_AMNESIA, - MOVE_EARTHQUAKE, - }, - }, - { -#line 5103 - .species = SPECIES_SEALEO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5105 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5104 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5106 - MOVE_ENCORE, - MOVE_BODY_SLAM, - MOVE_AURORA_BEAM, - MOVE_WATER_PULSE, - }, - }, - { -#line 5111 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5113 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5112 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5114 - MOVE_WATER_PULSE, - MOVE_CRABHAMMER, - MOVE_TAUNT, - MOVE_LEER, - }, - }, - { -#line 5119 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5119 - .heldItem = ITEM_CHESTO_BERRY, -#line 5121 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 5120 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5122 - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_ICE_BEAM, - MOVE_REST, - }, - }, - }, - }, -#line 5127 - [DIFFICULTY_NORMAL][TRAINER_JERRY_1] = - { -#line 5128 - .trainerName = _("JERRY"), -#line 5129 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5130 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5132 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5133 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5134 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5136 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5138 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5137 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5140 - [DIFFICULTY_NORMAL][TRAINER_TED] = - { -#line 5141 - .trainerName = _("TED"), -#line 5142 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5143 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5145 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5146 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5147 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5149 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5151 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5150 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5153 - [DIFFICULTY_NORMAL][TRAINER_PAUL] = - { -#line 5154 - .trainerName = _("PAUL"), -#line 5155 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5156 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5158 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5159 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5160 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 5162 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5164 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5163 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5166 - .species = SPECIES_ODDISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5168 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5167 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5170 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5172 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5171 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5174 - [DIFFICULTY_NORMAL][TRAINER_JERRY_2] = - { -#line 5175 - .trainerName = _("JERRY"), -#line 5176 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5177 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5179 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5180 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5181 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5183 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5185 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5184 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5187 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5189 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5188 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5191 - [DIFFICULTY_NORMAL][TRAINER_JERRY_3] = - { -#line 5192 - .trainerName = _("JERRY"), -#line 5193 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5194 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5196 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5197 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5198 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5200 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5202 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5201 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5204 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5206 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5205 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5208 - [DIFFICULTY_NORMAL][TRAINER_JERRY_4] = - { -#line 5209 - .trainerName = _("JERRY"), -#line 5210 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5211 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5213 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5214 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5215 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5217 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5219 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5218 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5221 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5223 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5222 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5225 - [DIFFICULTY_NORMAL][TRAINER_JERRY_5] = - { -#line 5226 - .trainerName = _("JERRY"), -#line 5227 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5228 - .trainerPic = TRAINER_PIC_SCHOOL_KID_M, - .encounterMusic_gender = -#line 5230 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5231 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5232 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 5234 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5236 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5235 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5238 - .species = SPECIES_BANETTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5240 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5239 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5242 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5244 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5243 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5246 - [DIFFICULTY_NORMAL][TRAINER_KAREN_1] = - { -#line 5247 - .trainerName = _("KAREN"), -#line 5248 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5249 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5250 -F_TRAINER_FEMALE | -#line 5251 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5252 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5253 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5255 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5257 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5256 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5259 - [DIFFICULTY_NORMAL][TRAINER_GEORGIA] = - { -#line 5260 - .trainerName = _("GEORGIA"), -#line 5261 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5262 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5263 -F_TRAINER_FEMALE | -#line 5264 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5265 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5266 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5268 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5270 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5269 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5272 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5274 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5273 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5276 - [DIFFICULTY_NORMAL][TRAINER_KAREN_2] = - { -#line 5277 - .trainerName = _("KAREN"), -#line 5278 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5279 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5280 -F_TRAINER_FEMALE | -#line 5281 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5282 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5283 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5285 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5287 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5286 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5289 - .species = SPECIES_WHISMUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5291 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5290 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5293 - [DIFFICULTY_NORMAL][TRAINER_KAREN_3] = - { -#line 5294 - .trainerName = _("KAREN"), -#line 5295 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5296 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5297 -F_TRAINER_FEMALE | -#line 5298 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5299 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5300 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5302 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5304 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5303 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5306 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5308 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5307 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5310 - [DIFFICULTY_NORMAL][TRAINER_KAREN_4] = - { -#line 5311 - .trainerName = _("KAREN"), -#line 5312 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5313 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5314 -F_TRAINER_FEMALE | -#line 5315 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5316 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5317 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5319 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5321 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5320 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5323 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5325 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5324 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5327 - [DIFFICULTY_NORMAL][TRAINER_KAREN_5] = - { -#line 5328 - .trainerName = _("KAREN"), -#line 5329 - .trainerClass = TRAINER_CLASS_SCHOOL_KID, -#line 5330 - .trainerPic = TRAINER_PIC_SCHOOL_KID_F, - .encounterMusic_gender = -#line 5331 -F_TRAINER_FEMALE | -#line 5332 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 5333 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5334 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5336 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5338 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5337 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5340 - .species = SPECIES_EXPLOUD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5342 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5341 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5344 - [DIFFICULTY_NORMAL][TRAINER_KATE_AND_JOY] = - { -#line 5345 - .trainerName = _("KATE & JOY"), -#line 5346 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5347 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5349 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5350 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5353 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5355 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5354 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5356 - MOVE_HYPNOSIS, - MOVE_PSYBEAM, - MOVE_DIZZY_PUNCH, - MOVE_TEETER_DANCE, - }, - }, - { -#line 5361 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5363 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5362 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5364 - MOVE_FOCUS_PUNCH, - MOVE_YAWN, - MOVE_SLACK_OFF, - MOVE_FEINT_ATTACK, - }, - }, - }, - }, -#line 5369 - [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_1] = - { -#line 5370 - .trainerName = _("ANNA & MEG"), -#line 5371 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5372 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5374 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5375 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5376 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5378 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5380 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5379 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5381 - MOVE_GROWL, - MOVE_TAIL_WHIP, - MOVE_HEADBUTT, - MOVE_ODOR_SLEUTH, - }, - }, - { -#line 5386 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5388 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5387 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5389 - MOVE_TACKLE, - MOVE_FOCUS_ENERGY, - MOVE_ARM_THRUST, - }, - }, - }, - }, -#line 5393 - [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_2] = - { -#line 5394 - .trainerName = _("ANNA & MEG"), -#line 5395 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5396 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5398 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5399 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5400 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5402 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5404 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5403 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5405 - MOVE_GROWL, - MOVE_TAIL_WHIP, - MOVE_HEADBUTT, - MOVE_ODOR_SLEUTH, - }, - }, - { -#line 5410 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5412 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5411 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5413 - MOVE_TACKLE, - MOVE_FOCUS_ENERGY, - MOVE_ARM_THRUST, - }, - }, - }, - }, -#line 5417 - [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_3] = - { -#line 5418 - .trainerName = _("ANNA & MEG"), -#line 5419 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5420 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5422 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5423 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5424 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5426 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5428 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5427 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5429 - MOVE_GROWL, - MOVE_TAIL_WHIP, - MOVE_HEADBUTT, - MOVE_ODOR_SLEUTH, - }, - }, - { -#line 5434 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5436 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5435 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5437 - MOVE_TACKLE, - MOVE_FOCUS_ENERGY, - MOVE_ARM_THRUST, - }, - }, - }, - }, -#line 5441 - [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_4] = - { -#line 5442 - .trainerName = _("ANNA & MEG"), -#line 5443 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5444 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5446 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5447 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5448 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5450 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5452 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5451 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5453 - MOVE_GROWL, - MOVE_TAIL_WHIP, - MOVE_HEADBUTT, - MOVE_ODOR_SLEUTH, - }, - }, - { -#line 5458 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5460 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5459 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5461 - MOVE_TACKLE, - MOVE_FOCUS_ENERGY, - MOVE_ARM_THRUST, - }, - }, - }, - }, -#line 5465 - [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_5] = - { -#line 5466 - .trainerName = _("ANNA & MEG"), -#line 5467 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 5468 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 5470 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5471 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 5472 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5474 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5476 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5475 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5477 - MOVE_GROWL, - MOVE_TAIL_WHIP, - MOVE_HEADBUTT, - MOVE_ODOR_SLEUTH, - }, - }, - { -#line 5482 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5484 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5483 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5485 - MOVE_TACKLE, - MOVE_FOCUS_ENERGY, - MOVE_ARM_THRUST, - }, - }, - }, - }, -#line 5489 - [DIFFICULTY_NORMAL][TRAINER_VICTOR] = - { -#line 5490 - .trainerName = _("VICTOR"), -#line 5491 - .trainerClass = TRAINER_CLASS_WINSTRATE, -#line 5492 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5494 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5495 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5496 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5498 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5498 - .heldItem = ITEM_ORAN_BERRY, -#line 5500 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5499 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5502 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5502 - .heldItem = ITEM_ORAN_BERRY, -#line 5504 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5503 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5506 - [DIFFICULTY_NORMAL][TRAINER_MIGUEL_1] = - { -#line 5507 - .trainerName = _("MIGUEL"), -#line 5508 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5509 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5511 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5512 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5513 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5515 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5515 - .heldItem = ITEM_ORAN_BERRY, -#line 5517 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5516 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5519 - [DIFFICULTY_NORMAL][TRAINER_COLTON] = - { -#line 5520 - .trainerName = _("COLTON"), -#line 5521 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5522 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5524 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5525 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5526 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 5528 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5528 - .heldItem = ITEM_ORAN_BERRY, -#line 5530 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5529 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5531 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - { -#line 5536 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5536 - .heldItem = ITEM_ORAN_BERRY, -#line 5538 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5537 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5539 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - { -#line 5544 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5544 - .heldItem = ITEM_ORAN_BERRY, -#line 5546 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5545 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5547 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - { -#line 5552 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5552 - .heldItem = ITEM_ORAN_BERRY, -#line 5554 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5553 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5555 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - { -#line 5560 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5560 - .heldItem = ITEM_ORAN_BERRY, -#line 5562 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5561 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5563 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - { -#line 5568 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5568 - .heldItem = ITEM_ORAN_BERRY, -#line 5570 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5569 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5571 - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - MOVE_HEAL_BELL, - }, - }, - }, - }, -#line 5576 - [DIFFICULTY_NORMAL][TRAINER_MIGUEL_2] = - { -#line 5577 - .trainerName = _("MIGUEL"), -#line 5578 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5579 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5581 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5582 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5583 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5585 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5585 - .heldItem = ITEM_ORAN_BERRY, -#line 5587 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5586 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5589 - [DIFFICULTY_NORMAL][TRAINER_MIGUEL_3] = - { -#line 5590 - .trainerName = _("MIGUEL"), -#line 5591 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5592 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5594 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5595 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5596 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5598 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5598 - .heldItem = ITEM_ORAN_BERRY, -#line 5600 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5599 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5602 - [DIFFICULTY_NORMAL][TRAINER_MIGUEL_4] = - { -#line 5603 - .trainerName = _("MIGUEL"), -#line 5604 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5605 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5607 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5608 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5609 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5611 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5611 - .heldItem = ITEM_ORAN_BERRY, -#line 5613 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5612 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5615 - [DIFFICULTY_NORMAL][TRAINER_MIGUEL_5] = - { -#line 5616 - .trainerName = _("MIGUEL"), -#line 5617 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5618 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 5620 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5621 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5622 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5624 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5624 - .heldItem = ITEM_SITRUS_BERRY, -#line 5626 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5625 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5628 - [DIFFICULTY_NORMAL][TRAINER_VICTORIA] = - { -#line 5629 - .trainerName = _("VICTORIA"), -#line 5630 - .trainerClass = TRAINER_CLASS_WINSTRATE, -#line 5631 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5632 -F_TRAINER_FEMALE | -#line 5633 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5634 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5635 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5637 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5637 - .heldItem = ITEM_ORAN_BERRY, -#line 5639 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 5638 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5641 - [DIFFICULTY_NORMAL][TRAINER_VANESSA] = - { -#line 5642 - .trainerName = _("VANESSA"), -#line 5643 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5644 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5645 -F_TRAINER_FEMALE | -#line 5646 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5647 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5648 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5650 - .species = SPECIES_PIKACHU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5650 - .heldItem = ITEM_ORAN_BERRY, -#line 5652 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5651 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5654 - [DIFFICULTY_NORMAL][TRAINER_BETHANY] = - { -#line 5655 - .trainerName = _("BETHANY"), -#line 5656 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5657 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5658 -F_TRAINER_FEMALE | -#line 5659 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5660 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5661 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 5663 - .species = SPECIES_AZURILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5663 - .heldItem = ITEM_ORAN_BERRY, -#line 5665 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 5664 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5667 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5667 - .heldItem = ITEM_ORAN_BERRY, -#line 5669 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 5668 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5671 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5671 - .heldItem = ITEM_ORAN_BERRY, -#line 5673 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 5672 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5675 - [DIFFICULTY_NORMAL][TRAINER_ISABEL_1] = - { -#line 5676 - .trainerName = _("ISABEL"), -#line 5677 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5678 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5679 -F_TRAINER_FEMALE | -#line 5680 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5681 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5682 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5684 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5684 - .heldItem = ITEM_ORAN_BERRY, -#line 5686 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5685 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5688 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5688 - .heldItem = ITEM_ORAN_BERRY, -#line 5690 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5689 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5692 - [DIFFICULTY_NORMAL][TRAINER_ISABEL_2] = - { -#line 5693 - .trainerName = _("ISABEL"), -#line 5694 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5695 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5696 -F_TRAINER_FEMALE | -#line 5697 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5698 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5699 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5701 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5701 - .heldItem = ITEM_ORAN_BERRY, -#line 5703 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5702 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5705 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5705 - .heldItem = ITEM_ORAN_BERRY, -#line 5707 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 5706 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5709 - [DIFFICULTY_NORMAL][TRAINER_ISABEL_3] = - { -#line 5710 - .trainerName = _("ISABEL"), -#line 5711 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5712 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5713 -F_TRAINER_FEMALE | -#line 5714 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5715 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5716 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5718 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5718 - .heldItem = ITEM_ORAN_BERRY, -#line 5720 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5719 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5722 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5722 - .heldItem = ITEM_ORAN_BERRY, -#line 5724 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 5723 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5726 - [DIFFICULTY_NORMAL][TRAINER_ISABEL_4] = - { -#line 5727 - .trainerName = _("ISABEL"), -#line 5728 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5729 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5730 -F_TRAINER_FEMALE | -#line 5731 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5732 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5733 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5735 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5735 - .heldItem = ITEM_ORAN_BERRY, -#line 5737 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5736 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5739 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5739 - .heldItem = ITEM_ORAN_BERRY, -#line 5741 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 5740 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5743 - [DIFFICULTY_NORMAL][TRAINER_ISABEL_5] = - { -#line 5744 - .trainerName = _("ISABEL"), -#line 5745 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 5746 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 5747 -F_TRAINER_FEMALE | -#line 5748 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 5749 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5750 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5752 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5752 - .heldItem = ITEM_SITRUS_BERRY, -#line 5754 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5753 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5756 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5756 - .heldItem = ITEM_SITRUS_BERRY, -#line 5758 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 5757 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5760 - [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_1] = - { -#line 5761 - .trainerName = _("TIMOTHY"), -#line 5762 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5763 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 5765 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5766 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5767 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5769 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5771 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5770 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5773 - [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_2] = - { -#line 5774 - .trainerName = _("TIMOTHY"), -#line 5775 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5776 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 5778 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5779 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5780 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5782 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5784 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 5783 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5785 - MOVE_ARM_THRUST, - MOVE_KNOCK_OFF, - MOVE_SAND_ATTACK, - MOVE_DIG, - }, - }, - }, - }, -#line 5790 - [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_3] = - { -#line 5791 - .trainerName = _("TIMOTHY"), -#line 5792 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5793 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 5795 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5796 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5797 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5799 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5801 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 5800 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5802 - MOVE_ARM_THRUST, - MOVE_KNOCK_OFF, - MOVE_SAND_ATTACK, - MOVE_DIG, - }, - }, - }, - }, -#line 5807 - [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_4] = - { -#line 5808 - .trainerName = _("TIMOTHY"), -#line 5809 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5810 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 5812 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5813 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5814 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5816 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5818 - .iv = TRAINER_PARTY_IVS(27, 27, 27, 27, 27, 27), -#line 5817 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5819 - MOVE_ARM_THRUST, - MOVE_BELLY_DRUM, - MOVE_SAND_ATTACK, - MOVE_DIG, - }, - }, - }, - }, -#line 5824 - [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_5] = - { -#line 5825 - .trainerName = _("TIMOTHY"), -#line 5826 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5827 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 5829 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5830 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5831 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5833 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5835 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 5834 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5836 - MOVE_ARM_THRUST, - MOVE_BELLY_DRUM, - MOVE_SAND_ATTACK, - MOVE_DIG, - }, - }, - }, - }, -#line 5841 - [DIFFICULTY_NORMAL][TRAINER_VICKY] = - { -#line 5842 - .trainerName = _("VICKY"), -#line 5843 - .trainerClass = TRAINER_CLASS_WINSTRATE, -#line 5844 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5845 -F_TRAINER_FEMALE | -#line 5846 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5847 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5848 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5850 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5852 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5851 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5853 - MOVE_HIGH_JUMP_KICK, - MOVE_MEDITATE, - MOVE_CONFUSION, - MOVE_DETECT, - }, - }, - }, - }, -#line 5858 - [DIFFICULTY_NORMAL][TRAINER_SHELBY_1] = - { -#line 5859 - .trainerName = _("SHELBY"), -#line 5860 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5861 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5862 -F_TRAINER_FEMALE | -#line 5863 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5864 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5865 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5867 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5869 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5868 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5871 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5873 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 5872 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5875 - [DIFFICULTY_NORMAL][TRAINER_SHELBY_2] = - { -#line 5876 - .trainerName = _("SHELBY"), -#line 5877 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5878 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5879 -F_TRAINER_FEMALE | -#line 5880 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5881 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5882 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5884 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5886 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 5885 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5888 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5890 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 5889 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5892 - [DIFFICULTY_NORMAL][TRAINER_SHELBY_3] = - { -#line 5893 - .trainerName = _("SHELBY"), -#line 5894 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5895 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5896 -F_TRAINER_FEMALE | -#line 5897 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5898 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5899 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5901 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5903 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 5902 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5905 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5907 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 5906 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5909 - [DIFFICULTY_NORMAL][TRAINER_SHELBY_4] = - { -#line 5910 - .trainerName = _("SHELBY"), -#line 5911 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5912 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5913 -F_TRAINER_FEMALE | -#line 5914 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5915 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5916 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5918 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5920 - .iv = TRAINER_PARTY_IVS(27, 27, 27, 27, 27, 27), -#line 5919 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5922 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5924 - .iv = TRAINER_PARTY_IVS(27, 27, 27, 27, 27, 27), -#line 5923 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5926 - [DIFFICULTY_NORMAL][TRAINER_SHELBY_5] = - { -#line 5927 - .trainerName = _("SHELBY"), -#line 5928 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 5929 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 5930 -F_TRAINER_FEMALE | -#line 5931 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 5932 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5933 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5935 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5937 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 5936 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5939 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5941 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 5940 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5943 - [DIFFICULTY_NORMAL][TRAINER_CALVIN_1] = - { -#line 5944 - .trainerName = _("CALVIN"), -#line 5945 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 5946 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 5948 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5949 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5950 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5952 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5954 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5953 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5956 - [DIFFICULTY_NORMAL][TRAINER_BILLY] = - { -#line 5957 - .trainerName = _("BILLY"), -#line 5958 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 5959 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 5961 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5962 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5963 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5965 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5967 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5966 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 5969 - .species = SPECIES_SEEDOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5971 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 5970 - .lvl = 7, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 5973 - [DIFFICULTY_NORMAL][TRAINER_JOSH] = - { -#line 5974 - .trainerName = _("JOSH"), -#line 5975 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 5976 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 5978 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5979 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5980 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 5982 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5984 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 5983 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 5985 - MOVE_TACKLE, - }, - }, - }, - }, -#line 5987 - [DIFFICULTY_NORMAL][TRAINER_TOMMY] = - { -#line 5988 - .trainerName = _("TOMMY"), -#line 5989 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 5990 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 5992 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 5993 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 5994 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 5996 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 5998 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 5997 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6000 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6002 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 6001 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6004 - [DIFFICULTY_NORMAL][TRAINER_JOEY] = - { -#line 6005 - .trainerName = _("JOEY"), -#line 6006 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6007 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6009 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6010 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6011 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6013 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6015 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6014 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6017 - [DIFFICULTY_NORMAL][TRAINER_BEN] = - { -#line 6018 - .trainerName = _("BEN"), -#line 6019 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6020 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6022 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6023 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6024 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6026 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6028 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 6027 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6029 - MOVE_HEADBUTT, - MOVE_SAND_ATTACK, - MOVE_GROWL, - MOVE_THUNDERBOLT, - }, - }, - { -#line 6034 - .species = SPECIES_GULPIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6036 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 6035 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6037 - MOVE_AMNESIA, - MOVE_SLUDGE, - MOVE_YAWN, - MOVE_POUND, - }, - }, - }, - }, -#line 6042 - [DIFFICULTY_NORMAL][TRAINER_QUINCY] = - { -#line 6043 - .trainerName = _("QUINCY"), -#line 6044 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 6045 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 6047 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 6048 - .items = { ITEM_FULL_RESTORE }, -#line 6049 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6050 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6052 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6054 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 6053 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6055 - MOVE_ATTRACT, - MOVE_ICE_BEAM, - MOVE_THUNDERBOLT, - MOVE_FLAMETHROWER, - }, - }, - { -#line 6060 - .species = SPECIES_DUSCLOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6062 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 6061 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6063 - MOVE_SKILL_SWAP, - MOVE_PROTECT, - MOVE_WILL_O_WISP, - MOVE_TOXIC, - }, - }, - }, - }, -#line 6068 - [DIFFICULTY_NORMAL][TRAINER_KATELYNN] = - { -#line 6069 - .trainerName = _("KATELYNN"), -#line 6070 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 6071 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 6072 -F_TRAINER_FEMALE | -#line 6073 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 6074 - .items = { ITEM_FULL_RESTORE }, -#line 6075 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6076 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6078 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6080 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 6079 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6081 - MOVE_SKILL_SWAP, - MOVE_PSYCHIC, - MOVE_THUNDERBOLT, - MOVE_CALM_MIND, - }, - }, - { -#line 6086 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6088 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 6087 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6089 - MOVE_EARTHQUAKE, - MOVE_SHADOW_BALL, - MOVE_AERIAL_ACE, - MOVE_BRICK_BREAK, - }, - }, - }, - }, -#line 6094 - [DIFFICULTY_NORMAL][TRAINER_JAYLEN] = - { -#line 6095 - .trainerName = _("JAYLEN"), -#line 6096 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6097 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6099 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6100 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6101 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6103 - .species = SPECIES_TRAPINCH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6105 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6104 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6107 - [DIFFICULTY_NORMAL][TRAINER_DILLON] = - { -#line 6108 - .trainerName = _("DILLON"), -#line 6109 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6110 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6112 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6113 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6114 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6116 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6118 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6117 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6120 - [DIFFICULTY_NORMAL][TRAINER_CALVIN_2] = - { -#line 6121 - .trainerName = _("CALVIN"), -#line 6122 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6123 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6125 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6126 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6127 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6129 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6131 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6130 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6133 - [DIFFICULTY_NORMAL][TRAINER_CALVIN_3] = - { -#line 6134 - .trainerName = _("CALVIN"), -#line 6135 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6136 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6138 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6139 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6140 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6142 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6144 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6143 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6146 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6148 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6147 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6150 - [DIFFICULTY_NORMAL][TRAINER_CALVIN_4] = - { -#line 6151 - .trainerName = _("CALVIN"), -#line 6152 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6153 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6155 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6156 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6157 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6159 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6161 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6160 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6163 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6165 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6164 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6167 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6169 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6168 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6171 - [DIFFICULTY_NORMAL][TRAINER_CALVIN_5] = - { -#line 6172 - .trainerName = _("CALVIN"), -#line 6173 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6174 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6176 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6177 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6178 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6180 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6182 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6181 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6184 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6186 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6185 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6188 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6190 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6189 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6192 - [DIFFICULTY_NORMAL][TRAINER_EDDIE] = - { -#line 6193 - .trainerName = _("EDDIE"), -#line 6194 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6195 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6197 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6198 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6199 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6201 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6203 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6202 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6205 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6207 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6206 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6209 - [DIFFICULTY_NORMAL][TRAINER_ALLEN] = - { -#line 6210 - .trainerName = _("ALLEN"), -#line 6211 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6212 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6214 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6215 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6216 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6218 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6220 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6219 - .lvl = 4, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6222 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6224 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6223 - .lvl = 3, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6226 - [DIFFICULTY_NORMAL][TRAINER_TIMMY] = - { -#line 6227 - .trainerName = _("TIMMY"), -#line 6228 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6229 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6231 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6232 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6233 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6235 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6237 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6236 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6239 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6241 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6240 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6243 - [DIFFICULTY_NORMAL][TRAINER_WALLACE] = - { -#line 6244 - .trainerName = _("WALLACE"), -#line 6245 - .trainerClass = TRAINER_CLASS_CHAMPION, -#line 6246 - .trainerPic = TRAINER_PIC_CHAMPION_WALLACE, - .encounterMusic_gender = -#line 6248 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6249 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 6250 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6251 - .aiFlags = AI_FLAG_BASIC_TRAINER, -#line 6252 - .mugshotColor = MUGSHOT_COLOR_YELLOW, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 6254 - .species = SPECIES_WAILORD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6256 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6255 - .lvl = 57, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6257 - MOVE_RAIN_DANCE, - MOVE_WATER_SPOUT, - MOVE_DOUBLE_EDGE, - MOVE_BLIZZARD, - }, - }, - { -#line 6262 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6264 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6263 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6265 - MOVE_TOXIC, - MOVE_HYDRO_PUMP, - MOVE_SLUDGE_BOMB, - MOVE_ICE_BEAM, - }, - }, - { -#line 6270 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6272 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6271 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6273 - MOVE_GIGA_DRAIN, - MOVE_SURF, - MOVE_LEECH_SEED, - MOVE_DOUBLE_TEAM, - }, - }, - { -#line 6278 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6280 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6279 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6281 - MOVE_EARTHQUAKE, - MOVE_SURF, - MOVE_AMNESIA, - MOVE_HYPER_BEAM, - }, - }, - { -#line 6286 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6288 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6287 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6289 - MOVE_DRAGON_DANCE, - MOVE_EARTHQUAKE, - MOVE_HYPER_BEAM, - MOVE_SURF, - }, - }, - { -#line 6294 - .species = SPECIES_MILOTIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6294 - .heldItem = ITEM_SITRUS_BERRY, -#line 6296 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 6295 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 6297 - MOVE_RECOVER, - MOVE_SURF, - MOVE_ICE_BEAM, - MOVE_TOXIC, - }, - }, - }, - }, -#line 6302 - [DIFFICULTY_NORMAL][TRAINER_ANDREW] = - { -#line 6303 - .trainerName = _("ANDREW"), -#line 6304 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6305 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6307 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6308 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6309 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6311 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6313 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6312 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6315 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6317 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6316 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6319 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6321 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6320 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6323 - [DIFFICULTY_NORMAL][TRAINER_IVAN] = - { -#line 6324 - .trainerName = _("IVAN"), -#line 6325 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6326 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6328 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6329 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6330 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6332 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6334 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6333 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6336 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6338 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6337 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6340 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6342 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6341 - .lvl = 7, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6344 - [DIFFICULTY_NORMAL][TRAINER_CLAUDE] = - { -#line 6345 - .trainerName = _("CLAUDE"), -#line 6346 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6347 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6349 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6350 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6353 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6355 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6354 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6357 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6359 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6358 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6361 - .species = SPECIES_BARBOACH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6363 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6362 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6365 - [DIFFICULTY_NORMAL][TRAINER_ELLIOT_1] = - { -#line 6366 - .trainerName = _("ELLIOT"), -#line 6367 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6368 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6370 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6371 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6372 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6374 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6376 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6375 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6378 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6380 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6379 - .lvl = 7, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6382 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6384 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6383 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6386 - [DIFFICULTY_NORMAL][TRAINER_NED] = - { -#line 6387 - .trainerName = _("NED"), -#line 6388 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6389 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6391 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6392 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6393 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6395 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6397 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6396 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6399 - [DIFFICULTY_NORMAL][TRAINER_DALE] = - { -#line 6400 - .trainerName = _("DALE"), -#line 6401 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6402 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6404 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6405 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6406 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 6408 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6410 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6409 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6412 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6414 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6413 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6416 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6418 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6417 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6420 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6422 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6421 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6424 - [DIFFICULTY_NORMAL][TRAINER_NOLAN] = - { -#line 6425 - .trainerName = _("NOLAN"), -#line 6426 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6427 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6429 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6430 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6431 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6433 - .species = SPECIES_BARBOACH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6435 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6434 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6437 - [DIFFICULTY_NORMAL][TRAINER_BARNY] = - { -#line 6438 - .trainerName = _("BARNY"), -#line 6439 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6440 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6442 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6443 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6444 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6446 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6448 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6447 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6450 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6452 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6451 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6454 - [DIFFICULTY_NORMAL][TRAINER_WADE] = - { -#line 6455 - .trainerName = _("WADE"), -#line 6456 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6457 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6459 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6460 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6461 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6463 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6465 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6464 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6467 - [DIFFICULTY_NORMAL][TRAINER_CARTER] = - { -#line 6468 - .trainerName = _("CARTER"), -#line 6469 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6470 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6472 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6473 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6474 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6476 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6478 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6477 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6480 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6482 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6481 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6484 - [DIFFICULTY_NORMAL][TRAINER_ELLIOT_2] = - { -#line 6485 - .trainerName = _("ELLIOT"), -#line 6486 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6487 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6489 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6490 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6491 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6493 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6495 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6494 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6497 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6499 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6498 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6501 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6503 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6502 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6505 - [DIFFICULTY_NORMAL][TRAINER_ELLIOT_3] = - { -#line 6506 - .trainerName = _("ELLIOT"), -#line 6507 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6508 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6510 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6511 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6512 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 6514 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6516 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6515 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6518 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6520 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6519 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6522 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6524 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6523 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6526 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6528 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6527 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6530 - [DIFFICULTY_NORMAL][TRAINER_ELLIOT_4] = - { -#line 6531 - .trainerName = _("ELLIOT"), -#line 6532 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6533 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6535 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6536 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6537 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 6539 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6541 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6540 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6543 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6545 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6544 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6547 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6549 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6548 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6551 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6553 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6552 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6555 - [DIFFICULTY_NORMAL][TRAINER_ELLIOT_5] = - { -#line 6556 - .trainerName = _("ELLIOT"), -#line 6557 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6558 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6560 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6561 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6562 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 6564 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6566 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6565 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6568 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6570 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6569 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6572 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6574 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6573 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6576 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6578 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6577 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6580 - [DIFFICULTY_NORMAL][TRAINER_RONALD] = - { -#line 6581 - .trainerName = _("RONALD"), -#line 6582 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 6583 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 6585 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 6586 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6587 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 6589 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6591 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6590 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6593 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6595 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6594 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6597 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6599 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6598 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6601 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6603 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6602 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6605 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6607 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6606 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6609 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6611 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6610 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6613 - [DIFFICULTY_NORMAL][TRAINER_JACOB] = - { -#line 6614 - .trainerName = _("JACOB"), -#line 6615 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6616 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6618 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6619 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6620 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6622 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6624 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6623 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6626 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6628 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6627 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6630 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6632 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 6631 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6634 - [DIFFICULTY_NORMAL][TRAINER_ANTHONY] = - { -#line 6635 - .trainerName = _("ANTHONY"), -#line 6636 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6637 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6639 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6640 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6641 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6643 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6645 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6644 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6647 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6649 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6648 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6651 - [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_1] = - { -#line 6652 - .trainerName = _("BENJAMIN"), -#line 6653 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6654 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6656 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6657 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6658 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6660 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6662 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6661 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6664 - [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_2] = - { -#line 6665 - .trainerName = _("BENJAMIN"), -#line 6666 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6667 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6669 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6670 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6671 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6673 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6675 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6674 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6677 - [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_3] = - { -#line 6678 - .trainerName = _("BENJAMIN"), -#line 6679 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6680 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6682 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6683 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6684 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6686 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6688 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6687 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6690 - [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_4] = - { -#line 6691 - .trainerName = _("BENJAMIN"), -#line 6692 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6693 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6695 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6696 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6697 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6699 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6701 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6700 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6703 - [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_5] = - { -#line 6704 - .trainerName = _("BENJAMIN"), -#line 6705 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6706 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6708 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6709 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6710 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6712 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6714 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6713 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6716 - [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_1] = - { -#line 6717 - .trainerName = _("ABIGAIL"), -#line 6718 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6719 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6720 -F_TRAINER_FEMALE | -#line 6721 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6722 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6723 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6725 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6727 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6726 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6729 - [DIFFICULTY_NORMAL][TRAINER_JASMINE] = - { -#line 6730 - .trainerName = _("JASMINE"), -#line 6731 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6732 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6733 -F_TRAINER_FEMALE | -#line 6734 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6735 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6736 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 6738 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6740 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 6739 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6742 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6744 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 6743 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6746 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6748 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6747 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6750 - [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_2] = - { -#line 6751 - .trainerName = _("ABIGAIL"), -#line 6752 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6753 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6754 -F_TRAINER_FEMALE | -#line 6755 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6756 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6757 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6759 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6761 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6760 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6763 - [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_3] = - { -#line 6764 - .trainerName = _("ABIGAIL"), -#line 6765 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6766 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6767 -F_TRAINER_FEMALE | -#line 6768 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6769 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6770 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6772 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6774 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6773 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6776 - [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_4] = - { -#line 6777 - .trainerName = _("ABIGAIL"), -#line 6778 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6779 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6780 -F_TRAINER_FEMALE | -#line 6781 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6782 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6783 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6785 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6787 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6786 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6789 - [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_5] = - { -#line 6790 - .trainerName = _("ABIGAIL"), -#line 6791 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6792 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6793 -F_TRAINER_FEMALE | -#line 6794 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6795 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6796 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6798 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6800 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6799 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6802 - [DIFFICULTY_NORMAL][TRAINER_DYLAN_1] = - { -#line 6803 - .trainerName = _("DYLAN"), -#line 6804 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6805 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6807 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6808 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6809 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6811 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6813 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6812 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6815 - [DIFFICULTY_NORMAL][TRAINER_DYLAN_2] = - { -#line 6816 - .trainerName = _("DYLAN"), -#line 6817 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6818 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6820 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6821 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6822 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6824 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6826 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6825 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6828 - [DIFFICULTY_NORMAL][TRAINER_DYLAN_3] = - { -#line 6829 - .trainerName = _("DYLAN"), -#line 6830 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6831 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6833 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6834 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6835 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6837 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6839 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6838 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6841 - [DIFFICULTY_NORMAL][TRAINER_DYLAN_4] = - { -#line 6842 - .trainerName = _("DYLAN"), -#line 6843 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6844 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6846 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6847 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6848 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6850 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6852 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6851 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6854 - [DIFFICULTY_NORMAL][TRAINER_DYLAN_5] = - { -#line 6855 - .trainerName = _("DYLAN"), -#line 6856 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6857 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6859 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6860 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6861 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6863 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6865 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6864 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6867 - [DIFFICULTY_NORMAL][TRAINER_MARIA_1] = - { -#line 6868 - .trainerName = _("MARIA"), -#line 6869 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6870 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6871 -F_TRAINER_FEMALE | -#line 6872 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6873 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6874 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6876 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6878 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6877 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6880 - [DIFFICULTY_NORMAL][TRAINER_MARIA_2] = - { -#line 6881 - .trainerName = _("MARIA"), -#line 6882 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6883 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6884 -F_TRAINER_FEMALE | -#line 6885 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6886 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6887 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6889 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6891 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 6890 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6893 - [DIFFICULTY_NORMAL][TRAINER_MARIA_3] = - { -#line 6894 - .trainerName = _("MARIA"), -#line 6895 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6896 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6897 -F_TRAINER_FEMALE | -#line 6898 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6899 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6900 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6902 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6904 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 6903 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6906 - [DIFFICULTY_NORMAL][TRAINER_MARIA_4] = - { -#line 6907 - .trainerName = _("MARIA"), -#line 6908 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6909 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6910 -F_TRAINER_FEMALE | -#line 6911 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6912 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6913 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6915 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6917 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 6916 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6919 - [DIFFICULTY_NORMAL][TRAINER_MARIA_5] = - { -#line 6920 - .trainerName = _("MARIA"), -#line 6921 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6922 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 6923 -F_TRAINER_FEMALE | -#line 6924 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 6925 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6926 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6928 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6930 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 6929 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6932 - [DIFFICULTY_NORMAL][TRAINER_CAMDEN] = - { -#line 6933 - .trainerName = _("CAMDEN"), -#line 6934 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6935 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6937 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 6938 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6939 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6941 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6943 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6942 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6945 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6947 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6946 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6949 - [DIFFICULTY_NORMAL][TRAINER_DEMETRIUS] = - { -#line 6950 - .trainerName = _("DEMETRIUS"), -#line 6951 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 6952 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 6954 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 6955 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6956 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6958 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6960 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6959 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6962 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6964 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6963 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6966 - [DIFFICULTY_NORMAL][TRAINER_ISAIAH_1] = - { -#line 6967 - .trainerName = _("ISAIAH"), -#line 6968 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6969 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6971 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 6972 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6973 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 6975 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6977 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6976 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6979 - [DIFFICULTY_NORMAL][TRAINER_PABLO_1] = - { -#line 6980 - .trainerName = _("PABLO"), -#line 6981 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6982 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 6984 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 6985 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 6986 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 6988 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6990 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6989 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 6992 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 6994 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 6993 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 6996 - [DIFFICULTY_NORMAL][TRAINER_CHASE] = - { -#line 6997 - .trainerName = _("CHASE"), -#line 6998 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 6999 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 7001 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7002 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7003 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7005 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7007 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7006 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7009 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7011 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 7010 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7013 - [DIFFICULTY_NORMAL][TRAINER_ISAIAH_2] = - { -#line 7014 - .trainerName = _("ISAIAH"), -#line 7015 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7016 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 7018 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7019 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7020 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7022 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7024 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 7023 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7026 - [DIFFICULTY_NORMAL][TRAINER_ISAIAH_3] = - { -#line 7027 - .trainerName = _("ISAIAH"), -#line 7028 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7029 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 7031 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7032 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7033 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7035 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7037 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7036 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7039 - [DIFFICULTY_NORMAL][TRAINER_ISAIAH_4] = - { -#line 7040 - .trainerName = _("ISAIAH"), -#line 7041 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7042 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 7044 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7045 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7046 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7048 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7050 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7049 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7052 - [DIFFICULTY_NORMAL][TRAINER_ISAIAH_5] = - { -#line 7053 - .trainerName = _("ISAIAH"), -#line 7054 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7055 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 7057 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7058 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7059 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7061 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7063 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7062 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7065 - [DIFFICULTY_NORMAL][TRAINER_ISOBEL] = - { -#line 7066 - .trainerName = _("ISOBEL"), -#line 7067 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7068 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7069 -F_TRAINER_FEMALE | -#line 7070 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7071 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7072 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7074 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7076 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7075 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7078 - [DIFFICULTY_NORMAL][TRAINER_DONNY] = - { -#line 7079 - .trainerName = _("DONNY"), -#line 7080 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7081 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7082 -F_TRAINER_FEMALE | -#line 7083 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7084 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7085 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7087 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7089 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7088 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7091 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7093 - .iv = TRAINER_PARTY_IVS(19, 19, 19, 19, 19, 19), -#line 7092 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7095 - [DIFFICULTY_NORMAL][TRAINER_TALIA] = - { -#line 7096 - .trainerName = _("TALIA"), -#line 7097 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7098 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7099 -F_TRAINER_FEMALE | -#line 7100 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7101 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7102 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7104 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7106 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7105 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7108 - [DIFFICULTY_NORMAL][TRAINER_KATELYN_1] = - { -#line 7109 - .trainerName = _("KATELYN"), -#line 7110 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7111 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7112 -F_TRAINER_FEMALE | -#line 7113 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7114 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7115 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7117 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7119 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7118 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7121 - [DIFFICULTY_NORMAL][TRAINER_ALLISON] = - { -#line 7122 - .trainerName = _("ALLISON"), -#line 7123 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7124 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7125 -F_TRAINER_FEMALE | -#line 7126 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7127 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7128 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7130 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7132 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7131 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7134 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7136 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 7135 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7138 - [DIFFICULTY_NORMAL][TRAINER_KATELYN_2] = - { -#line 7139 - .trainerName = _("KATELYN"), -#line 7140 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7141 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7142 -F_TRAINER_FEMALE | -#line 7143 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7144 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7145 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7147 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7149 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 7148 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7151 - [DIFFICULTY_NORMAL][TRAINER_KATELYN_3] = - { -#line 7152 - .trainerName = _("KATELYN"), -#line 7153 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7154 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7155 -F_TRAINER_FEMALE | -#line 7156 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7157 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7158 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7160 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7162 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7161 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7164 - [DIFFICULTY_NORMAL][TRAINER_KATELYN_4] = - { -#line 7165 - .trainerName = _("KATELYN"), -#line 7166 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7167 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7168 -F_TRAINER_FEMALE | -#line 7169 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7170 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7171 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7173 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7175 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7174 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7177 - [DIFFICULTY_NORMAL][TRAINER_KATELYN_5] = - { -#line 7178 - .trainerName = _("KATELYN"), -#line 7179 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 7180 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 7181 -F_TRAINER_FEMALE | -#line 7182 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 7183 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7184 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7186 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7188 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7187 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7190 - [DIFFICULTY_NORMAL][TRAINER_NICOLAS_1] = - { -#line 7191 - .trainerName = _("NICOLAS"), -#line 7192 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7193 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7195 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7196 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7197 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7199 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7201 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7200 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7203 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7205 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7204 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7207 - [DIFFICULTY_NORMAL][TRAINER_NICOLAS_2] = - { -#line 7208 - .trainerName = _("NICOLAS"), -#line 7209 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7210 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7212 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7213 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7214 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7216 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7218 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 7217 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7220 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7222 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 7221 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7224 - [DIFFICULTY_NORMAL][TRAINER_NICOLAS_3] = - { -#line 7225 - .trainerName = _("NICOLAS"), -#line 7226 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7227 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7229 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7230 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7231 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7233 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7235 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 7234 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7237 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7239 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 7238 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7241 - [DIFFICULTY_NORMAL][TRAINER_NICOLAS_4] = - { -#line 7242 - .trainerName = _("NICOLAS"), -#line 7243 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7244 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7246 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7247 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7248 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 7250 - .species = SPECIES_BAGON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7252 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7251 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7254 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7256 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7255 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7258 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7260 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7259 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7262 - [DIFFICULTY_NORMAL][TRAINER_NICOLAS_5] = - { -#line 7263 - .trainerName = _("NICOLAS"), -#line 7264 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7265 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7267 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7268 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7269 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 7271 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7273 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 7272 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7275 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7277 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 7276 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7279 - .species = SPECIES_SHELGON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7279 - .heldItem = ITEM_DRAGON_FANG, -#line 7281 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 7280 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7283 - [DIFFICULTY_NORMAL][TRAINER_AARON] = - { -#line 7284 - .trainerName = _("AARON"), -#line 7285 - .trainerClass = TRAINER_CLASS_DRAGON_TAMER, -#line 7286 - .trainerPic = TRAINER_PIC_DRAGON_TAMER, - .encounterMusic_gender = -#line 7288 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7289 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7290 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7292 - .species = SPECIES_BAGON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7294 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 7293 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7295 - MOVE_DRAGON_BREATH, - MOVE_HEADBUTT, - MOVE_FOCUS_ENERGY, - MOVE_EMBER, - }, - }, - }, - }, -#line 7300 - [DIFFICULTY_NORMAL][TRAINER_PERRY] = - { -#line 7301 - .trainerName = _("PERRY"), -#line 7302 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7303 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7305 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7306 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7307 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7309 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7311 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7310 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7313 - [DIFFICULTY_NORMAL][TRAINER_HUGH] = - { -#line 7314 - .trainerName = _("HUGH"), -#line 7315 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7316 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7318 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7319 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7320 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7322 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7324 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7323 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7326 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7328 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7327 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7330 - [DIFFICULTY_NORMAL][TRAINER_PHIL] = - { -#line 7331 - .trainerName = _("PHIL"), -#line 7332 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7333 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7335 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7336 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7337 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7339 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7341 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7340 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7343 - [DIFFICULTY_NORMAL][TRAINER_JARED] = - { -#line 7344 - .trainerName = _("JARED"), -#line 7345 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7346 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7348 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7349 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7350 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 7352 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7354 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7353 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7356 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7358 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7357 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7360 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7362 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7361 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7364 - [DIFFICULTY_NORMAL][TRAINER_HUMBERTO] = - { -#line 7365 - .trainerName = _("HUMBERTO"), -#line 7366 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7367 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7369 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7370 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7371 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7373 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7375 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 7374 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7377 - [DIFFICULTY_NORMAL][TRAINER_PRESLEY] = - { -#line 7378 - .trainerName = _("PRESLEY"), -#line 7379 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7380 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7382 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7383 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7384 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7386 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7388 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7387 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7390 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7392 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7391 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7394 - [DIFFICULTY_NORMAL][TRAINER_EDWARDO] = - { -#line 7395 - .trainerName = _("EDWARDO"), -#line 7396 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7397 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7399 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7400 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7401 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7403 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7405 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 7404 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7407 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7409 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 7408 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7411 - [DIFFICULTY_NORMAL][TRAINER_COLIN] = - { -#line 7412 - .trainerName = _("COLIN"), -#line 7413 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7414 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7416 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7417 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7418 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7420 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7422 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7421 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7424 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7426 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7425 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7428 - [DIFFICULTY_NORMAL][TRAINER_ROBERT_1] = - { -#line 7429 - .trainerName = _("ROBERT"), -#line 7430 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7431 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7433 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7434 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7435 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7437 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7439 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7438 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7441 - [DIFFICULTY_NORMAL][TRAINER_BENNY] = - { -#line 7442 - .trainerName = _("BENNY"), -#line 7443 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7444 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7446 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7447 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7448 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 7450 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7452 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7451 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7454 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7456 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7455 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7458 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7460 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7459 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7462 - [DIFFICULTY_NORMAL][TRAINER_CHESTER] = - { -#line 7463 - .trainerName = _("CHESTER"), -#line 7464 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7465 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7467 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7468 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7469 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7471 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7473 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7472 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7475 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7477 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7476 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7479 - [DIFFICULTY_NORMAL][TRAINER_ROBERT_2] = - { -#line 7480 - .trainerName = _("ROBERT"), -#line 7481 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7482 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7484 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7485 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7486 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7488 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7490 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 7489 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7492 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7494 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 7493 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7496 - [DIFFICULTY_NORMAL][TRAINER_ROBERT_3] = - { -#line 7497 - .trainerName = _("ROBERT"), -#line 7498 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7499 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7501 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7502 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7503 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7505 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7507 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7506 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7509 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7511 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7510 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7513 - [DIFFICULTY_NORMAL][TRAINER_ROBERT_4] = - { -#line 7514 - .trainerName = _("ROBERT"), -#line 7515 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7516 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7518 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7519 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7520 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7522 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7524 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7523 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7526 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7528 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7527 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7530 - [DIFFICULTY_NORMAL][TRAINER_ROBERT_5] = - { -#line 7531 - .trainerName = _("ROBERT"), -#line 7532 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7533 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7535 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7536 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7537 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7539 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7541 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7540 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7543 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7545 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7544 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7547 - [DIFFICULTY_NORMAL][TRAINER_ALEX] = - { -#line 7548 - .trainerName = _("ALEX"), -#line 7549 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7550 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7552 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7553 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7554 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7556 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7558 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 7557 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7560 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7562 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 7561 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7564 - [DIFFICULTY_NORMAL][TRAINER_BECK] = - { -#line 7565 - .trainerName = _("BECK"), -#line 7566 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 7567 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 7569 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7570 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7571 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7573 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7575 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7574 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7577 - [DIFFICULTY_NORMAL][TRAINER_YASU] = - { -#line 7578 - .trainerName = _("YASU"), -#line 7579 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7580 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7582 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7583 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7584 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7586 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7588 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7587 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7590 - [DIFFICULTY_NORMAL][TRAINER_TAKASHI] = - { -#line 7591 - .trainerName = _("TAKASHI"), -#line 7592 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7593 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7595 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7596 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7597 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7599 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7601 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7600 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7603 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7605 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7604 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7607 - [DIFFICULTY_NORMAL][TRAINER_DIANNE] = - { -#line 7608 - .trainerName = _("DIANNE"), -#line 7609 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 7610 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 7611 -F_TRAINER_FEMALE | -#line 7612 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 7613 - .items = { ITEM_FULL_RESTORE }, -#line 7614 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7616 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7618 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7617 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7619 - MOVE_SKILL_SWAP, - MOVE_EARTHQUAKE, - }, - }, - { -#line 7622 - .species = SPECIES_LANTURN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7624 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7623 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7625 - MOVE_THUNDERBOLT, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 7628 - [DIFFICULTY_NORMAL][TRAINER_JANI] = - { -#line 7629 - .trainerName = _("JANI"), -#line 7630 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 7631 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 7632 -F_TRAINER_FEMALE | -#line 7633 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 7634 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7636 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7638 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7637 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7640 - [DIFFICULTY_NORMAL][TRAINER_LAO_1] = - { -#line 7641 - .trainerName = _("LAO"), -#line 7642 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7643 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7645 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7646 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 7648 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7650 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7649 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7651 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SMOG, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7656 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7658 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7657 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7659 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SMOG, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7664 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7666 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7665 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7667 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - }, - }, -#line 7672 - [DIFFICULTY_NORMAL][TRAINER_LUNG] = - { -#line 7673 - .trainerName = _("LUNG"), -#line 7674 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7675 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7677 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7678 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7680 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7682 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7681 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7684 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7686 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7685 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7688 - [DIFFICULTY_NORMAL][TRAINER_LAO_2] = - { -#line 7689 - .trainerName = _("LAO"), -#line 7690 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7691 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7693 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7694 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 7696 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7698 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7697 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7699 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7704 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7706 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7705 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7707 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7711 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7713 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7712 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7714 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7719 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7721 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7720 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7722 - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - }, - }, -#line 7725 - [DIFFICULTY_NORMAL][TRAINER_LAO_3] = - { -#line 7726 - .trainerName = _("LAO"), -#line 7727 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7728 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7730 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7731 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 7733 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7735 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7734 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7736 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7741 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7743 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7742 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7744 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7749 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7751 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7750 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7752 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7756 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7758 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 7757 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7759 - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - }, - }, -#line 7762 - [DIFFICULTY_NORMAL][TRAINER_LAO_4] = - { -#line 7763 - .trainerName = _("LAO"), -#line 7764 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7765 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7767 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7768 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 7770 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7772 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7771 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7773 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7777 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7779 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7778 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7780 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7784 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7786 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7785 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7787 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7791 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7793 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 7792 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7794 - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - }, - }, -#line 7797 - [DIFFICULTY_NORMAL][TRAINER_LAO_5] = - { -#line 7798 - .trainerName = _("LAO"), -#line 7799 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 7800 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 7802 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 7803 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 7805 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7807 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7806 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7808 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - { -#line 7812 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7814 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7813 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7815 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7820 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7822 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7821 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7823 - MOVE_POISON_GAS, - MOVE_TACKLE, - MOVE_SLUDGE, - MOVE_SELF_DESTRUCT, - }, - }, - { -#line 7828 - .species = SPECIES_WEEZING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7828 - .heldItem = ITEM_SMOKE_BALL, -#line 7830 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 7829 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7831 - MOVE_TACKLE, - MOVE_SLUDGE, - }, - }, - }, - }, -#line 7834 - [DIFFICULTY_NORMAL][TRAINER_JOCELYN] = - { -#line 7835 - .trainerName = _("JOCELYN"), -#line 7836 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7837 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7838 -F_TRAINER_FEMALE | -#line 7839 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7840 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7841 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7843 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7845 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7844 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7847 - [DIFFICULTY_NORMAL][TRAINER_LAURA] = - { -#line 7848 - .trainerName = _("LAURA"), -#line 7849 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7850 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7851 -F_TRAINER_FEMALE | -#line 7852 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7853 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7854 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7856 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7858 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 7857 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7860 - [DIFFICULTY_NORMAL][TRAINER_CYNDY_1] = - { -#line 7861 - .trainerName = _("CYNDY"), -#line 7862 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7863 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7864 -F_TRAINER_FEMALE | -#line 7865 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7866 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7867 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7869 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7871 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7870 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7873 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7875 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7874 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7877 - [DIFFICULTY_NORMAL][TRAINER_CORA] = - { -#line 7878 - .trainerName = _("CORA"), -#line 7879 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7880 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7881 -F_TRAINER_FEMALE | -#line 7882 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7883 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7884 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7886 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7888 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7887 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7890 - [DIFFICULTY_NORMAL][TRAINER_PAULA] = - { -#line 7891 - .trainerName = _("PAULA"), -#line 7892 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7893 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7894 -F_TRAINER_FEMALE | -#line 7895 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7896 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7897 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7899 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7901 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 7900 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7903 - [DIFFICULTY_NORMAL][TRAINER_CYNDY_2] = - { -#line 7904 - .trainerName = _("CYNDY"), -#line 7905 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7906 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7907 -F_TRAINER_FEMALE | -#line 7908 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7909 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7910 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7912 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7914 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 7913 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7916 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7918 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 7917 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7920 - [DIFFICULTY_NORMAL][TRAINER_CYNDY_3] = - { -#line 7921 - .trainerName = _("CYNDY"), -#line 7922 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7923 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7924 -F_TRAINER_FEMALE | -#line 7925 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7926 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7927 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7929 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7931 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 7930 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7933 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7935 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 7934 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7937 - [DIFFICULTY_NORMAL][TRAINER_CYNDY_4] = - { -#line 7938 - .trainerName = _("CYNDY"), -#line 7939 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7940 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7941 -F_TRAINER_FEMALE | -#line 7942 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7943 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7944 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7946 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7948 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7947 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7950 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7952 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 7951 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7954 - [DIFFICULTY_NORMAL][TRAINER_CYNDY_5] = - { -#line 7955 - .trainerName = _("CYNDY"), -#line 7956 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 7957 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 7958 -F_TRAINER_FEMALE | -#line 7959 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 7960 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7961 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7963 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7965 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 7964 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 7967 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7969 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 7968 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 7971 - [DIFFICULTY_NORMAL][TRAINER_MADELINE_1] = - { -#line 7972 - .trainerName = _("MADELINE"), -#line 7973 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 7974 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 7975 -F_TRAINER_FEMALE | -#line 7976 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 7977 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7978 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 7980 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7982 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7981 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 7983 - MOVE_EMBER, - MOVE_TACKLE, - MOVE_MAGNITUDE, - MOVE_SUNNY_DAY, - }, - }, - }, - }, -#line 7988 - [DIFFICULTY_NORMAL][TRAINER_CLARISSA] = - { -#line 7989 - .trainerName = _("CLARISSA"), -#line 7990 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 7991 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 7992 -F_TRAINER_FEMALE | -#line 7993 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 7994 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 7995 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 7997 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 7999 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 7998 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8001 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8003 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8002 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8005 - [DIFFICULTY_NORMAL][TRAINER_ANGELICA] = - { -#line 8006 - .trainerName = _("ANGELICA"), -#line 8007 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 8008 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 8009 -F_TRAINER_FEMALE | -#line 8010 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 8011 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8012 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8014 - .species = SPECIES_CASTFORM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8016 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 8015 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8017 - MOVE_RAIN_DANCE, - MOVE_WEATHER_BALL, - MOVE_THUNDER, - MOVE_WATER_PULSE, - }, - }, - }, - }, -#line 8022 - [DIFFICULTY_NORMAL][TRAINER_MADELINE_2] = - { -#line 8023 - .trainerName = _("MADELINE"), -#line 8024 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 8025 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 8026 -F_TRAINER_FEMALE | -#line 8027 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 8028 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8029 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8031 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8033 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8032 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8034 - MOVE_EMBER, - MOVE_TACKLE, - MOVE_MAGNITUDE, - MOVE_SUNNY_DAY, - }, - }, - }, - }, -#line 8039 - [DIFFICULTY_NORMAL][TRAINER_MADELINE_3] = - { -#line 8040 - .trainerName = _("MADELINE"), -#line 8041 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 8042 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 8043 -F_TRAINER_FEMALE | -#line 8044 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 8045 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8046 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8048 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8050 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8049 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8051 - MOVE_EMBER, - MOVE_TAKE_DOWN, - MOVE_MAGNITUDE, - MOVE_SUNNY_DAY, - }, - }, - }, - }, -#line 8056 - [DIFFICULTY_NORMAL][TRAINER_MADELINE_4] = - { -#line 8057 - .trainerName = _("MADELINE"), -#line 8058 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 8059 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 8060 -F_TRAINER_FEMALE | -#line 8061 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 8062 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8063 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8065 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8067 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8066 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8068 - MOVE_LEECH_SEED, - MOVE_MEGA_DRAIN, - MOVE_GRASS_WHISTLE, - MOVE_SUNNY_DAY, - }, - }, - { -#line 8073 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8075 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8074 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8076 - MOVE_FLAMETHROWER, - MOVE_TAKE_DOWN, - MOVE_MAGNITUDE, - MOVE_SUNNY_DAY, - }, - }, - }, - }, -#line 8081 - [DIFFICULTY_NORMAL][TRAINER_MADELINE_5] = - { -#line 8082 - .trainerName = _("MADELINE"), -#line 8083 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 8084 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 8085 -F_TRAINER_FEMALE | -#line 8086 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 8087 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8088 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8090 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8092 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8091 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8093 - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_SOLAR_BEAM, - MOVE_SUNNY_DAY, - }, - }, - { -#line 8098 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8100 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8099 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8101 - MOVE_FLAMETHROWER, - MOVE_TAKE_DOWN, - MOVE_EARTHQUAKE, - MOVE_SUNNY_DAY, - }, - }, - }, - }, -#line 8106 - [DIFFICULTY_NORMAL][TRAINER_BEVERLY] = - { -#line 8107 - .trainerName = _("BEVERLY"), -#line 8108 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8109 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8110 -F_TRAINER_FEMALE | -#line 8111 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8112 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8113 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8115 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8117 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8116 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8119 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8121 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8120 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8123 - [DIFFICULTY_NORMAL][TRAINER_IMANI] = - { -#line 8124 - .trainerName = _("IMANI"), -#line 8125 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8126 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8127 -F_TRAINER_FEMALE | -#line 8128 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8129 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8130 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8132 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8134 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8133 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8136 - [DIFFICULTY_NORMAL][TRAINER_KYLA] = - { -#line 8137 - .trainerName = _("KYLA"), -#line 8138 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8139 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8140 -F_TRAINER_FEMALE | -#line 8141 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8142 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8143 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8145 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8147 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8146 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8149 - [DIFFICULTY_NORMAL][TRAINER_DENISE] = - { -#line 8150 - .trainerName = _("DENISE"), -#line 8151 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8152 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8153 -F_TRAINER_FEMALE | -#line 8154 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8155 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8156 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8158 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8160 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8159 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8162 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8164 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8163 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8166 - [DIFFICULTY_NORMAL][TRAINER_BETH] = - { -#line 8167 - .trainerName = _("BETH"), -#line 8168 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8169 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8170 -F_TRAINER_FEMALE | -#line 8171 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8172 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8173 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8175 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8177 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8176 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8179 - [DIFFICULTY_NORMAL][TRAINER_TARA] = - { -#line 8180 - .trainerName = _("TARA"), -#line 8181 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8182 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8183 -F_TRAINER_FEMALE | -#line 8184 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8185 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8186 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8188 - .species = SPECIES_HORSEA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8190 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8189 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8192 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8194 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8193 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8196 - [DIFFICULTY_NORMAL][TRAINER_MISSY] = - { -#line 8197 - .trainerName = _("MISSY"), -#line 8198 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8199 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8200 -F_TRAINER_FEMALE | -#line 8201 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8202 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8203 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8205 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8207 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8206 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8209 - [DIFFICULTY_NORMAL][TRAINER_ALICE] = - { -#line 8210 - .trainerName = _("ALICE"), -#line 8211 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8212 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8213 -F_TRAINER_FEMALE | -#line 8214 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8215 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8216 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8218 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8220 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8219 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8222 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8224 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8223 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8226 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8228 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8227 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8230 - [DIFFICULTY_NORMAL][TRAINER_JENNY_1] = - { -#line 8231 - .trainerName = _("JENNY"), -#line 8232 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8233 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8234 -F_TRAINER_FEMALE | -#line 8235 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8236 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8237 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8239 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8241 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8240 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8243 - [DIFFICULTY_NORMAL][TRAINER_GRACE] = - { -#line 8244 - .trainerName = _("GRACE"), -#line 8245 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8246 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8247 -F_TRAINER_FEMALE | -#line 8248 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8249 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8250 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8252 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8254 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8253 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8256 - [DIFFICULTY_NORMAL][TRAINER_TANYA] = - { -#line 8257 - .trainerName = _("TANYA"), -#line 8258 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8259 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8260 -F_TRAINER_FEMALE | -#line 8261 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8262 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8263 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8265 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8267 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8266 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8269 - [DIFFICULTY_NORMAL][TRAINER_SHARON] = - { -#line 8270 - .trainerName = _("SHARON"), -#line 8271 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8272 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8273 -F_TRAINER_FEMALE | -#line 8274 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8275 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8276 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8278 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8280 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8279 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8282 - [DIFFICULTY_NORMAL][TRAINER_NIKKI] = - { -#line 8283 - .trainerName = _("NIKKI"), -#line 8284 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8285 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8286 -F_TRAINER_FEMALE | -#line 8287 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8288 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8289 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8291 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8293 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8292 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8295 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8297 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8296 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8299 - [DIFFICULTY_NORMAL][TRAINER_BRENDA] = - { -#line 8300 - .trainerName = _("BRENDA"), -#line 8301 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8302 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8303 -F_TRAINER_FEMALE | -#line 8304 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8305 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8306 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8308 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8310 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8309 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8312 - [DIFFICULTY_NORMAL][TRAINER_KATIE] = - { -#line 8313 - .trainerName = _("KATIE"), -#line 8314 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8315 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8316 -F_TRAINER_FEMALE | -#line 8317 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8318 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8319 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8321 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8323 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8322 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8325 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8327 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8326 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8329 - [DIFFICULTY_NORMAL][TRAINER_SUSIE] = - { -#line 8330 - .trainerName = _("SUSIE"), -#line 8331 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8332 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8333 -F_TRAINER_FEMALE | -#line 8334 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8335 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8336 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8338 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8340 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8339 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8342 - [DIFFICULTY_NORMAL][TRAINER_KARA] = - { -#line 8343 - .trainerName = _("KARA"), -#line 8344 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8345 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8346 -F_TRAINER_FEMALE | -#line 8347 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8348 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8349 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8351 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8353 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8352 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8355 - [DIFFICULTY_NORMAL][TRAINER_DANA] = - { -#line 8356 - .trainerName = _("DANA"), -#line 8357 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8358 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8359 -F_TRAINER_FEMALE | -#line 8360 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8361 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8362 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8364 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8366 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8365 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8368 - [DIFFICULTY_NORMAL][TRAINER_SIENNA] = - { -#line 8369 - .trainerName = _("SIENNA"), -#line 8370 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8371 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8372 -F_TRAINER_FEMALE | -#line 8373 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8374 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8375 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8377 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8379 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8378 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8381 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8383 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8382 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8385 - [DIFFICULTY_NORMAL][TRAINER_DEBRA] = - { -#line 8386 - .trainerName = _("DEBRA"), -#line 8387 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8388 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8389 -F_TRAINER_FEMALE | -#line 8390 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8391 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8392 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8394 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8396 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8395 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8398 - [DIFFICULTY_NORMAL][TRAINER_LINDA] = - { -#line 8399 - .trainerName = _("LINDA"), -#line 8400 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8401 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8402 -F_TRAINER_FEMALE | -#line 8403 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8404 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8405 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8407 - .species = SPECIES_HORSEA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8409 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8408 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8411 - .species = SPECIES_SEADRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8413 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8412 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8415 - [DIFFICULTY_NORMAL][TRAINER_KAYLEE] = - { -#line 8416 - .trainerName = _("KAYLEE"), -#line 8417 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8418 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8419 -F_TRAINER_FEMALE | -#line 8420 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8421 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8422 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8424 - .species = SPECIES_LANTURN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8426 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8425 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8428 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8430 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8429 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8432 - [DIFFICULTY_NORMAL][TRAINER_LAUREL] = - { -#line 8433 - .trainerName = _("LAUREL"), -#line 8434 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8435 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8436 -F_TRAINER_FEMALE | -#line 8437 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8438 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8439 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8441 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8443 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8442 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8445 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8447 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8446 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8449 - [DIFFICULTY_NORMAL][TRAINER_CARLEE] = - { -#line 8450 - .trainerName = _("CARLEE"), -#line 8451 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8452 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8453 -F_TRAINER_FEMALE | -#line 8454 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8455 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8456 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8458 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8460 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8459 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8462 - [DIFFICULTY_NORMAL][TRAINER_JENNY_2] = - { -#line 8463 - .trainerName = _("JENNY"), -#line 8464 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8465 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8466 -F_TRAINER_FEMALE | -#line 8467 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8468 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8469 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8471 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8473 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8472 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8475 - [DIFFICULTY_NORMAL][TRAINER_JENNY_3] = - { -#line 8476 - .trainerName = _("JENNY"), -#line 8477 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8478 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8479 -F_TRAINER_FEMALE | -#line 8480 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8481 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8482 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8484 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8486 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8485 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8488 - [DIFFICULTY_NORMAL][TRAINER_JENNY_4] = - { -#line 8489 - .trainerName = _("JENNY"), -#line 8490 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8491 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8492 -F_TRAINER_FEMALE | -#line 8493 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8494 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8495 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8497 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8499 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8498 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8501 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8503 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8502 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8505 - [DIFFICULTY_NORMAL][TRAINER_JENNY_5] = - { -#line 8506 - .trainerName = _("JENNY"), -#line 8507 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 8508 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 8509 -F_TRAINER_FEMALE | -#line 8510 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 8511 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8512 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8514 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8516 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8515 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8518 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8520 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8519 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8522 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8524 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8523 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8526 - [DIFFICULTY_NORMAL][TRAINER_HEIDI] = - { -#line 8527 - .trainerName = _("HEIDI"), -#line 8528 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8529 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8530 -F_TRAINER_FEMALE | -#line 8531 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8532 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8533 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8535 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8537 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8536 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8538 - MOVE_DIG, - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - MOVE_SLASH, - }, - }, - { -#line 8543 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8545 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8544 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8546 - MOVE_RAPID_SPIN, - MOVE_MUD_SLAP, - MOVE_PSYBEAM, - MOVE_ROCK_TOMB, - }, - }, - }, - }, -#line 8551 - [DIFFICULTY_NORMAL][TRAINER_BECKY] = - { -#line 8552 - .trainerName = _("BECKY"), -#line 8553 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8554 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8555 -F_TRAINER_FEMALE | -#line 8556 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8557 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8558 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8560 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8562 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8561 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8563 - MOVE_SAND_ATTACK, - MOVE_POISON_STING, - MOVE_SLASH, - MOVE_DIG, - }, - }, - { -#line 8568 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8570 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8569 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8571 - MOVE_ROLLOUT, - MOVE_BUBBLE_BEAM, - MOVE_TAIL_WHIP, - MOVE_DEFENSE_CURL, - }, - }, - }, - }, -#line 8576 - [DIFFICULTY_NORMAL][TRAINER_CAROL] = - { -#line 8577 - .trainerName = _("CAROL"), -#line 8578 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8579 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8580 -F_TRAINER_FEMALE | -#line 8581 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8582 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8583 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8585 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8587 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8586 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8589 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8591 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8590 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8593 - [DIFFICULTY_NORMAL][TRAINER_NANCY] = - { -#line 8594 - .trainerName = _("NANCY"), -#line 8595 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8596 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8597 -F_TRAINER_FEMALE | -#line 8598 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8599 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8600 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8602 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8604 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8603 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8606 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8608 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8607 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8610 - [DIFFICULTY_NORMAL][TRAINER_MARTHA] = - { -#line 8611 - .trainerName = _("MARTHA"), -#line 8612 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8613 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8614 -F_TRAINER_FEMALE | -#line 8615 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8616 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8617 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8619 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8621 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8620 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8623 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8625 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8624 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8627 - [DIFFICULTY_NORMAL][TRAINER_DIANA_1] = - { -#line 8628 - .trainerName = _("DIANA"), -#line 8629 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8630 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8631 -F_TRAINER_FEMALE | -#line 8632 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8633 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8634 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8636 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8638 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8637 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8640 - .species = SPECIES_ODDISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8642 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8641 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8644 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8646 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8645 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8648 - [DIFFICULTY_NORMAL][TRAINER_CEDRIC] = - { -#line 8649 - .trainerName = _("CEDRIC"), -#line 8650 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 8651 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 8653 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 8654 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8655 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8657 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8659 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8658 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8660 - MOVE_DESTINY_BOND, - MOVE_SAFEGUARD, - MOVE_COUNTER, - MOVE_MIRROR_COAT, - }, - }, - }, - }, -#line 8665 - [DIFFICULTY_NORMAL][TRAINER_IRENE] = - { -#line 8666 - .trainerName = _("IRENE"), -#line 8667 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8668 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8669 -F_TRAINER_FEMALE | -#line 8670 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8671 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8672 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8674 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8676 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8675 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8678 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8680 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8679 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8682 - [DIFFICULTY_NORMAL][TRAINER_DIANA_2] = - { -#line 8683 - .trainerName = _("DIANA"), -#line 8684 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8685 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8686 -F_TRAINER_FEMALE | -#line 8687 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8688 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8689 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8691 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8693 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8692 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8695 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8697 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8696 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8699 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8701 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8700 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8703 - [DIFFICULTY_NORMAL][TRAINER_DIANA_3] = - { -#line 8704 - .trainerName = _("DIANA"), -#line 8705 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8706 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8707 -F_TRAINER_FEMALE | -#line 8708 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8709 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8710 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8712 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8714 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8713 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8716 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8718 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8717 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8720 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8722 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8721 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8724 - [DIFFICULTY_NORMAL][TRAINER_DIANA_4] = - { -#line 8725 - .trainerName = _("DIANA"), -#line 8726 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8727 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8728 -F_TRAINER_FEMALE | -#line 8729 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8730 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8731 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8733 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8735 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8734 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8737 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8739 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8738 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8741 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8743 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8742 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8745 - [DIFFICULTY_NORMAL][TRAINER_DIANA_5] = - { -#line 8746 - .trainerName = _("DIANA"), -#line 8747 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 8748 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 8749 -F_TRAINER_FEMALE | -#line 8750 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 8751 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8752 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8754 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8756 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8755 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8758 - .species = SPECIES_VILEPLUME, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8760 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8759 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8762 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8764 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8763 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8766 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_1] = - { -#line 8767 - .trainerName = _("AMY & LIV"), -#line 8768 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8769 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8771 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8772 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8773 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8775 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8777 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8776 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8779 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8781 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8780 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8783 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_2] = - { -#line 8784 - .trainerName = _("AMY & LIV"), -#line 8785 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8786 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8788 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8789 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8790 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8792 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8794 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8793 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8796 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8798 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8797 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8800 - [DIFFICULTY_NORMAL][TRAINER_GINA_AND_MIA_1] = - { -#line 8801 - .trainerName = _("GINA & MIA"), -#line 8802 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8803 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8805 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8806 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8807 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8809 - .species = SPECIES_SEEDOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8811 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8810 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8813 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8815 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8814 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8817 - [DIFFICULTY_NORMAL][TRAINER_MIU_AND_YUKI] = - { -#line 8818 - .trainerName = _("MIU & YUKI"), -#line 8819 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8820 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8822 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8823 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8824 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8826 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8828 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8827 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8830 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8832 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8831 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8834 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_3] = - { -#line 8835 - .trainerName = _("AMY & LIV"), -#line 8836 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8837 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8839 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8840 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8841 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8843 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8845 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8844 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8847 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8849 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8848 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8851 - [DIFFICULTY_NORMAL][TRAINER_GINA_AND_MIA_2] = - { -#line 8852 - .trainerName = _("GINA & MIA"), -#line 8853 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8854 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8856 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8857 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8858 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8860 - .species = SPECIES_DUSKULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8862 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8861 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8863 - MOVE_NIGHT_SHADE, - MOVE_DISABLE, - }, - }, - { -#line 8866 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8868 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8867 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8869 - MOVE_ABSORB, - MOVE_LEECH_SEED, - }, - }, - }, - }, -#line 8872 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_4] = - { -#line 8873 - .trainerName = _("AMY & LIV"), -#line 8874 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8875 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8877 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8878 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8879 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8881 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8883 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8882 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8885 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8887 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 8886 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8889 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_5] = - { -#line 8890 - .trainerName = _("AMY & LIV"), -#line 8891 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8892 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8894 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8895 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8896 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8898 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8900 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8899 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8901 - MOVE_SPARK, - MOVE_CHARGE, - MOVE_FAKE_TEARS, - MOVE_HELPING_HAND, - }, - }, - { -#line 8906 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8908 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 8907 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8909 - MOVE_SPARK, - MOVE_CHARGE, - MOVE_CHARM, - MOVE_HELPING_HAND, - }, - }, - }, - }, -#line 8914 - [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_6] = - { -#line 8915 - .trainerName = _("AMY & LIV"), -#line 8916 - .trainerClass = TRAINER_CLASS_TWINS, -#line 8917 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 8919 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 8920 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 8921 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8923 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8925 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8924 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8926 - MOVE_THUNDER, - MOVE_CHARGE, - MOVE_FAKE_TEARS, - MOVE_HELPING_HAND, - }, - }, - { -#line 8931 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8933 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 8932 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 8934 - MOVE_THUNDER, - MOVE_CHARGE, - MOVE_CHARM, - MOVE_HELPING_HAND, - }, - }, - }, - }, -#line 8939 - [DIFFICULTY_NORMAL][TRAINER_HUEY] = - { -#line 8940 - .trainerName = _("HUEY"), -#line 8941 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 8942 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 8944 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 8945 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8946 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8948 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8950 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8949 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8952 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8954 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 8953 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8956 - [DIFFICULTY_NORMAL][TRAINER_EDMOND] = - { -#line 8957 - .trainerName = _("EDMOND"), -#line 8958 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 8959 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 8961 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 8962 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8963 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 8965 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8967 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8966 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8969 - [DIFFICULTY_NORMAL][TRAINER_ERNEST_1] = - { -#line 8970 - .trainerName = _("ERNEST"), -#line 8971 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 8972 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 8974 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 8975 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8976 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 8978 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8980 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8979 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8982 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8984 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8983 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 8986 - [DIFFICULTY_NORMAL][TRAINER_DWAYNE] = - { -#line 8987 - .trainerName = _("DWAYNE"), -#line 8988 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 8989 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 8991 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 8992 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 8993 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 8995 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 8997 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 8996 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 8999 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9001 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9000 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9003 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9005 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9004 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9007 - [DIFFICULTY_NORMAL][TRAINER_PHILLIP] = - { -#line 9008 - .trainerName = _("PHILLIP"), -#line 9009 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9010 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9012 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9013 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9014 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9016 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9018 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9017 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9020 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9022 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9021 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9024 - [DIFFICULTY_NORMAL][TRAINER_LEONARD] = - { -#line 9025 - .trainerName = _("LEONARD"), -#line 9026 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9027 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9029 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9030 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9031 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9033 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9035 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9034 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9037 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9039 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9038 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9041 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9043 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9042 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9045 - [DIFFICULTY_NORMAL][TRAINER_DUNCAN] = - { -#line 9046 - .trainerName = _("DUNCAN"), -#line 9047 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9048 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9050 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9051 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9052 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9054 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9056 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9055 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9058 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9060 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9059 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9062 - [DIFFICULTY_NORMAL][TRAINER_ERNEST_2] = - { -#line 9063 - .trainerName = _("ERNEST"), -#line 9064 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9065 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9067 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9068 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9069 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9071 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9073 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9072 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9075 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9077 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9076 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9079 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9081 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9080 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9083 - [DIFFICULTY_NORMAL][TRAINER_ERNEST_3] = - { -#line 9084 - .trainerName = _("ERNEST"), -#line 9085 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9086 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9088 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9089 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9090 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9092 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9094 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9093 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9096 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9098 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9097 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9100 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9102 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9101 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9104 - [DIFFICULTY_NORMAL][TRAINER_ERNEST_4] = - { -#line 9105 - .trainerName = _("ERNEST"), -#line 9106 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9107 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9109 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9110 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9111 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9113 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9115 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9114 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9117 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9119 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9118 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9121 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9123 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9122 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9125 - [DIFFICULTY_NORMAL][TRAINER_ERNEST_5] = - { -#line 9126 - .trainerName = _("ERNEST"), -#line 9127 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9128 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9130 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9131 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9132 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9134 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9136 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 9135 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9138 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9140 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 9139 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9142 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9144 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 9143 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9146 - [DIFFICULTY_NORMAL][TRAINER_ELI] = - { -#line 9147 - .trainerName = _("ELI"), -#line 9148 - .trainerClass = TRAINER_CLASS_HIKER, -#line 9149 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 9151 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 9152 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9153 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9155 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9157 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9156 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9159 - [DIFFICULTY_NORMAL][TRAINER_ANNIKA] = - { -#line 9160 - .trainerName = _("ANNIKA"), -#line 9161 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 9162 - .trainerPic = TRAINER_PIC_POKEFAN_F, - .encounterMusic_gender = -#line 9163 -F_TRAINER_FEMALE | -#line 9164 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 9165 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9166 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9168 - .species = SPECIES_FEEBAS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9168 - .heldItem = ITEM_ORAN_BERRY, -#line 9170 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9169 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9171 - MOVE_FLAIL, - MOVE_WATER_PULSE, - MOVE_RETURN, - MOVE_ATTRACT, - }, - }, - { -#line 9176 - .species = SPECIES_FEEBAS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9176 - .heldItem = ITEM_ORAN_BERRY, -#line 9178 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9177 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9179 - MOVE_FLAIL, - MOVE_WATER_PULSE, - MOVE_RETURN, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 9184 - [DIFFICULTY_NORMAL][TRAINER_JAZMYN] = - { -#line 9185 - .trainerName = _("JAZMYN"), -#line 9186 - .trainerClass = TRAINER_CLASS_COOLTRAINER_2, -#line 9187 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 9188 -F_TRAINER_FEMALE | -#line 9189 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 9190 - .items = { ITEM_HYPER_POTION }, -#line 9191 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9192 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9194 - .species = SPECIES_ABSOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9196 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9195 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9198 - [DIFFICULTY_NORMAL][TRAINER_JONAS] = - { -#line 9199 - .trainerName = _("JONAS"), -#line 9200 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 9201 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 9203 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9204 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9205 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9207 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9209 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9208 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9210 - MOVE_TOXIC, - MOVE_THUNDER, - MOVE_SELF_DESTRUCT, - MOVE_SLUDGE_BOMB, - }, - }, - }, - }, -#line 9215 - [DIFFICULTY_NORMAL][TRAINER_KAYLEY] = - { -#line 9216 - .trainerName = _("KAYLEY"), -#line 9217 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 9218 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 9219 -F_TRAINER_FEMALE | -#line 9220 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9221 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9222 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9224 - .species = SPECIES_CASTFORM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9226 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9225 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9227 - MOVE_SUNNY_DAY, - MOVE_WEATHER_BALL, - MOVE_FLAMETHROWER, - MOVE_SOLAR_BEAM, - }, - }, - }, - }, -#line 9232 - [DIFFICULTY_NORMAL][TRAINER_AURON] = - { -#line 9233 - .trainerName = _("AURON"), -#line 9234 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 9235 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 9237 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 9238 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9239 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9241 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9243 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9242 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9245 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9247 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9246 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9249 - [DIFFICULTY_NORMAL][TRAINER_KELVIN] = - { -#line 9250 - .trainerName = _("KELVIN"), -#line 9251 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9252 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9254 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9255 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9256 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9258 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9260 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9259 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9262 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9264 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9263 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9266 - [DIFFICULTY_NORMAL][TRAINER_MARLEY] = - { -#line 9267 - .trainerName = _("MARLEY"), -#line 9268 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 9269 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 9270 -F_TRAINER_FEMALE | -#line 9271 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 9272 - .items = { ITEM_HYPER_POTION }, -#line 9273 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9274 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9276 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9278 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 9277 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9279 - MOVE_BITE, - MOVE_ROAR, - MOVE_THUNDER_WAVE, - MOVE_THUNDERBOLT, - }, - }, - }, - }, -#line 9284 - [DIFFICULTY_NORMAL][TRAINER_REYNA] = - { -#line 9285 - .trainerName = _("REYNA"), -#line 9286 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 9287 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 9288 -F_TRAINER_FEMALE | -#line 9289 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 9290 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9291 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9293 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9295 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9294 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9297 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9299 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 9298 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9301 - [DIFFICULTY_NORMAL][TRAINER_HUDSON] = - { -#line 9302 - .trainerName = _("HUDSON"), -#line 9303 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 9304 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 9306 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9307 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9308 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9310 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9312 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9311 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9314 - [DIFFICULTY_NORMAL][TRAINER_CONOR] = - { -#line 9315 - .trainerName = _("CONOR"), -#line 9316 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 9317 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 9319 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 9320 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9321 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9323 - .species = SPECIES_CHINCHOU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9325 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9324 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9327 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9329 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 9328 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9331 - [DIFFICULTY_NORMAL][TRAINER_EDWIN_1] = - { -#line 9332 - .trainerName = _("EDWIN"), -#line 9333 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9334 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9336 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9337 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9338 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9340 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9342 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9341 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9344 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9346 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9345 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9348 - [DIFFICULTY_NORMAL][TRAINER_HECTOR] = - { -#line 9349 - .trainerName = _("HECTOR"), -#line 9350 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9351 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9353 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9354 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9355 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9357 - .species = SPECIES_ZANGOOSE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9359 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9358 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9361 - .species = SPECIES_SEVIPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9363 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9362 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9365 - [DIFFICULTY_NORMAL][TRAINER_TABITHA_MOSSDEEP] = - { -#line 9366 - .trainerName = _("TABITHA"), -#line 9367 - .trainerClass = TRAINER_CLASS_MAGMA_ADMIN, -#line 9368 - .trainerPic = TRAINER_PIC_MAGMA_ADMIN, - .encounterMusic_gender = -#line 9370 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 9371 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9372 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9374 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9376 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9375 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9378 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9380 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9379 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9382 - .species = SPECIES_GOLBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9384 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9383 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9386 - [DIFFICULTY_NORMAL][TRAINER_EDWIN_2] = - { -#line 9387 - .trainerName = _("EDWIN"), -#line 9388 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9389 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9391 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9392 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9393 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9395 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9397 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9396 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9399 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9401 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9400 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9403 - [DIFFICULTY_NORMAL][TRAINER_EDWIN_3] = - { -#line 9404 - .trainerName = _("EDWIN"), -#line 9405 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9406 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9408 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9409 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9410 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9412 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9414 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9413 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9416 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9418 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9417 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9420 - [DIFFICULTY_NORMAL][TRAINER_EDWIN_4] = - { -#line 9421 - .trainerName = _("EDWIN"), -#line 9422 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9423 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9425 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9426 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9427 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9429 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9431 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9430 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9433 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9435 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9434 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9437 - [DIFFICULTY_NORMAL][TRAINER_EDWIN_5] = - { -#line 9438 - .trainerName = _("EDWIN"), -#line 9439 - .trainerClass = TRAINER_CLASS_COLLECTOR, -#line 9440 - .trainerPic = TRAINER_PIC_COLLECTOR, - .encounterMusic_gender = -#line 9442 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 9443 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9444 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9446 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9448 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9447 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9450 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9452 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9451 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9454 - [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_1] = - { -#line 9455 - .trainerName = _("WALLY"), -#line 9456 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9457 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 9459 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9460 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 9461 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9462 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 9464 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9466 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9465 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9467 - MOVE_AERIAL_ACE, - MOVE_SAFEGUARD, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - }, - }, - { -#line 9472 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9474 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9473 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9475 - MOVE_SING, - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 9480 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9482 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9481 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9483 - MOVE_MAGICAL_LEAF, - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_TOXIC, - }, - }, - { -#line 9488 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9490 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9489 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9491 - MOVE_SUPERSONIC, - MOVE_THUNDERBOLT, - MOVE_TRI_ATTACK, - MOVE_SCREECH, - }, - }, - { -#line 9496 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9498 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 9497 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9499 - MOVE_DOUBLE_TEAM, - MOVE_CALM_MIND, - MOVE_PSYCHIC, - MOVE_FUTURE_SIGHT, - }, - }, - }, - }, -#line 9504 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_MUDKIP] = - { -#line 9505 - .trainerName = _("BRENDAN"), -#line 9506 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9507 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9509 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9510 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9511 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9513 - .species = SPECIES_TREECKO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9515 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9514 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9517 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_MUDKIP] = - { -#line 9518 - .trainerName = _("BRENDAN"), -#line 9519 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9520 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9522 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9523 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9524 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9526 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9528 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9527 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9530 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9532 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9531 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9534 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9536 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9535 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9538 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_MUDKIP] = - { -#line 9539 - .trainerName = _("BRENDAN"), -#line 9540 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9541 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9543 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9544 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9545 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9547 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9549 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9548 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9551 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9553 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9552 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9555 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9557 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9556 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9559 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_TREECKO] = - { -#line 9560 - .trainerName = _("BRENDAN"), -#line 9561 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9562 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9564 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9565 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9566 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9568 - .species = SPECIES_TORCHIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9570 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9569 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9572 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_TREECKO] = - { -#line 9573 - .trainerName = _("BRENDAN"), -#line 9574 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9575 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9577 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9578 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9579 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9581 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9583 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9582 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9585 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9587 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9586 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9589 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9591 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9590 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9593 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_TREECKO] = - { -#line 9594 - .trainerName = _("BRENDAN"), -#line 9595 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9596 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9598 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9599 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9600 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9602 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9604 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9603 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9606 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9608 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9607 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9610 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9612 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9611 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9614 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_TORCHIC] = - { -#line 9615 - .trainerName = _("BRENDAN"), -#line 9616 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9617 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9619 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9620 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9621 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9623 - .species = SPECIES_MUDKIP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9625 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9624 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9627 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_TORCHIC] = - { -#line 9628 - .trainerName = _("BRENDAN"), -#line 9629 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9630 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9632 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9633 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9634 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9636 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9638 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9637 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9640 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9642 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9641 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9644 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9646 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9645 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9648 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_TORCHIC] = - { -#line 9649 - .trainerName = _("BRENDAN"), -#line 9650 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9651 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 9653 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9654 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9655 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9657 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9659 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9658 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9661 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9663 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9662 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9665 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9667 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9666 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9669 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_MUDKIP] = - { -#line 9670 - .trainerName = _("MAY"), -#line 9671 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9672 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9673 -F_TRAINER_FEMALE | -#line 9674 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9675 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9676 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9678 - .species = SPECIES_TREECKO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9680 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9679 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9682 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_MUDKIP] = - { -#line 9683 - .trainerName = _("MAY"), -#line 9684 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9685 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9686 -F_TRAINER_FEMALE | -#line 9687 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9688 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9689 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9691 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9693 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9692 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9695 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9697 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9696 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9699 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9701 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9700 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9703 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_MUDKIP] = - { -#line 9704 - .trainerName = _("MAY"), -#line 9705 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9706 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9707 -F_TRAINER_FEMALE | -#line 9708 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9709 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9710 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9712 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9714 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9713 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9716 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9718 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9717 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9720 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9722 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9721 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9724 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_TREECKO] = - { -#line 9725 - .trainerName = _("MAY"), -#line 9726 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9727 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9728 -F_TRAINER_FEMALE | -#line 9729 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9730 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9731 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9733 - .species = SPECIES_TORCHIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9735 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9734 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9737 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_TREECKO] = - { -#line 9738 - .trainerName = _("MAY"), -#line 9739 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9740 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9741 -F_TRAINER_FEMALE | -#line 9742 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9743 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9744 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9746 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9748 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9747 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9750 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9752 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9751 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9754 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9756 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9755 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9758 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_TREECKO] = - { -#line 9759 - .trainerName = _("MAY"), -#line 9760 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9761 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9762 -F_TRAINER_FEMALE | -#line 9763 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9764 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9765 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9767 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9769 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9768 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9771 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9773 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9772 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9775 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9777 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9776 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9779 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_TORCHIC] = - { -#line 9780 - .trainerName = _("MAY"), -#line 9781 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9782 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9783 -F_TRAINER_FEMALE | -#line 9784 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9785 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9786 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9788 - .species = SPECIES_MUDKIP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9790 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9789 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9792 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_TORCHIC] = - { -#line 9793 - .trainerName = _("MAY"), -#line 9794 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9795 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9796 -F_TRAINER_FEMALE | -#line 9797 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9798 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9799 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9801 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9803 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9802 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9805 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9807 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 9806 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9809 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9811 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9810 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9813 - [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_TORCHIC] = - { -#line 9814 - .trainerName = _("MAY"), -#line 9815 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 9816 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 9817 -F_TRAINER_FEMALE | -#line 9818 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 9819 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9820 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9822 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9824 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9823 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9826 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9828 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 9827 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9830 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9832 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 9831 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9834 - [DIFFICULTY_NORMAL][TRAINER_ISAAC_1] = - { -#line 9835 - .trainerName = _("ISAAC"), -#line 9836 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 9837 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 9839 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9840 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9841 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 9843 - .species = SPECIES_WHISMUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9845 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9844 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9847 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9849 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9848 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9851 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9853 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9852 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9855 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9857 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9856 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9859 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9861 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9860 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9863 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9865 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9864 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9867 - [DIFFICULTY_NORMAL][TRAINER_DAVIS] = - { -#line 9868 - .trainerName = _("DAVIS"), -#line 9869 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 9870 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 9872 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9873 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9874 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 9876 - .species = SPECIES_PINSIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9878 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9877 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9880 - [DIFFICULTY_NORMAL][TRAINER_MITCHELL] = - { -#line 9881 - .trainerName = _("MITCHELL"), -#line 9882 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 9883 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 9885 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 9886 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9887 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 9889 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9891 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9890 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9892 - MOVE_EXPLOSION, - MOVE_REFLECT, - MOVE_LIGHT_SCREEN, - MOVE_PSYCHIC, - }, - }, - { -#line 9897 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9899 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 9898 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 9900 - MOVE_EXPLOSION, - MOVE_REFLECT, - MOVE_LIGHT_SCREEN, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 9905 - [DIFFICULTY_NORMAL][TRAINER_ISAAC_2] = - { -#line 9906 - .trainerName = _("ISAAC"), -#line 9907 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 9908 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 9910 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9911 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9912 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 9914 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9916 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9915 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9918 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9920 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9919 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9922 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9924 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9923 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9926 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9928 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9927 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9930 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9932 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9931 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9934 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9936 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 9935 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9938 - [DIFFICULTY_NORMAL][TRAINER_ISAAC_3] = - { -#line 9939 - .trainerName = _("ISAAC"), -#line 9940 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 9941 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 9943 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9944 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9945 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 9947 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9949 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9948 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9951 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9953 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9952 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9955 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9957 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9956 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9959 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9961 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9960 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9963 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9965 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9964 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9967 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9969 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 9968 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 9971 - [DIFFICULTY_NORMAL][TRAINER_ISAAC_4] = - { -#line 9972 - .trainerName = _("ISAAC"), -#line 9973 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 9974 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 9976 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 9977 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 9978 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 9980 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9982 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9981 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9984 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9986 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9985 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9988 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9990 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9989 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9992 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9994 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9993 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 9996 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 9998 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 9997 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10000 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10002 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10001 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10004 - [DIFFICULTY_NORMAL][TRAINER_ISAAC_5] = - { -#line 10005 - .trainerName = _("ISAAC"), -#line 10006 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10007 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 10009 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10010 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10011 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10013 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10015 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10014 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10017 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10019 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10018 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10021 - .species = SPECIES_LAIRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10023 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10022 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10025 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10027 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10026 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10029 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10031 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10030 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10033 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10035 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10034 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10037 - [DIFFICULTY_NORMAL][TRAINER_LYDIA_1] = - { -#line 10038 - .trainerName = _("LYDIA"), -#line 10039 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10040 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 10041 -F_TRAINER_FEMALE | -#line 10042 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10043 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10044 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10046 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10048 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10047 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10050 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10052 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10051 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10054 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10056 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10055 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10058 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10060 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10059 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10062 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10064 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10063 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10066 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10068 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10067 - .lvl = 11, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10070 - [DIFFICULTY_NORMAL][TRAINER_HALLE] = - { -#line 10071 - .trainerName = _("HALLE"), -#line 10072 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 10073 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 10074 -F_TRAINER_FEMALE | -#line 10075 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10076 - .items = { ITEM_FULL_RESTORE }, -#line 10077 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10078 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10080 - .species = SPECIES_SABLEYE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10082 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10081 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10084 - .species = SPECIES_ABSOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10086 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10085 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10088 - [DIFFICULTY_NORMAL][TRAINER_GARRISON] = - { -#line 10089 - .trainerName = _("GARRISON"), -#line 10090 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 10091 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 10093 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 10094 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10095 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10097 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10099 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10098 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10101 - [DIFFICULTY_NORMAL][TRAINER_LYDIA_2] = - { -#line 10102 - .trainerName = _("LYDIA"), -#line 10103 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10104 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 10105 -F_TRAINER_FEMALE | -#line 10106 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10107 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10108 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10110 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10112 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10111 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10114 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10116 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10115 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10118 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10120 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10119 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10122 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10124 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10123 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10126 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10128 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10127 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10130 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10132 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 10131 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10134 - [DIFFICULTY_NORMAL][TRAINER_LYDIA_3] = - { -#line 10135 - .trainerName = _("LYDIA"), -#line 10136 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10137 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 10138 -F_TRAINER_FEMALE | -#line 10139 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10140 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10141 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10143 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10145 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10144 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10147 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10149 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10148 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10151 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10153 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10152 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10155 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10157 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10156 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10159 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10161 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10160 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10163 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10165 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 10164 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10167 - [DIFFICULTY_NORMAL][TRAINER_LYDIA_4] = - { -#line 10168 - .trainerName = _("LYDIA"), -#line 10169 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10170 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 10171 -F_TRAINER_FEMALE | -#line 10172 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10173 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10174 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10176 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10178 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10177 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10180 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10182 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10181 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10184 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10186 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10185 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10188 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10190 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10189 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10192 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10194 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10193 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10196 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10198 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10197 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10200 - [DIFFICULTY_NORMAL][TRAINER_LYDIA_5] = - { -#line 10201 - .trainerName = _("LYDIA"), -#line 10202 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 10203 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 10204 -F_TRAINER_FEMALE | -#line 10205 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10206 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10207 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 10209 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10211 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10210 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10213 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10215 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10214 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10217 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10219 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10218 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10221 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10223 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10222 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10225 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10227 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10226 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10229 - .species = SPECIES_SEAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10231 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 10230 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10233 - [DIFFICULTY_NORMAL][TRAINER_JACKSON_1] = - { -#line 10234 - .trainerName = _("JACKSON"), -#line 10235 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10236 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10238 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10239 - .items = { ITEM_FULL_RESTORE }, -#line 10240 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10241 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10243 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10245 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10244 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10247 - [DIFFICULTY_NORMAL][TRAINER_LORENZO] = - { -#line 10248 - .trainerName = _("LORENZO"), -#line 10249 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10250 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10252 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10253 - .items = { ITEM_FULL_RESTORE }, -#line 10254 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10255 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 10257 - .species = SPECIES_SEEDOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10259 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10258 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10261 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10263 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10262 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10265 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10267 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10266 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10269 - [DIFFICULTY_NORMAL][TRAINER_SEBASTIAN] = - { -#line 10270 - .trainerName = _("SEBASTIAN"), -#line 10271 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10272 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10274 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10275 - .items = { ITEM_FULL_RESTORE }, -#line 10276 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10277 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10279 - .species = SPECIES_CACTURNE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10281 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10280 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10283 - [DIFFICULTY_NORMAL][TRAINER_JACKSON_2] = - { -#line 10284 - .trainerName = _("JACKSON"), -#line 10285 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10286 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10288 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10289 - .items = { ITEM_FULL_RESTORE }, -#line 10290 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10291 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10293 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10295 - .iv = TRAINER_PARTY_IVS(7, 7, 7, 7, 7, 7), -#line 10294 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10297 - [DIFFICULTY_NORMAL][TRAINER_JACKSON_3] = - { -#line 10298 - .trainerName = _("JACKSON"), -#line 10299 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10300 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10302 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10303 - .items = { ITEM_FULL_RESTORE }, -#line 10304 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10305 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10307 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10309 - .iv = TRAINER_PARTY_IVS(8, 8, 8, 8, 8, 8), -#line 10308 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10311 - [DIFFICULTY_NORMAL][TRAINER_JACKSON_4] = - { -#line 10312 - .trainerName = _("JACKSON"), -#line 10313 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10314 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10316 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10317 - .items = { ITEM_FULL_RESTORE }, -#line 10318 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10319 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10321 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10323 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 10322 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10325 - [DIFFICULTY_NORMAL][TRAINER_JACKSON_5] = - { -#line 10326 - .trainerName = _("JACKSON"), -#line 10327 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10328 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_M, - .encounterMusic_gender = -#line 10330 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10331 - .items = { ITEM_FULL_RESTORE }, -#line 10332 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10333 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10335 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10337 - .iv = TRAINER_PARTY_IVS(10, 10, 10, 10, 10, 10), -#line 10336 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10339 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10341 - .iv = TRAINER_PARTY_IVS(10, 10, 10, 10, 10, 10), -#line 10340 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10343 - [DIFFICULTY_NORMAL][TRAINER_CATHERINE_1] = - { -#line 10344 - .trainerName = _("CATHERINE"), -#line 10345 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10346 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10347 -F_TRAINER_FEMALE | -#line 10348 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10349 - .items = { ITEM_FULL_RESTORE }, -#line 10350 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10353 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10355 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10354 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10357 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10359 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10358 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10361 - [DIFFICULTY_NORMAL][TRAINER_JENNA] = - { -#line 10362 - .trainerName = _("JENNA"), -#line 10363 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10364 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10365 -F_TRAINER_FEMALE | -#line 10366 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10367 - .items = { ITEM_FULL_RESTORE }, -#line 10368 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10369 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 10371 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10373 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10372 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10375 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10377 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10376 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10379 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10381 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10380 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10383 - [DIFFICULTY_NORMAL][TRAINER_SOPHIA] = - { -#line 10384 - .trainerName = _("SOPHIA"), -#line 10385 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10386 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10387 -F_TRAINER_FEMALE | -#line 10388 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10389 - .items = { ITEM_FULL_RESTORE }, -#line 10390 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10391 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10393 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10395 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10394 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10397 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10399 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10398 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10401 - [DIFFICULTY_NORMAL][TRAINER_CATHERINE_2] = - { -#line 10402 - .trainerName = _("CATHERINE"), -#line 10403 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10404 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10405 -F_TRAINER_FEMALE | -#line 10406 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10407 - .items = { ITEM_FULL_RESTORE }, -#line 10408 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10409 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10411 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10413 - .iv = TRAINER_PARTY_IVS(7, 7, 7, 7, 7, 7), -#line 10412 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10415 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10417 - .iv = TRAINER_PARTY_IVS(7, 7, 7, 7, 7, 7), -#line 10416 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10419 - [DIFFICULTY_NORMAL][TRAINER_CATHERINE_3] = - { -#line 10420 - .trainerName = _("CATHERINE"), -#line 10421 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10422 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10423 -F_TRAINER_FEMALE | -#line 10424 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10425 - .items = { ITEM_FULL_RESTORE }, -#line 10426 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10427 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10429 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10431 - .iv = TRAINER_PARTY_IVS(8, 8, 8, 8, 8, 8), -#line 10430 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10433 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10435 - .iv = TRAINER_PARTY_IVS(8, 8, 8, 8, 8, 8), -#line 10434 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10437 - [DIFFICULTY_NORMAL][TRAINER_CATHERINE_4] = - { -#line 10438 - .trainerName = _("CATHERINE"), -#line 10439 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10440 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10441 -F_TRAINER_FEMALE | -#line 10442 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10443 - .items = { ITEM_FULL_RESTORE }, -#line 10444 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10445 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10447 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10449 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 10448 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10451 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10453 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 10452 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10455 - [DIFFICULTY_NORMAL][TRAINER_CATHERINE_5] = - { -#line 10456 - .trainerName = _("CATHERINE"), -#line 10457 - .trainerClass = TRAINER_CLASS_PKMN_RANGER, -#line 10458 - .trainerPic = TRAINER_PIC_POKEMON_RANGER_F, - .encounterMusic_gender = -#line 10459 -F_TRAINER_FEMALE | -#line 10460 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10461 - .items = { ITEM_FULL_RESTORE }, -#line 10462 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10463 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10465 - .species = SPECIES_BELLOSSOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10467 - .iv = TRAINER_PARTY_IVS(10, 10, 10, 10, 10, 10), -#line 10466 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10469 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10471 - .iv = TRAINER_PARTY_IVS(10, 10, 10, 10, 10, 10), -#line 10470 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10473 - [DIFFICULTY_NORMAL][TRAINER_JULIO] = - { -#line 10474 - .trainerName = _("JULIO"), -#line 10475 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 10476 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_M, - .encounterMusic_gender = -#line 10478 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10479 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10480 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10482 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10484 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10483 - .lvl = 21, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10486 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_5] = - { -#line 10487 - .trainerName = _("GRUNT"), -#line 10488 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 10489 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_M, - .encounterMusic_gender = -#line 10491 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 10492 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10493 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10495 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10497 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10496 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10499 - .species = SPECIES_GOLBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10501 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10500 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10503 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_UNUSED] = - { -#line 10504 - .trainerName = _("GRUNT"), -#line 10505 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10506 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 10507 -F_TRAINER_FEMALE | -#line 10508 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 10509 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10510 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10512 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10514 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10513 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10516 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10518 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10517 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10520 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_4] = - { -#line 10521 - .trainerName = _("GRUNT"), -#line 10522 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 10523 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 10524 -F_TRAINER_FEMALE | -#line 10525 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 10526 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10527 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10529 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10531 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10530 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10533 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10535 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10534 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10537 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_JAGGED_PASS] = - { -#line 10538 - .trainerName = _("GRUNT"), -#line 10539 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10540 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10542 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10543 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10544 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10546 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10548 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10547 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10550 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10552 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10551 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10554 - [DIFFICULTY_NORMAL][TRAINER_MARC] = - { -#line 10555 - .trainerName = _("MARC"), -#line 10556 - .trainerClass = TRAINER_CLASS_HIKER, -#line 10557 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 10559 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 10560 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10561 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10563 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10565 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 10564 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10567 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10569 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 10568 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10571 - [DIFFICULTY_NORMAL][TRAINER_BRENDEN] = - { -#line 10572 - .trainerName = _("BRENDEN"), -#line 10573 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 10574 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 10576 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10577 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10578 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10580 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10582 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10581 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10584 - [DIFFICULTY_NORMAL][TRAINER_LILITH] = - { -#line 10585 - .trainerName = _("LILITH"), -#line 10586 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 10587 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 10588 -F_TRAINER_FEMALE | -#line 10589 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10590 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10591 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10593 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10595 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 10594 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10597 - [DIFFICULTY_NORMAL][TRAINER_CRISTIAN] = - { -#line 10598 - .trainerName = _("CRISTIAN"), -#line 10599 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 10600 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 10602 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10603 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10604 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10606 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10608 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 10607 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10610 - [DIFFICULTY_NORMAL][TRAINER_SYLVIA] = - { -#line 10611 - .trainerName = _("SYLVIA"), -#line 10612 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 10613 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 10614 -F_TRAINER_FEMALE | -#line 10615 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 10616 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10617 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10619 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10621 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10620 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10623 - [DIFFICULTY_NORMAL][TRAINER_LEONARDO] = - { -#line 10624 - .trainerName = _("LEONARDO"), -#line 10625 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 10626 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 10628 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 10629 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10630 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10632 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10634 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10633 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10636 - [DIFFICULTY_NORMAL][TRAINER_ATHENA] = - { -#line 10637 - .trainerName = _("ATHENA"), -#line 10638 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 10639 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 10640 -F_TRAINER_FEMALE | -#line 10641 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10642 - .items = { ITEM_HYPER_POTION }, -#line 10643 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10644 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10646 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10648 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10647 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 10649 - MOVE_THUNDER, - MOVE_THUNDER_WAVE, - MOVE_QUICK_ATTACK, - }, - }, - { -#line 10653 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10655 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10654 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 10656 - MOVE_SURF, - MOVE_THIEF, - }, - }, - }, - }, -#line 10659 - [DIFFICULTY_NORMAL][TRAINER_HARRISON] = - { -#line 10660 - .trainerName = _("HARRISON"), -#line 10661 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 10662 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 10664 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 10665 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10666 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10668 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10670 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10669 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10672 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_CHIMNEY_2] = - { -#line 10673 - .trainerName = _("GRUNT"), -#line 10674 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10675 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10677 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10678 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10679 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10681 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10683 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10682 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10685 - [DIFFICULTY_NORMAL][TRAINER_CLARENCE] = - { -#line 10686 - .trainerName = _("CLARENCE"), -#line 10687 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 10688 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 10690 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 10691 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10692 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10694 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10696 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10695 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10698 - [DIFFICULTY_NORMAL][TRAINER_TERRY] = - { -#line 10699 - .trainerName = _("TERRY"), -#line 10700 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 10701 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 10702 -F_TRAINER_FEMALE | -#line 10703 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10704 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10705 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10707 - .species = SPECIES_GIRAFARIG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10709 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10708 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10711 - [DIFFICULTY_NORMAL][TRAINER_NATE] = - { -#line 10712 - .trainerName = _("NATE"), -#line 10713 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 10714 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 10716 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 10717 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10718 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10720 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10722 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10721 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10724 - [DIFFICULTY_NORMAL][TRAINER_KATHLEEN] = - { -#line 10725 - .trainerName = _("KATHLEEN"), -#line 10726 - .trainerClass = TRAINER_CLASS_HEX_MANIAC, -#line 10727 - .trainerPic = TRAINER_PIC_HEX_MANIAC, - .encounterMusic_gender = -#line 10728 -F_TRAINER_FEMALE | -#line 10729 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 10730 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10731 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10733 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10735 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 10734 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10737 - [DIFFICULTY_NORMAL][TRAINER_CLIFFORD] = - { -#line 10738 - .trainerName = _("CLIFFORD"), -#line 10739 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 10740 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 10742 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 10743 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10744 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10746 - .species = SPECIES_GIRAFARIG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10748 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10747 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10750 - [DIFFICULTY_NORMAL][TRAINER_NICHOLAS] = - { -#line 10751 - .trainerName = _("NICHOLAS"), -#line 10752 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 10753 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 10755 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10756 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10757 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10759 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10761 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10760 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10763 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_3] = - { -#line 10764 - .trainerName = _("GRUNT"), -#line 10765 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10766 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_F, - .encounterMusic_gender = -#line 10767 -F_TRAINER_FEMALE | -#line 10768 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10769 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10770 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10772 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10774 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10773 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10776 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10778 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10777 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10780 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_4] = - { -#line 10781 - .trainerName = _("GRUNT"), -#line 10782 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10783 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10785 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10786 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10787 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10789 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10791 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10790 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10793 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_5] = - { -#line 10794 - .trainerName = _("GRUNT"), -#line 10795 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10796 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10798 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10799 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10800 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10802 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10804 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10803 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10806 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_6] = - { -#line 10807 - .trainerName = _("GRUNT"), -#line 10808 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10809 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10811 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10812 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10813 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10815 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10817 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10816 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10819 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_7] = - { -#line 10820 - .trainerName = _("GRUNT"), -#line 10821 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 10822 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 10824 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10825 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10826 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10828 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10830 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10829 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10832 - [DIFFICULTY_NORMAL][TRAINER_MACEY] = - { -#line 10833 - .trainerName = _("MACEY"), -#line 10834 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 10835 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 10836 -F_TRAINER_FEMALE | -#line 10837 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10838 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10839 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10841 - .species = SPECIES_NATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10843 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10842 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10845 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_TREECKO] = - { -#line 10846 - .trainerName = _("BRENDAN"), -#line 10847 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 10848 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 10850 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10851 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10852 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10854 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10856 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10855 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10858 - .species = SPECIES_TORCHIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10860 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10859 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10862 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_MUDKIP] = - { -#line 10863 - .trainerName = _("BRENDAN"), -#line 10864 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 10865 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 10867 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10868 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10869 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10871 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10873 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10872 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10875 - .species = SPECIES_TREECKO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10877 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10876 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10879 - [DIFFICULTY_NORMAL][TRAINER_PAXTON] = - { -#line 10880 - .trainerName = _("PAXTON"), -#line 10881 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 10882 - .trainerPic = TRAINER_PIC_EXPERT_M, - .encounterMusic_gender = -#line 10884 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 10885 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10886 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10888 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10890 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10889 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10892 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10894 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10893 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10896 - [DIFFICULTY_NORMAL][TRAINER_ISABELLA] = - { -#line 10897 - .trainerName = _("ISABELLA"), -#line 10898 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 10899 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_F, - .encounterMusic_gender = -#line 10900 -F_TRAINER_FEMALE | -#line 10901 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 10902 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10903 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 10905 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10907 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10906 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10909 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_5] = - { -#line 10910 - .trainerName = _("GRUNT"), -#line 10911 - .trainerClass = TRAINER_CLASS_TEAM_AQUA, -#line 10912 - .trainerPic = TRAINER_PIC_AQUA_GRUNT_F, - .encounterMusic_gender = -#line 10913 -F_TRAINER_FEMALE | -#line 10914 - TRAINER_ENCOUNTER_MUSIC_AQUA, -#line 10915 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10916 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10918 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10920 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10919 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10922 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10924 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10923 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10926 - [DIFFICULTY_NORMAL][TRAINER_TABITHA_MT_CHIMNEY] = - { -#line 10927 - .trainerName = _("TABITHA"), -#line 10928 - .trainerClass = TRAINER_CLASS_MAGMA_ADMIN, -#line 10929 - .trainerPic = TRAINER_PIC_MAGMA_ADMIN, - .encounterMusic_gender = -#line 10931 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 10932 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10933 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 10935 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10937 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10936 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10939 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10941 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10940 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10943 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10945 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10944 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10947 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10949 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10948 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10951 - [DIFFICULTY_NORMAL][TRAINER_JONATHAN] = - { -#line 10952 - .trainerName = _("JONATHAN"), -#line 10953 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 10954 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 10956 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 10957 - .items = { ITEM_HYPER_POTION }, -#line 10958 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10959 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10961 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10963 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10962 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10965 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10967 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 10966 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10969 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_TORCHIC] = - { -#line 10970 - .trainerName = _("BRENDAN"), -#line 10971 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 10972 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 10974 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 10975 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10976 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10978 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10980 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10979 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10982 - .species = SPECIES_MUDKIP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10984 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 10983 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 10986 - [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_MUDKIP] = - { -#line 10987 - .trainerName = _("MAY"), -#line 10988 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 10989 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 10990 -F_TRAINER_FEMALE | -#line 10991 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 10992 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 10993 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 10995 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 10997 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 10996 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 10999 - .species = SPECIES_TREECKO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11001 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 11000 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11003 - [DIFFICULTY_NORMAL][TRAINER_MAXIE_MAGMA_HIDEOUT] = - { -#line 11004 - .trainerName = _("MAXIE"), -#line 11005 - .trainerClass = TRAINER_CLASS_MAGMA_LEADER, -#line 11006 - .trainerPic = TRAINER_PIC_MAGMA_LEADER_MAXIE, - .encounterMusic_gender = -#line 11008 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 11009 - .items = { ITEM_SUPER_POTION, ITEM_SUPER_POTION }, -#line 11010 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11011 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11013 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11015 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11014 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11017 - .species = SPECIES_CROBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11019 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11018 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11021 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11023 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11022 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11025 - [DIFFICULTY_NORMAL][TRAINER_MAXIE_MT_CHIMNEY] = - { -#line 11026 - .trainerName = _("MAXIE"), -#line 11027 - .trainerClass = TRAINER_CLASS_MAGMA_LEADER, -#line 11028 - .trainerPic = TRAINER_PIC_MAGMA_LEADER_MAXIE, - .encounterMusic_gender = -#line 11030 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 11031 - .items = { ITEM_SUPER_POTION, ITEM_SUPER_POTION }, -#line 11032 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11033 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11035 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11037 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11036 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11039 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11041 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11040 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11043 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11045 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 11044 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11047 - [DIFFICULTY_NORMAL][TRAINER_TIANA] = - { -#line 11048 - .trainerName = _("TIANA"), -#line 11049 - .trainerClass = TRAINER_CLASS_LASS, -#line 11050 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11051 -F_TRAINER_FEMALE | -#line 11052 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11053 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11054 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11056 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11058 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11057 - .lvl = 4, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11060 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11062 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11061 - .lvl = 4, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11064 - [DIFFICULTY_NORMAL][TRAINER_HALEY_1] = - { -#line 11065 - .trainerName = _("HALEY"), -#line 11066 - .trainerClass = TRAINER_CLASS_LASS, -#line 11067 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11068 -F_TRAINER_FEMALE | -#line 11069 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11070 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11071 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11073 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11075 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11074 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11077 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11079 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11078 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11081 - [DIFFICULTY_NORMAL][TRAINER_JANICE] = - { -#line 11082 - .trainerName = _("JANICE"), -#line 11083 - .trainerClass = TRAINER_CLASS_LASS, -#line 11084 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11085 -F_TRAINER_FEMALE | -#line 11086 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11087 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11088 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11090 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11092 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11091 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11094 - [DIFFICULTY_NORMAL][TRAINER_VIVI] = - { -#line 11095 - .trainerName = _("VIVI"), -#line 11096 - .trainerClass = TRAINER_CLASS_WINSTRATE, -#line 11097 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11098 -F_TRAINER_FEMALE | -#line 11099 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11100 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11101 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11103 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11105 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11104 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11107 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11109 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11108 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11111 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11113 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11112 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11115 - [DIFFICULTY_NORMAL][TRAINER_HALEY_2] = - { -#line 11116 - .trainerName = _("HALEY"), -#line 11117 - .trainerClass = TRAINER_CLASS_LASS, -#line 11118 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11119 -F_TRAINER_FEMALE | -#line 11120 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11121 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11122 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11124 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11126 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11125 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11128 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11130 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11129 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11132 - [DIFFICULTY_NORMAL][TRAINER_HALEY_3] = - { -#line 11133 - .trainerName = _("HALEY"), -#line 11134 - .trainerClass = TRAINER_CLASS_LASS, -#line 11135 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11136 -F_TRAINER_FEMALE | -#line 11137 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11138 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11139 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11141 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11143 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11142 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11145 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11147 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11146 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11149 - [DIFFICULTY_NORMAL][TRAINER_HALEY_4] = - { -#line 11150 - .trainerName = _("HALEY"), -#line 11151 - .trainerClass = TRAINER_CLASS_LASS, -#line 11152 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11153 -F_TRAINER_FEMALE | -#line 11154 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11155 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11156 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11158 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11160 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11159 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11162 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11164 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11163 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11166 - [DIFFICULTY_NORMAL][TRAINER_HALEY_5] = - { -#line 11167 - .trainerName = _("HALEY"), -#line 11168 - .trainerClass = TRAINER_CLASS_LASS, -#line 11169 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11170 -F_TRAINER_FEMALE | -#line 11171 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11172 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11173 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11175 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11177 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11176 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11179 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11181 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11180 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11183 - .species = SPECIES_BRELOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11185 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11184 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11187 - [DIFFICULTY_NORMAL][TRAINER_SALLY] = - { -#line 11188 - .trainerName = _("SALLY"), -#line 11189 - .trainerClass = TRAINER_CLASS_LASS, -#line 11190 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11191 -F_TRAINER_FEMALE | -#line 11192 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11193 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11194 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11196 - .species = SPECIES_ODDISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11198 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11197 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11200 - [DIFFICULTY_NORMAL][TRAINER_ROBIN] = - { -#line 11201 - .trainerName = _("ROBIN"), -#line 11202 - .trainerClass = TRAINER_CLASS_LASS, -#line 11203 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11204 -F_TRAINER_FEMALE | -#line 11205 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11206 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11207 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11209 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11211 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11210 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11213 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11215 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11214 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11217 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11219 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11218 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11221 - [DIFFICULTY_NORMAL][TRAINER_ANDREA] = - { -#line 11222 - .trainerName = _("ANDREA"), -#line 11223 - .trainerClass = TRAINER_CLASS_LASS, -#line 11224 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11225 -F_TRAINER_FEMALE | -#line 11226 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11227 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11228 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11230 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11232 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11231 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11234 - [DIFFICULTY_NORMAL][TRAINER_CRISSY] = - { -#line 11235 - .trainerName = _("CRISSY"), -#line 11236 - .trainerClass = TRAINER_CLASS_LASS, -#line 11237 - .trainerPic = TRAINER_PIC_LASS, - .encounterMusic_gender = -#line 11238 -F_TRAINER_FEMALE | -#line 11239 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11240 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11241 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11243 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11245 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11244 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11247 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11249 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11248 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11251 - [DIFFICULTY_NORMAL][TRAINER_RICK] = - { -#line 11252 - .trainerName = _("RICK"), -#line 11253 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11254 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11256 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11257 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11258 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11260 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11262 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11261 - .lvl = 4, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11264 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11266 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11265 - .lvl = 4, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11268 - [DIFFICULTY_NORMAL][TRAINER_LYLE] = - { -#line 11269 - .trainerName = _("LYLE"), -#line 11270 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11271 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11273 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11274 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11275 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11277 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11279 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11278 - .lvl = 3, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11281 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11283 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11282 - .lvl = 3, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11285 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11287 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11286 - .lvl = 3, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11289 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11291 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11290 - .lvl = 3, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11293 - [DIFFICULTY_NORMAL][TRAINER_JOSE] = - { -#line 11294 - .trainerName = _("JOSE"), -#line 11295 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11296 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11298 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11299 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11300 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11302 - .species = SPECIES_WURMPLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11304 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 11303 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11306 - .species = SPECIES_NINCADA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11308 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 11307 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11310 - [DIFFICULTY_NORMAL][TRAINER_DOUG] = - { -#line 11311 - .trainerName = _("DOUG"), -#line 11312 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11313 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11315 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11316 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11317 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11319 - .species = SPECIES_NINCADA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11321 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11320 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11323 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11325 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11324 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11327 - [DIFFICULTY_NORMAL][TRAINER_GREG] = - { -#line 11328 - .trainerName = _("GREG"), -#line 11329 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11330 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11332 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11333 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11334 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11336 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11338 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11337 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11340 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11342 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11341 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11344 - [DIFFICULTY_NORMAL][TRAINER_KENT] = - { -#line 11345 - .trainerName = _("KENT"), -#line 11346 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11347 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11349 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11350 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11353 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11355 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11354 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11357 - [DIFFICULTY_NORMAL][TRAINER_JAMES_1] = - { -#line 11358 - .trainerName = _("JAMES"), -#line 11359 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11360 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11362 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11363 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11364 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11366 - .species = SPECIES_NINCADA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11368 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11367 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11370 - .species = SPECIES_NINCADA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11372 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11371 - .lvl = 6, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11374 - [DIFFICULTY_NORMAL][TRAINER_JAMES_2] = - { -#line 11375 - .trainerName = _("JAMES"), -#line 11376 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11377 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11379 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11380 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11381 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11383 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11385 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11384 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11387 - [DIFFICULTY_NORMAL][TRAINER_JAMES_3] = - { -#line 11388 - .trainerName = _("JAMES"), -#line 11389 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11390 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11392 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11393 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11394 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11396 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11398 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11397 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11400 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11402 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11401 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11404 - [DIFFICULTY_NORMAL][TRAINER_JAMES_4] = - { -#line 11405 - .trainerName = _("JAMES"), -#line 11406 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11407 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11409 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11410 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11411 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11413 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11415 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11414 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11417 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11419 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11418 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11421 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11423 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11422 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11425 - [DIFFICULTY_NORMAL][TRAINER_JAMES_5] = - { -#line 11426 - .trainerName = _("JAMES"), -#line 11427 - .trainerClass = TRAINER_CLASS_BUG_CATCHER, -#line 11428 - .trainerPic = TRAINER_PIC_BUG_CATCHER, - .encounterMusic_gender = -#line 11430 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 11431 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11432 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11434 - .species = SPECIES_SURSKIT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11436 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11435 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11438 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11440 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11439 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11442 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11444 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11443 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11446 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11448 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11447 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11450 - [DIFFICULTY_NORMAL][TRAINER_BRICE] = - { -#line 11451 - .trainerName = _("BRICE"), -#line 11452 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11453 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11455 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11456 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11457 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11459 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11461 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11460 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11463 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11465 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11464 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11467 - [DIFFICULTY_NORMAL][TRAINER_TRENT_1] = - { -#line 11468 - .trainerName = _("TRENT"), -#line 11469 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11470 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11472 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11473 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11474 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11476 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11478 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11477 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11480 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11482 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11481 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11484 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11486 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11485 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11488 - [DIFFICULTY_NORMAL][TRAINER_LENNY] = - { -#line 11489 - .trainerName = _("LENNY"), -#line 11490 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11491 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11493 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11494 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11495 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11497 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11499 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11498 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11501 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11503 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11502 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11505 - [DIFFICULTY_NORMAL][TRAINER_LUCAS_1] = - { -#line 11506 - .trainerName = _("LUCAS"), -#line 11507 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11508 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11510 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11511 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11512 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11514 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11516 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11515 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11518 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11520 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11519 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11522 - [DIFFICULTY_NORMAL][TRAINER_ALAN] = - { -#line 11523 - .trainerName = _("ALAN"), -#line 11524 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11525 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11527 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11528 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11529 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11531 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11533 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11532 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11535 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11537 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11536 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11539 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11541 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11540 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11543 - [DIFFICULTY_NORMAL][TRAINER_CLARK] = - { -#line 11544 - .trainerName = _("CLARK"), -#line 11545 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11546 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11548 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11549 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11550 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11552 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11554 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11553 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11556 - [DIFFICULTY_NORMAL][TRAINER_ERIC] = - { -#line 11557 - .trainerName = _("ERIC"), -#line 11558 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11559 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11561 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11562 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11563 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11565 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11567 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11566 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11569 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11571 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11570 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11573 - [DIFFICULTY_NORMAL][TRAINER_LUCAS_2] = - { -#line 11574 - .trainerName = _("LUCAS"), -#line 11575 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11576 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11578 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11579 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11580 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11582 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11584 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11583 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11585 - MOVE_SPLASH, - MOVE_WATER_GUN, - }, - }, - }, - }, -#line 11588 - [DIFFICULTY_NORMAL][TRAINER_MIKE_1] = - { -#line 11589 - .trainerName = _("MIKE"), -#line 11590 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11591 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11593 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11594 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11595 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11597 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11599 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11598 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11600 - MOVE_GUST, - MOVE_GROWL, - }, - }, - { -#line 11603 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11605 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11604 - .lvl = 10, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11606 - MOVE_BITE, - MOVE_SCARY_FACE, - }, - }, - }, - }, -#line 11609 - [DIFFICULTY_NORMAL][TRAINER_MIKE_2] = - { -#line 11610 - .trainerName = _("MIKE"), -#line 11611 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11612 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11614 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11615 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11616 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 11618 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11620 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11619 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11622 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11624 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11623 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11626 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11628 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11627 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11630 - [DIFFICULTY_NORMAL][TRAINER_TRENT_2] = - { -#line 11631 - .trainerName = _("TRENT"), -#line 11632 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11633 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11635 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11636 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11637 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11639 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11641 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11640 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11643 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11645 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11644 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11647 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11649 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11648 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11651 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11653 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11652 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11655 - [DIFFICULTY_NORMAL][TRAINER_TRENT_3] = - { -#line 11656 - .trainerName = _("TRENT"), -#line 11657 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11658 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11660 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11661 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11662 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11664 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11666 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11665 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11668 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11670 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11669 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11672 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11674 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11673 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11676 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11678 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11677 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11680 - [DIFFICULTY_NORMAL][TRAINER_TRENT_4] = - { -#line 11681 - .trainerName = _("TRENT"), -#line 11682 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11683 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11685 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11686 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11687 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11689 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11691 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11690 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11693 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11695 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11694 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11697 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11699 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11698 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11701 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11703 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11702 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11705 - [DIFFICULTY_NORMAL][TRAINER_TRENT_5] = - { -#line 11706 - .trainerName = _("TRENT"), -#line 11707 - .trainerClass = TRAINER_CLASS_HIKER, -#line 11708 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 11710 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 11711 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11712 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 11714 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11716 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11715 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11718 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11720 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11719 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11722 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11724 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11723 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11726 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11728 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11727 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11730 - [DIFFICULTY_NORMAL][TRAINER_DEZ_AND_LUKE] = - { -#line 11731 - .trainerName = _("DEZ & LUKE"), -#line 11732 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11733 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11735 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11736 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11737 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11739 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11741 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11740 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11743 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11745 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11744 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11747 - [DIFFICULTY_NORMAL][TRAINER_LEA_AND_JED] = - { -#line 11748 - .trainerName = _("LEA & JED"), -#line 11749 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11750 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11752 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11753 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11754 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11756 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11758 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11757 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11760 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11762 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11761 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11764 - [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_1] = - { -#line 11765 - .trainerName = _("KIRA & DAN"), -#line 11766 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11767 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11769 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11770 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11771 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11773 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11775 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11774 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11777 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11779 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11778 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11781 - [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_2] = - { -#line 11782 - .trainerName = _("KIRA & DAN"), -#line 11783 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11784 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11786 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11787 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11788 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11790 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11792 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11791 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11794 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11796 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 11795 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11798 - [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_3] = - { -#line 11799 - .trainerName = _("KIRA & DAN"), -#line 11800 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11801 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11803 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11804 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11805 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11807 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11809 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11808 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11811 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11813 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 11812 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11815 - [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_4] = - { -#line 11816 - .trainerName = _("KIRA & DAN"), -#line 11817 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11818 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11820 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11821 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11822 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11824 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11826 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11825 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11828 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11830 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 11829 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11832 - [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_5] = - { -#line 11833 - .trainerName = _("KIRA & DAN"), -#line 11834 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 11835 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 11837 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 11838 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 11839 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11841 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11843 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11842 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 11845 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11847 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 11846 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11849 - [DIFFICULTY_NORMAL][TRAINER_JOHANNA] = - { -#line 11850 - .trainerName = _("JOHANNA"), -#line 11851 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 11852 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 11853 -F_TRAINER_FEMALE | -#line 11854 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 11855 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11856 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11858 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11860 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11859 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 11862 - [DIFFICULTY_NORMAL][TRAINER_GERALD] = - { -#line 11863 - .trainerName = _("GERALD"), -#line 11864 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 11865 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 11867 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 11868 - .items = { ITEM_HYPER_POTION }, -#line 11869 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11870 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11872 - .species = SPECIES_KECLEON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11874 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11873 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11875 - MOVE_FLAMETHROWER, - MOVE_FURY_SWIPES, - MOVE_FEINT_ATTACK, - MOVE_BIND, - }, - }, - }, - }, -#line 11880 - [DIFFICULTY_NORMAL][TRAINER_VIVIAN] = - { -#line 11881 - .trainerName = _("VIVIAN"), -#line 11882 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 11883 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 11884 -F_TRAINER_FEMALE | -#line 11885 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 11886 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11887 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11889 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11891 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11890 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11892 - MOVE_BIDE, - MOVE_DETECT, - MOVE_CONFUSION, - MOVE_THUNDER_PUNCH, - }, - }, - { -#line 11897 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11899 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11898 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11900 - MOVE_THUNDER_PUNCH, - MOVE_DETECT, - MOVE_CONFUSION, - MOVE_MEDITATE, - }, - }, - }, - }, -#line 11905 - [DIFFICULTY_NORMAL][TRAINER_DANIELLE] = - { -#line 11906 - .trainerName = _("DANIELLE"), -#line 11907 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 11908 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 11909 -F_TRAINER_FEMALE | -#line 11910 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 11911 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11912 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 11914 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11916 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 11915 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11917 - MOVE_BIDE, - MOVE_DETECT, - MOVE_CONFUSION, - MOVE_FIRE_PUNCH, - }, - }, - }, - }, -#line 11922 - [DIFFICULTY_NORMAL][TRAINER_HIDEO] = - { -#line 11923 - .trainerName = _("HIDEO"), -#line 11924 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 11925 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 11927 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 11928 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11929 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11931 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11933 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11932 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11934 - MOVE_TACKLE, - MOVE_SELF_DESTRUCT, - MOVE_SLUDGE, - MOVE_SMOKESCREEN, - }, - }, - { -#line 11939 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11941 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11940 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11942 - MOVE_TACKLE, - MOVE_POISON_GAS, - MOVE_SLUDGE, - MOVE_SMOKESCREEN, - }, - }, - }, - }, -#line 11947 - [DIFFICULTY_NORMAL][TRAINER_KEIGO] = - { -#line 11948 - .trainerName = _("KEIGO"), -#line 11949 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 11950 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 11952 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 11953 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11954 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11956 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11958 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11957 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11959 - MOVE_POISON_GAS, - MOVE_SELF_DESTRUCT, - MOVE_SLUDGE, - MOVE_SMOKESCREEN, - }, - }, - { -#line 11964 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11966 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11965 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11967 - MOVE_SAND_ATTACK, - MOVE_DOUBLE_TEAM, - MOVE_FURY_CUTTER, - MOVE_SWORDS_DANCE, - }, - }, - }, - }, -#line 11972 - [DIFFICULTY_NORMAL][TRAINER_RILEY] = - { -#line 11973 - .trainerName = _("RILEY"), -#line 11974 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 11975 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 11977 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 11978 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 11979 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 11981 - .species = SPECIES_NINCADA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11983 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11982 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11984 - MOVE_LEECH_LIFE, - MOVE_FURY_SWIPES, - MOVE_MIND_READER, - MOVE_DIG, - }, - }, - { -#line 11989 - .species = SPECIES_KOFFING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 11991 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 11990 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 11992 - MOVE_TACKLE, - MOVE_SELF_DESTRUCT, - MOVE_SLUDGE, - MOVE_SMOKESCREEN, - }, - }, - }, - }, -#line 11997 - [DIFFICULTY_NORMAL][TRAINER_FLINT] = - { -#line 11998 - .trainerName = _("FLINT"), -#line 11999 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 12000 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 12002 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12003 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12004 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12006 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12008 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12007 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12010 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12012 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12011 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12014 - [DIFFICULTY_NORMAL][TRAINER_ASHLEY] = - { -#line 12015 - .trainerName = _("ASHLEY"), -#line 12016 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 12017 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 12018 -F_TRAINER_FEMALE | -#line 12019 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 12020 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12021 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 12023 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12025 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12024 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12027 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12029 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12028 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12031 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12033 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12032 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12035 - [DIFFICULTY_NORMAL][TRAINER_WALLY_MAUVILLE] = - { -#line 12036 - .trainerName = _("WALLY"), -#line 12037 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12038 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 12040 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12041 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12042 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 12044 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12046 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 12045 - .lvl = 16, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12048 - [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_2] = - { -#line 12049 - .trainerName = _("WALLY"), -#line 12050 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12051 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 12053 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12054 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 12055 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12056 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 12058 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12060 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12059 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12061 - MOVE_AERIAL_ACE, - MOVE_SAFEGUARD, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - }, - }, - { -#line 12066 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12068 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12067 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12069 - MOVE_SING, - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 12074 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12076 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12075 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12077 - MOVE_MAGICAL_LEAF, - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_TOXIC, - }, - }, - { -#line 12082 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12084 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12083 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12085 - MOVE_SUPERSONIC, - MOVE_THUNDERBOLT, - MOVE_TRI_ATTACK, - MOVE_SCREECH, - }, - }, - { -#line 12090 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12092 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 12091 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12093 - MOVE_DOUBLE_TEAM, - MOVE_CALM_MIND, - MOVE_PSYCHIC, - MOVE_FUTURE_SIGHT, - }, - }, - }, - }, -#line 12098 - [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_3] = - { -#line 12099 - .trainerName = _("WALLY"), -#line 12100 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12101 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 12103 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12104 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 12105 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12106 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 12108 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12110 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12109 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12111 - MOVE_AERIAL_ACE, - MOVE_SAFEGUARD, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - }, - }, - { -#line 12116 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12118 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12117 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12119 - MOVE_SING, - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 12124 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12126 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12125 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12127 - MOVE_MAGICAL_LEAF, - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_TOXIC, - }, - }, - { -#line 12132 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12134 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12133 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12135 - MOVE_SUPERSONIC, - MOVE_THUNDERBOLT, - MOVE_TRI_ATTACK, - MOVE_SCREECH, - }, - }, - { -#line 12140 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12142 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 12141 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12143 - MOVE_DOUBLE_TEAM, - MOVE_CALM_MIND, - MOVE_PSYCHIC, - MOVE_FUTURE_SIGHT, - }, - }, - }, - }, -#line 12148 - [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_4] = - { -#line 12149 - .trainerName = _("WALLY"), -#line 12150 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12151 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 12153 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12154 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 12155 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12156 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 12158 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12160 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12159 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12161 - MOVE_AERIAL_ACE, - MOVE_SAFEGUARD, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - }, - }, - { -#line 12166 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12168 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12167 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12169 - MOVE_SING, - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 12174 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12176 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12175 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12177 - MOVE_MAGICAL_LEAF, - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_TOXIC, - }, - }, - { -#line 12182 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12184 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12183 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12185 - MOVE_SUPERSONIC, - MOVE_THUNDERBOLT, - MOVE_TRI_ATTACK, - MOVE_SCREECH, - }, - }, - { -#line 12190 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12192 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 12191 - .lvl = 54, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12193 - MOVE_DOUBLE_TEAM, - MOVE_CALM_MIND, - MOVE_PSYCHIC, - MOVE_FUTURE_SIGHT, - }, - }, - }, - }, -#line 12198 - [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_5] = - { -#line 12199 - .trainerName = _("WALLY"), -#line 12200 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12201 - .trainerPic = TRAINER_PIC_WALLY, - .encounterMusic_gender = -#line 12203 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12204 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 12205 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12206 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 12208 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12210 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12209 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12211 - MOVE_AERIAL_ACE, - MOVE_SAFEGUARD, - MOVE_DRAGON_BREATH, - MOVE_DRAGON_DANCE, - }, - }, - { -#line 12216 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12218 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12217 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12219 - MOVE_SING, - MOVE_ASSIST, - MOVE_CHARM, - MOVE_FEINT_ATTACK, - }, - }, - { -#line 12224 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12226 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12225 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12227 - MOVE_MAGICAL_LEAF, - MOVE_LEECH_SEED, - MOVE_GIGA_DRAIN, - MOVE_TOXIC, - }, - }, - { -#line 12232 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12234 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12233 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12235 - MOVE_SUPERSONIC, - MOVE_THUNDERBOLT, - MOVE_TRI_ATTACK, - MOVE_SCREECH, - }, - }, - { -#line 12240 - .species = SPECIES_GARDEVOIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12242 - .iv = TRAINER_PARTY_IVS(30, 30, 30, 30, 30, 30), -#line 12241 - .lvl = 57, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12243 - MOVE_DOUBLE_TEAM, - MOVE_CALM_MIND, - MOVE_PSYCHIC, - MOVE_FUTURE_SIGHT, - }, - }, - }, - }, -#line 12248 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_MUDKIP] = - { -#line 12249 - .trainerName = _("BRENDAN"), -#line 12250 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12251 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 12253 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12254 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12255 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12257 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12259 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12258 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12261 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12263 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12262 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12265 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12267 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12266 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12269 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12271 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12270 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12273 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_TREECKO] = - { -#line 12274 - .trainerName = _("BRENDAN"), -#line 12275 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12276 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 12278 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12279 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12280 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12282 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12284 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12283 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12286 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12288 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12287 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12290 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12292 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12291 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12294 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12296 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12295 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12298 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_TORCHIC] = - { -#line 12299 - .trainerName = _("BRENDAN"), -#line 12300 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12301 - .trainerPic = TRAINER_PIC_BRENDAN, - .encounterMusic_gender = -#line 12303 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 12304 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12305 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12307 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12309 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12308 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12311 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12313 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12312 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12315 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12317 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12316 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12319 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12321 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12320 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12323 - [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_MUDKIP] = - { -#line 12324 - .trainerName = _("MAY"), -#line 12325 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12326 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 12327 -F_TRAINER_FEMALE | -#line 12328 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 12329 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12330 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12332 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12334 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12333 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12336 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12338 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12337 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12340 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12342 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12341 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12344 - .species = SPECIES_GROVYLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12346 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12345 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12348 - [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_TREECKO] = - { -#line 12349 - .trainerName = _("MAY"), -#line 12350 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12351 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 12352 -F_TRAINER_FEMALE | -#line 12353 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 12354 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12355 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12357 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12359 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12358 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12361 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12363 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12362 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12365 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12367 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12366 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12369 - .species = SPECIES_COMBUSKEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12371 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12370 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12373 - [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_TORCHIC] = - { -#line 12374 - .trainerName = _("MAY"), -#line 12375 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 12376 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 12377 -F_TRAINER_FEMALE | -#line 12378 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 12379 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12380 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12382 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12384 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12383 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12386 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12388 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12387 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12390 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12392 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 12391 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12394 - .species = SPECIES_MARSHTOMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12396 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12395 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12398 - [DIFFICULTY_NORMAL][TRAINER_JONAH] = - { -#line 12399 - .trainerName = _("JONAH"), -#line 12400 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12401 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12403 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12404 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12405 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 12407 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12409 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12408 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12411 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12413 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12412 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12415 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12417 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12416 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12419 - [DIFFICULTY_NORMAL][TRAINER_HENRY] = - { -#line 12420 - .trainerName = _("HENRY"), -#line 12421 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12422 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12424 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12425 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12426 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12428 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12430 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12429 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12432 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12434 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12433 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12436 - [DIFFICULTY_NORMAL][TRAINER_ROGER] = - { -#line 12437 - .trainerName = _("ROGER"), -#line 12438 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12439 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12441 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12442 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12443 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 12445 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12447 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12446 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12449 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12451 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12450 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12453 - .species = SPECIES_GYARADOS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12455 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12454 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12457 - [DIFFICULTY_NORMAL][TRAINER_ALEXA] = - { -#line 12458 - .trainerName = _("ALEXA"), -#line 12459 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 12460 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 12461 -F_TRAINER_FEMALE | -#line 12462 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 12463 - .items = { ITEM_FULL_RESTORE }, -#line 12464 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12465 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12467 - .species = SPECIES_GLOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12469 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12468 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12471 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12473 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12472 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12475 - [DIFFICULTY_NORMAL][TRAINER_RUBEN] = - { -#line 12476 - .trainerName = _("RUBEN"), -#line 12477 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 12478 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 12480 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 12481 - .items = { ITEM_HYPER_POTION }, -#line 12482 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12483 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12485 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12487 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12486 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12489 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12491 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 12490 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12493 - [DIFFICULTY_NORMAL][TRAINER_KOJI_1] = - { -#line 12494 - .trainerName = _("KOJI"), -#line 12495 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 12496 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 12498 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12499 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12500 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 12502 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12504 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12503 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12506 - [DIFFICULTY_NORMAL][TRAINER_WAYNE] = - { -#line 12507 - .trainerName = _("WAYNE"), -#line 12508 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12509 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12511 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12512 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12513 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 12515 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12517 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12516 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12519 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12521 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12520 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12523 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12525 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12524 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12527 - [DIFFICULTY_NORMAL][TRAINER_AIDAN] = - { -#line 12528 - .trainerName = _("AIDAN"), -#line 12529 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 12530 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 12532 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 12533 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12534 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12536 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12538 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12537 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12540 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12542 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12541 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12544 - [DIFFICULTY_NORMAL][TRAINER_REED] = - { -#line 12545 - .trainerName = _("REED"), -#line 12546 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 12547 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 12549 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12550 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12551 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12553 - .species = SPECIES_SPHEAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12555 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12554 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12557 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12559 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12558 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12561 - [DIFFICULTY_NORMAL][TRAINER_TISHA] = - { -#line 12562 - .trainerName = _("TISHA"), -#line 12563 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 12564 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 12565 -F_TRAINER_FEMALE | -#line 12566 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12567 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12568 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 12570 - .species = SPECIES_CHINCHOU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12572 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12571 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12574 - [DIFFICULTY_NORMAL][TRAINER_TORI_AND_TIA] = - { -#line 12575 - .trainerName = _("TORI & TIA"), -#line 12576 - .trainerClass = TRAINER_CLASS_TWINS, -#line 12577 - .trainerPic = TRAINER_PIC_TWINS, - .encounterMusic_gender = -#line 12579 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 12580 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12581 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12583 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12585 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12584 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12587 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12589 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12588 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12591 - [DIFFICULTY_NORMAL][TRAINER_KIM_AND_IRIS] = - { -#line 12592 - .trainerName = _("KIM & IRIS"), -#line 12593 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 12594 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 12596 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 12597 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12598 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12600 - .species = SPECIES_SWABLU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12602 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12601 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12603 - MOVE_SING, - MOVE_FURY_ATTACK, - MOVE_SAFEGUARD, - MOVE_AERIAL_ACE, - }, - }, - { -#line 12608 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12610 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12609 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12611 - MOVE_FLAMETHROWER, - MOVE_TAKE_DOWN, - MOVE_REST, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 12616 - [DIFFICULTY_NORMAL][TRAINER_TYRA_AND_IVY] = - { -#line 12617 - .trainerName = _("TYRA & IVY"), -#line 12618 - .trainerClass = TRAINER_CLASS_SR_AND_JR, -#line 12619 - .trainerPic = TRAINER_PIC_SR_AND_JR, - .encounterMusic_gender = -#line 12621 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 12622 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12623 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12625 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12627 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12626 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12628 - MOVE_GROWTH, - MOVE_STUN_SPORE, - MOVE_MEGA_DRAIN, - MOVE_LEECH_SEED, - }, - }, - { -#line 12633 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12635 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12634 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12636 - MOVE_DEFENSE_CURL, - MOVE_ROLLOUT, - MOVE_MUD_SPORT, - MOVE_ROCK_THROW, - }, - }, - }, - }, -#line 12641 - [DIFFICULTY_NORMAL][TRAINER_MEL_AND_PAUL] = - { -#line 12642 - .trainerName = _("MEL & PAUL"), -#line 12643 - .trainerClass = TRAINER_CLASS_YOUNG_COUPLE, -#line 12644 - .trainerPic = TRAINER_PIC_YOUNG_COUPLE, - .encounterMusic_gender = -#line 12646 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 12647 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12648 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12650 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12652 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12651 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12653 - MOVE_GUST, - MOVE_PSYBEAM, - MOVE_TOXIC, - MOVE_PROTECT, - }, - }, - { -#line 12658 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12660 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12659 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12661 - MOVE_GUST, - MOVE_MEGA_DRAIN, - MOVE_ATTRACT, - MOVE_STUN_SPORE, - }, - }, - }, - }, -#line 12666 - [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_1] = - { -#line 12667 - .trainerName = _("JOHN & JAY"), -#line 12668 - .trainerClass = TRAINER_CLASS_OLD_COUPLE, -#line 12669 - .trainerPic = TRAINER_PIC_OLD_COUPLE, - .encounterMusic_gender = -#line 12671 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12672 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12673 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12675 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12677 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12676 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12678 - MOVE_PSYCHIC, - MOVE_FIRE_PUNCH, - MOVE_PSYCH_UP, - MOVE_PROTECT, - }, - }, - { -#line 12683 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12685 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 12684 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12686 - MOVE_FOCUS_PUNCH, - MOVE_ROCK_TOMB, - MOVE_REST, - MOVE_BELLY_DRUM, - }, - }, - }, - }, -#line 12691 - [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_2] = - { -#line 12692 - .trainerName = _("JOHN & JAY"), -#line 12693 - .trainerClass = TRAINER_CLASS_OLD_COUPLE, -#line 12694 - .trainerPic = TRAINER_PIC_OLD_COUPLE, - .encounterMusic_gender = -#line 12696 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12697 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12698 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12700 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12702 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 12701 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12703 - MOVE_PSYCHIC, - MOVE_FIRE_PUNCH, - MOVE_PSYCH_UP, - MOVE_PROTECT, - }, - }, - { -#line 12708 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12710 - .iv = TRAINER_PARTY_IVS(25, 25, 25, 25, 25, 25), -#line 12709 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12711 - MOVE_FOCUS_PUNCH, - MOVE_ROCK_TOMB, - MOVE_REST, - MOVE_BELLY_DRUM, - }, - }, - }, - }, -#line 12716 - [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_3] = - { -#line 12717 - .trainerName = _("JOHN & JAY"), -#line 12718 - .trainerClass = TRAINER_CLASS_OLD_COUPLE, -#line 12719 - .trainerPic = TRAINER_PIC_OLD_COUPLE, - .encounterMusic_gender = -#line 12721 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12722 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12723 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12725 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12727 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 12726 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12728 - MOVE_PSYCHIC, - MOVE_FIRE_PUNCH, - MOVE_PSYCH_UP, - MOVE_PROTECT, - }, - }, - { -#line 12733 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12735 - .iv = TRAINER_PARTY_IVS(26, 26, 26, 26, 26, 26), -#line 12734 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12736 - MOVE_FOCUS_PUNCH, - MOVE_ROCK_TOMB, - MOVE_REST, - MOVE_BELLY_DRUM, - }, - }, - }, - }, -#line 12741 - [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_4] = - { -#line 12742 - .trainerName = _("JOHN & JAY"), -#line 12743 - .trainerClass = TRAINER_CLASS_OLD_COUPLE, -#line 12744 - .trainerPic = TRAINER_PIC_OLD_COUPLE, - .encounterMusic_gender = -#line 12746 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12747 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12748 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12750 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12752 - .iv = TRAINER_PARTY_IVS(27, 27, 27, 27, 27, 27), -#line 12751 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12753 - MOVE_PSYCHIC, - MOVE_FIRE_PUNCH, - MOVE_PSYCH_UP, - MOVE_PROTECT, - }, - }, - { -#line 12758 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12760 - .iv = TRAINER_PARTY_IVS(27, 27, 27, 27, 27, 27), -#line 12759 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12761 - MOVE_FOCUS_PUNCH, - MOVE_ROCK_TOMB, - MOVE_REST, - MOVE_BELLY_DRUM, - }, - }, - }, - }, -#line 12766 - [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_5] = - { -#line 12767 - .trainerName = _("JOHN & JAY"), -#line 12768 - .trainerClass = TRAINER_CLASS_OLD_COUPLE, -#line 12769 - .trainerPic = TRAINER_PIC_OLD_COUPLE, - .encounterMusic_gender = -#line 12771 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 12772 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12773 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12775 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12777 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 12776 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12778 - MOVE_PSYCHIC, - MOVE_FIRE_PUNCH, - MOVE_PSYCH_UP, - MOVE_PROTECT, - }, - }, - { -#line 12783 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12785 - .iv = TRAINER_PARTY_IVS(29, 29, 29, 29, 29, 29), -#line 12784 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 12786 - MOVE_FOCUS_PUNCH, - MOVE_ROCK_TOMB, - MOVE_REST, - MOVE_BELLY_DRUM, - }, - }, - }, - }, -#line 12791 - [DIFFICULTY_NORMAL][TRAINER_RELI_AND_IAN] = - { -#line 12792 - .trainerName = _("RELI & IAN"), -#line 12793 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12794 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12796 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12797 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12798 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12800 - .species = SPECIES_AZUMARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12802 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12801 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12804 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12806 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12805 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12808 - [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_1] = - { -#line 12809 - .trainerName = _("LILA & ROY"), -#line 12810 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12811 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12813 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12814 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12815 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12817 - .species = SPECIES_CHINCHOU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12819 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12818 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12821 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12823 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12822 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12825 - [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_2] = - { -#line 12826 - .trainerName = _("LILA & ROY"), -#line 12827 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12828 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12830 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12831 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12832 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12834 - .species = SPECIES_CHINCHOU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12836 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12835 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12838 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12840 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12839 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12842 - [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_3] = - { -#line 12843 - .trainerName = _("LILA & ROY"), -#line 12844 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12845 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12847 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12848 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12849 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12851 - .species = SPECIES_LANTURN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12853 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12852 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12855 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12857 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12856 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12859 - [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_4] = - { -#line 12860 - .trainerName = _("LILA & ROY"), -#line 12861 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12862 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12864 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12865 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12866 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12868 - .species = SPECIES_LANTURN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12870 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12869 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12872 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12874 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12873 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12876 - [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_5] = - { -#line 12877 - .trainerName = _("LILA & ROY"), -#line 12878 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12879 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12881 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12882 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12883 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12885 - .species = SPECIES_LANTURN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12887 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12886 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12889 - .species = SPECIES_SHARPEDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12891 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12890 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12893 - [DIFFICULTY_NORMAL][TRAINER_LISA_AND_RAY] = - { -#line 12894 - .trainerName = _("LISA & RAY"), -#line 12895 - .trainerClass = TRAINER_CLASS_SIS_AND_BRO, -#line 12896 - .trainerPic = TRAINER_PIC_SIS_AND_BRO, - .encounterMusic_gender = -#line 12898 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 12899 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 12900 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12902 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12904 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12903 - .lvl = 27, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12906 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12908 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12907 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12910 - [DIFFICULTY_NORMAL][TRAINER_CHRIS] = - { -#line 12911 - .trainerName = _("CHRIS"), -#line 12912 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12913 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12915 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12916 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12917 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 12919 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12921 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12920 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12923 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12925 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12924 - .lvl = 20, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12927 - .species = SPECIES_FEEBAS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12929 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12928 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12931 - .species = SPECIES_CARVANHA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12933 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12932 - .lvl = 23, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12935 - [DIFFICULTY_NORMAL][TRAINER_DAWSON] = - { -#line 12936 - .trainerName = _("DAWSON"), -#line 12937 - .trainerClass = TRAINER_CLASS_RICH_BOY, -#line 12938 - .trainerPic = TRAINER_PIC_RICH_BOY, - .encounterMusic_gender = -#line 12940 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 12941 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12942 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12944 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12944 - .heldItem = ITEM_NUGGET, -#line 12946 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12945 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12948 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12950 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12949 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12952 - [DIFFICULTY_NORMAL][TRAINER_SARAH] = - { -#line 12953 - .trainerName = _("SARAH"), -#line 12954 - .trainerClass = TRAINER_CLASS_LADY, -#line 12955 - .trainerPic = TRAINER_PIC_LADY, - .encounterMusic_gender = -#line 12956 -F_TRAINER_FEMALE | -#line 12957 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 12958 - .items = { ITEM_FULL_RESTORE }, -#line 12959 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12960 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 12962 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12964 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12963 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 12966 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12966 - .heldItem = ITEM_NUGGET, -#line 12968 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12967 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12970 - [DIFFICULTY_NORMAL][TRAINER_DARIAN] = - { -#line 12971 - .trainerName = _("DARIAN"), -#line 12972 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 12973 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 12975 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 12976 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12977 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 12979 - .species = SPECIES_MAGIKARP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12981 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12980 - .lvl = 9, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12983 - [DIFFICULTY_NORMAL][TRAINER_HAILEY] = - { -#line 12984 - .trainerName = _("HAILEY"), -#line 12985 - .trainerClass = TRAINER_CLASS_TUBER_F, -#line 12986 - .trainerPic = TRAINER_PIC_TUBER_F, - .encounterMusic_gender = -#line 12987 -F_TRAINER_FEMALE | -#line 12988 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 12989 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 12990 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 12992 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 12994 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 12993 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 12996 - [DIFFICULTY_NORMAL][TRAINER_CHANDLER] = - { -#line 12997 - .trainerName = _("CHANDLER"), -#line 12998 - .trainerClass = TRAINER_CLASS_TUBER_M, -#line 12999 - .trainerPic = TRAINER_PIC_TUBER_M, - .encounterMusic_gender = -#line 13001 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13002 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13003 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13005 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13007 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13006 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13009 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13011 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13010 - .lvl = 12, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13013 - [DIFFICULTY_NORMAL][TRAINER_KALEB] = - { -#line 13014 - .trainerName = _("KALEB"), -#line 13015 - .trainerClass = TRAINER_CLASS_POKEFAN, -#line 13016 - .trainerPic = TRAINER_PIC_POKEFAN_M, - .encounterMusic_gender = -#line 13018 - TRAINER_ENCOUNTER_MUSIC_TWINS, -#line 13019 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13020 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13022 - .species = SPECIES_MINUN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13022 - .heldItem = ITEM_ORAN_BERRY, -#line 13024 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13023 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13026 - .species = SPECIES_PLUSLE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13026 - .heldItem = ITEM_ORAN_BERRY, -#line 13028 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13027 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13030 - [DIFFICULTY_NORMAL][TRAINER_JOSEPH] = - { -#line 13031 - .trainerName = _("JOSEPH"), -#line 13032 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 13033 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 13035 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13036 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13037 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13039 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13041 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13040 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13043 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13045 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13044 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13047 - [DIFFICULTY_NORMAL][TRAINER_ALYSSA] = - { -#line 13048 - .trainerName = _("ALYSSA"), -#line 13049 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 13050 - .trainerPic = TRAINER_PIC_CYCLING_TRIATHLETE_F, - .encounterMusic_gender = -#line 13051 -F_TRAINER_FEMALE | -#line 13052 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13053 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13054 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13056 - .species = SPECIES_MAGNEMITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13058 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13057 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13060 - [DIFFICULTY_NORMAL][TRAINER_MARCOS] = - { -#line 13061 - .trainerName = _("MARCOS"), -#line 13062 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 13063 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 13065 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13066 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13067 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13069 - .species = SPECIES_VOLTORB, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13071 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 13070 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13073 - [DIFFICULTY_NORMAL][TRAINER_RHETT] = - { -#line 13074 - .trainerName = _("RHETT"), -#line 13075 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 13076 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 13078 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13079 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13080 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13082 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13084 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 13083 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13086 - [DIFFICULTY_NORMAL][TRAINER_TYRON] = - { -#line 13087 - .trainerName = _("TYRON"), -#line 13088 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 13089 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 13091 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13092 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13093 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13095 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13097 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13096 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13099 - [DIFFICULTY_NORMAL][TRAINER_CELINA] = - { -#line 13100 - .trainerName = _("CELINA"), -#line 13101 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 13102 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 13103 -F_TRAINER_FEMALE | -#line 13104 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13105 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13106 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13108 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13110 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13109 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13112 - [DIFFICULTY_NORMAL][TRAINER_BIANCA] = - { -#line 13113 - .trainerName = _("BIANCA"), -#line 13114 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 13115 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 13116 -F_TRAINER_FEMALE | -#line 13117 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13118 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13119 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13121 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13123 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13122 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13125 - [DIFFICULTY_NORMAL][TRAINER_HAYDEN] = - { -#line 13126 - .trainerName = _("HAYDEN"), -#line 13127 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 13128 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 13130 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13131 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13132 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13134 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13136 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13135 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13138 - [DIFFICULTY_NORMAL][TRAINER_SOPHIE] = - { -#line 13139 - .trainerName = _("SOPHIE"), -#line 13140 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 13141 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 13142 -F_TRAINER_FEMALE | -#line 13143 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13144 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13145 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13147 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13149 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13148 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13151 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13153 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13152 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13155 - [DIFFICULTY_NORMAL][TRAINER_COBY] = - { -#line 13156 - .trainerName = _("COBY"), -#line 13157 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 13158 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 13160 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13161 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13162 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13164 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13166 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13165 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13168 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13170 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13169 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13172 - [DIFFICULTY_NORMAL][TRAINER_LAWRENCE] = - { -#line 13173 - .trainerName = _("LAWRENCE"), -#line 13174 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 13175 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 13177 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13178 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13179 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13181 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13183 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13182 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13185 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13187 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13186 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13189 - [DIFFICULTY_NORMAL][TRAINER_WYATT] = - { -#line 13190 - .trainerName = _("WYATT"), -#line 13191 - .trainerClass = TRAINER_CLASS_POKEMANIAC, -#line 13192 - .trainerPic = TRAINER_PIC_POKEMANIAC, - .encounterMusic_gender = -#line 13194 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 13195 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13196 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13198 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13200 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13199 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13202 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13204 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13203 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13206 - [DIFFICULTY_NORMAL][TRAINER_ANGELINA] = - { -#line 13207 - .trainerName = _("ANGELINA"), -#line 13208 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 13209 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 13210 -F_TRAINER_FEMALE | -#line 13211 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13212 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13213 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13215 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13217 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13216 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13219 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13221 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13220 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13223 - [DIFFICULTY_NORMAL][TRAINER_KAI] = - { -#line 13224 - .trainerName = _("KAI"), -#line 13225 - .trainerClass = TRAINER_CLASS_FISHERMAN, -#line 13226 - .trainerPic = TRAINER_PIC_FISHERMAN, - .encounterMusic_gender = -#line 13228 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13229 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13230 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13232 - .species = SPECIES_BARBOACH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13234 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13233 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13236 - [DIFFICULTY_NORMAL][TRAINER_CHARLOTTE] = - { -#line 13237 - .trainerName = _("CHARLOTTE"), -#line 13238 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 13239 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 13240 -F_TRAINER_FEMALE | -#line 13241 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13242 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13243 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13245 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13247 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13246 - .lvl = 19, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13249 - [DIFFICULTY_NORMAL][TRAINER_DEANDRE] = - { -#line 13250 - .trainerName = _("DEANDRE"), -#line 13251 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 13252 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 13254 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13255 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13256 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 13258 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13260 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13259 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13262 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13264 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13263 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13266 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13268 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13267 - .lvl = 14, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13270 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_1] = - { -#line 13271 - .trainerName = _("GRUNT"), -#line 13272 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13273 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13275 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13276 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13277 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13279 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13281 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13280 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13283 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_2] = - { -#line 13284 - .trainerName = _("GRUNT"), -#line 13285 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13286 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13288 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13289 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13290 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13292 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13294 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13293 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13296 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_3] = - { -#line 13297 - .trainerName = _("GRUNT"), -#line 13298 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13299 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13301 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13302 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13303 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13305 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13307 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13306 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13309 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_4] = - { -#line 13310 - .trainerName = _("GRUNT"), -#line 13311 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13312 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13314 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13315 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13316 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13318 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13320 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13319 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13322 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13324 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13323 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13326 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_5] = - { -#line 13327 - .trainerName = _("GRUNT"), -#line 13328 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13329 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13331 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13332 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13333 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13335 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13337 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13336 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13339 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13341 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13340 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13343 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_6] = - { -#line 13344 - .trainerName = _("GRUNT"), -#line 13345 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13346 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13348 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13349 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13350 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13352 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13354 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13353 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13356 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_7] = - { -#line 13357 - .trainerName = _("GRUNT"), -#line 13358 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13359 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13361 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13362 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13363 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13365 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13367 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13366 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13369 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_8] = - { -#line 13370 - .trainerName = _("GRUNT"), -#line 13371 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13372 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13374 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13375 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13376 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13378 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13380 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13379 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13382 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_9] = - { -#line 13383 - .trainerName = _("GRUNT"), -#line 13384 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13385 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13387 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13388 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13389 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13391 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13393 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13392 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13395 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_10] = - { -#line 13396 - .trainerName = _("GRUNT"), -#line 13397 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13398 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13400 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13401 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13402 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13404 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13406 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13405 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13408 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_11] = - { -#line 13409 - .trainerName = _("GRUNT"), -#line 13410 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13411 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13413 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13414 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13415 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13417 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13419 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13418 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13421 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_12] = - { -#line 13422 - .trainerName = _("GRUNT"), -#line 13423 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13424 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13426 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13427 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13428 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13430 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13432 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13431 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13434 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_13] = - { -#line 13435 - .trainerName = _("GRUNT"), -#line 13436 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13437 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_M, - .encounterMusic_gender = -#line 13439 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13440 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13441 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13443 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13445 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13444 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13447 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_14] = - { -#line 13448 - .trainerName = _("GRUNT"), -#line 13449 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13450 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_F, - .encounterMusic_gender = -#line 13451 -F_TRAINER_FEMALE | -#line 13452 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13453 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13454 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13456 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13458 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13457 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13460 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_15] = - { -#line 13461 - .trainerName = _("GRUNT"), -#line 13462 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13463 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_F, - .encounterMusic_gender = -#line 13464 -F_TRAINER_FEMALE | -#line 13465 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13466 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13467 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13469 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13471 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13470 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13473 - [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_16] = - { -#line 13474 - .trainerName = _("GRUNT"), -#line 13475 - .trainerClass = TRAINER_CLASS_TEAM_MAGMA, -#line 13476 - .trainerPic = TRAINER_PIC_MAGMA_GRUNT_F, - .encounterMusic_gender = -#line 13477 -F_TRAINER_FEMALE | -#line 13478 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13479 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13480 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13482 - .species = SPECIES_BALTOY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13484 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13483 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13486 - [DIFFICULTY_NORMAL][TRAINER_TABITHA_MAGMA_HIDEOUT] = - { -#line 13487 - .trainerName = _("TABITHA"), -#line 13488 - .trainerClass = TRAINER_CLASS_MAGMA_ADMIN, -#line 13489 - .trainerPic = TRAINER_PIC_MAGMA_ADMIN, - .encounterMusic_gender = -#line 13491 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13492 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13493 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 13495 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13497 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 13496 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13499 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13501 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 13500 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13503 - .species = SPECIES_ZUBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13505 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 13504 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13507 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13509 - .iv = TRAINER_PARTY_IVS(9, 9, 9, 9, 9, 9), -#line 13508 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13511 - [DIFFICULTY_NORMAL][TRAINER_DARCY] = - { -#line 13512 - .trainerName = _("DARCY"), -#line 13513 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 13514 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 13515 -F_TRAINER_FEMALE | -#line 13516 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13517 - .items = { ITEM_HYPER_POTION }, -#line 13518 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13519 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13521 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13523 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13522 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13525 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13527 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13526 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13529 - [DIFFICULTY_NORMAL][TRAINER_MAXIE_MOSSDEEP] = - { -#line 13530 - .trainerName = _("MAXIE"), -#line 13531 - .trainerClass = TRAINER_CLASS_MAGMA_LEADER, -#line 13532 - .trainerPic = TRAINER_PIC_MAGMA_LEADER_MAXIE, - .encounterMusic_gender = -#line 13534 - TRAINER_ENCOUNTER_MUSIC_MAGMA, -#line 13535 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13536 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 13538 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13540 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 13539 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13542 - .species = SPECIES_CROBAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13544 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 13543 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13546 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13548 - .iv = TRAINER_PARTY_IVS(18, 18, 18, 18, 18, 18), -#line 13547 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13550 - [DIFFICULTY_NORMAL][TRAINER_PETE] = - { -#line 13551 - .trainerName = _("PETE"), -#line 13552 - .trainerClass = TRAINER_CLASS_SWIMMER_M, -#line 13553 - .trainerPic = TRAINER_PIC_SWIMMER_M, - .encounterMusic_gender = -#line 13555 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 13556 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13557 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13559 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13561 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13560 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13563 - [DIFFICULTY_NORMAL][TRAINER_ISABELLE] = - { -#line 13564 - .trainerName = _("ISABELLE"), -#line 13565 - .trainerClass = TRAINER_CLASS_SWIMMER_F, -#line 13566 - .trainerPic = TRAINER_PIC_SWIMMER_F, - .encounterMusic_gender = -#line 13567 -F_TRAINER_FEMALE | -#line 13568 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 13569 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13570 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13572 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13574 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13573 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13576 - [DIFFICULTY_NORMAL][TRAINER_ANDRES_1] = - { -#line 13577 - .trainerName = _("ANDRES"), -#line 13578 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 13579 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 13581 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13582 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13583 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13585 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13587 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13586 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13589 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13591 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13590 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13593 - [DIFFICULTY_NORMAL][TRAINER_JOSUE] = - { -#line 13594 - .trainerName = _("JOSUE"), -#line 13595 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 13596 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 13598 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13599 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13600 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13602 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13604 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13603 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13606 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13608 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13607 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13610 - [DIFFICULTY_NORMAL][TRAINER_CAMRON] = - { -#line 13611 - .trainerName = _("CAMRON"), -#line 13612 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 13613 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 13615 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 13616 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13617 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13619 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13621 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13620 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13623 - [DIFFICULTY_NORMAL][TRAINER_CORY_1] = - { -#line 13624 - .trainerName = _("CORY"), -#line 13625 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 13626 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 13628 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13629 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13630 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 13632 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13634 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13633 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13636 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13638 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13637 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13640 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13642 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13641 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13644 - [DIFFICULTY_NORMAL][TRAINER_CAROLINA] = - { -#line 13645 - .trainerName = _("CAROLINA"), -#line 13646 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 13647 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 13648 -F_TRAINER_FEMALE | -#line 13649 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13650 - .items = { ITEM_HYPER_POTION }, -#line 13651 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13652 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 13654 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13656 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13655 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13658 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13660 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13659 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13662 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13664 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 13663 - .lvl = 24, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13666 - [DIFFICULTY_NORMAL][TRAINER_ELIJAH] = - { -#line 13667 - .trainerName = _("ELIJAH"), -#line 13668 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 13669 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 13671 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13672 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13673 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13675 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13677 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13676 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13679 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13681 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13680 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13683 - [DIFFICULTY_NORMAL][TRAINER_CELIA] = - { -#line 13684 - .trainerName = _("CELIA"), -#line 13685 - .trainerClass = TRAINER_CLASS_PICNICKER, -#line 13686 - .trainerPic = TRAINER_PIC_PICNICKER, - .encounterMusic_gender = -#line 13687 -F_TRAINER_FEMALE | -#line 13688 - TRAINER_ENCOUNTER_MUSIC_GIRL, -#line 13689 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13690 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13692 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13694 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13693 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13696 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13698 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13697 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13700 - [DIFFICULTY_NORMAL][TRAINER_BRYAN] = - { -#line 13701 - .trainerName = _("BRYAN"), -#line 13702 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 13703 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 13705 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13706 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13707 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13709 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13711 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13710 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13713 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13715 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13714 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13717 - [DIFFICULTY_NORMAL][TRAINER_BRANDEN] = - { -#line 13718 - .trainerName = _("BRANDEN"), -#line 13719 - .trainerClass = TRAINER_CLASS_CAMPER, -#line 13720 - .trainerPic = TRAINER_PIC_CAMPER, - .encounterMusic_gender = -#line 13722 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13723 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13724 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13726 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13728 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13727 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13730 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13732 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13731 - .lvl = 22, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13734 - [DIFFICULTY_NORMAL][TRAINER_BRYANT] = - { -#line 13735 - .trainerName = _("BRYANT"), -#line 13736 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 13737 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 13739 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13740 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13741 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13743 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13745 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13744 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13747 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13749 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13748 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13751 - [DIFFICULTY_NORMAL][TRAINER_SHAYLA] = - { -#line 13752 - .trainerName = _("SHAYLA"), -#line 13753 - .trainerClass = TRAINER_CLASS_AROMA_LADY, -#line 13754 - .trainerPic = TRAINER_PIC_AROMA_LADY, - .encounterMusic_gender = -#line 13755 -F_TRAINER_FEMALE | -#line 13756 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13757 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13758 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13760 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13762 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13761 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13764 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13766 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13765 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13768 - [DIFFICULTY_NORMAL][TRAINER_KYRA] = - { -#line 13769 - .trainerName = _("KYRA"), -#line 13770 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 13771 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 13772 -F_TRAINER_FEMALE | -#line 13773 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13774 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13775 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13777 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13779 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13778 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13781 - .species = SPECIES_DODRIO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13783 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13782 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13785 - [DIFFICULTY_NORMAL][TRAINER_JAIDEN] = - { -#line 13786 - .trainerName = _("JAIDEN"), -#line 13787 - .trainerClass = TRAINER_CLASS_NINJA_BOY, -#line 13788 - .trainerPic = TRAINER_PIC_NINJA_BOY, - .encounterMusic_gender = -#line 13790 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 13791 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13792 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13794 - .species = SPECIES_NINJASK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13796 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13795 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13798 - .species = SPECIES_GULPIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13800 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13799 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13802 - [DIFFICULTY_NORMAL][TRAINER_ALIX] = - { -#line 13803 - .trainerName = _("ALIX"), -#line 13804 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 13805 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 13806 -F_TRAINER_FEMALE | -#line 13807 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13808 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13809 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13811 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13813 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13812 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13815 - .species = SPECIES_KIRLIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13817 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13816 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13819 - [DIFFICULTY_NORMAL][TRAINER_HELENE] = - { -#line 13820 - .trainerName = _("HELENE"), -#line 13821 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 13822 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 13823 -F_TRAINER_FEMALE | -#line 13824 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13825 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13826 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13828 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13830 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13829 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13832 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13834 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13833 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13836 - [DIFFICULTY_NORMAL][TRAINER_MARLENE] = - { -#line 13837 - .trainerName = _("MARLENE"), -#line 13838 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 13839 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 13840 -F_TRAINER_FEMALE | -#line 13841 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13842 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13843 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13845 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13847 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13846 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13849 - .species = SPECIES_SPOINK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13851 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13850 - .lvl = 18, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13853 - [DIFFICULTY_NORMAL][TRAINER_DEVAN] = - { -#line 13854 - .trainerName = _("DEVAN"), -#line 13855 - .trainerClass = TRAINER_CLASS_HIKER, -#line 13856 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 13858 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13859 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13860 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13862 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13864 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13863 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13866 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13868 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13867 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13870 - [DIFFICULTY_NORMAL][TRAINER_JOHNSON] = - { -#line 13871 - .trainerName = _("JOHNSON"), -#line 13872 - .trainerClass = TRAINER_CLASS_YOUNGSTER, -#line 13873 - .trainerPic = TRAINER_PIC_YOUNGSTER, - .encounterMusic_gender = -#line 13875 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 13876 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13877 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13879 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13881 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13880 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13883 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13885 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13884 - .lvl = 8, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13887 - [DIFFICULTY_NORMAL][TRAINER_MELINA] = - { -#line 13888 - .trainerName = _("MELINA"), -#line 13889 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 13890 - .trainerPic = TRAINER_PIC_RUNNING_TRIATHLETE_F, - .encounterMusic_gender = -#line 13891 -F_TRAINER_FEMALE | -#line 13892 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13893 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13894 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13896 - .species = SPECIES_DODUO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13898 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13897 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13900 - [DIFFICULTY_NORMAL][TRAINER_BRANDI] = - { -#line 13901 - .trainerName = _("BRANDI"), -#line 13902 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 13903 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 13904 -F_TRAINER_FEMALE | -#line 13905 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13906 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13907 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13909 - .species = SPECIES_RALTS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13911 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13910 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13913 - [DIFFICULTY_NORMAL][TRAINER_AISHA] = - { -#line 13914 - .trainerName = _("AISHA"), -#line 13915 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 13916 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 13917 -F_TRAINER_FEMALE | -#line 13918 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13919 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13920 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13922 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13924 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13923 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13926 - [DIFFICULTY_NORMAL][TRAINER_MAKAYLA] = - { -#line 13927 - .trainerName = _("MAKAYLA"), -#line 13928 - .trainerClass = TRAINER_CLASS_EXPERT, -#line 13929 - .trainerPic = TRAINER_PIC_EXPERT_F, - .encounterMusic_gender = -#line 13930 -F_TRAINER_FEMALE | -#line 13931 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13932 - .items = { ITEM_HYPER_POTION }, -#line 13933 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13934 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13936 - .species = SPECIES_ROSELIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13938 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13937 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13940 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13942 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13941 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13944 - [DIFFICULTY_NORMAL][TRAINER_FABIAN] = - { -#line 13945 - .trainerName = _("FABIAN"), -#line 13946 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 13947 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 13949 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 13950 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13951 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13953 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13955 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13954 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13957 - [DIFFICULTY_NORMAL][TRAINER_DAYTON] = - { -#line 13958 - .trainerName = _("DAYTON"), -#line 13959 - .trainerClass = TRAINER_CLASS_KINDLER, -#line 13960 - .trainerPic = TRAINER_PIC_KINDLER, - .encounterMusic_gender = -#line 13962 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 13963 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13964 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 13966 - .species = SPECIES_SLUGMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13968 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13967 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 13970 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13972 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13971 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13974 - [DIFFICULTY_NORMAL][TRAINER_RACHEL] = - { -#line 13975 - .trainerName = _("RACHEL"), -#line 13976 - .trainerClass = TRAINER_CLASS_PARASOL_LADY, -#line 13977 - .trainerPic = TRAINER_PIC_PARASOL_LADY, - .encounterMusic_gender = -#line 13978 -F_TRAINER_FEMALE | -#line 13979 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 13980 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13981 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13983 - .species = SPECIES_GOLDEEN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13985 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 13984 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 13987 - [DIFFICULTY_NORMAL][TRAINER_LEONEL] = - { -#line 13988 - .trainerName = _("LEONEL"), -#line 13989 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 13990 - .trainerPic = TRAINER_PIC_COOLTRAINER_M, - .encounterMusic_gender = -#line 13992 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 13993 - .items = { ITEM_HYPER_POTION }, -#line 13994 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 13995 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 13997 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 13999 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 13998 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14000 - MOVE_THUNDER, - MOVE_QUICK_ATTACK, - MOVE_THUNDER_WAVE, - }, - }, - }, - }, -#line 14004 - [DIFFICULTY_NORMAL][TRAINER_CALLIE] = - { -#line 14005 - .trainerName = _("CALLIE"), -#line 14006 - .trainerClass = TRAINER_CLASS_BATTLE_GIRL, -#line 14007 - .trainerPic = TRAINER_PIC_BATTLE_GIRL, - .encounterMusic_gender = -#line 14008 -F_TRAINER_FEMALE | -#line 14009 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 14010 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14011 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 14013 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14015 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 14014 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14017 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14019 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 14018 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14021 - [DIFFICULTY_NORMAL][TRAINER_CALE] = - { -#line 14022 - .trainerName = _("CALE"), -#line 14023 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 14024 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 14026 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 14027 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14028 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 14030 - .species = SPECIES_DUSTOX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14032 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 14031 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14034 - .species = SPECIES_BEAUTIFLY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14036 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 14035 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14038 - [DIFFICULTY_NORMAL][TRAINER_MYLES] = - { -#line 14039 - .trainerName = _("MYLES"), -#line 14040 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 14041 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_M, - .encounterMusic_gender = -#line 14043 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14044 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14045 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14047 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14049 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14048 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14051 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14053 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14052 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14055 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14057 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14056 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14059 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14061 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14060 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14063 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14065 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14064 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14067 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14069 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14068 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14071 - [DIFFICULTY_NORMAL][TRAINER_PAT] = - { -#line 14072 - .trainerName = _("PAT"), -#line 14073 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 14074 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 14075 -F_TRAINER_FEMALE | -#line 14076 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14077 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14078 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14080 - .species = SPECIES_POOCHYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14082 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14081 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14084 - .species = SPECIES_SHROOMISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14086 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14085 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14088 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14090 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14089 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14092 - .species = SPECIES_MARILL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14094 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14093 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14096 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14098 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14097 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14100 - .species = SPECIES_GULPIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14102 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 14101 - .lvl = 25, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14104 - [DIFFICULTY_NORMAL][TRAINER_CRISTIN_1] = - { -#line 14105 - .trainerName = _("CRISTIN"), -#line 14106 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 14107 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 14108 -F_TRAINER_FEMALE | -#line 14109 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 14110 - .items = { ITEM_HYPER_POTION }, -#line 14111 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14112 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 14114 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14116 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 14115 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14118 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14120 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 14119 - .lvl = 29, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14122 - [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_TREECKO] = - { -#line 14123 - .trainerName = _("MAY"), -#line 14124 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 14125 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 14126 -F_TRAINER_FEMALE | -#line 14127 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14128 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14129 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 14131 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14133 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 14132 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14135 - .species = SPECIES_TORCHIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14137 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 14136 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14139 - [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_TORCHIC] = - { -#line 14140 - .trainerName = _("MAY"), -#line 14141 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 14142 - .trainerPic = TRAINER_PIC_MAY, - .encounterMusic_gender = -#line 14143 -F_TRAINER_FEMALE | -#line 14144 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14145 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 14146 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 14148 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14150 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 14149 - .lvl = 13, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 14152 - .species = SPECIES_MUDKIP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14154 - .iv = TRAINER_PARTY_IVS(6, 6, 6, 6, 6, 6), -#line 14153 - .lvl = 15, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 14156 - [DIFFICULTY_NORMAL][TRAINER_ROXANNE_2] = - { -#line 14157 - .trainerName = _("ROXANNE"), -#line 14158 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14159 - .trainerPic = TRAINER_PIC_LEADER_ROXANNE, - .encounterMusic_gender = -#line 14160 -F_TRAINER_FEMALE | -#line 14161 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14162 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14163 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14164 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14166 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14168 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14167 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14169 - MOVE_PROTECT, - MOVE_ROLLOUT, - MOVE_MAGNITUDE, - MOVE_EXPLOSION, - }, - }, - { -#line 14174 - .species = SPECIES_KABUTO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14174 - .heldItem = ITEM_SITRUS_BERRY, -#line 14176 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14175 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14177 - MOVE_SWORDS_DANCE, - MOVE_ICE_BEAM, - MOVE_SURF, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14182 - .species = SPECIES_ONIX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14184 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14183 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14185 - MOVE_IRON_TAIL, - MOVE_EXPLOSION, - MOVE_ROAR, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14190 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14190 - .heldItem = ITEM_SITRUS_BERRY, -#line 14192 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14191 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14193 - MOVE_DOUBLE_TEAM, - MOVE_EXPLOSION, - MOVE_PROTECT, - MOVE_ROCK_SLIDE, - }, - }, - }, - }, -#line 14198 - [DIFFICULTY_NORMAL][TRAINER_ROXANNE_3] = - { -#line 14199 - .trainerName = _("ROXANNE"), -#line 14200 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14201 - .trainerPic = TRAINER_PIC_LEADER_ROXANNE, - .encounterMusic_gender = -#line 14202 -F_TRAINER_FEMALE | -#line 14203 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14204 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14205 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14206 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14208 - .species = SPECIES_OMANYTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14210 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14209 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14211 - MOVE_PROTECT, - MOVE_ICE_BEAM, - MOVE_ROCK_SLIDE, - MOVE_SURF, - }, - }, - { -#line 14216 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14218 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14217 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14219 - MOVE_PROTECT, - MOVE_ROLLOUT, - MOVE_MAGNITUDE, - MOVE_EXPLOSION, - }, - }, - { -#line 14224 - .species = SPECIES_KABUTOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14224 - .heldItem = ITEM_SITRUS_BERRY, -#line 14226 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14225 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14227 - MOVE_SWORDS_DANCE, - MOVE_ICE_BEAM, - MOVE_SURF, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14232 - .species = SPECIES_ONIX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14234 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14233 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14235 - MOVE_IRON_TAIL, - MOVE_EXPLOSION, - MOVE_ROAR, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14240 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14240 - .heldItem = ITEM_SITRUS_BERRY, -#line 14242 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14241 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14243 - MOVE_DOUBLE_TEAM, - MOVE_EXPLOSION, - MOVE_PROTECT, - MOVE_ROCK_SLIDE, - }, - }, - }, - }, -#line 14248 - [DIFFICULTY_NORMAL][TRAINER_ROXANNE_4] = - { -#line 14249 - .trainerName = _("ROXANNE"), -#line 14250 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14251 - .trainerPic = TRAINER_PIC_LEADER_ROXANNE, - .encounterMusic_gender = -#line 14252 -F_TRAINER_FEMALE | -#line 14253 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14254 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14255 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14256 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14258 - .species = SPECIES_OMASTAR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14260 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14259 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14261 - MOVE_PROTECT, - MOVE_ICE_BEAM, - MOVE_ROCK_SLIDE, - MOVE_SURF, - }, - }, - { -#line 14266 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14268 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14267 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14269 - MOVE_PROTECT, - MOVE_ROLLOUT, - MOVE_EARTHQUAKE, - MOVE_EXPLOSION, - }, - }, - { -#line 14274 - .species = SPECIES_KABUTOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14274 - .heldItem = ITEM_SITRUS_BERRY, -#line 14276 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14275 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14277 - MOVE_SWORDS_DANCE, - MOVE_ICE_BEAM, - MOVE_SURF, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14282 - .species = SPECIES_ONIX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14284 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14283 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14285 - MOVE_IRON_TAIL, - MOVE_EXPLOSION, - MOVE_ROAR, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14290 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14290 - .heldItem = ITEM_SITRUS_BERRY, -#line 14292 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14291 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14293 - MOVE_DOUBLE_TEAM, - MOVE_EXPLOSION, - MOVE_PROTECT, - MOVE_ROCK_SLIDE, - }, - }, - }, - }, -#line 14298 - [DIFFICULTY_NORMAL][TRAINER_ROXANNE_5] = - { -#line 14299 - .trainerName = _("ROXANNE"), -#line 14300 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14301 - .trainerPic = TRAINER_PIC_LEADER_ROXANNE, - .encounterMusic_gender = -#line 14302 -F_TRAINER_FEMALE | -#line 14303 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14304 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14305 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14306 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14308 - .species = SPECIES_AERODACTYL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14310 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14309 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14311 - MOVE_ROCK_SLIDE, - MOVE_HYPER_BEAM, - MOVE_SUPERSONIC, - MOVE_PROTECT, - }, - }, - { -#line 14316 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14318 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14317 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14319 - MOVE_FOCUS_PUNCH, - MOVE_ROLLOUT, - MOVE_EARTHQUAKE, - MOVE_EXPLOSION, - }, - }, - { -#line 14324 - .species = SPECIES_OMASTAR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14326 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14325 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14327 - MOVE_PROTECT, - MOVE_ICE_BEAM, - MOVE_ROCK_SLIDE, - MOVE_SURF, - }, - }, - { -#line 14332 - .species = SPECIES_KABUTOPS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14332 - .heldItem = ITEM_SITRUS_BERRY, -#line 14334 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14333 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14335 - MOVE_SWORDS_DANCE, - MOVE_ICE_BEAM, - MOVE_SURF, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14340 - .species = SPECIES_STEELIX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14342 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14341 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14343 - MOVE_IRON_TAIL, - MOVE_EXPLOSION, - MOVE_ROAR, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14348 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14348 - .heldItem = ITEM_SITRUS_BERRY, -#line 14350 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14349 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14351 - MOVE_DOUBLE_TEAM, - MOVE_EXPLOSION, - MOVE_PROTECT, - MOVE_ROCK_SLIDE, - }, - }, - }, - }, -#line 14356 - [DIFFICULTY_NORMAL][TRAINER_BRAWLY_2] = - { -#line 14357 - .trainerName = _("BRAWLY"), -#line 14358 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14359 - .trainerPic = TRAINER_PIC_LEADER_BRAWLY, - .encounterMusic_gender = -#line 14361 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14362 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14363 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14364 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14366 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14366 - .heldItem = ITEM_SITRUS_BERRY, -#line 14368 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14367 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14369 - MOVE_KARATE_CHOP, - MOVE_ROCK_SLIDE, - MOVE_FOCUS_PUNCH, - MOVE_BULK_UP, - }, - }, - { -#line 14374 - .species = SPECIES_MEDITITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14376 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14375 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14377 - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - MOVE_REFLECT, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 14382 - .species = SPECIES_HITMONTOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14384 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14383 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14385 - MOVE_PURSUIT, - MOVE_COUNTER, - MOVE_PROTECT, - MOVE_TRIPLE_KICK, - }, - }, - { -#line 14390 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14390 - .heldItem = ITEM_SITRUS_BERRY, -#line 14392 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14391 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14393 - MOVE_FAKE_OUT, - MOVE_FOCUS_PUNCH, - MOVE_BELLY_DRUM, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 14398 - [DIFFICULTY_NORMAL][TRAINER_BRAWLY_3] = - { -#line 14399 - .trainerName = _("BRAWLY"), -#line 14400 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14401 - .trainerPic = TRAINER_PIC_LEADER_BRAWLY, - .encounterMusic_gender = -#line 14403 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14404 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14405 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14406 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14408 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14408 - .heldItem = ITEM_SITRUS_BERRY, -#line 14410 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14409 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14411 - MOVE_KARATE_CHOP, - MOVE_ROCK_SLIDE, - MOVE_FOCUS_PUNCH, - MOVE_BULK_UP, - }, - }, - { -#line 14416 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14418 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14417 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14419 - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - MOVE_REFLECT, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 14424 - .species = SPECIES_HITMONTOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14426 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14425 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14427 - MOVE_PURSUIT, - MOVE_COUNTER, - MOVE_PROTECT, - MOVE_TRIPLE_KICK, - }, - }, - { -#line 14432 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14432 - .heldItem = ITEM_SITRUS_BERRY, -#line 14434 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14433 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14435 - MOVE_FAKE_OUT, - MOVE_FOCUS_PUNCH, - MOVE_BELLY_DRUM, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 14440 - [DIFFICULTY_NORMAL][TRAINER_BRAWLY_4] = - { -#line 14441 - .trainerName = _("BRAWLY"), -#line 14442 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14443 - .trainerPic = TRAINER_PIC_LEADER_BRAWLY, - .encounterMusic_gender = -#line 14445 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14446 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14447 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14448 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14450 - .species = SPECIES_HITMONCHAN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14452 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14451 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14453 - MOVE_SKY_UPPERCUT, - MOVE_PROTECT, - MOVE_FIRE_PUNCH, - MOVE_ICE_PUNCH, - }, - }, - { -#line 14458 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14458 - .heldItem = ITEM_SITRUS_BERRY, -#line 14460 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14459 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14461 - MOVE_KARATE_CHOP, - MOVE_ROCK_SLIDE, - MOVE_FOCUS_PUNCH, - MOVE_BULK_UP, - }, - }, - { -#line 14466 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14468 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14467 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14469 - MOVE_FOCUS_PUNCH, - MOVE_LIGHT_SCREEN, - MOVE_REFLECT, - MOVE_PSYCHIC, - }, - }, - { -#line 14474 - .species = SPECIES_HITMONTOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14476 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14475 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14477 - MOVE_PURSUIT, - MOVE_COUNTER, - MOVE_PROTECT, - MOVE_TRIPLE_KICK, - }, - }, - { -#line 14482 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14482 - .heldItem = ITEM_SITRUS_BERRY, -#line 14484 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14483 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14485 - MOVE_FAKE_OUT, - MOVE_FOCUS_PUNCH, - MOVE_BELLY_DRUM, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 14490 - [DIFFICULTY_NORMAL][TRAINER_BRAWLY_5] = - { -#line 14491 - .trainerName = _("BRAWLY"), -#line 14492 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14493 - .trainerPic = TRAINER_PIC_LEADER_BRAWLY, - .encounterMusic_gender = -#line 14495 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14496 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14497 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14498 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14500 - .species = SPECIES_HITMONLEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14502 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14501 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14503 - MOVE_MEGA_KICK, - MOVE_FOCUS_PUNCH, - MOVE_EARTHQUAKE, - MOVE_BULK_UP, - }, - }, - { -#line 14508 - .species = SPECIES_HITMONCHAN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14510 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14509 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14511 - MOVE_SKY_UPPERCUT, - MOVE_PROTECT, - MOVE_FIRE_PUNCH, - MOVE_ICE_PUNCH, - }, - }, - { -#line 14516 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14516 - .heldItem = ITEM_SITRUS_BERRY, -#line 14518 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14517 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14519 - MOVE_CROSS_CHOP, - MOVE_ROCK_SLIDE, - MOVE_FOCUS_PUNCH, - MOVE_BULK_UP, - }, - }, - { -#line 14524 - .species = SPECIES_MEDICHAM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14526 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14525 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14527 - MOVE_FOCUS_PUNCH, - MOVE_LIGHT_SCREEN, - MOVE_REFLECT, - MOVE_PSYCHIC, - }, - }, - { -#line 14532 - .species = SPECIES_HITMONTOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14534 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14533 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14535 - MOVE_PURSUIT, - MOVE_COUNTER, - MOVE_PROTECT, - MOVE_TRIPLE_KICK, - }, - }, - { -#line 14540 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14540 - .heldItem = ITEM_SITRUS_BERRY, -#line 14542 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14541 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14543 - MOVE_FAKE_OUT, - MOVE_FOCUS_PUNCH, - MOVE_BELLY_DRUM, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 14548 - [DIFFICULTY_NORMAL][TRAINER_WATTSON_2] = - { -#line 14549 - .trainerName = _("WATTSON"), -#line 14550 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14551 - .trainerPic = TRAINER_PIC_LEADER_WATTSON, - .encounterMusic_gender = -#line 14553 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14554 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14555 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14556 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14558 - .species = SPECIES_MAREEP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14560 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14559 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14561 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_THUNDER_WAVE, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 14566 - .species = SPECIES_ELECTRODE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14568 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14567 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14569 - MOVE_ROLLOUT, - MOVE_THUNDER, - MOVE_EXPLOSION, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14574 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14574 - .heldItem = ITEM_SITRUS_BERRY, -#line 14576 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14575 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14577 - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_THUNDER, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14582 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14582 - .heldItem = ITEM_SITRUS_BERRY, -#line 14584 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14583 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14585 - MOVE_BITE, - MOVE_THUNDER_WAVE, - MOVE_THUNDER, - MOVE_PROTECT, - }, - }, - }, - }, -#line 14590 - [DIFFICULTY_NORMAL][TRAINER_WATTSON_3] = - { -#line 14591 - .trainerName = _("WATTSON"), -#line 14592 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14593 - .trainerPic = TRAINER_PIC_LEADER_WATTSON, - .encounterMusic_gender = -#line 14595 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14596 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14597 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14598 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14600 - .species = SPECIES_PIKACHU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14602 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14601 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14603 - MOVE_THUNDER, - MOVE_SLAM, - MOVE_RAIN_DANCE, - MOVE_SHOCK_WAVE, - }, - }, - { -#line 14608 - .species = SPECIES_FLAAFFY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14610 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14609 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14611 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_THUNDER_WAVE, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 14616 - .species = SPECIES_ELECTRODE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14618 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14617 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14619 - MOVE_ROLLOUT, - MOVE_THUNDER, - MOVE_EXPLOSION, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14624 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14624 - .heldItem = ITEM_SITRUS_BERRY, -#line 14626 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14625 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14627 - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_THUNDER, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14632 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14632 - .heldItem = ITEM_SITRUS_BERRY, -#line 14634 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14633 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14635 - MOVE_BITE, - MOVE_THUNDER_WAVE, - MOVE_THUNDER, - MOVE_PROTECT, - }, - }, - }, - }, -#line 14640 - [DIFFICULTY_NORMAL][TRAINER_WATTSON_4] = - { -#line 14641 - .trainerName = _("WATTSON"), -#line 14642 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14643 - .trainerPic = TRAINER_PIC_LEADER_WATTSON, - .encounterMusic_gender = -#line 14645 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14646 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14647 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14648 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14650 - .species = SPECIES_RAICHU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14652 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14651 - .lvl = 44, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14653 - MOVE_THUNDER, - MOVE_SLAM, - MOVE_RAIN_DANCE, - MOVE_PROTECT, - }, - }, - { -#line 14658 - .species = SPECIES_AMPHAROS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14660 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14659 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14661 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_THUNDER_WAVE, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 14666 - .species = SPECIES_ELECTRODE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14668 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14667 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14669 - MOVE_ROLLOUT, - MOVE_THUNDER, - MOVE_EXPLOSION, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14674 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14674 - .heldItem = ITEM_SITRUS_BERRY, -#line 14676 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14675 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14677 - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_THUNDER, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14682 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14682 - .heldItem = ITEM_SITRUS_BERRY, -#line 14684 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14683 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14685 - MOVE_BITE, - MOVE_THUNDER_WAVE, - MOVE_THUNDER, - MOVE_PROTECT, - }, - }, - }, - }, -#line 14690 - [DIFFICULTY_NORMAL][TRAINER_WATTSON_5] = - { -#line 14691 - .trainerName = _("WATTSON"), -#line 14692 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14693 - .trainerPic = TRAINER_PIC_LEADER_WATTSON, - .encounterMusic_gender = -#line 14695 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14696 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14697 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14698 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14700 - .species = SPECIES_ELECTABUZZ, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14702 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14701 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14703 - MOVE_SWIFT, - MOVE_FOCUS_PUNCH, - MOVE_THUNDER_PUNCH, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 14708 - .species = SPECIES_RAICHU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14710 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14709 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14711 - MOVE_THUNDER, - MOVE_SLAM, - MOVE_RAIN_DANCE, - MOVE_PROTECT, - }, - }, - { -#line 14716 - .species = SPECIES_AMPHAROS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14718 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14717 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14719 - MOVE_THUNDER, - MOVE_PROTECT, - MOVE_THUNDER_WAVE, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 14724 - .species = SPECIES_ELECTRODE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14726 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14725 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14727 - MOVE_ROLLOUT, - MOVE_THUNDER, - MOVE_EXPLOSION, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14732 - .species = SPECIES_MAGNETON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14732 - .heldItem = ITEM_SITRUS_BERRY, -#line 14734 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14733 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14735 - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_THUNDER, - MOVE_RAIN_DANCE, - }, - }, - { -#line 14740 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14740 - .heldItem = ITEM_SITRUS_BERRY, -#line 14742 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14741 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14743 - MOVE_BITE, - MOVE_THUNDER_WAVE, - MOVE_THUNDER, - MOVE_PROTECT, - }, - }, - }, - }, -#line 14748 - [DIFFICULTY_NORMAL][TRAINER_FLANNERY_2] = - { -#line 14749 - .trainerName = _("FLANNERY"), -#line 14750 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14751 - .trainerPic = TRAINER_PIC_LEADER_FLANNERY, - .encounterMusic_gender = -#line 14752 -F_TRAINER_FEMALE | -#line 14753 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14754 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14755 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14756 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14758 - .species = SPECIES_MAGCARGO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14758 - .heldItem = ITEM_WHITE_HERB, -#line 14760 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14759 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14761 - MOVE_OVERHEAT, - MOVE_ATTRACT, - MOVE_LIGHT_SCREEN, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14766 - .species = SPECIES_PONYTA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14768 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14767 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14769 - MOVE_FLAMETHROWER, - MOVE_ATTRACT, - MOVE_SOLAR_BEAM, - MOVE_BOUNCE, - }, - }, - { -#line 14774 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14774 - .heldItem = ITEM_WHITE_HERB, -#line 14776 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14775 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14777 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EARTHQUAKE, - MOVE_ATTRACT, - }, - }, - { -#line 14782 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14782 - .heldItem = ITEM_WHITE_HERB, -#line 14784 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14783 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14785 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EXPLOSION, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 14790 - [DIFFICULTY_NORMAL][TRAINER_FLANNERY_3] = - { -#line 14791 - .trainerName = _("FLANNERY"), -#line 14792 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14793 - .trainerPic = TRAINER_PIC_LEADER_FLANNERY, - .encounterMusic_gender = -#line 14794 -F_TRAINER_FEMALE | -#line 14795 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14796 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14797 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14798 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 14800 - .species = SPECIES_GROWLITHE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14802 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14801 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14803 - MOVE_HELPING_HAND, - MOVE_FLAMETHROWER, - MOVE_ROAR, - MOVE_SUNNY_DAY, - }, - }, - { -#line 14808 - .species = SPECIES_MAGCARGO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14808 - .heldItem = ITEM_WHITE_HERB, -#line 14810 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14809 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14811 - MOVE_OVERHEAT, - MOVE_ATTRACT, - MOVE_LIGHT_SCREEN, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14816 - .species = SPECIES_PONYTA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14818 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14817 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14819 - MOVE_FLAMETHROWER, - MOVE_ATTRACT, - MOVE_SOLAR_BEAM, - MOVE_BOUNCE, - }, - }, - { -#line 14824 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14824 - .heldItem = ITEM_WHITE_HERB, -#line 14826 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14825 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14827 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EARTHQUAKE, - MOVE_ATTRACT, - }, - }, - { -#line 14832 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14832 - .heldItem = ITEM_WHITE_HERB, -#line 14834 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14833 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14835 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EXPLOSION, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 14840 - [DIFFICULTY_NORMAL][TRAINER_FLANNERY_4] = - { -#line 14841 - .trainerName = _("FLANNERY"), -#line 14842 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14843 - .trainerPic = TRAINER_PIC_LEADER_FLANNERY, - .encounterMusic_gender = -#line 14844 -F_TRAINER_FEMALE | -#line 14845 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14846 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14847 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14848 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14850 - .species = SPECIES_HOUNDOUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14852 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14851 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14853 - MOVE_ROAR, - MOVE_SOLAR_BEAM, - MOVE_TAUNT, - MOVE_SUNNY_DAY, - }, - }, - { -#line 14858 - .species = SPECIES_GROWLITHE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14860 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14859 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14861 - MOVE_HELPING_HAND, - MOVE_FLAMETHROWER, - MOVE_SUNNY_DAY, - MOVE_ROAR, - }, - }, - { -#line 14866 - .species = SPECIES_MAGCARGO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14866 - .heldItem = ITEM_WHITE_HERB, -#line 14868 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14867 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14869 - MOVE_OVERHEAT, - MOVE_ATTRACT, - MOVE_LIGHT_SCREEN, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14874 - .species = SPECIES_RAPIDASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14876 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14875 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14877 - MOVE_FLAMETHROWER, - MOVE_ATTRACT, - MOVE_SOLAR_BEAM, - MOVE_BOUNCE, - }, - }, - { -#line 14882 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14882 - .heldItem = ITEM_WHITE_HERB, -#line 14884 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14883 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14885 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EARTHQUAKE, - MOVE_ATTRACT, - }, - }, - { -#line 14890 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14890 - .heldItem = ITEM_WHITE_HERB, -#line 14892 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14891 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14893 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EXPLOSION, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 14898 - [DIFFICULTY_NORMAL][TRAINER_FLANNERY_5] = - { -#line 14899 - .trainerName = _("FLANNERY"), -#line 14900 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14901 - .trainerPic = TRAINER_PIC_LEADER_FLANNERY, - .encounterMusic_gender = -#line 14902 -F_TRAINER_FEMALE | -#line 14903 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 14904 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14905 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14906 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 14908 - .species = SPECIES_ARCANINE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14910 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14909 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14911 - MOVE_HELPING_HAND, - MOVE_FLAMETHROWER, - MOVE_SUNNY_DAY, - MOVE_ROAR, - }, - }, - { -#line 14916 - .species = SPECIES_MAGCARGO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14916 - .heldItem = ITEM_WHITE_HERB, -#line 14918 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14917 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14919 - MOVE_OVERHEAT, - MOVE_ATTRACT, - MOVE_LIGHT_SCREEN, - MOVE_ROCK_SLIDE, - }, - }, - { -#line 14924 - .species = SPECIES_HOUNDOOM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14926 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14925 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14927 - MOVE_ROAR, - MOVE_SOLAR_BEAM, - MOVE_TAUNT, - MOVE_SUNNY_DAY, - }, - }, - { -#line 14932 - .species = SPECIES_RAPIDASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14934 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14933 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14935 - MOVE_FLAMETHROWER, - MOVE_ATTRACT, - MOVE_SOLAR_BEAM, - MOVE_BOUNCE, - }, - }, - { -#line 14940 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14940 - .heldItem = ITEM_WHITE_HERB, -#line 14942 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14941 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14943 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EARTHQUAKE, - MOVE_ATTRACT, - }, - }, - { -#line 14948 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14948 - .heldItem = ITEM_WHITE_HERB, -#line 14950 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14949 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14951 - MOVE_OVERHEAT, - MOVE_SUNNY_DAY, - MOVE_EXPLOSION, - MOVE_ATTRACT, - }, - }, - }, - }, -#line 14956 - [DIFFICULTY_NORMAL][TRAINER_NORMAN_2] = - { -#line 14957 - .trainerName = _("NORMAN"), -#line 14958 - .trainerClass = TRAINER_CLASS_LEADER, -#line 14959 - .trainerPic = TRAINER_PIC_LEADER_NORMAN, - .encounterMusic_gender = -#line 14961 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 14962 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 14963 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 14964 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 14966 - .species = SPECIES_CHANSEY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14968 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14967 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14969 - MOVE_LIGHT_SCREEN, - MOVE_SING, - MOVE_SKILL_SWAP, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 14974 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14974 - .heldItem = ITEM_SITRUS_BERRY, -#line 14976 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14975 - .lvl = 42, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14977 - MOVE_BLIZZARD, - MOVE_SHADOW_BALL, - MOVE_DOUBLE_EDGE, - MOVE_FIRE_BLAST, - }, - }, - { -#line 14982 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14984 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14983 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14985 - MOVE_TEETER_DANCE, - MOVE_SKILL_SWAP, - MOVE_FACADE, - MOVE_HYPNOSIS, - }, - }, - { -#line 14990 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 14990 - .heldItem = ITEM_SITRUS_BERRY, -#line 14992 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 14991 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 14993 - MOVE_HYPER_BEAM, - MOVE_FLAMETHROWER, - MOVE_THUNDERBOLT, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 14998 - [DIFFICULTY_NORMAL][TRAINER_NORMAN_3] = - { -#line 14999 - .trainerName = _("NORMAN"), -#line 15000 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15001 - .trainerPic = TRAINER_PIC_LEADER_NORMAN, - .encounterMusic_gender = -#line 15003 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15004 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15005 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15006 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15008 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15008 - .heldItem = ITEM_SITRUS_BERRY, -#line 15010 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15009 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15011 - MOVE_BLIZZARD, - MOVE_SHADOW_BALL, - MOVE_DOUBLE_EDGE, - MOVE_FIRE_BLAST, - }, - }, - { -#line 15016 - .species = SPECIES_CHANSEY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15018 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15017 - .lvl = 47, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15019 - MOVE_LIGHT_SCREEN, - MOVE_SING, - MOVE_SKILL_SWAP, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 15024 - .species = SPECIES_KANGASKHAN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15026 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15025 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15027 - MOVE_FAKE_OUT, - MOVE_DIZZY_PUNCH, - MOVE_ENDURE, - MOVE_REVERSAL, - }, - }, - { -#line 15032 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15034 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15033 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15035 - MOVE_TEETER_DANCE, - MOVE_SKILL_SWAP, - MOVE_FACADE, - MOVE_HYPNOSIS, - }, - }, - { -#line 15040 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15040 - .heldItem = ITEM_SITRUS_BERRY, -#line 15042 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15041 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15043 - MOVE_HYPER_BEAM, - MOVE_FLAMETHROWER, - MOVE_THUNDERBOLT, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 15048 - [DIFFICULTY_NORMAL][TRAINER_NORMAN_4] = - { -#line 15049 - .trainerName = _("NORMAN"), -#line 15050 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15051 - .trainerPic = TRAINER_PIC_LEADER_NORMAN, - .encounterMusic_gender = -#line 15053 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15054 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15055 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15056 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15058 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15058 - .heldItem = ITEM_SITRUS_BERRY, -#line 15060 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15059 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15061 - MOVE_BLIZZARD, - MOVE_SHADOW_BALL, - MOVE_DOUBLE_EDGE, - MOVE_FIRE_BLAST, - }, - }, - { -#line 15066 - .species = SPECIES_BLISSEY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15068 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15067 - .lvl = 52, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15069 - MOVE_LIGHT_SCREEN, - MOVE_SING, - MOVE_SKILL_SWAP, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 15074 - .species = SPECIES_KANGASKHAN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15076 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15075 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15077 - MOVE_FAKE_OUT, - MOVE_DIZZY_PUNCH, - MOVE_ENDURE, - MOVE_REVERSAL, - }, - }, - { -#line 15082 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15084 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15083 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15085 - MOVE_TEETER_DANCE, - MOVE_SKILL_SWAP, - MOVE_FACADE, - MOVE_HYPNOSIS, - }, - }, - { -#line 15090 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15090 - .heldItem = ITEM_SITRUS_BERRY, -#line 15092 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15091 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15093 - MOVE_HYPER_BEAM, - MOVE_FLAMETHROWER, - MOVE_THUNDERBOLT, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 15098 - [DIFFICULTY_NORMAL][TRAINER_NORMAN_5] = - { -#line 15099 - .trainerName = _("NORMAN"), -#line 15100 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15101 - .trainerPic = TRAINER_PIC_LEADER_NORMAN, - .encounterMusic_gender = -#line 15103 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15104 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15105 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15106 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15108 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15108 - .heldItem = ITEM_SITRUS_BERRY, -#line 15110 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15109 - .lvl = 57, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15111 - MOVE_BLIZZARD, - MOVE_SHADOW_BALL, - MOVE_DOUBLE_EDGE, - MOVE_FIRE_BLAST, - }, - }, - { -#line 15116 - .species = SPECIES_BLISSEY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15118 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15117 - .lvl = 57, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15119 - MOVE_PROTECT, - MOVE_SING, - MOVE_SKILL_SWAP, - MOVE_FOCUS_PUNCH, - }, - }, - { -#line 15124 - .species = SPECIES_KANGASKHAN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15126 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15125 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15127 - MOVE_FAKE_OUT, - MOVE_DIZZY_PUNCH, - MOVE_ENDURE, - MOVE_REVERSAL, - }, - }, - { -#line 15132 - .species = SPECIES_TAUROS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15134 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15133 - .lvl = 57, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15135 - MOVE_TAKE_DOWN, - MOVE_PROTECT, - MOVE_FIRE_BLAST, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15140 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15142 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15141 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15143 - MOVE_TEETER_DANCE, - MOVE_SKILL_SWAP, - MOVE_FACADE, - MOVE_HYPNOSIS, - }, - }, - { -#line 15148 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15148 - .heldItem = ITEM_SITRUS_BERRY, -#line 15150 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15149 - .lvl = 60, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15151 - MOVE_HYPER_BEAM, - MOVE_FLAMETHROWER, - MOVE_THUNDERBOLT, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 15156 - [DIFFICULTY_NORMAL][TRAINER_WINONA_2] = - { -#line 15157 - .trainerName = _("WINONA"), -#line 15158 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15159 - .trainerPic = TRAINER_PIC_LEADER_WINONA, - .encounterMusic_gender = -#line 15160 -F_TRAINER_FEMALE | -#line 15161 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15162 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15163 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15164 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_RISKY, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15166 - .species = SPECIES_DRATINI, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15166 - .heldItem = ITEM_SITRUS_BERRY, -#line 15168 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15167 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15169 - MOVE_THUNDER_WAVE, - MOVE_THUNDERBOLT, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15174 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15176 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15175 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15177 - MOVE_SUNNY_DAY, - MOVE_AERIAL_ACE, - MOVE_SOLAR_BEAM, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15182 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15184 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15183 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15185 - MOVE_SURF, - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15190 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15192 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15191 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15193 - MOVE_WHIRLWIND, - MOVE_SPIKES, - MOVE_STEEL_WING, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15198 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15198 - .heldItem = ITEM_CHESTO_BERRY, -#line 15200 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15199 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15201 - MOVE_AERIAL_ACE, - MOVE_REST, - MOVE_DRAGON_DANCE, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 15206 - [DIFFICULTY_NORMAL][TRAINER_WINONA_3] = - { -#line 15207 - .trainerName = _("WINONA"), -#line 15208 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15209 - .trainerPic = TRAINER_PIC_LEADER_WINONA, - .encounterMusic_gender = -#line 15210 -F_TRAINER_FEMALE | -#line 15211 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15212 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15213 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15214 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_RISKY, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15216 - .species = SPECIES_HOOTHOOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15218 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15217 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15219 - MOVE_HYPNOSIS, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_DREAM_EATER, - }, - }, - { -#line 15224 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15226 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15225 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15227 - MOVE_SUNNY_DAY, - MOVE_AERIAL_ACE, - MOVE_SOLAR_BEAM, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15232 - .species = SPECIES_DRAGONAIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15232 - .heldItem = ITEM_SITRUS_BERRY, -#line 15234 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15233 - .lvl = 45, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15235 - MOVE_THUNDER_WAVE, - MOVE_THUNDERBOLT, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15240 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15242 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15241 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15243 - MOVE_SURF, - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15248 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15250 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15249 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15251 - MOVE_WHIRLWIND, - MOVE_SPIKES, - MOVE_STEEL_WING, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15256 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15256 - .heldItem = ITEM_CHESTO_BERRY, -#line 15258 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15257 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15259 - MOVE_AERIAL_ACE, - MOVE_REST, - MOVE_DRAGON_DANCE, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 15264 - [DIFFICULTY_NORMAL][TRAINER_WINONA_4] = - { -#line 15265 - .trainerName = _("WINONA"), -#line 15266 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15267 - .trainerPic = TRAINER_PIC_LEADER_WINONA, - .encounterMusic_gender = -#line 15268 -F_TRAINER_FEMALE | -#line 15269 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15270 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15271 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15272 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_RISKY, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15274 - .species = SPECIES_NOCTOWL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15276 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15275 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15277 - MOVE_HYPNOSIS, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_DREAM_EATER, - }, - }, - { -#line 15282 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15284 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15283 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15285 - MOVE_SUNNY_DAY, - MOVE_AERIAL_ACE, - MOVE_SOLAR_BEAM, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15290 - .species = SPECIES_DRAGONAIR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15290 - .heldItem = ITEM_SITRUS_BERRY, -#line 15292 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15291 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15293 - MOVE_THUNDER_WAVE, - MOVE_THUNDERBOLT, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15298 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15300 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15299 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15301 - MOVE_SURF, - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15306 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15308 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15307 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15309 - MOVE_WHIRLWIND, - MOVE_SPIKES, - MOVE_STEEL_WING, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15314 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15314 - .heldItem = ITEM_CHESTO_BERRY, -#line 15316 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15315 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15317 - MOVE_AERIAL_ACE, - MOVE_REST, - MOVE_DRAGON_DANCE, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 15322 - [DIFFICULTY_NORMAL][TRAINER_WINONA_5] = - { -#line 15323 - .trainerName = _("WINONA"), -#line 15324 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15325 - .trainerPic = TRAINER_PIC_LEADER_WINONA, - .encounterMusic_gender = -#line 15326 -F_TRAINER_FEMALE | -#line 15327 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15328 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15329 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15330 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_RISKY, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15332 - .species = SPECIES_NOCTOWL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15334 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15333 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15335 - MOVE_HYPNOSIS, - MOVE_PSYCHIC, - MOVE_REFLECT, - MOVE_DREAM_EATER, - }, - }, - { -#line 15340 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15342 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15341 - .lvl = 54, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15343 - MOVE_SUNNY_DAY, - MOVE_AERIAL_ACE, - MOVE_SOLAR_BEAM, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15348 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15350 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15349 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15351 - MOVE_SURF, - MOVE_SUPERSONIC, - MOVE_PROTECT, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15356 - .species = SPECIES_DRAGONITE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15356 - .heldItem = ITEM_SITRUS_BERRY, -#line 15358 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15357 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15359 - MOVE_HYPER_BEAM, - MOVE_THUNDERBOLT, - MOVE_EARTHQUAKE, - MOVE_ICE_BEAM, - }, - }, - { -#line 15364 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15366 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15365 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15367 - MOVE_WHIRLWIND, - MOVE_SPIKES, - MOVE_STEEL_WING, - MOVE_AERIAL_ACE, - }, - }, - { -#line 15372 - .species = SPECIES_ALTARIA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15372 - .heldItem = ITEM_CHESTO_BERRY, -#line 15374 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15373 - .lvl = 60, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15375 - MOVE_SKY_ATTACK, - MOVE_REST, - MOVE_DRAGON_DANCE, - MOVE_EARTHQUAKE, - }, - }, - }, - }, -#line 15380 - [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_2] = - { -#line 15381 - .trainerName = _("TATE&LIZA"), -#line 15382 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15383 - .trainerPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, - .encounterMusic_gender = -#line 15385 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15386 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15387 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15388 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15390 - .species = SPECIES_SLOWPOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15392 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15391 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15393 - MOVE_YAWN, - MOVE_PSYCHIC, - MOVE_CALM_MIND, - MOVE_PROTECT, - }, - }, - { -#line 15398 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15400 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15399 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15401 - MOVE_EARTHQUAKE, - MOVE_ANCIENT_POWER, - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 15406 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15406 - .heldItem = ITEM_CHESTO_BERRY, -#line 15408 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15407 - .lvl = 49, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15409 - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CONFUSE_RAY, - MOVE_CALM_MIND, - }, - }, - { -#line 15414 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15414 - .heldItem = ITEM_CHESTO_BERRY, -#line 15416 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15415 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15417 - MOVE_EARTHQUAKE, - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CALM_MIND, - }, - }, - { -#line 15422 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15422 - .heldItem = ITEM_SITRUS_BERRY, -#line 15424 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15423 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15425 - MOVE_SUNNY_DAY, - MOVE_SOLAR_BEAM, - MOVE_PSYCHIC, - MOVE_FLAMETHROWER, - }, - }, - }, - }, -#line 15430 - [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_3] = - { -#line 15431 - .trainerName = _("TATE&LIZA"), -#line 15432 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15433 - .trainerPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, - .encounterMusic_gender = -#line 15435 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15436 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15437 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15438 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15440 - .species = SPECIES_DROWZEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15442 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15441 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15443 - MOVE_HYPNOSIS, - MOVE_DREAM_EATER, - MOVE_HEADBUTT, - MOVE_PROTECT, - }, - }, - { -#line 15448 - .species = SPECIES_SLOWPOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15450 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15449 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15451 - MOVE_YAWN, - MOVE_PSYCHIC, - MOVE_CALM_MIND, - MOVE_PROTECT, - }, - }, - { -#line 15456 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15458 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15457 - .lvl = 54, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15459 - MOVE_EARTHQUAKE, - MOVE_EXPLOSION, - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 15464 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15464 - .heldItem = ITEM_CHESTO_BERRY, -#line 15466 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15465 - .lvl = 54, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15467 - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CONFUSE_RAY, - MOVE_CALM_MIND, - }, - }, - { -#line 15472 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15472 - .heldItem = ITEM_CHESTO_BERRY, -#line 15474 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15473 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15475 - MOVE_EARTHQUAKE, - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CALM_MIND, - }, - }, - { -#line 15480 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15480 - .heldItem = ITEM_SITRUS_BERRY, -#line 15482 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15481 - .lvl = 55, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15483 - MOVE_SUNNY_DAY, - MOVE_SOLAR_BEAM, - MOVE_PSYCHIC, - MOVE_FLAMETHROWER, - }, - }, - }, - }, -#line 15488 - [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_4] = - { -#line 15489 - .trainerName = _("TATE&LIZA"), -#line 15490 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15491 - .trainerPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, - .encounterMusic_gender = -#line 15493 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15494 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15495 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15496 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15498 - .species = SPECIES_HYPNO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15500 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15499 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15501 - MOVE_HYPNOSIS, - MOVE_DREAM_EATER, - MOVE_HEADBUTT, - MOVE_PROTECT, - }, - }, - { -#line 15506 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15508 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15507 - .lvl = 59, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15509 - MOVE_EARTHQUAKE, - MOVE_EXPLOSION, - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 15514 - .species = SPECIES_SLOWPOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15516 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15515 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15517 - MOVE_YAWN, - MOVE_PSYCHIC, - MOVE_CALM_MIND, - MOVE_PROTECT, - }, - }, - { -#line 15522 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15522 - .heldItem = ITEM_CHESTO_BERRY, -#line 15524 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15523 - .lvl = 59, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15525 - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CONFUSE_RAY, - MOVE_CALM_MIND, - }, - }, - { -#line 15530 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15530 - .heldItem = ITEM_CHESTO_BERRY, -#line 15532 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15531 - .lvl = 60, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15533 - MOVE_EARTHQUAKE, - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CALM_MIND, - }, - }, - { -#line 15538 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15538 - .heldItem = ITEM_SITRUS_BERRY, -#line 15540 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15539 - .lvl = 60, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15541 - MOVE_SUNNY_DAY, - MOVE_SOLAR_BEAM, - MOVE_PSYCHIC, - MOVE_FLAMETHROWER, - }, - }, - }, - }, -#line 15546 - [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_5] = - { -#line 15547 - .trainerName = _("TATE&LIZA"), -#line 15548 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15549 - .trainerPic = TRAINER_PIC_LEADER_TATE_AND_LIZA, - .encounterMusic_gender = -#line 15551 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 15552 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15553 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15554 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15556 - .species = SPECIES_HYPNO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15558 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15557 - .lvl = 63, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15559 - MOVE_HYPNOSIS, - MOVE_DREAM_EATER, - MOVE_HEADBUTT, - MOVE_PROTECT, - }, - }, - { -#line 15564 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15566 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15565 - .lvl = 64, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15567 - MOVE_EARTHQUAKE, - MOVE_EXPLOSION, - MOVE_PSYCHIC, - MOVE_LIGHT_SCREEN, - }, - }, - { -#line 15572 - .species = SPECIES_SLOWKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15574 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15573 - .lvl = 63, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15575 - MOVE_YAWN, - MOVE_PSYCHIC, - MOVE_CALM_MIND, - MOVE_PROTECT, - }, - }, - { -#line 15580 - .species = SPECIES_XATU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15580 - .heldItem = ITEM_CHESTO_BERRY, -#line 15582 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15581 - .lvl = 64, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15583 - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CONFUSE_RAY, - MOVE_CALM_MIND, - }, - }, - { -#line 15588 - .species = SPECIES_LUNATONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15588 - .heldItem = ITEM_CHESTO_BERRY, -#line 15590 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15589 - .lvl = 65, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15591 - MOVE_EARTHQUAKE, - MOVE_PSYCHIC, - MOVE_REST, - MOVE_CALM_MIND, - }, - }, - { -#line 15596 - .species = SPECIES_SOLROCK, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15596 - .heldItem = ITEM_SITRUS_BERRY, -#line 15598 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15597 - .lvl = 65, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15599 - MOVE_SUNNY_DAY, - MOVE_SOLAR_BEAM, - MOVE_PSYCHIC, - MOVE_FLAMETHROWER, - }, - }, - }, - }, -#line 15604 - [DIFFICULTY_NORMAL][TRAINER_JUAN_2] = - { -#line 15605 - .trainerName = _("JUAN"), -#line 15606 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15607 - .trainerPic = TRAINER_PIC_LEADER_JUAN, - .encounterMusic_gender = -#line 15609 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15610 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15611 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15612 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15614 - .species = SPECIES_POLIWAG, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15616 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15615 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15617 - MOVE_HYPNOSIS, - MOVE_RAIN_DANCE, - MOVE_PROTECT, - MOVE_HYDRO_PUMP, - }, - }, - { -#line 15622 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15624 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15623 - .lvl = 46, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15625 - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_FISSURE, - }, - }, - { -#line 15630 - .species = SPECIES_WALREIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15632 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15631 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15633 - MOVE_WATER_PULSE, - MOVE_BODY_SLAM, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15638 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15638 - .heldItem = ITEM_CHESTO_BERRY, -#line 15640 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15639 - .lvl = 48, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15641 - MOVE_REST, - MOVE_CRABHAMMER, - MOVE_TAUNT, - MOVE_DOUBLE_TEAM, - }, - }, - { -#line 15646 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15646 - .heldItem = ITEM_CHESTO_BERRY, -#line 15648 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15647 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15649 - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_ICE_BEAM, - MOVE_REST, - }, - }, - }, - }, -#line 15654 - [DIFFICULTY_NORMAL][TRAINER_JUAN_3] = - { -#line 15655 - .trainerName = _("JUAN"), -#line 15656 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15657 - .trainerPic = TRAINER_PIC_LEADER_JUAN, - .encounterMusic_gender = -#line 15659 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15660 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15661 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15662 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 5, - .party = (const struct TrainerMon[]) - { - { -#line 15664 - .species = SPECIES_POLIWHIRL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15666 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15665 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15667 - MOVE_HYPNOSIS, - MOVE_RAIN_DANCE, - MOVE_PROTECT, - MOVE_HYDRO_PUMP, - }, - }, - { -#line 15672 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15674 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15673 - .lvl = 51, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15675 - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_FISSURE, - }, - }, - { -#line 15680 - .species = SPECIES_WALREIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15682 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15681 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15683 - MOVE_WATER_PULSE, - MOVE_BODY_SLAM, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15688 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15688 - .heldItem = ITEM_CHESTO_BERRY, -#line 15690 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15689 - .lvl = 53, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15691 - MOVE_REST, - MOVE_GUILLOTINE, - MOVE_TAUNT, - MOVE_DOUBLE_TEAM, - }, - }, - { -#line 15696 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15696 - .heldItem = ITEM_CHESTO_BERRY, -#line 15698 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15697 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15699 - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_ICE_BEAM, - MOVE_REST, - }, - }, - }, - }, -#line 15704 - [DIFFICULTY_NORMAL][TRAINER_JUAN_4] = - { -#line 15705 - .trainerName = _("JUAN"), -#line 15706 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15707 - .trainerPic = TRAINER_PIC_LEADER_JUAN, - .encounterMusic_gender = -#line 15709 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15710 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15711 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15712 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15714 - .species = SPECIES_LAPRAS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15716 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15715 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15717 - MOVE_HYDRO_PUMP, - MOVE_PERISH_SONG, - MOVE_ICE_BEAM, - MOVE_CONFUSE_RAY, - }, - }, - { -#line 15722 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15724 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15723 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15725 - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_FISSURE, - }, - }, - { -#line 15730 - .species = SPECIES_POLIWHIRL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15732 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15731 - .lvl = 56, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15733 - MOVE_HYPNOSIS, - MOVE_RAIN_DANCE, - MOVE_PROTECT, - MOVE_HYDRO_PUMP, - }, - }, - { -#line 15738 - .species = SPECIES_WALREIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15740 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15739 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15741 - MOVE_WATER_PULSE, - MOVE_BODY_SLAM, - MOVE_PROTECT, - MOVE_ICE_BEAM, - }, - }, - { -#line 15746 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15746 - .heldItem = ITEM_CHESTO_BERRY, -#line 15748 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15747 - .lvl = 58, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15749 - MOVE_REST, - MOVE_GUILLOTINE, - MOVE_TAUNT, - MOVE_DOUBLE_TEAM, - }, - }, - { -#line 15754 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15754 - .heldItem = ITEM_CHESTO_BERRY, -#line 15756 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15755 - .lvl = 61, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15757 - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_ICE_BEAM, - MOVE_REST, - }, - }, - }, - }, -#line 15762 - [DIFFICULTY_NORMAL][TRAINER_JUAN_5] = - { -#line 15763 - .trainerName = _("JUAN"), -#line 15764 - .trainerClass = TRAINER_CLASS_LEADER, -#line 15765 - .trainerPic = TRAINER_PIC_LEADER_JUAN, - .encounterMusic_gender = -#line 15767 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15768 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15769 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 15770 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15772 - .species = SPECIES_LAPRAS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15774 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15773 - .lvl = 61, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15775 - MOVE_HYDRO_PUMP, - MOVE_PERISH_SONG, - MOVE_ICE_BEAM, - MOVE_CONFUSE_RAY, - }, - }, - { -#line 15780 - .species = SPECIES_WHISCASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15782 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15781 - .lvl = 63, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15783 - MOVE_RAIN_DANCE, - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_FISSURE, - }, - }, - { -#line 15788 - .species = SPECIES_POLITOED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15790 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15789 - .lvl = 61, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15791 - MOVE_HYPNOSIS, - MOVE_RAIN_DANCE, - MOVE_HYDRO_PUMP, - MOVE_PERISH_SONG, - }, - }, - { -#line 15796 - .species = SPECIES_WALREIN, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15798 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15797 - .lvl = 63, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15799 - MOVE_WATER_PULSE, - MOVE_BODY_SLAM, - MOVE_PROTECT, - MOVE_SHEER_COLD, - }, - }, - { -#line 15804 - .species = SPECIES_CRAWDAUNT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15804 - .heldItem = ITEM_CHESTO_BERRY, -#line 15806 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15805 - .lvl = 63, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15807 - MOVE_REST, - MOVE_GUILLOTINE, - MOVE_TAUNT, - MOVE_DOUBLE_TEAM, - }, - }, - { -#line 15812 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15812 - .heldItem = ITEM_CHESTO_BERRY, -#line 15814 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15813 - .lvl = 66, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15815 - MOVE_WATER_PULSE, - MOVE_DOUBLE_TEAM, - MOVE_ICE_BEAM, - MOVE_REST, - }, - }, - }, - }, -#line 15820 - [DIFFICULTY_NORMAL][TRAINER_ANGELO] = - { -#line 15821 - .trainerName = _("ANGELO"), -#line 15822 - .trainerClass = TRAINER_CLASS_BUG_MANIAC, -#line 15823 - .trainerPic = TRAINER_PIC_BUG_MANIAC, - .encounterMusic_gender = -#line 15825 - TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS, -#line 15826 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15827 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 15829 - .species = SPECIES_ILLUMISE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15831 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 15830 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15832 - MOVE_SHOCK_WAVE, - MOVE_QUICK_ATTACK, - MOVE_CHARM, - }, - }, - { -#line 15836 - .species = SPECIES_VOLBEAT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15838 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 15837 - .lvl = 17, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15839 - MOVE_SHOCK_WAVE, - MOVE_QUICK_ATTACK, - MOVE_CONFUSE_RAY, - }, - }, - }, - }, -#line 15843 - [DIFFICULTY_NORMAL][TRAINER_DARIUS] = - { -#line 15844 - .trainerName = _("DARIUS"), -#line 15845 - .trainerClass = TRAINER_CLASS_BIRD_KEEPER, -#line 15846 - .trainerPic = TRAINER_PIC_BIRD_KEEPER, - .encounterMusic_gender = -#line 15848 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 15849 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15850 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15852 - .species = SPECIES_TROPIUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15854 - .iv = TRAINER_PARTY_IVS(24, 24, 24, 24, 24, 24), -#line 15853 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15856 - [DIFFICULTY_NORMAL][TRAINER_STEVEN] = - { -#line 15857 - .trainerName = _("STEVEN"), -#line 15858 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 15859 - .trainerPic = TRAINER_PIC_STEVEN, - .encounterMusic_gender = -#line 15861 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15862 - .items = { ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE, ITEM_FULL_RESTORE }, -#line 15863 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15864 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 15866 - .species = SPECIES_SKARMORY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15868 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15867 - .lvl = 77, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15869 - MOVE_TOXIC, - MOVE_AERIAL_ACE, - MOVE_SPIKES, - MOVE_STEEL_WING, - }, - }, - { -#line 15874 - .species = SPECIES_CLAYDOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15876 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15875 - .lvl = 75, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15877 - MOVE_REFLECT, - MOVE_LIGHT_SCREEN, - MOVE_ANCIENT_POWER, - MOVE_EARTHQUAKE, - }, - }, - { -#line 15882 - .species = SPECIES_AGGRON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15884 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15883 - .lvl = 76, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15885 - MOVE_THUNDER, - MOVE_EARTHQUAKE, - MOVE_SOLAR_BEAM, - MOVE_DRAGON_CLAW, - }, - }, - { -#line 15890 - .species = SPECIES_CRADILY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15892 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15891 - .lvl = 76, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15893 - MOVE_GIGA_DRAIN, - MOVE_ANCIENT_POWER, - MOVE_INGRAIN, - MOVE_CONFUSE_RAY, - }, - }, - { -#line 15898 - .species = SPECIES_ARMALDO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15900 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15899 - .lvl = 76, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15901 - MOVE_WATER_PULSE, - MOVE_ANCIENT_POWER, - MOVE_AERIAL_ACE, - MOVE_SLASH, - }, - }, - { -#line 15906 - .species = SPECIES_METAGROSS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15906 - .heldItem = ITEM_SITRUS_BERRY, -#line 15908 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 15907 - .lvl = 78, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - .moves = { -#line 15909 - MOVE_EARTHQUAKE, - MOVE_PSYCHIC, - MOVE_METEOR_MASH, - MOVE_SHADOW_BALL, - }, - }, - }, - }, -#line 15914 - [DIFFICULTY_NORMAL][TRAINER_ANABEL] = - { -#line 15915 - .trainerName = _("ANABEL"), -#line 15916 - .trainerClass = TRAINER_CLASS_SALON_MAIDEN, -#line 15917 - .trainerPic = TRAINER_PIC_SALON_MAIDEN_ANABEL, - .encounterMusic_gender = -#line 15918 -F_TRAINER_FEMALE | -#line 15919 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15920 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15921 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15923 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15925 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15924 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15927 - [DIFFICULTY_NORMAL][TRAINER_TUCKER] = - { -#line 15928 - .trainerName = _("TUCKER"), -#line 15929 - .trainerClass = TRAINER_CLASS_DOME_ACE, -#line 15930 - .trainerPic = TRAINER_PIC_DOME_ACE_TUCKER, - .encounterMusic_gender = -#line 15932 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15933 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15934 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15936 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15938 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15937 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15940 - [DIFFICULTY_NORMAL][TRAINER_SPENSER] = - { -#line 15941 - .trainerName = _("SPENSER"), -#line 15942 - .trainerClass = TRAINER_CLASS_PALACE_MAVEN, -#line 15943 - .trainerPic = TRAINER_PIC_PALACE_MAVEN_SPENSER, - .encounterMusic_gender = -#line 15945 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15946 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15947 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15949 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15951 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15950 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15953 - [DIFFICULTY_NORMAL][TRAINER_GRETA] = - { -#line 15954 - .trainerName = _("GRETA"), -#line 15955 - .trainerClass = TRAINER_CLASS_ARENA_TYCOON, -#line 15956 - .trainerPic = TRAINER_PIC_ARENA_TYCOON_GRETA, - .encounterMusic_gender = -#line 15957 -F_TRAINER_FEMALE | -#line 15958 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15959 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15960 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15962 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15964 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15963 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15966 - [DIFFICULTY_NORMAL][TRAINER_NOLAND] = - { -#line 15967 - .trainerName = _("NOLAND"), -#line 15968 - .trainerClass = TRAINER_CLASS_FACTORY_HEAD, -#line 15969 - .trainerPic = TRAINER_PIC_FACTORY_HEAD_NOLAND, - .encounterMusic_gender = -#line 15971 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15972 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15973 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15975 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15977 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15976 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15979 - [DIFFICULTY_NORMAL][TRAINER_LUCY] = - { -#line 15980 - .trainerName = _("LUCY"), -#line 15981 - .trainerClass = TRAINER_CLASS_PIKE_QUEEN, -#line 15982 - .trainerPic = TRAINER_PIC_PIKE_QUEEN_LUCY, - .encounterMusic_gender = -#line 15983 -F_TRAINER_FEMALE | -#line 15984 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15985 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15986 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 15988 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 15990 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 15989 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 15992 - [DIFFICULTY_NORMAL][TRAINER_BRANDON] = - { -#line 15993 - .trainerName = _("BRANDON"), -#line 15994 - .trainerClass = TRAINER_CLASS_PYRAMID_KING, -#line 15995 - .trainerPic = TRAINER_PIC_PYRAMID_KING_BRANDON, - .encounterMusic_gender = -#line 15997 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 15998 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 15999 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16001 - .species = SPECIES_BELDUM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16003 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16002 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16005 - [DIFFICULTY_NORMAL][TRAINER_ANDRES_2] = - { -#line 16006 - .trainerName = _("ANDRES"), -#line 16007 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 16008 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 16010 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16011 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16012 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16014 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16016 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16015 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16018 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16020 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16019 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16022 - [DIFFICULTY_NORMAL][TRAINER_ANDRES_3] = - { -#line 16023 - .trainerName = _("ANDRES"), -#line 16024 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 16025 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 16027 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16028 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16029 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16031 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16033 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16032 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16035 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16037 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16036 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16039 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16041 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16040 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16043 - [DIFFICULTY_NORMAL][TRAINER_ANDRES_4] = - { -#line 16044 - .trainerName = _("ANDRES"), -#line 16045 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 16046 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 16048 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16049 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16050 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16052 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16054 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16053 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16056 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16058 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16057 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16060 - .species = SPECIES_SANDSHREW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16062 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16061 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16064 - [DIFFICULTY_NORMAL][TRAINER_ANDRES_5] = - { -#line 16065 - .trainerName = _("ANDRES"), -#line 16066 - .trainerClass = TRAINER_CLASS_RUIN_MANIAC, -#line 16067 - .trainerPic = TRAINER_PIC_RUIN_MANIAC, - .encounterMusic_gender = -#line 16069 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16070 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16071 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16073 - .species = SPECIES_NOSEPASS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16075 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16074 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16077 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16079 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16078 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16081 - .species = SPECIES_SANDSLASH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16083 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16082 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16085 - [DIFFICULTY_NORMAL][TRAINER_CORY_2] = - { -#line 16086 - .trainerName = _("CORY"), -#line 16087 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 16088 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 16090 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16091 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16092 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16094 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16096 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16095 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16098 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16100 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16099 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16102 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16104 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16103 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16106 - [DIFFICULTY_NORMAL][TRAINER_CORY_3] = - { -#line 16107 - .trainerName = _("CORY"), -#line 16108 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 16109 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 16111 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16112 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16113 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16115 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16117 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16116 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16119 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16121 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16120 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16123 - .species = SPECIES_TENTACOOL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16125 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16124 - .lvl = 32, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16127 - [DIFFICULTY_NORMAL][TRAINER_CORY_4] = - { -#line 16128 - .trainerName = _("CORY"), -#line 16129 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 16130 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 16132 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16133 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16134 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16136 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16138 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16137 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16140 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16142 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16141 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16144 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16146 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16145 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16148 - [DIFFICULTY_NORMAL][TRAINER_CORY_5] = - { -#line 16149 - .trainerName = _("CORY"), -#line 16150 - .trainerClass = TRAINER_CLASS_SAILOR, -#line 16151 - .trainerPic = TRAINER_PIC_SAILOR, - .encounterMusic_gender = -#line 16153 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16154 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16155 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16157 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16159 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16158 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16161 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16163 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16162 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16165 - .species = SPECIES_TENTACRUEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16167 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16166 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16169 - [DIFFICULTY_NORMAL][TRAINER_PABLO_2] = - { -#line 16170 - .trainerName = _("PABLO"), -#line 16171 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 16172 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 16174 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 16175 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16176 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16178 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16180 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16179 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16182 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16184 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16183 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16186 - [DIFFICULTY_NORMAL][TRAINER_PABLO_3] = - { -#line 16187 - .trainerName = _("PABLO"), -#line 16188 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 16189 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 16191 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 16192 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16193 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16195 - .species = SPECIES_WINGULL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16197 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16196 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16199 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16201 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16200 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16203 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16205 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16204 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16207 - [DIFFICULTY_NORMAL][TRAINER_PABLO_4] = - { -#line 16208 - .trainerName = _("PABLO"), -#line 16209 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 16210 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 16212 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 16213 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16214 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16216 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16218 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16217 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16220 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16222 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16221 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16224 - .species = SPECIES_STARYU, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16226 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16225 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16228 - [DIFFICULTY_NORMAL][TRAINER_PABLO_5] = - { -#line 16229 - .trainerName = _("PABLO"), -#line 16230 - .trainerClass = TRAINER_CLASS_TRIATHLETE, -#line 16231 - .trainerPic = TRAINER_PIC_SWIMMING_TRIATHLETE_M, - .encounterMusic_gender = -#line 16233 - TRAINER_ENCOUNTER_MUSIC_SWIMMER, -#line 16234 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16235 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16237 - .species = SPECIES_PELIPPER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16239 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16238 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16241 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16243 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16242 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16245 - .species = SPECIES_STARMIE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16247 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16246 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16249 - [DIFFICULTY_NORMAL][TRAINER_KOJI_2] = - { -#line 16250 - .trainerName = _("KOJI"), -#line 16251 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 16252 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 16254 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16255 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16256 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16258 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16260 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16259 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16262 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16264 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16263 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16266 - [DIFFICULTY_NORMAL][TRAINER_KOJI_3] = - { -#line 16267 - .trainerName = _("KOJI"), -#line 16268 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 16269 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 16271 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16272 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16273 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16275 - .species = SPECIES_MAKUHITA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16277 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16276 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16279 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16281 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16280 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16283 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16285 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16284 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16287 - [DIFFICULTY_NORMAL][TRAINER_KOJI_4] = - { -#line 16288 - .trainerName = _("KOJI"), -#line 16289 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 16290 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 16292 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16293 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16294 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16296 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16298 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16297 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16300 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16302 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16301 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16304 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16306 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16305 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16308 - [DIFFICULTY_NORMAL][TRAINER_KOJI_5] = - { -#line 16309 - .trainerName = _("KOJI"), -#line 16310 - .trainerClass = TRAINER_CLASS_BLACK_BELT, -#line 16311 - .trainerPic = TRAINER_PIC_BLACK_BELT, - .encounterMusic_gender = -#line 16313 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16314 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16315 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16317 - .species = SPECIES_HARIYAMA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16319 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16318 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16321 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16323 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16322 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16325 - .species = SPECIES_MACHAMP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16327 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16326 - .lvl = 43, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16329 - [DIFFICULTY_NORMAL][TRAINER_CRISTIN_2] = - { -#line 16330 - .trainerName = _("CRISTIN"), -#line 16331 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 16332 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 16333 -F_TRAINER_FEMALE | -#line 16334 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 16335 - .items = { ITEM_HYPER_POTION }, -#line 16336 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16337 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16339 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16341 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 16340 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16343 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16345 - .iv = TRAINER_PARTY_IVS(13, 13, 13, 13, 13, 13), -#line 16344 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16347 - [DIFFICULTY_NORMAL][TRAINER_CRISTIN_3] = - { -#line 16348 - .trainerName = _("CRISTIN"), -#line 16349 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 16350 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 16351 -F_TRAINER_FEMALE | -#line 16352 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 16353 - .items = { ITEM_HYPER_POTION }, -#line 16354 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16355 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16357 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16359 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 16358 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16361 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16363 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 16362 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16365 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16367 - .iv = TRAINER_PARTY_IVS(14, 14, 14, 14, 14, 14), -#line 16366 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16369 - [DIFFICULTY_NORMAL][TRAINER_CRISTIN_4] = - { -#line 16370 - .trainerName = _("CRISTIN"), -#line 16371 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 16372 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 16373 -F_TRAINER_FEMALE | -#line 16374 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 16375 - .items = { ITEM_HYPER_POTION }, -#line 16376 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16377 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16379 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16381 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 16380 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16383 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16385 - .iv = TRAINER_PARTY_IVS(15, 15, 15, 15, 15, 15), -#line 16384 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16387 - .species = SPECIES_VIGOROTH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16389 - .iv = TRAINER_PARTY_IVS(12, 12, 12, 12, 12, 12), -#line 16388 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16391 - [DIFFICULTY_NORMAL][TRAINER_CRISTIN_5] = - { -#line 16392 - .trainerName = _("CRISTIN"), -#line 16393 - .trainerClass = TRAINER_CLASS_COOLTRAINER, -#line 16394 - .trainerPic = TRAINER_PIC_COOLTRAINER_F, - .encounterMusic_gender = -#line 16395 -F_TRAINER_FEMALE | -#line 16396 - TRAINER_ENCOUNTER_MUSIC_COOL, -#line 16397 - .items = { ITEM_HYPER_POTION }, -#line 16398 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16399 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16401 - .species = SPECIES_SPINDA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16403 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 16402 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16405 - .species = SPECIES_EXPLOUD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16407 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 16406 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16409 - .species = SPECIES_SLAKING, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16411 - .iv = TRAINER_PARTY_IVS(17, 17, 17, 17, 17, 17), -#line 16410 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16413 - [DIFFICULTY_NORMAL][TRAINER_FERNANDO_2] = - { -#line 16414 - .trainerName = _("FERNANDO"), -#line 16415 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 16416 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 16418 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16419 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16420 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16422 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16424 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16423 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16426 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16428 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16427 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16430 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16432 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16431 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16434 - [DIFFICULTY_NORMAL][TRAINER_FERNANDO_3] = - { -#line 16435 - .trainerName = _("FERNANDO"), -#line 16436 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 16437 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 16439 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16440 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16441 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16443 - .species = SPECIES_ELECTRIKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16445 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16444 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16447 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16449 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16448 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16451 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16453 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16452 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16455 - [DIFFICULTY_NORMAL][TRAINER_FERNANDO_4] = - { -#line 16456 - .trainerName = _("FERNANDO"), -#line 16457 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 16458 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 16460 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16461 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16462 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16464 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16466 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16465 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16468 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16470 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16469 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16472 - .species = SPECIES_LOUDRED, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16474 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16473 - .lvl = 39, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16476 - [DIFFICULTY_NORMAL][TRAINER_FERNANDO_5] = - { -#line 16477 - .trainerName = _("FERNANDO"), -#line 16478 - .trainerClass = TRAINER_CLASS_GUITARIST, -#line 16479 - .trainerPic = TRAINER_PIC_GUITARIST, - .encounterMusic_gender = -#line 16481 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16482 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16483 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16485 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16487 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16486 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16489 - .species = SPECIES_MANECTRIC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16491 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16490 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16493 - .species = SPECIES_EXPLOUD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16495 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16494 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16497 - [DIFFICULTY_NORMAL][TRAINER_SAWYER_2] = - { -#line 16498 - .trainerName = _("SAWYER"), -#line 16499 - .trainerClass = TRAINER_CLASS_HIKER, -#line 16500 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 16502 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16503 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16504 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16506 - .species = SPECIES_GEODUDE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16508 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16507 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16510 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16512 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16511 - .lvl = 26, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16514 - [DIFFICULTY_NORMAL][TRAINER_SAWYER_3] = - { -#line 16515 - .trainerName = _("SAWYER"), -#line 16516 - .trainerClass = TRAINER_CLASS_HIKER, -#line 16517 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 16519 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16520 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16521 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16523 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16525 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16524 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16527 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16529 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16528 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16531 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16533 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16532 - .lvl = 28, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16535 - [DIFFICULTY_NORMAL][TRAINER_SAWYER_4] = - { -#line 16536 - .trainerName = _("SAWYER"), -#line 16537 - .trainerClass = TRAINER_CLASS_HIKER, -#line 16538 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 16540 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16541 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16542 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16544 - .species = SPECIES_MACHOP, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16546 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16545 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16548 - .species = SPECIES_NUMEL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16550 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16549 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16552 - .species = SPECIES_GRAVELER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16554 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16553 - .lvl = 30, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16556 - [DIFFICULTY_NORMAL][TRAINER_SAWYER_5] = - { -#line 16557 - .trainerName = _("SAWYER"), -#line 16558 - .trainerClass = TRAINER_CLASS_HIKER, -#line 16559 - .trainerPic = TRAINER_PIC_HIKER, - .encounterMusic_gender = -#line 16561 - TRAINER_ENCOUNTER_MUSIC_HIKER, -#line 16562 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16563 - .aiFlags = AI_FLAG_BASIC_TRAINER, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16565 - .species = SPECIES_MACHOKE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16567 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16566 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16569 - .species = SPECIES_CAMERUPT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16571 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16570 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16573 - .species = SPECIES_GOLEM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16575 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16574 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16577 - [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_2] = - { -#line 16578 - .trainerName = _("GABRIELLE"), -#line 16579 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 16580 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 16581 -F_TRAINER_FEMALE | -#line 16582 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16583 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16584 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 16586 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16588 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16587 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16590 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16592 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16591 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16594 - .species = SPECIES_ZIGZAGOON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16596 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16595 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16598 - .species = SPECIES_LOTAD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16600 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16599 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16602 - .species = SPECIES_SEEDOT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16604 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16603 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16606 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16608 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16607 - .lvl = 31, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16610 - [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_3] = - { -#line 16611 - .trainerName = _("GABRIELLE"), -#line 16612 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 16613 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 16614 -F_TRAINER_FEMALE | -#line 16615 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16616 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16617 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 16619 - .species = SPECIES_SKITTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16621 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16620 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16623 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16625 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16624 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16627 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16629 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16628 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16631 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16633 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16632 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16635 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16637 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16636 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16639 - .species = SPECIES_TAILLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16641 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16640 - .lvl = 33, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16643 - [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_4] = - { -#line 16644 - .trainerName = _("GABRIELLE"), -#line 16645 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 16646 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 16647 -F_TRAINER_FEMALE | -#line 16648 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16649 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16650 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 16652 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16654 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16653 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16656 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16658 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16657 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16660 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16662 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16661 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16664 - .species = SPECIES_LOMBRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16666 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16665 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16668 - .species = SPECIES_NUZLEAF, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16670 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16669 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16672 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16674 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16673 - .lvl = 35, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16676 - [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_5] = - { -#line 16677 - .trainerName = _("GABRIELLE"), -#line 16678 - .trainerClass = TRAINER_CLASS_PKMN_BREEDER, -#line 16679 - .trainerPic = TRAINER_PIC_POKEMON_BREEDER_F, - .encounterMusic_gender = -#line 16680 -F_TRAINER_FEMALE | -#line 16681 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16682 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16683 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 16685 - .species = SPECIES_DELCATTY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16687 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16686 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16689 - .species = SPECIES_MIGHTYENA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16691 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16690 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16693 - .species = SPECIES_LINOONE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16695 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16694 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16697 - .species = SPECIES_LUDICOLO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16699 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16698 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16701 - .species = SPECIES_SHIFTRY, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16703 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16702 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16705 - .species = SPECIES_SWELLOW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16707 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16706 - .lvl = 37, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16709 - [DIFFICULTY_NORMAL][TRAINER_THALIA_2] = - { -#line 16710 - .trainerName = _("THALIA"), -#line 16711 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 16712 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 16713 -F_TRAINER_FEMALE | -#line 16714 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16715 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16716 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16718 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16720 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16719 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16722 - .species = SPECIES_HORSEA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16724 - .iv = TRAINER_PARTY_IVS(1, 1, 1, 1, 1, 1), -#line 16723 - .lvl = 34, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16726 - [DIFFICULTY_NORMAL][TRAINER_THALIA_3] = - { -#line 16727 - .trainerName = _("THALIA"), -#line 16728 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 16729 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 16730 -F_TRAINER_FEMALE | -#line 16731 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16732 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16733 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16735 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16737 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16736 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16739 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16741 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16740 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16743 - .species = SPECIES_SEADRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16745 - .iv = TRAINER_PARTY_IVS(2, 2, 2, 2, 2, 2), -#line 16744 - .lvl = 36, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16747 - [DIFFICULTY_NORMAL][TRAINER_THALIA_4] = - { -#line 16748 - .trainerName = _("THALIA"), -#line 16749 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 16750 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 16751 -F_TRAINER_FEMALE | -#line 16752 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16753 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16754 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16756 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16758 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16757 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16760 - .species = SPECIES_WAILMER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16762 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16761 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16764 - .species = SPECIES_SEADRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16766 - .iv = TRAINER_PARTY_IVS(3, 3, 3, 3, 3, 3), -#line 16765 - .lvl = 38, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16768 - [DIFFICULTY_NORMAL][TRAINER_THALIA_5] = - { -#line 16769 - .trainerName = _("THALIA"), -#line 16770 - .trainerClass = TRAINER_CLASS_BEAUTY, -#line 16771 - .trainerPic = TRAINER_PIC_BEAUTY, - .encounterMusic_gender = -#line 16772 -F_TRAINER_FEMALE | -#line 16773 - TRAINER_ENCOUNTER_MUSIC_FEMALE, -#line 16774 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 16775 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 16777 - .species = SPECIES_LUVDISC, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16779 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16778 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16781 - .species = SPECIES_WAILORD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16783 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16782 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16785 - .species = SPECIES_KINGDRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16787 - .iv = TRAINER_PARTY_IVS(4, 4, 4, 4, 4, 4), -#line 16786 - .lvl = 40, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16789 - [DIFFICULTY_NORMAL][TRAINER_MARIELA] = - { -#line 16790 - .trainerName = _("MARIELA"), -#line 16791 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 16792 - .trainerPic = TRAINER_PIC_PSYCHIC_F, - .encounterMusic_gender = -#line 16793 -F_TRAINER_FEMALE | -#line 16794 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16795 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16797 - .species = SPECIES_CHIMECHO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16799 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16798 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16801 - [DIFFICULTY_NORMAL][TRAINER_ALVARO] = - { -#line 16802 - .trainerName = _("ALVARO"), -#line 16803 - .trainerClass = TRAINER_CLASS_PSYCHIC, -#line 16804 - .trainerPic = TRAINER_PIC_PSYCHIC_M, - .encounterMusic_gender = -#line 16806 - TRAINER_ENCOUNTER_MUSIC_INTENSE, -#line 16807 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 16809 - .species = SPECIES_BANETTE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16811 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16810 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 16813 - .species = SPECIES_KADABRA, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16815 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16814 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16817 - [DIFFICULTY_NORMAL][TRAINER_EVERETT] = - { -#line 16818 - .trainerName = _("EVERETT"), -#line 16819 - .trainerClass = TRAINER_CLASS_GENTLEMAN, -#line 16820 - .trainerPic = TRAINER_PIC_GENTLEMAN, - .encounterMusic_gender = -#line 16822 - TRAINER_ENCOUNTER_MUSIC_RICH, -#line 16823 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16825 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16827 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16826 - .lvl = 41, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16829 - [DIFFICULTY_NORMAL][TRAINER_RED] = - { -#line 16830 - .trainerName = _("RED"), -#line 16831 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 16832 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 16834 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16835 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16837 - .species = SPECIES_CHARMANDER, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16839 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16838 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16841 - [DIFFICULTY_NORMAL][TRAINER_LEAF] = - { -#line 16842 - .trainerName = _("LEAF"), -#line 16843 - .trainerClass = TRAINER_CLASS_RIVAL, -#line 16844 - .trainerPic = TRAINER_PIC_LEAF, - .encounterMusic_gender = -#line 16845 -F_TRAINER_FEMALE | -#line 16846 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16847 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16849 - .species = SPECIES_BULBASAUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16851 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16850 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16853 - [DIFFICULTY_NORMAL][TRAINER_BRENDAN_PLACEHOLDER] = - { -#line 16854 - .trainerName = _("BRENDAN"), -#line 16855 - .trainerClass = TRAINER_CLASS_RS_PROTAG, -#line 16856 - .trainerPic = TRAINER_PIC_RS_BRENDAN, - .encounterMusic_gender = -#line 16858 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16859 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16861 - .species = SPECIES_GROUDON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16863 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16862 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 16865 - [DIFFICULTY_NORMAL][TRAINER_MAY_PLACEHOLDER] = - { -#line 16866 - .trainerName = _("MAY"), -#line 16867 - .trainerClass = TRAINER_CLASS_RS_PROTAG, -#line 16868 - .trainerPic = TRAINER_PIC_RS_MAY, - .encounterMusic_gender = -#line 16869 -F_TRAINER_FEMALE | -#line 16870 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 16871 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 16873 - .species = SPECIES_KYOGRE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 16875 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 16874 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, diff --git a/test/battle/trainer_control.h b/test/battle/trainer_control.h deleted file mode 100644 index 482e7a0a6e..0000000000 --- a/test/battle/trainer_control.h +++ /dev/null @@ -1,792 +0,0 @@ -// -// DO NOT MODIFY THIS FILE! It is auto-generated from test/battle/trainer_control.party -// -// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE -// in include/config/general.h and remove this notice. -// Use sed -i '/^#line/d' 'test/battle/trainer_control.h' to remove #line markers. -// - -#line 1 "test/battle/trainer_control.party" - -#line 1 - [DIFFICULTY_NORMAL][0] = - { -#line 2 - .trainerName = _("Test1"), -#line 3 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 4 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 6 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 7 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 9 - .nickname = COMPOUND_STRING("Bubbles"), -#line 9 - .species = SPECIES_WOBBUFFET, -#line 9 - .gender = TRAINER_MON_FEMALE, -#line 9 - .heldItem = ITEM_ASSAULT_VEST, -#line 14 - .ev = TRAINER_PARTY_EVS(252, 0, 0, 252, 4, 0), -#line 13 - .iv = TRAINER_PARTY_IVS(25, 26, 27, 28, 29, 30), -#line 12 - .ability = ABILITY_TELEPATHY, -#line 11 - .lvl = 67, -#line 17 - .ball = ITEM_MASTER_BALL, -#line 15 - .friendship = 42, -#line 10 - .nature = NATURE_HASTY, -#line 16 - .isShiny = TRUE, -#line 18 - .dynamaxLevel = 5, - .shouldUseDynamax = TRUE, - .moves = { -#line 19 - MOVE_AIR_SLASH, - MOVE_BARRIER, - MOVE_SOLAR_BEAM, - MOVE_EXPLOSION, - }, - }, - { -#line 24 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 27 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 26 - .ability = ABILITY_SHADOW_TAG, -#line 25 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 29 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 31 - .iv = TRAINER_PARTY_IVS(0, 0, 0, 0, 0, 0), -#line 30 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 33 -#line 40 - [DIFFICULTY_NORMAL][1] = - { -#line 34 - .trainerName = _("Test2"), -#line 35 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 36 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 38 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 39 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 42 - .species = SPECIES_MEWTWO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 44 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 43 - .lvl = 5, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 45 -#line 52 - [DIFFICULTY_NORMAL][2] = - { -#line 46 - .trainerName = _("Test2"), -#line 47 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 48 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 50 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 51 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 54 - .species = SPECIES_MEWTWO, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 56 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 55 - .lvl = 50, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 57 -#line 64 - [DIFFICULTY_EASY][2] = - { -#line 58 - .trainerName = _("Test2"), -#line 59 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 60 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 62 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 63 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 66 - .species = SPECIES_METAPOD, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 68 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 67 - .lvl = 1, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 69 -#line 76 - [DIFFICULTY_HARD][2] = - { -#line 70 - .trainerName = _("Test2"), -#line 71 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 72 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 74 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 75 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, - .partySize = 1, - .party = (const struct TrainerMon[]) - { - { -#line 78 - .species = SPECIES_ARCEUS, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 80 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 79 - .lvl = 99, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 81 - [DIFFICULTY_NORMAL][3] = - { -#line 82 - .trainerName = _("Test3"), -#line 83 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 84 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 86 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 87 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 88 - .partySize = 1, - .poolSize = 4, - .party = (const struct TrainerMon[]) - { - { -#line 90 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 91 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 91 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 92 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 93 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 93 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 94 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 95 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 95 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 96 - .species = SPECIES_MEW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 97 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 97 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 98 - [DIFFICULTY_NORMAL][4] = - { -#line 99 - .trainerName = _("Test4"), -#line 100 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 101 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 103 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 104 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 105 - .partySize = 3, - .poolSize = 6, - .party = (const struct TrainerMon[]) - { - { -#line 107 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 108 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 108 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 109 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 111 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 111 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 110 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 112 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 114 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 114 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 113 - .tags = MON_POOL_TAG_ACE, - }, - { -#line 115 - .species = SPECIES_MEW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 116 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 116 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 117 - .species = SPECIES_ODDISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 119 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 119 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 118 - .tags = MON_POOL_TAG_ACE, - }, - { -#line 120 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 122 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 122 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 121 - .tags = MON_POOL_TAG_LEAD, - }, - }, - }, -#line 123 - [DIFFICULTY_NORMAL][5] = - { -#line 124 - .trainerName = _("Test5"), -#line 125 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 126 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 128 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 129 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 131 - .poolRuleIndex = POOL_RULESET_WEATHER_DOUBLES, -#line 130 - .partySize = 3, - .poolSize = 10, - .party = (const struct TrainerMon[]) - { - { -#line 133 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 135 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 135 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 134 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 136 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 138 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 138 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 137 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 139 - .species = SPECIES_VULPIX, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 141 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 141 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 140 - .tags = MON_POOL_TAG_LEAD | MON_POOL_TAG_WEATHER_SETTER, - }, - { -#line 142 - .species = SPECIES_BULBASAUR, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 144 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 144 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 143 - .tags = MON_POOL_TAG_LEAD | MON_POOL_TAG_WEATHER_ABUSER, - }, - { -#line 145 - .species = SPECIES_TORKOAL, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 147 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 147 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 146 - .tags = MON_POOL_TAG_LEAD | MON_POOL_TAG_WEATHER_SETTER, - }, - { -#line 148 - .species = SPECIES_CHERRIM, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 150 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 150 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 149 - .tags = MON_POOL_TAG_LEAD | MON_POOL_TAG_WEATHER_ABUSER, - }, - { -#line 151 - .species = SPECIES_MEW, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 153 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 153 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 152 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 154 - .species = SPECIES_ARON, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 156 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 156 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 155 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 157 - .species = SPECIES_ODDISH, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 158 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 158 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 159 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 160 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 160 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 161 - [DIFFICULTY_NORMAL][6] = - { -#line 162 - .trainerName = _("Test6"), -#line 163 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 164 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 166 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 167 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 169 - .poolRuleIndex = POOL_RULESET_BASIC, -#line 168 - .partySize = 2, - .poolSize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 171 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 173 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 173 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 172 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 174 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 176 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 176 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 175 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 177 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 179 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 179 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 178 - .tags = MON_POOL_TAG_LEAD, - }, - }, - }, -#line 180 - [DIFFICULTY_NORMAL][7] = - { -#line 181 - .trainerName = _("Test1"), -#line 182 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 183 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 185 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 186 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 188 - .poolRuleIndex = POOL_RULESET_BASIC, -#line 189 - .poolPruneIndex = POOL_PRUNE_TEST, -#line 187 - .partySize = 2, - .poolSize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 191 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 192 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 192 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 193 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 195 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 195 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 194 - .tags = MON_POOL_TAG_LEAD, - }, - { -#line 196 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 197 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 197 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 198 - [DIFFICULTY_NORMAL][8] = - { -#line 199 - .trainerName = _("Test1"), -#line 200 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 201 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 203 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 204 - .battleType = TRAINER_BATTLE_TYPE_SINGLES, -#line 206 - .poolRuleIndex = POOL_RULESET_BASIC, -#line 207 - .poolPickIndex = POOL_PICK_LOWEST, -#line 205 - .partySize = 2, - .poolSize = 3, - .party = (const struct TrainerMon[]) - { - { -#line 209 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 211 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 211 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 210 - .tags = MON_POOL_TAG_ACE, - }, - { -#line 212 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 213 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 213 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 214 - .species = SPECIES_EEVEE, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 216 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 216 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, -#line 215 - .tags = MON_POOL_TAG_LEAD, - }, - }, - }, -#line 217 - [DIFFICULTY_NORMAL][9] = - { -#line 218 - .trainerName = _("Test9"), -#line 219 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 220 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 222 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 223 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 224 - .partySize = 2, - .poolSize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 226 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 227 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 227 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 228 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 229 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 229 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, -#line 230 - [DIFFICULTY_NORMAL][10] = - { -#line 231 - .trainerName = _("Test10"), -#line 232 - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, -#line 233 - .trainerPic = TRAINER_PIC_RED, - .encounterMusic_gender = -#line 235 - TRAINER_ENCOUNTER_MUSIC_MALE, -#line 236 - .battleType = TRAINER_BATTLE_TYPE_DOUBLES, -#line 237 - .partySize = 2, - .poolSize = 2, - .party = (const struct TrainerMon[]) - { - { -#line 239 - .species = SPECIES_WYNAUT, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 240 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 240 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - { -#line 241 - .species = SPECIES_WOBBUFFET, - .gender = TRAINER_MON_RANDOM_GENDER, -#line 242 - .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), -#line 242 - .lvl = 100, - .nature = NATURE_HARDY, - .dynamaxLevel = MAX_DYNAMAX_LEVEL, - }, - }, - }, diff --git a/trainer_rules.mk b/trainer_rules.mk new file mode 100644 index 0000000000..c5df373a1e --- /dev/null +++ b/trainer_rules.mk @@ -0,0 +1,10 @@ +# party files are run through trainerproc, which is a tool that converts party data to an output file +# matching the current trainer .h formatting + +AUTO_GEN_TARGETS += src/data/trainers.h +AUTO_GEN_TARGETS += src/data/battle_partners.h +AUTO_GEN_TARGETS += test/battle/trainer_control.h +AUTO_GEN_TARGETS += src/data/debug_trainers.h + +%.h: %.party + $(CPP) $(CPPFLAGS) -traditional-cpp - < $< | $(TRAINERPROC) -o $@ -i $< - From f6b0a1584157f2acefc08876b2e400b165feb2f6 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 12 Jul 2025 18:50:08 -0400 Subject: [PATCH 092/283] Renaming to AI_ASSUME_STATUS_MOVES and making a config for universal status move guessing + disabling the custom tuning. --- docs/tutorials/ai_flags.md | 8 +- include/config/ai.h | 11 +- include/constants/battle_ai.h | 2 +- include/random.h | 11 +- src/battle_ai_util.c | 140 +++++++----------- ...rful_status.c => ai_assume_status_moves.c} | 29 +++- 6 files changed, 98 insertions(+), 103 deletions(-) rename test/battle/ai/{ai_assume_powerful_status.c => ai_assume_status_moves.c} (53%) diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 6b8a2e941f..98657210d9 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -147,10 +147,12 @@ AI has full knowledge of player moves, abilities, and hold items, and can use th ## `AI_FLAG_ASSUME_STAB` A significantly more restricted version of `AI_FLAG_OMNISCIENT`, the AI only knows the player's STAB moves, as their existence would be reasonable to assume in almost any case. -## `AI_FLAG_ASSUME_POWERFUL_STATUS` -A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know if the player has certain strong status moves, plus also Fake Out and fixed percentage moves like Super Fang. The intention is so that if the AI has a counterplay implemented, it will seem to have guessed if the player's pokemon has a move, without giving the AI perfect information. For example, with Omniscient set, the AI will not put a pokemon to sleep if it has Sleep Talk; with neither Assume Powerful Status nor Omniscient set, the AI will always assume the pokemon does not have Sleep Talk. +## `AI_FLAG_ASSUME_STATUS_MOVES` +A more restricted version of `AI_FLAG_OMNISCIENT`. The AI has a _chance_ to know what status moves the player has, plus additionally Fake Out and fixed percentage moves like Super Fang. The intention is so that if the AI has a counterplay implemented, it will seem to have guessed if the player's pokemon has a move, without giving the AI perfect information. For example, with Omniscient set, the AI will not usually put a pokemon to sleep if it has Sleep Talk; with neither Assume Powerful Status nor Omniscient set, the AI will always assume the pokemon does not have Sleep Talk. -Percentages for the three groupings (high odds, medium odds, and low odds) are defined in `include/config/ai.h` under `ASSUME_POWERFUL_STATUS_HIGH_ODDS`, `ASSUME_POWERFUL_STATUS_MEDIUM_ODDS`, and `ASSUME_POWERFUL_STATUS_LOW_ODDS`. Moves are sorted in `src/battle_ai_util.c` within `ShouldRecordStatusMove()` +By default, there are three groups of higher likelihood status moves defined in `include/config/ai.h` under `ASSUME_STATUS_HIGH_ODDS`, `ASSUME_STATUS_MEDIUM_ODDS`, and `ASSUME_STATUS_LOW_ODDS`. Moves are sorted in `src/battle_ai_util.c` within `ShouldRecordStatusMove()`. + +Any move that is not special cased is then potentially caught by `ASSUME_ALL_STATUS_ODDS`. ## `AI_FLAG_SMART_MON_CHOICES` Affects what the AI chooses to send out after a switch. AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are handled separately. Automatically included when `AI_FLAG_SMART_SWITCHING` is enabled. diff --git a/include/config/ai.h b/include/config/ai.h index 8a97430d4b..44d2f3236d 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -76,10 +76,13 @@ // AI_FLAG_ASSUME_STAB settings #define ASSUME_STAB_SEES_ABILITY FALSE // Flag also gives omniscience for player's ability. Can use AI_FLAG_WEIGH_ABILITY_PREDICTION instead for smarter prediction without omniscience. -// AI_FLAG_ASSUME_POWERFUL_STATUS settings -#define ASSUME_POWERFUL_STATUS_HIGH_ODDS 90 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore -#define ASSUME_POWERFUL_STATUS_MEDIUM_ODDS 70 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect -#define ASSUME_POWERFUL_STATUS_LOW_ODDS 40 // Chance for AI to see niche moves a pokemon may have but probably won't, like Trick Room or Speed Swap +// AI_FLAG_ASSUME_STATUS_MOVES settings +#define ASSUME_STATUS_MOVES_HAS_TUNING TRUE // Flag has varying rates for different kinds of status move. + // Setting to false also means it will not alert on Fake Out or Super Fang. +#define ASSUME_STATUS_HIGH_ODDS 90 // Chance for AI to see extremely likely moves for a pokemon to have, like Spore +#define ASSUME_STATUS_MEDIUM_ODDS 70 // Chance for AI to see moderately likely moves for a pokemon to have, like Protect +#define ASSUME_STATUS_LOW_ODDS 40 // Chance for AI to see niche moves a pokemon may have but probably won't, like Entrainment +#define ASSUME_ALL_STATUS_ODDS 25 // Chance for the AI to see any kind of status move. // AI_FLAG_SMART_SWITCHING settings #define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index fa2a96ee5d..db386be4b0 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -34,7 +34,7 @@ #define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT #define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). #define AI_FLAG_ASSUME_STAB (1 << 28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. -#define AI_FLAG_ASSUME_POWERFUL_STATUS (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ASSUME_STATUS_MOVES (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. #define AI_FLAG_COUNT 30 diff --git a/include/random.h b/include/random.h index df749312fd..130fb32e69 100644 --- a/include/random.h +++ b/include/random.h @@ -202,11 +202,12 @@ enum RandomTag RNG_AI_BOOST_INTO_HAZE, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, - RNG_AI_ASSUME_POWERFUL_STATUS_SLEEP, - RNG_AI_ASSUME_POWERFUL_STATUS_NONVOLATILE, - RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS, - RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, - RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS, + RNG_AI_ASSUME_STATUS_SLEEP, + RNG_AI_ASSUME_STATUS_NONVOLATILE, + RNG_AI_ASSUME_STATUS_HIGH_ODDS, + RNG_AI_ASSUME_STATUS_MEDIUM_ODDS, + RNG_AI_ASSUME_STATUS_LOW_ODDS, + RNG_AI_ASSUME_ALL_STATUS, }; #define RandomWeighted(tag, ...) \ diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2c7c850d1e..c14dddacf5 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -143,8 +143,8 @@ bool32 IsAiBattlerAssumingStab() bool32 IsAiBattlerAssumingPowerfulStatus() { - if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_POWERFUL_STATUS - || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_POWERFUL_STATUS) + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_STATUS_MOVES + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_STATUS_MOVES) return TRUE; return FALSE; @@ -260,92 +260,62 @@ void SaveBattlerData(u32 battlerId) bool32 ShouldRecordStatusMove(u32 move) { - switch (GetMoveEffect(move)) + if (ASSUME_STATUS_MOVES_HAS_TUNING) { - // variable odds by additional effect - case EFFECT_NON_VOLATILE_STATUS: - if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP && RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_SLEEP, ASSUME_POWERFUL_STATUS_HIGH_ODDS)) - return TRUE; - else if (RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_NONVOLATILE, ASSUME_POWERFUL_STATUS_MEDIUM_ODDS)) - return TRUE; - break; - // High odds - case EFFECT_AURORA_VEIL: - case EFFECT_CHILLY_RECEPTION: - case EFFECT_CONVERSION: - case EFFECT_FIRST_TURN_ONLY: - case EFFECT_FOLLOW_ME: - case EFFECT_INSTRUCT: - case EFFECT_JUNGLE_HEALING: - case EFFECT_REVIVAL_BLESSING: - case EFFECT_SHED_TAIL: - case EFFECT_STICKY_WEB: - return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS, ASSUME_POWERFUL_STATUS_HIGH_ODDS); - // Medium odds - case EFFECT_AFTER_YOU: - case EFFECT_DEFOG: - case EFFECT_ENCORE: - case EFFECT_HAZE: - case EFFECT_HEAL_BELL: - case EFFECT_HEALING_WISH: - case EFFECT_HELPING_HAND: - case EFFECT_LIFE_DEW: - case EFFECT_MEMENTO: - case EFFECT_MOONLIGHT: - case EFFECT_MORNING_SUN: - case EFFECT_PARTING_SHOT: - case EFFECT_PROTECT: - case EFFECT_REST: - case EFFECT_RESTORE_HP: - case EFFECT_ROAR: - case EFFECT_ROOST: - case EFFECT_SHORE_UP: - case EFFECT_SLEEP_TALK: - case EFFECT_SOFTBOILED: - case EFFECT_SYNTHESIS: - case EFFECT_TAUNT: - case EFFECT_TAILWIND: - case EFFECT_TELEPORT: - case EFFECT_TRICK: - // defoggables / screens and hazards - case EFFECT_LIGHT_SCREEN: - case EFFECT_REFLECT: - case EFFECT_SPIKES: - case EFFECT_STEALTH_ROCK: - case EFFECT_TOXIC_SPIKES: - // field status - case EFFECT_HAIL: - case EFFECT_RAIN_DANCE: - case EFFECT_SANDSTORM: - case EFFECT_SNOWSCAPE: - case EFFECT_SUNNY_DAY: - case EFFECT_TRICK_ROOM: - case EFFECT_ELECTRIC_TERRAIN: - case EFFECT_GRASSY_TERRAIN: - case EFFECT_MISTY_TERRAIN: - case EFFECT_PSYCHIC_TERRAIN: - return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, ASSUME_POWERFUL_STATUS_MEDIUM_ODDS); - // Low odds - case EFFECT_COURT_CHANGE: - case EFFECT_DOODLE: - case EFFECT_ENTRAINMENT: - case EFFECT_FIXED_PERCENT_DAMAGE: - case EFFECT_GASTRO_ACID: - case EFFECT_GUARD_SPLIT: - case EFFECT_IMPRISON: - case EFFECT_PERISH_SONG: - case EFFECT_POWER_SPLIT: - case EFFECT_QUASH: - case EFFECT_ROLE_PLAY: - case EFFECT_SKILL_SWAP: - case EFFECT_SPEED_SWAP: - case EFFECT_WORRY_SEED: - return RandomPercentage(RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS, ASSUME_POWERFUL_STATUS_LOW_ODDS); - default: - break; + switch (GetMoveEffect(move)) + { + // variable odds by additional effect + case EFFECT_NON_VOLATILE_STATUS: + if (GetMoveNonVolatileStatus(move) == MOVE_EFFECT_SLEEP && RandomPercentage(RNG_AI_ASSUME_STATUS_SLEEP, ASSUME_STATUS_HIGH_ODDS)) + return TRUE; + else if (RandomPercentage(RNG_AI_ASSUME_STATUS_NONVOLATILE, ASSUME_STATUS_MEDIUM_ODDS)) + return TRUE; + break; + // High odds + case EFFECT_AURORA_VEIL: + case EFFECT_CHILLY_RECEPTION: + case EFFECT_FIRST_TURN_ONLY: + case EFFECT_FOLLOW_ME: + case EFFECT_INSTRUCT: + case EFFECT_JUNGLE_HEALING: + case EFFECT_SHED_TAIL: + return RandomPercentage(RNG_AI_ASSUME_STATUS_HIGH_ODDS, ASSUME_STATUS_HIGH_ODDS); + // Medium odds + case EFFECT_AFTER_YOU: + case EFFECT_DOODLE: + case EFFECT_ENCORE: + case EFFECT_HAZE: + case EFFECT_PARTING_SHOT: + case EFFECT_PROTECT: + case EFFECT_REST: + case EFFECT_ROAR: + case EFFECT_ROOST: + case EFFECT_SLEEP_TALK: + case EFFECT_TAUNT: + case EFFECT_TAILWIND: + case EFFECT_TRICK: + case EFFECT_TRICK_ROOM: + // defoggables / screens and hazards + case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: + case EFFECT_SPIKES: + case EFFECT_STEALTH_ROCK: + case EFFECT_STICKY_WEB: + case EFFECT_TOXIC_SPIKES: + return RandomPercentage(RNG_AI_ASSUME_STATUS_MEDIUM_ODDS, ASSUME_STATUS_MEDIUM_ODDS); + // Low odds + case EFFECT_ENTRAINMENT: + case EFFECT_FIXED_PERCENT_DAMAGE: + case EFFECT_GASTRO_ACID: + case EFFECT_IMPRISON: + case EFFECT_TELEPORT: + return RandomPercentage(RNG_AI_ASSUME_STATUS_LOW_ODDS, ASSUME_STATUS_LOW_ODDS); + default: + break; + } } - return FALSE; + return RandomPercentage(RNG_AI_ASSUME_ALL_STATUS, ASSUME_ALL_STATUS_ODDS) && IsBattleMoveStatus(move); } static bool32 ShouldFailForIllusion(u32 illusionSpecies, u32 battlerId) diff --git a/test/battle/ai/ai_assume_powerful_status.c b/test/battle/ai/ai_assume_status_moves.c similarity index 53% rename from test/battle/ai/ai_assume_powerful_status.c rename to test/battle/ai/ai_assume_status_moves.c index 1fd16adcf4..8fbaf01101 100644 --- a/test/battle/ai/ai_assume_powerful_status.c +++ b/test/battle/ai/ai_assume_status_moves.c @@ -2,14 +2,15 @@ #include "test/battle.h" #include "battle_ai_util.h" -AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_POWERFUL_STATUS correctly records assumed status moves") +AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_STATUS_MOVES correctly records assumed status moves") { - PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_HIGH_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_HIGH_ODDS); - PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_MEDIUM_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_MEDIUM_ODDS); - PASSES_RANDOMLY(ASSUME_POWERFUL_STATUS_LOW_ODDS, 100, RNG_AI_ASSUME_POWERFUL_STATUS_LOW_ODDS); + PASSES_RANDOMLY(ASSUME_STATUS_HIGH_ODDS, 100, RNG_AI_ASSUME_STATUS_HIGH_ODDS); + PASSES_RANDOMLY(ASSUME_STATUS_MEDIUM_ODDS, 100, RNG_AI_ASSUME_STATUS_MEDIUM_ODDS); + PASSES_RANDOMLY(ASSUME_STATUS_LOW_ODDS, 100, RNG_AI_ASSUME_STATUS_LOW_ODDS); + PASSES_RANDOMLY(ASSUME_ALL_STATUS_ODDS, 100, RNG_AI_ASSUME_ALL_STATUS); GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ASSUME_POWERFUL_STATUS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ASSUME_STATUS_MOVES); PLAYER(SPECIES_TYPHLOSION) { Moves(MOVE_TACKLE, MOVE_COURT_CHANGE, MOVE_FAKE_OUT); } PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_HAIL, MOVE_SHED_TAIL, MOVE_THUNDERBOLT); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); } @@ -28,3 +29,21 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_ASSUME_POWERFUL_STATUS correctly records assumed EXPECT_EQ(gBattleHistory->usedMoves[B_POSITION_PLAYER_RIGHT][3], MOVE_NONE); } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_ASSUME_STATUS_MOVES changes behavior") +{ + if (ASSUME_STATUS_MOVES_HAS_TUNING) + PASSES_RANDOMLY(ASSUME_STATUS_MEDIUM_ODDS, 100, RNG_AI_ASSUME_STATUS_MEDIUM_ODDS); + else + PASSES_RANDOMLY(ASSUME_ALL_STATUS_ODDS, 100, RNG_AI_ASSUME_ALL_STATUS); + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ASSUME_STATUS_MOVES); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_REST, MOVE_HEADBUTT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_WORRY_SEED, MOVE_HEADBUTT); } + } WHEN { + TURN { MOVE(player, MOVE_HEADBUTT); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); } + } +} + + From 165e7502bc38232b769e306bab5f63e9663273b0 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sun, 13 Jul 2025 16:21:37 +0200 Subject: [PATCH 093/283] Instant Win option in Battle Debug --- include/battle_main.h | 1 + src/battle_debug.c | 10 ++++++++++ src/battle_main.c | 7 +++++++ 3 files changed, 18 insertions(+) diff --git a/include/battle_main.h b/include/battle_main.h index 6367f7e0f4..bf8e88fc5d 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -116,6 +116,7 @@ u32 GeneratePersonalityForGender(u32 gender, u32 species); void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon *partyEntry); bool32 CanPlayerForfeitNormalTrainerBattle(void); bool32 DidPlayerForfeitNormalTrainerBattle(void); +void BattleDebug_WonBattle(void); extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; diff --git a/src/battle_debug.c b/src/battle_debug.c index cd3b3cd253..e746ee619d 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -114,6 +114,7 @@ enum LIST_ITEM_AI_INFO, LIST_ITEM_AI_PARTY, LIST_ITEM_VARIOUS, + LIST_ITEM_INSTANT_WIN, LIST_ITEM_COUNT }; @@ -376,6 +377,7 @@ static const struct ListMenuItem sMainListItems[] = {COMPOUND_STRING("AI Info"), LIST_ITEM_AI_INFO}, {COMPOUND_STRING("AI Party"), LIST_ITEM_AI_PARTY}, {COMPOUND_STRING("Various"), LIST_ITEM_VARIOUS}, + {COMPOUND_STRING("Instant Win"), LIST_ITEM_INSTANT_WIN}, }; static const struct ListMenuItem sStatsListItems[] = @@ -1243,6 +1245,13 @@ static void Task_DebugMenuProcessInput(u8 taskId) SwitchToAiPartyView(taskId); return; } + else if (listItemId == LIST_ITEM_INSTANT_WIN && JOY_NEW(A_BUTTON)) + { + BattleDebug_WonBattle(); + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_DebugMenuFadeOut; + return; + } data->currentMainListItemId = listItemId; // Create the secondary menu list. @@ -1445,6 +1454,7 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) listTemplate.items = sSideStatusListItems; itemsCount = ARRAY_COUNT(sSideStatusListItems); break; + case LIST_ITEM_INSTANT_WIN: case LIST_ITEM_AI_MOVES_PTS: case LIST_ITEM_AI_INFO: return; diff --git a/src/battle_main.c b/src/battle_main.c index 22c27ea460..eeb9cd5065 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -6142,3 +6142,10 @@ bool32 DidPlayerForfeitNormalTrainerBattle(void) return (gBattleOutcome == B_OUTCOME_FORFEITED); } + +// Wins the battle instantly. Used in the battle debug with LIST_ITEM_INSTANT_WIN +void BattleDebug_WonBattle(void) +{ + gBattleOutcome |= B_OUTCOME_WON; + gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; +} \ No newline at end of file From 06c54a2d607dfe0223aca6f0af2773e62bf157e2 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 13 Jul 2025 11:45:59 -0400 Subject: [PATCH 094/283] Fix switching 1v1 calcs not handling 0 (#7131) --- src/battle_ai_switch_items.c | 34 +++++++++++++++++++++++----------- test/battle/ai/ai_switching.c | 13 +++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 9138f59d59..2ca97a5720 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -261,13 +261,10 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) { damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); - if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move + if (damageTaken > maxDamageTaken && !AI_DoesChoiceItemBlockMove(opposingBattler, playerMove)) { - return maxDamageTaken = damageTaken; - break; - } - if (damageTaken > maxDamageTaken) maxDamageTaken = damageTaken; + } } } @@ -281,7 +278,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) } // Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can - if (hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove))) + if ((hitsToKoPlayer != 0 && (hitsToKoPlayer < hitsToKoAI || hitsToKoAI == 0)) || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove))) return FALSE; // If we don't have any other viable options, don't switch out @@ -1805,7 +1802,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) // No damage being dealt if ((damageTaken + statusDamage + recurringDamage <= recurringHealing) || damageTaken + statusDamage + recurringDamage == 0) - return startingHP; + return hitsToKO; // Mon fainted to hazards if (startingHP == 0) @@ -2012,6 +2009,18 @@ static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchi static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool32 isSwitchinFirst, bool32 isFreeSwitch) { + // Player's best move deals 0 damage + if (hitsToKOAI == 0 && hitsToKOPlayer > 0) + return TRUE; + + // AI's best move deals 0 damage + if (hitsToKOPlayer == 0 && hitsToKOAI > 0) + return FALSE; + + // Neither mon can damage the other + if (hitsToKOPlayer == 0 && hitsToKOAI == 0) + return FALSE; + // Free switch, need to outspeed or take 1 extra hit if (isFreeSwitch) { @@ -2028,7 +2037,7 @@ static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool3 // Everything runs in the same loop to minimize computation time. This makes it harder to read, but hopefully the comments can guide you! static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, enum SwitchType switchType) { - int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE; + int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE, generic1v1MonId = PARTY_SIZE; int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE; int i, j, aliveCount = 0, bits = 0, aceMonCount = 0; s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed @@ -2073,9 +2082,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, for (j = 0; j < MAX_MON_MOVES; j++) { aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; - - if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) - damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); // Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1 isSwitchinFirst = AI_WhoStrikesFirstPartyMon(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove); @@ -2106,6 +2113,9 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, defensiveMonId = i; } + if (canSwitchinWin1v1) + generic1v1MonId = i; + // Check for mon with resistance and super effective move for best type matchup mon with effective move if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) { @@ -2184,6 +2194,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (typeMatchupEffectiveId != PARTY_SIZE) return typeMatchupEffectiveId; else if (typeMatchupId != PARTY_SIZE) return typeMatchupId; else if (batonPassId != PARTY_SIZE) return batonPassId; + else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId; else if (damageMonId != PARTY_SIZE) return damageMonId; } else @@ -2194,6 +2205,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, else if (typeMatchupId != PARTY_SIZE) return typeMatchupId; else if (defensiveMonId != PARTY_SIZE) return defensiveMonId; else if (batonPassId != PARTY_SIZE) return batonPassId; + else if (generic1v1MonId != PARTY_SIZE) return generic1v1MonId; } // If ace mon is the last available Pokemon and U-Turn/Volt Switch or Eject Pack/Button was used - switch to the mon. if (aceMonId != PARTY_SIZE && CountUsablePartyMons(battler) <= aceMonCount diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index e9ad61bdfa..0c9e94695e 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1255,3 +1255,16 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't send out defensive mon TURN { MOVE(player, MOVE_WATER_PULSE); EXPECT_MOVE(opponent, MOVE_BULLDOZE); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as losing a 1v1") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_JOLTEON) { Level(100); Ability(ABILITY_VOLT_ABSORB); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(1); HP(1); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_TANGELA) { Level(100); Moves(MOVE_THUNDERBOLT); } + OPPONENT(SPECIES_TANGELA) { Level(100); Moves(MOVE_GIGA_DRAIN); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } + } +} From 939e168c041dc8499b50671a7b8a1645627b8402 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 13 Jul 2025 13:24:14 -0400 Subject: [PATCH 095/283] Fix AI_DoesChoiceEffectBlockMove typo (#7335) --- src/battle_ai_switch_items.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 2ca97a5720..c044ff2804 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -261,7 +261,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) { damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); - if (damageTaken > maxDamageTaken && !AI_DoesChoiceItemBlockMove(opposingBattler, playerMove)) + if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) { maxDamageTaken = damageTaken; } From 819e7d9c03721f90dc5de5dc43537cc7e79e0cb2 Mon Sep 17 00:00:00 2001 From: Pawkkie Date: Sun, 13 Jul 2025 14:16:22 -0400 Subject: [PATCH 096/283] Fix failing test --- test/battle/ai/ai_switching.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 8a1070b42c..0aae647030 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -714,7 +714,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will not switch out if it has PARAMETRIZE { hp = 10; } GIVEN { ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN); - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH, MOVE_YAWN); } OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH); HP(hp); MaxHP(30); } OPPONENT(SPECIES_SLAKOTH) { Level(1); Moves(MOVE_HEADBUTT); } From 688ec0023eb3fbc83da9c41ba4fa967da3211904 Mon Sep 17 00:00:00 2001 From: mudskipper13 <105766191+mudskipper13@users.noreply.github.com> Date: Mon, 14 Jul 2025 01:47:14 +0700 Subject: [PATCH 097/283] battle intro: fix issues with follower slide-in and wild shiny mon (#7325) --- src/battle_controllers.c | 10 ++++------ src/pokeball.c | 5 ++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 47bb0b37ee..8706cc9e06 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -2237,9 +2237,7 @@ void BtlController_HandleLoadMonSprite(u32 battler) SetBattlerShadowSpriteCallback(battler, species); - if (IsControllerOpponent(battler) - && IsControllerLinkOpponent(battler) - && IsControllerRecordedOpponent(battler)) + if (IsControllerOpponent(battler) || IsControllerLinkOpponent(battler) || IsControllerRecordedOpponent(battler)) gBattlerControllerFuncs[battler] = TryShinyAnimAfterMonAnim; else gBattlerControllerFuncs[battler] = WaitForMonAnimAfterLoad; @@ -2919,14 +2917,14 @@ void TrySetBattlerShadowSpriteCallback(u32 battler) void TryShinyAnimAfterMonAnim(u32 battler) { - if (gSprites[gBattlerSpriteIds[battler]].callback == SpriteCallbackDummy - && gSprites[gBattlerSpriteIds[battler]].x2 == 0) + if (gSprites[gBattlerSpriteIds[battler]].x2 == 0) { if (!gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim) { TryShinyAnimation(battler, GetBattlerMon(battler)); } - else if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) + + if (gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim) { gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = FALSE; gBattleSpritesDataPtr->healthBoxesData[battler].finishedShinyMonAnim = FALSE; diff --git a/src/pokeball.c b/src/pokeball.c index d77d49797d..5608de9647 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -1080,8 +1080,11 @@ static void HandleBallAnimEnd(struct Sprite *sprite) AnimateSprite(&gSprites[gBattlerSpriteIds[battler]]); gSprites[gBattlerSpriteIds[battler]].data[1] = 0x1000; } + else + { + gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; + } - gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; if (sprite->animEnded) sprite->invisible = TRUE; if (gSprites[gBattlerSpriteIds[battler]].affineAnimEnded) From 5c2980b906582edd564c75b8fdc583b7b584deeb Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 13 Jul 2025 16:31:19 -0400 Subject: [PATCH 098/283] AI assumes Magnitude / Present damage (#7334) --- src/battle_ai_util.c | 4 ++++ test/battle/ai/ai.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index c9fb43c143..7f3b6b74e2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -783,6 +783,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u SetDynamicMoveCategory(battlerAtk, battlerDef, move); SetTypeBeforeUsingMove(move, battlerAtk); + // We can set those globals because they are going to get rerolled on attack execution + gBattleStruct->magnitudeBasePower = 70; + gBattleStruct->presentBasePower = 80; + struct DamageContext ctx; ctx.battlerAtk = battlerAtk; ctx.battlerDef = battlerDef; diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 4f06680c8e..d9d0782b0d 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -897,3 +897,18 @@ AI_SINGLE_BATTLE_TEST("Move scoring comparison properly awards bonus point to be TURN { EXPECT_MOVE(opponent, MOVE_WATER_SPOUT); } } } + +AI_SINGLE_BATTLE_TEST("AI will see Magnitude damage") +{ + PASSES_RANDOMLY(SHOULD_SWITCH_HASBADODDS_PERCENTAGE, 100, RNG_AI_SWITCH_HASBADODDS); + GIVEN { + ASSUME(GetMoveEffect(MOVE_MAGNITUDE) == EFFECT_MAGNITUDE); + ASSUME(GetMoveType(MOVE_MAGNITUDE) == TYPE_GROUND); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_GEODUDE) { Level(15); Moves(MOVE_DEFENSE_CURL, MOVE_MAGNITUDE); } + OPPONENT(SPECIES_TYRUNT) { Level(13); Moves(MOVE_BITE, MOVE_THUNDER_FANG, MOVE_ROCK_TOMB); } + OPPONENT(SPECIES_ZUBAT) { Level(14); Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_MAGNITUDE); EXPECT_SWITCH(opponent, 1); } + } +} From f0da7c1707f5973bf15dc44760f451a7c843e4f2 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sun, 13 Jul 2025 22:00:00 -0400 Subject: [PATCH 099/283] Renaming Powerful status functions. --- include/battle_ai_util.h | 2 +- src/battle_ai_main.c | 6 +++--- src/battle_ai_util.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 1e03090dde..059809d6a5 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -61,7 +61,7 @@ bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); bool32 IsAiBattlerAssumingStab(void); -bool32 IsAiBattlerAssumingPowerfulStatus(void); +bool32 IsAiBattlerAssumingStatusMoves(void); bool32 ShouldRecordStatusMove(u32 move); void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a14ebd4c1a..a659c6befa 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -544,7 +544,7 @@ void RecordMovesBasedOnStab(u32 battler) } } -void RecordPowerfulStatusMoves(u32 battler) +void RecordStatusMoves(u32 battler) { u32 i; for (i = 0; i < MAX_MON_MOVES; i++) @@ -571,8 +571,8 @@ void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) if (IsAiBattlerAssumingStab()) RecordMovesBasedOnStab(battler); - if (IsAiBattlerAssumingPowerfulStatus()) - RecordPowerfulStatusMoves(battler); + if (IsAiBattlerAssumingStatusMoves()) + RecordStatusMoves(battler); } #define BYPASSES_ACCURACY_CALC 101 // 101 indicates for ai that the move will always hit diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index c14dddacf5..77aabccb11 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -141,7 +141,7 @@ bool32 IsAiBattlerAssumingStab() return FALSE; } -bool32 IsAiBattlerAssumingPowerfulStatus() +bool32 IsAiBattlerAssumingStatusMoves() { if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_ASSUME_STATUS_MOVES || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_ASSUME_STATUS_MOVES) From b62e4924a3220ce5a913b599b5d97a409eaae198 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Mon, 14 Jul 2025 06:08:14 -0500 Subject: [PATCH 100/283] Turn `OW_FRLG_WHITEOUT` into `OW_WHITEOUT_CUTSCENE` and make it generational (#6962) --- include/config/overworld.h | 2 +- src/field_screen_effect.c | 24 ++++++++++++------------ src/overworld.c | 8 ++++---- src/strings.c | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index fa87da4d83..b1f107ce63 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -9,7 +9,7 @@ #define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. #define OW_DOUBLE_APPROACH_WITH_ONE_MON FALSE // If enabled, you can be spotted by two trainers at the same time even if you only have one eligible Pokémon in your party. #define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last. -#define OW_FRLG_WHITEOUT FALSE // If enabled, shows an additional whiteout message and post whiteout event script with healing NPC. +#define OW_WHITEOUT_CUTSCENE GEN_LATEST // In Gen4+, whiting out shows an additional message and post whiteout event script cutscene with a healing NPC. (While this change was also in FRLG, for the sake of simplicity, setting this to GEN_3 will result in RSE behavior.) #define OW_DEFOG_FIELD_MOVE FALSE // If enabled, Defog can be used as a Field Move as seen in DPPt. // Item Obtain Description Box diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 44ef4dd286..fde3036730 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -1384,10 +1384,10 @@ static bool32 PrintWhiteOutRecoveryMessage(u8 taskId, const u8 *text, u32 x, u32 } enum { - FRLG_WHITEOUT_ENTER_MSG_SCREEN, - FRLG_WHITEOUT_PRINT_MSG, - FRLG_WHITEOUT_LEAVE_MSG_SCREEN, - FRLG_WHITEOUT_HEAL_SCRIPT, + WHITEOUT_CUTSCENE_ENTER_MSG_SCREEN, + WHITEOUT_CUTSCENE_PRINT_MSG, + WHITEOUT_CUTSCENE_LEAVE_MSG_SCREEN, + WHITEOUT_CUTSCENE_HEAL_SCRIPT, }; static const u8 *GenerateRecoveryMessage(u8 taskId) @@ -1411,7 +1411,7 @@ static void Task_RushInjuredPokemonToCenter(u8 taskId) switch (gTasks[taskId].tState) { - case FRLG_WHITEOUT_ENTER_MSG_SCREEN: + case WHITEOUT_CUTSCENE_ENTER_MSG_SCREEN: windowId = AddWindow(&sWindowTemplate_WhiteoutText); gTasks[taskId].tWindowId = windowId; Menu_LoadStdPalAt(BG_PLTT_ID(15)); @@ -1420,28 +1420,28 @@ static void Task_RushInjuredPokemonToCenter(u8 taskId) CopyWindowToVram(windowId, COPYWIN_FULL); gTasks[taskId].tIsPlayerHouse = IsLastHealLocationPlayerHouse(); - gTasks[taskId].tState = FRLG_WHITEOUT_PRINT_MSG; + gTasks[taskId].tState = WHITEOUT_CUTSCENE_PRINT_MSG; break; - case FRLG_WHITEOUT_PRINT_MSG: + case WHITEOUT_CUTSCENE_PRINT_MSG: { const u8 *recoveryMessage = GenerateRecoveryMessage(taskId); if (PrintWhiteOutRecoveryMessage(taskId, recoveryMessage, 2, 8)) { ObjectEventTurn(&gObjectEvents[gPlayerAvatar.objectEventId], DIR_NORTH); - gTasks[taskId].tState = FRLG_WHITEOUT_LEAVE_MSG_SCREEN; + gTasks[taskId].tState = WHITEOUT_CUTSCENE_LEAVE_MSG_SCREEN; } break; } - case FRLG_WHITEOUT_LEAVE_MSG_SCREEN: + case WHITEOUT_CUTSCENE_LEAVE_MSG_SCREEN: windowId = gTasks[taskId].tWindowId; ClearWindowTilemap(windowId); CopyWindowToVram(windowId, COPYWIN_MAP); RemoveWindow(windowId); FadeInFromBlack(); - gTasks[taskId].tState = FRLG_WHITEOUT_HEAL_SCRIPT; + gTasks[taskId].tState = WHITEOUT_CUTSCENE_HEAL_SCRIPT; break; - case FRLG_WHITEOUT_HEAL_SCRIPT: + case WHITEOUT_CUTSCENE_HEAL_SCRIPT: if (WaitForWeatherFadeIn() == TRUE) { DestroyTask(taskId); @@ -1461,7 +1461,7 @@ void FieldCB_RushInjuredPokemonToCenter(void) LockPlayerFieldControls(); FillPalBufferBlack(); taskId = CreateTask(Task_RushInjuredPokemonToCenter, 10); - gTasks[taskId].tState = FRLG_WHITEOUT_ENTER_MSG_SCREEN; + gTasks[taskId].tState = WHITEOUT_CUTSCENE_ENTER_MSG_SCREEN; } static void GetStairsMovementDirection(u32 metatileBehavior, s16 *speedX, s16 *speedY) diff --git a/src/overworld.c b/src/overworld.c index 9dac585f62..7fb339966b 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -707,16 +707,16 @@ void SetWarpDestinationToHealLocation(u8 healLocationId) SetWarpDestination(healLocation->mapGroup, healLocation->mapNum, WARP_ID_NONE, healLocation->x, healLocation->y); } -static bool32 IsFRLGWhiteout(void) +static bool32 IsWhiteoutCutscene(void) { - if (!OW_FRLG_WHITEOUT) + if (OW_WHITEOUT_CUTSCENE < GEN_4) return FALSE; return GetHealNpcLocalId(GetHealLocationIndexByWarpData(&gSaveBlock1Ptr->lastHealLocation)) > 0; } void SetWarpDestinationToLastHealLocation(void) { - if (IsFRLGWhiteout()) + if (IsWhiteoutCutscene()) SetWhiteoutRespawnWarpAndHealerNPC(&sWarpDestination); else sWarpDestination = gSaveBlock1Ptr->lastHealLocation; @@ -1810,7 +1810,7 @@ void CB2_WhiteOut(void) ResetInitialPlayerAvatarState(); ScriptContext_Init(); UnlockPlayerFieldControls(); - if (IsFRLGWhiteout()) + if (IsWhiteoutCutscene()) gFieldCallback = FieldCB_RushInjuredPokemonToCenter; else gFieldCallback = FieldCB_WarpExitFadeFromBlack; diff --git a/src/strings.c b/src/strings.c index 4846bea8ed..fd92b31e92 100644 --- a/src/strings.c +++ b/src/strings.c @@ -809,8 +809,8 @@ const u8 gText_ThankYou[] = _("THANK YOU"); const u8 gText_ByeBye[] = _("BYE-BYE!"); const u8 gText_PlayerScurriedToCenter[] = _("{PLAYER} scurried to a POKéMON CENTER,\nprotecting the exhausted and fainted\nPOKéMON from further harm…\p"); const u8 gText_PlayerScurriedBackHome[] = _("{PLAYER} scurried back home, protecting\nthe exhausted and fainted POKéMON from\nfurther harm…\p"); -const u8 gText_PlayerRegroupCenter[] = _("{PLAYER} went running back to a POKéMON CENTER\nto regroup and reconsider their battle\lstrategy…\p"); -const u8 gText_PlayerRegroupHome[] = _("{PLAYER} went running back home to regroup\nand reconsider their battle strategy…\p"); +const u8 gText_PlayerRegroupCenter[] = _("{PLAYER} scurried to a POKéMON CENTER,\nto regroup and reconsider the battle\nstrategy…\p"); +const u8 gText_PlayerRegroupHome[] = _("{PLAYER} scurried back home, to regroup\nand reconsider the battle strategy…\p"); const u8 gText_HatchedFromEgg[] = _("{STR_VAR_1} hatched from the EGG!"); const u8 gText_NicknameHatchPrompt[] = _("Would you like to nickname the newly\nhatched {STR_VAR_1}?"); ALIGNED(4) const u8 gText_ReadyPickBerry[] = _("Are you ready to BERRY-CRUSH?\nPlease pick a BERRY for use.\p"); From 73a2e5104e97f973ff0b2b4e6eb76340e83bd2dd Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:34:21 +0200 Subject: [PATCH 101/283] Bugfixes for Knock Off, Cover, Thief, Ceaseless Edge and Stone Axe (#7326) --- include/battle.h | 3 +- include/constants/battle.h | 13 +- include/constants/battle_move_effects.h | 3 + include/constants/battle_script_commands.h | 3 +- src/battle_ai_main.c | 147 +++-- src/battle_script_commands.c | 528 +++++++++--------- src/battle_tv.c | 4 - src/battle_util.c | 16 + src/data/battle_move_effects.h | 18 + src/data/moves_info.h | 20 +- test/battle/ability/sheer_force.c | 1 - test/battle/ability/sticky_hold.c | 2 +- test/battle/hold_effect/air_balloon.c | 9 +- test/battle/hold_effect/red_card.c | 2 +- test/battle/hold_effect/restore_stats.c | 7 +- .../spikes.c => move_effect/ceaseless_edge.c} | 18 +- test/battle/move_effect/hit_switch_target.c | 4 +- test/battle/move_effect/ice_spinner.c | 5 +- test/battle/move_effect/knock_off.c | 58 +- test/battle/move_effect/stone_axe.c | 94 ++++ test/battle/move_effect_secondary/pay_day.c | 2 +- .../battle/move_effect_secondary/steal_item.c | 42 +- .../move_effect_secondary/stealth_rock.c | 58 +- .../move_effects_combined/make_it_rain.c | 2 +- 24 files changed, 601 insertions(+), 458 deletions(-) rename test/battle/{move_effect_secondary/spikes.c => move_effect/ceaseless_edge.c} (76%) create mode 100644 test/battle/move_effect/stone_axe.c diff --git a/include/battle.h b/include/battle.h index 6b9609758b..d59432e6c1 100644 --- a/include/battle.h +++ b/include/battle.h @@ -588,7 +588,8 @@ struct BattlerState u32 pursuitTarget:1; u32 stompingTantrumTimer:2; u32 canPickupItem:1; - u32 padding:16; + u32 itemCanBeKnockedOff:1; + u32 padding:15; // End of Word }; diff --git a/include/constants/battle.h b/include/constants/battle.h index 39f2dbd236..bc7cdc1069 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -363,7 +363,6 @@ enum MoveEffects MOVE_EFFECT_REMOVE_ARG_TYPE, MOVE_EFFECT_RECHARGE, MOVE_EFFECT_RAGE, - MOVE_EFFECT_STEAL_ITEM, MOVE_EFFECT_PREVENT_ESCAPE, MOVE_EFFECT_NIGHTMARE, MOVE_EFFECT_ALL_STATS_UP, @@ -399,8 +398,6 @@ enum MoveEffects MOVE_EFFECT_TRAP_BOTH, MOVE_EFFECT_ROUND, MOVE_EFFECT_DIRE_CLAW, - MOVE_EFFECT_STEALTH_ROCK, - MOVE_EFFECT_SPIKES, MOVE_EFFECT_SYRUP_BOMB, MOVE_EFFECT_FLORAL_HEALING, MOVE_EFFECT_SECRET_POWER, @@ -414,6 +411,11 @@ enum MoveEffects MOVE_EFFECT_LIGHT_SCREEN, MOVE_EFFECT_SALT_CURE, MOVE_EFFECT_EERIE_SPELL, + + // Max move effects happen earlier in the execution chain. + // For example stealth rock from G-Max Stonesurge is set up before abilities but from Stone Axe after. + // Stone Axe can also fail to set up rocks if user faints where as Stonesurge will always go up. + // This means we need to be careful if we want to re-use those effects for (new) vanilla moves MOVE_EFFECT_RAISE_TEAM_ATTACK, MOVE_EFFECT_RAISE_TEAM_DEFENSE, MOVE_EFFECT_RAISE_TEAM_SPEED, @@ -455,11 +457,14 @@ enum MoveEffects MOVE_EFFECT_LOWER_EVASIVENESS_SIDE, MOVE_EFFECT_AROMATHERAPY, MOVE_EFFECT_CONFUSE_SIDE, - MOVE_EFFECT_STEELSURGE, + MOVE_EFFECT_STEELSURGE, // Steel type rocks + MOVE_EFFECT_STEALTH_ROCK, // Max Move rocks, not to be confused for rocks set up from Ceasless Edge (same but differ in execution order) MOVE_EFFECT_TORMENT_SIDE, MOVE_EFFECT_LOWER_SPEED_2_SIDE, MOVE_EFFECT_FIRE_SPIN_SIDE, MOVE_EFFECT_FIXED_POWER, + // Max move effects end. They can be used for (custom) normal moves. + NUM_MOVE_EFFECTS }; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index e21387c2af..97a48929d3 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -155,6 +155,7 @@ enum BattleMoveEffects EFFECT_BRICK_BREAK, EFFECT_YAWN, EFFECT_KNOCK_OFF, + EFFECT_STEAL_ITEM, EFFECT_ENDEAVOR, EFFECT_POWER_BASED_ON_USER_HP, EFFECT_SKILL_SWAP, @@ -351,6 +352,8 @@ enum BattleMoveEffects EFFECT_SMACK_DOWN, EFFECT_ICE_SPINNER, // Removes terrain unless attacker is removed from field either by fainting or ejected out EFFECT_STEEL_ROLLER, // Will fail if there is no terrain up but removes it regardless if attacker is removed from field or not + EFFECT_STONE_AXE, // Not to be confused with MOVE_EFFECT_STEALTH_ROCK. They have two different activation timings. + EFFECT_CEASELESS_EDGE, // Same applies to spikes NUM_BATTLE_MOVE_EFFECTS, }; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 9e0556d8c5..e5060b4102 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -260,7 +260,6 @@ enum MoveEndEffects MOVEEND_ATTACKER_VISIBLE, MOVEEND_TARGET_VISIBLE, MOVEEND_ITEM_EFFECTS_TARGET, - MOVEEND_FIRST_MOVE_BLOCK, MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_SYMBIOSIS, MOVEEND_KINGSROCK, // These item effects will occur each strike of a multi-hit move @@ -271,7 +270,7 @@ enum MoveEndEffects MOVEEND_DEFROST, MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move MOVEEND_MULTIHIT_MOVE, - MOVEEND_SECOND_MOVE_BLOCK, + MOVEEND_MOVE_BLOCK, MOVEEND_ITEM_EFFECTS_ATTACKER, MOVEEND_ABILITY_BLOCK, MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Opportunist diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index acf0bdb722..b785180bc2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5117,6 +5117,69 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } } break; + case EFFECT_STEAL_ITEM: + { + bool32 canSteal = FALSE; + + if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) + canSteal = TRUE; + + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) + canSteal = TRUE; + + if (canSteal && aiData->items[battlerAtk] == ITEM_NONE + && aiData->items[battlerDef] != ITEM_NONE + && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) + && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) + && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) + && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) + { + switch (aiData->holdEffects[battlerDef]) + { + case HOLD_EFFECT_NONE: + break; + case HOLD_EFFECT_CHOICE_BAND: + case HOLD_EFFECT_CHOICE_SCARF: + case HOLD_EFFECT_CHOICE_SPECS: + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_TOXIC_ORB: + if (ShouldPoison(battlerAtk, battlerAtk)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_FLAME_ORB: + if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_BLACK_SLUDGE: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_IRON_BALL: + if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_LAGGING_TAIL: + case HOLD_EFFECT_STICKY_BARB: + break; + default: + ADJUST_SCORE(WEAK_EFFECT); + break; + } + } + break; + } + break; + case EFFECT_STONE_AXE: + case EFFECT_CEASELESS_EDGE: + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); + { + if (gDisableStructs[battlerAtk].isFirstTurn) + ADJUST_SCORE(BEST_EFFECT); + else + ADJUST_SCORE(DECENT_EFFECT); + } + break; default: break; } // move effect checks @@ -5256,68 +5319,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) ADJUST_SCORE(DECENT_EFFECT); break; - case MOVE_EFFECT_STEAL_ITEM: - { - bool32 canSteal = FALSE; - - if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) - canSteal = TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) - canSteal = TRUE; - - if (canSteal && aiData->items[battlerAtk] == ITEM_NONE - && aiData->items[battlerDef] != ITEM_NONE - && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) - && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) - && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) - && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) - { - switch (aiData->holdEffects[battlerDef]) - { - case HOLD_EFFECT_NONE: - break; - case HOLD_EFFECT_CHOICE_BAND: - case HOLD_EFFECT_CHOICE_SCARF: - case HOLD_EFFECT_CHOICE_SPECS: - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_TOXIC_ORB: - if (ShouldPoison(battlerAtk, battlerAtk)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_FLAME_ORB: - if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_BLACK_SLUDGE: - if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_IRON_BALL: - if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_LAGGING_TAIL: - case HOLD_EFFECT_STICKY_BARB: - break; - default: - ADJUST_SCORE(WEAK_EFFECT); - break; - } - } - break; - } - break; - case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); - { - if (gDisableStructs[battlerAtk].isFirstTurn) - ADJUST_SCORE(BEST_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; case MOVE_EFFECT_FEINT: if (GetMoveEffect(predictedMove) == EFFECT_PROTECT) ADJUST_SCORE(GOOD_EFFECT); @@ -5375,7 +5376,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score // Effects that are encouraged on the first turn of battle static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { - u8 i; if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) || gBattleResults.battleTurnCounter != 0) return score; @@ -5473,27 +5473,10 @@ static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 case EFFECT_CHILLY_RECEPTION: case EFFECT_GEOMANCY: case EFFECT_VICTORY_DANCE: + case EFFECT_CEASELESS_EDGE: + case EFFECT_STONE_AXE: ADJUST_SCORE(DECENT_EFFECT); break; - case EFFECT_HIT: - { - // TEMPORARY - should applied to all moves regardless of EFFECT - // Consider move effects - u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); - for (i = 0; i < additionalEffectCount; i++) - { - const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - switch (additionalEffect->moveEffect) - { - case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: - ADJUST_SCORE(DECENT_EFFECT); - break; - default: - break; - } - } - } default: break; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 664fa22f25..cb746ebc99 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -964,8 +964,6 @@ static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / static const u16 sFinalStrikeOnlyEffects[] = { - MOVE_EFFECT_BUG_BITE, - MOVE_EFFECT_STEAL_ITEM, MOVE_EFFECT_REMOVE_ARG_TYPE, MOVE_EFFECT_REMOVE_STATUS, MOVE_EFFECT_RECOIL_HP_25, @@ -2749,6 +2747,14 @@ static void Cmd_datahpupdate(void) && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS && IsBattlerTurnDamaged(gBattlerTarget)) gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; + + if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF + && IsBattlerTurnDamaged(gBattlerTarget) + && gBattleMons[gBattlerTarget].item != 0 + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) + && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) + && !NoAliveMonsForEitherParty()) + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE; } TryRestoreDamageAfterCheekPouch(battler); @@ -3132,7 +3138,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) if (B_STEAL_WILD_ITEMS >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) - && MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_STEAL_ITEM) + && GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM && battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this { AddBagItem(gLastUsedItem, 1); @@ -3289,10 +3295,8 @@ void SetMoveEffect(bool32 primary, bool32 certain) switch (gBattleScripting.moveEffect) // Set move effects which happen later on { case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: case MOVE_EFFECT_PAYDAY: case MOVE_EFFECT_BUG_BITE: - case MOVE_EFFECT_STEAL_ITEM: activateAfterFaint = TRUE; break; } @@ -3470,6 +3474,26 @@ void SetMoveEffect(bool32 primary, bool32 certain) } gBattlescriptCurrInstr++; break; + case MOVE_EFFECT_BUG_BITE: + if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY) + { + // jaboca berry triggers instead of being stolen + gBattlescriptCurrInstr++; + } + else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES + && battlerAbility != ABILITY_STICKY_HOLD) + { + // target loses their berry + gLastUsedItem = gBattleMons[gEffectBattler].item; + gBattleMons[gEffectBattler].item = 0; + CheckSetUnburden(gEffectBattler); + + BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); + MarkBattlerForControllerExec(gEffectBattler); + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; + } + break; case MOVE_EFFECT_TRI_ATTACK: if (gBattleMons[gEffectBattler].status1) { @@ -3638,35 +3662,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattleMons[gBattlerAttacker].status2 |= STATUS2_RAGE; gBattlescriptCurrInstr++; break; - case MOVE_EFFECT_STEAL_ITEM: - if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) - || gBattleMons[gBattlerAttacker].item != ITEM_NONE - || gBattleMons[gBattlerTarget].item == ITEM_NONE) - { - gBattlescriptCurrInstr++; - } - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) - { - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_NoItemSteal; - - gLastUsedAbility = gBattleMons[gBattlerTarget].ability; - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); - } - else - { - StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item - - if (!(B_STEAL_WILD_ITEMS >= GEN_9 - && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) - { - gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) - gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later - } - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_ItemSteal; - } - break; case MOVE_EFFECT_PREVENT_ESCAPE: gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; @@ -3802,26 +3797,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattlescriptCurrInstr = BattleScript_MoveEffectIncinerate; } break; - case MOVE_EFFECT_BUG_BITE: - if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY) - { - // jaboca berry triggers instead of being stolen - gBattlescriptCurrInstr++; - } - else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES - && battlerAbility != ABILITY_STICKY_HOLD) - { - // target loses their berry - gLastUsedItem = gBattleMons[gEffectBattler].item; - gBattleMons[gEffectBattler].item = 0; - CheckSetUnburden(gEffectBattler); - - BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gEffectBattler].item), &gBattleMons[gEffectBattler].item); - MarkBattlerForControllerExec(gEffectBattler); - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; - } - break; case MOVE_EFFECT_TRAP_BOTH: if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION)) { @@ -3877,18 +3852,6 @@ void SetMoveEffect(bool32 primary, bool32 certain) gBattlescriptCurrInstr = BattleScript_StealthRockActivates; } break; - case MOVE_EFFECT_SPIKES: - if (gSideTimers[GetBattlerSide(gEffectBattler)].spikesAmount < 3) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; - BattleScriptPush(gBattlescriptCurrInstr + 1); - - if (gBattleStruct->isSkyBattle) - gBattlescriptCurrInstr++; - else - gBattlescriptCurrInstr = BattleScript_SpikesActivates; - } - break; case MOVE_EFFECT_SYRUP_BOMB: if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) { @@ -6073,47 +6036,6 @@ static void Cmd_playstatchangeanimation(void) } } -static bool32 TryKnockOffBattleScript(u32 battlerDef) -{ - if (gBattleMons[battlerDef].item != 0 - && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item) - && !NoAliveMonsForEitherParty()) - { - if (GetBattlerAbility(battlerDef) == ABILITY_STICKY_HOLD && IsBattlerAlive(battlerDef)) - { - gBattlerAbility = battlerDef; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - } - else - { - u32 side = GetBattlerSide(battlerDef); - - gLastUsedItem = gBattleMons[battlerDef].item; - gBattleMons[battlerDef].item = 0; - if (gBattleMons[battlerDef].ability != ABILITY_GORILLA_TACTICS) - gBattleStruct->choicedMove[battlerDef] = 0; - CheckSetUnburden(battlerDef); - - // In Gen 5+, Knock Off removes the target's item rather than rendering it unusable. - if (B_KNOCK_OFF_REMOVAL >= GEN_5) - { - BtlController_EmitSetMonData(battlerDef, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item); - MarkBattlerForControllerExec(battlerDef); - } - else - { - gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[battlerDef]; - } - - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_KnockedOff; - } - return TRUE; - } - return FALSE; -} - static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally) { return GetBattlerAbility(ally) == ABILITY_SYMBIOSIS @@ -6323,6 +6245,233 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move return effect; } +static bool32 HandleMoveEndMoveBlock(u32 moveEffect) +{ + if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + return FALSE; + + u32 effect = FALSE; + switch (moveEffect) + { + case EFFECT_KNOCK_OFF: + if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerAttacker)) + { + u32 side = GetBattlerSide(gBattlerTarget); + gLastUsedItem = gBattleMons[gBattlerTarget].item; + gBattleMons[gBattlerTarget].item = 0; + if (gBattleMons[gBattlerTarget].ability != ABILITY_GORILLA_TACTICS) + gBattleStruct->choicedMove[gBattlerTarget] = 0; + CheckSetUnburden(gBattlerTarget); + + // In Gen 5+, Knock Off removes the target's item rather than rendering it unusable. + if (B_KNOCK_OFF_REMOVAL >= GEN_5) + { + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); + MarkBattlerForControllerExec(gBattlerTarget); + } + else + { + gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; + } + + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KnockedOff; + effect = TRUE; + } + break; + case EFFECT_STEAL_ITEM: + if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) + || gBattleMons[gBattlerAttacker].item != ITEM_NONE + || gBattleMons[gBattlerTarget].item == ITEM_NONE + || !IsBattlerAlive(gBattlerAttacker) + || !IsBattlerTurnDamaged(gBattlerTarget)) + { + effect = FALSE; + } + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_NoItemSteal; + + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + effect = TRUE; + } + else + { + StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item + + if (!(B_STEAL_WILD_ITEMS >= GEN_9 + && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) + { + gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) + gBattleStruct->changedItems[gBattlerAttacker] = gLastUsedItem; // Stolen item to be assigned later + } + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_ItemSteal; + effect = TRUE; + } + break; + case EFFECT_HIT_SWITCH_TARGET: + if (IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER)) + { + u32 targetAbility = GetBattlerAbility(gBattlerTarget); + if (targetAbility == ABILITY_GUARD_DOG) + return FALSE; + + BattleScriptPushCursor(); + if (targetAbility == ABILITY_SUCTION_CUPS) + { + gBattlescriptCurrInstr = BattleScript_AbilityPreventsPhasingOutRet; + } + else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED) + { + gBattlescriptCurrInstr = BattleScript_PrintMonIsRootedRet; + } + else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) + { + gBattlescriptCurrInstr = BattleScript_HitSwitchTargetDynamaxed; + } + else + { + gBattleScripting.switchCase = B_SWITCH_HIT; + gBattlescriptCurrInstr = BattleScript_TryHitSwitchTarget; + } + effect = TRUE; + } + break; + case EFFECT_SMACK_DOWN: + if (!IsBattlerGrounded(gBattlerTarget) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + { + gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; + gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); + BattleScriptPush(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown; + effect = TRUE; + } + break; + case EFFECT_RECOIL_IF_MISS: + if (IsBattlerAlive(gBattlerAttacker) + && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + && !gBattleStruct->noTargetPresent) + { + if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE)) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget]) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower. + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RecoilIfMiss; + effect = TRUE; + } + break; + case EFFECT_RECOIL: + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleStruct->moveDamage[gBattlerTarget] * max(1, GetMoveRecoil(gCurrentMove)) / 100); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + effect = TRUE; + } + break; + case EFFECT_EXPLOSION: + if (!IsAbilityOnField(ABILITY_DAMP)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion; + effect = TRUE; + } + break; + case EFFECT_MAX_HP_50_RECOIL: + case EFFECT_MIND_BLOWN: + if (IsBattlerAlive(gBattlerAttacker) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil; + effect = TRUE; + } + break; + case EFFECT_CHLOROBLAST: + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + effect = TRUE; + } + break; + case EFFECT_RAPID_SPIN: + if (IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RapidSpinAway; + effect = TRUE; + } + break; + case EFFECT_FELL_STINGER: + if (IsBattlerAlive(gBattlerAttacker) + && !IsBattlerAlive(gBattlerTarget) + && IsBattlerTurnDamaged(gBattlerTarget) + && !NoAliveMonsForEitherParty() + && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat; + effect = TRUE; + } + break; + case EFFECT_STONE_AXE: + if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEALTH_ROCK) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StealthRockActivates; + effect = TRUE; + } + break; + case EFFECT_CEASELESS_EDGE: + if (gSideTimers[GetBattlerSide(gBattlerTarget)].spikesAmount < 3 && IsBattlerAlive(gBattlerAttacker)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; + BattleScriptPush(gBattlescriptCurrInstr + 1); + if (gBattleStruct->isSkyBattle) + { + effect = FALSE; + } + else + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SpikesActivates; + effect = TRUE; + } + } + break; + default: + effect = FALSE; + break; + } + + return effect; +} + static void Cmd_moveend(void) { CMD_ARGS(u8 endMode, u8 endState); @@ -6587,72 +6736,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_FIRST_MOVE_BLOCK: - if ((gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) - || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - { - gBattleScripting.moveendState++; - break; - } - - switch (moveEffect) - { - case EFFECT_KNOCK_OFF: - if (!DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - effect = TryKnockOffBattleScript(gBattlerTarget); - break; - case EFFECT_HIT_SWITCH_TARGET: - if (IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER)) - { - u32 targetAbility = GetBattlerAbility(gBattlerTarget); - if (targetAbility == ABILITY_GUARD_DOG) - { - gBattleScripting.moveendState++; - break; - } - - effect = TRUE; - BattleScriptPushCursor(); - if (targetAbility == ABILITY_SUCTION_CUPS) - { - gBattlescriptCurrInstr = BattleScript_AbilityPreventsPhasingOutRet; - } - else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED) - { - gBattlescriptCurrInstr = BattleScript_PrintMonIsRootedRet; - } - else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) - { - gBattlescriptCurrInstr = BattleScript_HitSwitchTargetDynamaxed; - } - else - { - gBattleScripting.switchCase = B_SWITCH_HIT; - gBattlescriptCurrInstr = BattleScript_TryHitSwitchTarget; - } - } - break; - case EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - { - gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); - effect = TRUE; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_MoveEffectSmackDown; - } - break; - default: - break; - } - gBattleScripting.moveendState++; - break; case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0, FALSE)) effect = TRUE; @@ -6992,99 +7075,8 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - case MOVEEND_SECOND_MOVE_BLOCK: - if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - { - gBattleScripting.moveendState++; - break; - } - - switch (moveEffect) - { - case EFFECT_RECOIL_IF_MISS: - if (IsBattlerAlive(gBattlerAttacker) - && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && !gBattleStruct->noTargetPresent) - { - if (B_RECOIL_IF_MISS_DMG >= GEN_5 || (B_CRASH_IF_TARGET_IMMUNE == GEN_4 && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_DOESNT_AFFECT_FOE)) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - else if (B_RECOIL_IF_MISS_DMG == GEN_4 && (GetNonDynamaxMaxHP(gBattlerTarget) / 2) < gBattleStruct->moveDamage[gBattlerTarget]) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - else // Fallback if B_RECOIL_IF_MISS_DMG is set to gen3 or lower. - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_RecoilIfMiss; - effect = TRUE; - } - break; - case EFFECT_RECOIL: - if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleStruct->moveDamage[gBattlerTarget] * max(1, GetMoveRecoil(gCurrentMove)) / 100); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; - effect = TRUE; - } - break; - case EFFECT_EXPLOSION: - if (!IsAbilityOnField(ABILITY_DAMP)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = 0; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion; - effect = TRUE; - } - break; - case EFFECT_MAX_HP_50_RECOIL: - case EFFECT_MIND_BLOWN: - if (IsBattlerAlive(gBattlerAttacker) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil; - effect = TRUE; - } - break; - case EFFECT_CHLOROBLAST: - if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) - { - gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; - effect = TRUE; - } - break; - case EFFECT_RAPID_SPIN: - if (IsBattlerTurnDamaged(gBattlerTarget)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_RapidSpinAway; - effect = TRUE; - } - break; - case EFFECT_FELL_STINGER: - if (IsBattlerAlive(gBattlerAttacker) - && !IsBattlerAlive(gBattlerTarget) - && IsBattlerTurnDamaged(gBattlerTarget) - && !NoAliveMonsForEitherParty() - && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat; - effect = TRUE; - } - break; - default: - break; - } + case MOVEEND_MOVE_BLOCK: + effect = HandleMoveEndMoveBlock(moveEffect); gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_ATTACKER: @@ -7378,7 +7370,9 @@ static void Cmd_moveend(void) switch (moveEffect) { case EFFECT_ICE_SPINNER: - if (IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget)) + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY + && IsBattlerAlive(gBattlerAttacker) + && IsBattlerTurnDamaged(gBattlerTarget)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_RemoveTerrain; diff --git a/src/battle_tv.c b/src/battle_tv.c index 96ce633440..8876127320 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -839,10 +839,6 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3) const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); switch (additionalEffect->moveEffect) { - case MOVE_EFFECT_STEAL_ITEM: - if ((additionalEffect->chance == 100 || additionalEffect->chance == 0)) - baseFromEffect += 3; - break; case MOVE_EFFECT_THRASH: if (additionalEffect->self == TRUE) baseFromEffect += 3; diff --git a/src/battle_util.c b/src/battle_util.c index a544d1484d..3e9090516e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4354,6 +4354,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITYEFFECT_MOVE_END: // Think contact abilities. switch (gLastUsedAbility) { + case ABILITY_STICKY_HOLD: + if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerTarget)) + { + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; + gBattlerAbility = gBattlerTarget; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + effect++; + } + break; case ABILITY_JUSTIFIED: if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) && IsBattlerTurnDamaged(gBattlerTarget) @@ -7045,6 +7055,12 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) case ITEMEFFECT_MOVE_END: for (battler = 0; battler < gBattlersCount; battler++) { + // If item can be knocked off berry activation will be blocked, but not other items + if (gBattleStruct->battlerState[battler].itemCanBeKnockedOff + && (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES + || GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RESTORE_HP)) + continue; + gLastUsedItem = gBattleMons[battler].item; effect = ItemEffectMoveEnd(battler, GetBattlerHoldEffect(battler, TRUE)); if (effect) diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 08d8123296..7101bc45fa 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -992,6 +992,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 2, }, + [EFFECT_STEAL_ITEM] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 3, + }, + [EFFECT_ENDEAVOR] = { .battleScript = BattleScript_EffectEndeavor, @@ -2230,4 +2236,16 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleScript = BattleScript_EffectSteelRoller, .battleTvScore = 0, // TODO: Assign points }, + + [EFFECT_STONE_AXE] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_CEASELESS_EDGE] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, }; diff --git a/src/data/moves_info.h b/src/data/moves_info.h index c0e44cf4df..00da8aa15f 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -4481,7 +4481,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "While attacking, it may\n" "steal the foe's held item."), - .effect = EFFECT_HIT, + .effect = EFFECT_STEAL_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 60 : 40, .type = TYPE_DARK, .accuracy = 100, @@ -4490,9 +4490,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEAL_ITEM, - }), .ignoresKingsRock = (B_UPDATED_MOVE_FLAGS == GEN_3 || B_UPDATED_MOVE_FLAGS == GEN_4), .meFirstBanned = TRUE, .metronomeBanned = TRUE, @@ -9040,7 +9037,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "Cutely begs to obtain an\n" "item held by the foe."), - .effect = EFFECT_HIT, + .effect = EFFECT_STEAL_ITEM, .power = B_UPDATED_MOVE_DATA >= GEN_5 ? 60 : 40, .type = TYPE_NORMAL, .accuracy = 100, @@ -9053,9 +9050,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, - .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEAL_ITEM, - }), .contestEffect = CONTEST_EFFECT_APPEAL_AS_GOOD_AS_PREV_ONES, .contestCategory = CONTEST_CATEGORY_CUTE, .contestComboStarterId = 0, @@ -19208,7 +19202,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "High critical hit ratio. Sets\n" "Splinters that hurt the foe."), - .effect = EFFECT_HIT, + .effect = EFFECT_STONE_AXE, .power = 65, .type = TYPE_ROCK, .accuracy = 90, @@ -19219,8 +19213,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_STEALTH_ROCK, - .chance = 100, + .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_StoneAxe, }, @@ -19534,7 +19527,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "High critical hit ratio. Sets\n" "Splinters that hurt the foe."), - .effect = EFFECT_HIT, + .effect = EFFECT_CEASELESS_EDGE, .power = 65, .type = TYPE_DARK, .accuracy = 90, @@ -19545,8 +19538,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .moveEffect = MOVE_EFFECT_SPIKES, - .chance = 100, + .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_CeaselessEdge, }, diff --git a/test/battle/ability/sheer_force.c b/test/battle/ability/sheer_force.c index ee3e10d14e..076597d49b 100644 --- a/test/battle/ability/sheer_force.c +++ b/test/battle/ability/sheer_force.c @@ -1,7 +1,6 @@ #include "global.h" #include "test/battle.h" - ASSUMPTIONS { ASSUME(MoveIsAffectedBySheerForce(MOVE_ELECTRO_SHOT) == TRUE); diff --git a/test/battle/ability/sticky_hold.c b/test/battle/ability/sticky_hold.c index 708c691c80..d6aee1ee51 100644 --- a/test/battle/ability/sticky_hold.c +++ b/test/battle/ability/sticky_hold.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Sticky Hold prevents item theft") { GIVEN { - ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM)); + ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); PLAYER(SPECIES_URSALUNA) { Item(ITEM_NONE); } OPPONENT(SPECIES_GASTRODON) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_LIFE_ORB); } } WHEN { diff --git a/test/battle/hold_effect/air_balloon.c b/test/battle/hold_effect/air_balloon.c index 17872d89b8..ad0fb457a8 100644 --- a/test/battle/hold_effect/air_balloon.c +++ b/test/battle/hold_effect/air_balloon.c @@ -102,17 +102,14 @@ SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen with Magician") } } -SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen with Thief or Covet") +SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen by Thief") { - u32 move; - PARAMETRIZE { move = MOVE_THIEF; } - PARAMETRIZE { move = MOVE_COVET; } GIVEN { - ASSUME(MoveHasAdditionalEffect(move, MOVE_EFFECT_STEAL_ITEM) == TRUE); + ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); }; OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, move); } + TURN { MOVE(opponent, MOVE_THIEF); } } SCENE { MESSAGE("Wobbuffet floats in the air with its Air Balloon!"); MESSAGE("Wobbuffet's Air Balloon popped!"); diff --git a/test/battle/hold_effect/red_card.c b/test/battle/hold_effect/red_card.c index f71ba51330..a21318d246 100644 --- a/test/battle/hold_effect/red_card.c +++ b/test/battle/hold_effect/red_card.c @@ -170,7 +170,7 @@ SINGLE_BATTLE_TEST("Red Card does not activate if stolen by a move") bool32 activate; PARAMETRIZE { item = ITEM_NONE; activate = FALSE; } PARAMETRIZE { item = ITEM_POTION; activate = TRUE; } - ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE); + ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); GIVEN { PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } diff --git a/test/battle/hold_effect/restore_stats.c b/test/battle/hold_effect/restore_stats.c index 7f48a05f13..f2508c45ee 100644 --- a/test/battle/hold_effect/restore_stats.c +++ b/test/battle/hold_effect/restore_stats.c @@ -132,23 +132,22 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off o PARAMETRIZE { move = MOVE_KNOCK_OFF; } GIVEN { - ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE); ASSUME(GetMoveEffect(MOVE_KNOCK_OFF) == EFFECT_KNOCK_OFF); + ASSUME(GetMoveEffect(MOVE_THIEF) == EFFECT_STEAL_ITEM); PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, opponent); - if (move == MOVE_THIEF) { - MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!"); - } ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Slugma's Weak Armor lowered its Defense!"); MESSAGE("Slugma's Weak Armor raised its Speed!"); if (move == MOVE_KNOCK_OFF) { MESSAGE("The opposing Wobbuffet knocked off Slugma's White Herb!"); + } else if (move == MOVE_THIEF) { + MESSAGE("The opposing Wobbuffet stole Slugma's White Herb!"); } NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); diff --git a/test/battle/move_effect_secondary/spikes.c b/test/battle/move_effect/ceaseless_edge.c similarity index 76% rename from test/battle/move_effect_secondary/spikes.c rename to test/battle/move_effect/ceaseless_edge.c index 1aa2630fd7..5a7e7f4a1a 100644 --- a/test/battle/move_effect_secondary/spikes.c +++ b/test/battle/move_effect/ceaseless_edge.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(MoveHasAdditionalEffect(MOVE_CEASELESS_EDGE, MOVE_EFFECT_SPIKES) == TRUE); + ASSUME(GetMoveEffect(MOVE_CEASELESS_EDGE) == EFFECT_CEASELESS_EDGE); } SINGLE_BATTLE_TEST("Ceaseless Edge sets up hazards after hitting the target") @@ -62,3 +62,19 @@ SINGLE_BATTLE_TEST("Ceaseless Edge can set up to 3 layers of Spikes") MESSAGE("The opposing Wynaut was hurt by the spikes!"); } } + +SINGLE_BATTLE_TEST("Ceaseless Edge fails to set up hazards if user faints") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); } + } WHEN { + TURN { MOVE(player, MOVE_CEASELESS_EDGE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CEASELESS_EDGE, player); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!"); + NOT MESSAGE("Spikes were scattered on the ground all around the opposing team!"); + } +} diff --git a/test/battle/move_effect/hit_switch_target.c b/test/battle/move_effect/hit_switch_target.c index e0d6548ec3..82f15bf30f 100644 --- a/test/battle/move_effect/hit_switch_target.c +++ b/test/battle/move_effect/hit_switch_target.c @@ -43,7 +43,7 @@ DOUBLE_BATTLE_TEST("Dragon Tail switches the target with a random non-battler, n } } -SINGLE_BATTLE_TEST("Dragon Tail does not fail if no replacements") +SINGLE_BATTLE_TEST("Dragon Tail fails if no replacements") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Dragon Tail does not fail if no replacements") } } -SINGLE_BATTLE_TEST("Dragon Tail does not fail if replacements fainted") +SINGLE_BATTLE_TEST("Dragon Tail fails if replacements fainted") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/ice_spinner.c b/test/battle/move_effect/ice_spinner.c index 44ce21eb4f..c04f16b880 100644 --- a/test/battle/move_effect/ice_spinner.c +++ b/test/battle/move_effect/ice_spinner.c @@ -96,7 +96,10 @@ SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field TURN { MOVE(player, MOVE_ICE_SPINNER); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player); - NOT MESSAGE("But it failed!"); + NONE_OF { + MESSAGE("But it failed!"); + MESSAGE("Mist swirled around the battlefield!"); + } } } diff --git a/test/battle/move_effect/knock_off.c b/test/battle/move_effect/knock_off.c index 626e0cde28..60be862c4c 100644 --- a/test/battle/move_effect/knock_off.c +++ b/test/battle/move_effect/knock_off.c @@ -99,6 +99,22 @@ SINGLE_BATTLE_TEST("Knock Off does not remove items through Substitute") } } +SINGLE_BATTLE_TEST("Knock Off does not remove items through Substitute even if it breaks it") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(4); HP(4); Item(ITEM_LEFTOVERS); }; + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); + MESSAGE("The opposing Wobbuffet's substitute faded!"); + NOT { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_KNOCKOFF); } + } THEN { + EXPECT(opponent->item == ITEM_LEFTOVERS); + } +} + SINGLE_BATTLE_TEST("Knock Off does not remove items through Protect") { GIVEN { @@ -229,18 +245,6 @@ DOUBLE_BATTLE_TEST("Knock Off does not trigger the opposing ally's Symbiosis") } } -SINGLE_BATTLE_TEST("Knock Off doesn't knock off items from Pokemon behind substitutes") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_POKE_BALL); } - } WHEN { - TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_KNOCK_OFF); } - } SCENE { - NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Poké Ball!"); - } -} - SINGLE_BATTLE_TEST("Knock Off does knock off Mega Stones from Pokemon that don't actually use them") { GIVEN { @@ -360,3 +364,33 @@ SINGLE_BATTLE_TEST("Knock Off doesn't knock off begin-battle form-change hold it NOT MESSAGE("Wobbuffet knocked off the opposing Zamazenta's Rusted Shield!"); } } + +SINGLE_BATTLE_TEST("Knock Off does not activate if user faints") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!"); + MESSAGE("Wobbuffet fainted!"); + } THEN { + EXPECT(opponent->item == ITEM_ROCKY_HELMET); + } +} + +SINGLE_BATTLE_TEST("Knock Off doesn't remove item if it's prevented by Sticky Hold") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_MUK) { MaxHP(100); HP(51); Item(ITEM_ORAN_BERRY); Ability(ABILITY_STICKY_HOLD); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_STICKY_HOLD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} diff --git a/test/battle/move_effect/stone_axe.c b/test/battle/move_effect/stone_axe.c new file mode 100644 index 0000000000..d65798d18b --- /dev/null +++ b/test/battle/move_effect/stone_axe.c @@ -0,0 +1,94 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_STONE_AXE) == EFFECT_STONE_AXE); +} + +SINGLE_BATTLE_TEST("Stone Axe sets up hazards after hitting the target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STONE_AXE); } + TURN { SWITCH(opponent, 1); } + } SCENE { + s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(opponent); + MESSAGE("Pointed stones float in the air around the opposing team!"); + MESSAGE("2 sent out Wobbuffet!"); + HP_BAR(opponent, damage: maxHP / 8); + MESSAGE("Pointed stones dug into the opposing Wobbuffet!"); + } +} + +SINGLE_BATTLE_TEST("Stone Axe can set up pointed stones only once") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_STONE_AXE); } + TURN { MOVE(player, MOVE_STONE_AXE); } + TURN { MOVE(player, MOVE_STONE_AXE); } + TURN { MOVE(player, MOVE_STONE_AXE); } + TURN { SWITCH(opponent, 1); } + } SCENE { + s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(opponent); + MESSAGE("Pointed stones float in the air around the opposing team!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(opponent); + NOT MESSAGE("Pointed stones float in the air around the opposing team!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(opponent); + NOT MESSAGE("Pointed stones float in the air around the opposing team!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(opponent); + NOT MESSAGE("Pointed stones float in the air around the opposing team!"); + + MESSAGE("2 sent out Wynaut!"); + HP_BAR(opponent, damage: maxHP / 8); + MESSAGE("Pointed stones dug into the opposing Wynaut!"); + } +} + +SINGLE_BATTLE_TEST("Stone Axe sets up hazards after any ability activation") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SKARMORY) { Ability(ABILITY_WEAK_ARMOR); } + } WHEN { + TURN { MOVE(player, MOVE_STONE_AXE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + ABILITY_POPUP(opponent, ABILITY_WEAK_ARMOR); + MESSAGE("Pointed stones float in the air around the opposing team!"); + } +} + +SINGLE_BATTLE_TEST("Stone Axe fails to set up hazards if user faints") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); } + } WHEN { + TURN { MOVE(player, MOVE_STONE_AXE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the opposing Wobbuffet's Rocky Helmet!"); + NOT MESSAGE("Pointed stones float in the air around the opposing team!"); + } +} diff --git a/test/battle/move_effect_secondary/pay_day.c b/test/battle/move_effect_secondary/pay_day.c index 3b0544a909..fc77e862e2 100644 --- a/test/battle/move_effect_secondary/pay_day.c +++ b/test/battle/move_effect_secondary/pay_day.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(MoveHasAdditionalEffect(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY)); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_PAY_DAY, MOVE_EFFECT_PAYDAY, 0) == TRUE); } SINGLE_BATTLE_TEST("Pay Day Scatters coins around after it hits - singles") diff --git a/test/battle/move_effect_secondary/steal_item.c b/test/battle/move_effect_secondary/steal_item.c index 8a4ae931d2..7dd922e8b2 100644 --- a/test/battle/move_effect_secondary/steal_item.c +++ b/test/battle/move_effect_secondary/steal_item.c @@ -3,8 +3,8 @@ ASSUMPTIONS { - ASSUME(MoveHasAdditionalEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE); - ASSUME(MoveHasAdditionalEffect(MOVE_COVET, MOVE_EFFECT_STEAL_ITEM) == TRUE); + ASSUME(GetMoveEffect(MOVE_THIEF == EFFECT_STEAL_ITEM)); + ASSUME(GetMoveEffect(MOVE_COVET == EFFECT_STEAL_ITEM)); } SINGLE_BATTLE_TEST("Thief and Covet steal target's held item") @@ -127,3 +127,41 @@ WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag EXPECT_EQ(opponent->item, ITEM_NONE); } } + +SINGLE_BATTLE_TEST("Thief and Covet can't steal target's held item if user faints before") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); }; + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROCKY_HELMET); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } THEN { + EXPECT_EQ(player->item, ITEM_NONE); + EXPECT_EQ(opponent->item, ITEM_ROCKY_HELMET); + } +} + +SINGLE_BATTLE_TEST("Thief and Covet: Berry activation happens before the item can be stolen") +{ + u32 move; + PARAMETRIZE { move = MOVE_THIEF; } + PARAMETRIZE { move = MOVE_COVET; } + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(200); HP(101); Item(ITEM_ORAN_BERRY); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ITEM_STEAL, opponent); + } +} diff --git a/test/battle/move_effect_secondary/stealth_rock.c b/test/battle/move_effect_secondary/stealth_rock.c index e9101b6591..026db13e7a 100644 --- a/test/battle/move_effect_secondary/stealth_rock.c +++ b/test/battle/move_effect_secondary/stealth_rock.c @@ -3,63 +3,19 @@ ASSUMPTIONS { - ASSUME(MoveHasAdditionalEffect(MOVE_STONE_AXE, MOVE_EFFECT_STEALTH_ROCK) == TRUE); + ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STONESURGE, MOVE_EFFECT_STEALTH_ROCK)); } -SINGLE_BATTLE_TEST("Stone Axe sets up hazards after hitting the target") +SINGLE_BATTLE_TEST("Steath Rock: Rock from G-Max Stonesurge are set up before any ability activation") { GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_DREDNAW) { GigantamaxFactor(TRUE); } + OPPONENT(SPECIES_SKARMORY) { Ability(ABILITY_WEAK_ARMOR); } } WHEN { - TURN { MOVE(player, MOVE_STONE_AXE); } - TURN { SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_WATERFALL, gimmick: GIMMICK_DYNAMAX); } } SCENE { - s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP); - ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); - HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_G_MAX_STONESURGE, player); MESSAGE("Pointed stones float in the air around the opposing team!"); - MESSAGE("2 sent out Wobbuffet!"); - HP_BAR(opponent, damage: maxHP / 8); - MESSAGE("Pointed stones dug into the opposing Wobbuffet!"); + ABILITY_POPUP(opponent, ABILITY_WEAK_ARMOR); } } - -SINGLE_BATTLE_TEST("Stone Axe can set up pointed stones only once") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WYNAUT); - } WHEN { - TURN { MOVE(player, MOVE_STONE_AXE); } - TURN { MOVE(player, MOVE_STONE_AXE); } - TURN { MOVE(player, MOVE_STONE_AXE); } - TURN { MOVE(player, MOVE_STONE_AXE); } - TURN { SWITCH(opponent, 1); } - } SCENE { - s32 maxHP = GetMonData(&OPPONENT_PARTY[1], MON_DATA_MAX_HP); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); - HP_BAR(opponent); - MESSAGE("Pointed stones float in the air around the opposing team!"); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); - HP_BAR(opponent); - NOT MESSAGE("Pointed stones float in the air around the opposing team!"); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); - HP_BAR(opponent); - NOT MESSAGE("Pointed stones float in the air around the opposing team!"); - - ANIMATION(ANIM_TYPE_MOVE, MOVE_STONE_AXE, player); - HP_BAR(opponent); - NOT MESSAGE("Pointed stones float in the air around the opposing team!"); - - MESSAGE("2 sent out Wynaut!"); - HP_BAR(opponent, damage: maxHP / 8); - MESSAGE("Pointed stones dug into the opposing Wynaut!"); - } -} - diff --git a/test/battle/move_effects_combined/make_it_rain.c b/test/battle/move_effects_combined/make_it_rain.c index e0e00015a4..655a34f8be 100644 --- a/test/battle/move_effects_combined/make_it_rain.c +++ b/test/battle/move_effects_combined/make_it_rain.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(MoveHasAdditionalEffect(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_PAYDAY)); + ASSUME(MoveHasAdditionalEffectWithChance(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_PAYDAY, 0) == TRUE); ASSUME(MoveHasAdditionalEffectSelf(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_SP_ATK_MINUS_1)); } From 674d46bb0f18462e19eaaf72782d4ab25f9d7c7f Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Tue, 15 Jul 2025 15:37:23 +0200 Subject: [PATCH 102/283] Fixes incorrect recoil damage after a berry was eaten --- src/battle_script_commands.c | 2 +- test/battle/move_flags/recoil.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cb746ebc99..8abed761e7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6380,7 +6380,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) case EFFECT_RECOIL: if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) { - gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleStruct->moveDamage[gBattlerTarget] * max(1, GetMoveRecoil(gCurrentMove)) / 100); + gBattleStruct->moveDamage[gBattlerAttacker] = max(1, gBattleScripting.savedDmg * max(1, GetMoveRecoil(gCurrentMove)) / 100); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; effect = TRUE; diff --git a/test/battle/move_flags/recoil.c b/test/battle/move_flags/recoil.c index 42b8b1a76b..c2b2e21b86 100644 --- a/test/battle/move_flags/recoil.c +++ b/test/battle/move_flags/recoil.c @@ -102,3 +102,23 @@ SINGLE_BATTLE_TEST("Recoil: Flare Blitz is absorbed by Flash Fire and no recoil } } } + +SINGLE_BATTLE_TEST("Recoil: The correct amount of recoil damage is dealt after targets recovery berry proc") +{ + s16 directDamage; + s16 recoilDamage; + + GIVEN { + ASSUME(GetMoveRecoil(MOVE_TAKE_DOWN) == 25); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); }; + } WHEN { + TURN { MOVE(player, MOVE_TAKE_DOWN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAKE_DOWN, player); + HP_BAR(opponent, captureDamage: &directDamage); + HP_BAR(player, captureDamage: &recoilDamage); + } THEN { + EXPECT_MUL_EQ(directDamage, UQ_4_12(0.25), recoilDamage); + } +} From d5c1d3322cc2712f2e7c21e45f43f931c100a364 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 15 Jul 2025 17:52:44 +0200 Subject: [PATCH 103/283] Fixes Status overwrites and Effect Spore wrong func args (#7340) --- include/battle.h | 3 ++- src/battle_script_commands.c | 6 +++-- src/battle_util.c | 30 ++++++++++++++-------- test/battle/ability/effect_spore.c | 19 ++++++++++++++ test/battle/move_effect/protect.c | 40 ++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 14 deletions(-) diff --git a/include/battle.h b/include/battle.h index b537f779af..17da0add57 100644 --- a/include/battle.h +++ b/include/battle.h @@ -658,7 +658,8 @@ struct BattleStruct u8 anyMonHasTransformed:1; // Only used in battle_tv.c u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; - u8 padding1:2; + u8 sleepClauseNotBlocked:1; + u8 padding1:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 26144cecd1..533c25171f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5864,7 +5864,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BANEFUL_BUNKER: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_POISON; @@ -5874,7 +5875,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BURNING_BULWARK: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) { gEffectBattler = gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; diff --git a/src/battle_util.c b/src/battle_util.c index 82a139cb26..da9dae3113 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4624,9 +4624,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_EFFECT_SPORE: { - u32 ability = GetBattlerAbility(gBattlerAttacker); + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if ((!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) || B_POWDER_GRASS < GEN_6) - && ability != ABILITY_OVERCOAT + && abilityAtk != ABILITY_OVERCOAT && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { u32 poison, paralysis, sleep; @@ -4653,7 +4653,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) + && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { if (IsSleepClauseEnabled()) @@ -4672,11 +4672,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_POISON_POINT, 30) : RandomChance(RNG_POISON_POINT, 1, 3)) { POISON_POINT: + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker)) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, abilityAtk) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -4691,11 +4692,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_STATIC, 30) : RandomChance(RNG_STATIC, 1, 3)) { STATIC: + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, abilityAtk) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { gEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerTarget; @@ -5498,9 +5500,13 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause) { - if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause) + if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE) return FALSE; + if (isBlockedBySleepClause == NOT_BLOCKED_BY_SLEEP_CLAUSE) + gBattleStruct->sleepClauseNotBlocked = TRUE; + + bool32 effect = FALSE; if (CanSetNonVolatileStatus( battlerAtk, battlerDef, @@ -5508,8 +5514,10 @@ bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClau abilityDef, MOVE_EFFECT_SLEEP, // also covers yawn CHECK_TRIGGER)) - return TRUE; - return FALSE; + effect = TRUE; + + gBattleStruct->sleepClauseNotBlocked = FALSE; + return effect; } bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) @@ -5665,7 +5673,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_CantMakeAsleep; } - else if (CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) + else if (!gBattleStruct->sleepClauseNotBlocked && CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) { battleScript = BattleScript_SleepClauseBlocked; } diff --git a/test/battle/ability/effect_spore.c b/test/battle/ability/effect_spore.c index 57f5399b53..912c311ca7 100644 --- a/test/battle/ability/effect_spore.c +++ b/test/battle/ability/effect_spore.c @@ -88,3 +88,22 @@ SINGLE_BATTLE_TEST("Effect Spore causes sleep 11% of the time") STATUS_ICON(player, sleep: TRUE); } } + +SINGLE_BATTLE_TEST("Effect Spore will check if it can inflict status onto attacker, not itself") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Status1(STATUS1_BURN); Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + } +} diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 75efb2faa6..111cb3ca42 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -194,6 +194,26 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making con } } +SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_NUZZLE); } + TURN { MOVE(opponent, MOVE_BANEFUL_BUNKER); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BANEFUL_BUNKER, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_POISON); + } + } +} + SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making contact") { u16 usedMove = MOVE_NONE; @@ -226,6 +246,26 @@ SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making cont } } +SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_NUZZLE); } + TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NUZZLE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURNING_BULWARK, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_BURN); + } + } +} + SINGLE_BATTLE_TEST("Protect: Recoil damage is not applied if target was protected") { u32 j, k; From 0e37bfd7ff1ecd97bbaa29ae0174051487a4bee9 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:07:26 -0400 Subject: [PATCH 104/283] Fix stat change / stat ID ambiguity (#7346) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_util.c | 42 +++++++++++++++++++++++++++++++++++------- test/battle/ai/ai.c | 13 +++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2d7136eefc..7b5e8e0d37 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -4141,13 +4141,41 @@ bool32 IsRecycleEncouragedItem(u32 item) return FALSE; } -static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statId, bool32 considerContrary) +static u32 GetStatBeingChanged(enum StatChange statChange) +{ + switch(statChange) + { + case STAT_CHANGE_ATK: + case STAT_CHANGE_ATK_2: + return STAT_ATK; + case STAT_CHANGE_DEF: + case STAT_CHANGE_DEF_2: + return STAT_DEF; + case STAT_CHANGE_SPEED: + case STAT_CHANGE_SPEED_2: + return STAT_SPEED; + case STAT_CHANGE_SPATK: + case STAT_CHANGE_SPATK_2: + return STAT_SPATK; + case STAT_CHANGE_SPDEF: + case STAT_CHANGE_SPDEF_2: + return STAT_SPDEF; + case STAT_CHANGE_ACC: + return STAT_ACC; + case STAT_CHANGE_EVASION: + return STAT_EVASION; + } + return 0; // STAT_HP, should never be getting changed +} + +static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statChange, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk); u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE); u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; + u32 statId = GetStatBeingChanged(statChange); if (considerContrary && gAiLogicData->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; @@ -4206,7 +4234,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, tempScore += WEAK_EFFECT; } - switch (statId) + switch (statChange) { case STAT_CHANGE_ATK: if (HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL) && shouldSetUp) @@ -4269,7 +4297,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, } break; case STAT_CHANGE_ACC: - if (gBattleMons[battlerAtk].statStages[STAT_ACC] <= 3) // Increase only if necessary + if (gBattleMons[battlerAtk].statStages[statId] <= 3) // Increase only if necessary tempScore += DECENT_EFFECT; break; case STAT_CHANGE_EVASION: @@ -4283,14 +4311,14 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, return tempScore; } -u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statId) +u32 IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, enum StatChange statChange) { - return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, TRUE); + return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, TRUE); } -u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statId) +u32 IncreaseStatUpScoreContrary(u32 battlerAtk, u32 battlerDef, enum StatChange statChange) { - return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statId, FALSE); + return IncreaseStatUpScoreInternal(battlerAtk, battlerDef, statChange, FALSE); } void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 3fe975fc66..62eae623bc 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -881,3 +881,16 @@ AI_SINGLE_BATTLE_TEST("Move scoring comparison properly awards bonus point to be TURN { EXPECT_MOVE(opponent, MOVE_WATER_SPOUT); } } } + +AI_SINGLE_BATTLE_TEST("AI will stop setting up at +4") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE, MOVE_IRON_DEFENSE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_IRON_DEFENSE); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_IRON_DEFENSE); } + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_TACKLE); } + } +} From 64f9d6a24ecd8e47b6707ff495769e9745ee2ba3 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 15 Jul 2025 13:13:30 -0400 Subject: [PATCH 105/283] Fix AI resisted move scoring (#7350) --- src/battle_ai_main.c | 23 ----------------------- test/battle/ai/ai.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2b6094c925..95c94eb455 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1118,30 +1118,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } if (effectiveness == UQ_4_12(0.0)) - { RETURN_SCORE_MINUS(20); - } - else if (effectiveness < UQ_4_12(0.5)) - { - switch (moveEffect) - { - case EFFECT_FIXED_HP_DAMAGE: - case EFFECT_LEVEL_DAMAGE: - case EFFECT_PSYWAVE: - case EFFECT_OHKO: - case EFFECT_SHEER_COLD: - case EFFECT_BIDE: - case EFFECT_FIXED_PERCENT_DAMAGE: - case EFFECT_ENDEAVOR: - case EFFECT_COUNTER: - case EFFECT_MIRROR_COAT: - case EFFECT_METAL_BURST: - case EFFECT_FINAL_GAMBIT: - break; - default: - RETURN_SCORE_MINUS(10); - } - } if (DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)) abilityDef = ABILITY_NONE; diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index d9d0782b0d..7eb06dd5d4 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -912,3 +912,14 @@ AI_SINGLE_BATTLE_TEST("AI will see Magnitude damage") TURN { MOVE(player, MOVE_MAGNITUDE); EXPECT_SWITCH(opponent, 1); } } } + +AI_SINGLE_BATTLE_TEST("AI will prefer resisted move over failing move") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_ROSELIA) { Moves(MOVE_ABSORB); }; + OPPONENT(SPECIES_GLOOM) { Moves(MOVE_MEGA_DRAIN, MOVE_STUN_SPORE, MOVE_LEECH_SEED, MOVE_SYNTHESIS); } + } WHEN { + TURN { MOVE(player, MOVE_ABSORB); EXPECT_MOVE(opponent, MOVE_MEGA_DRAIN);} + } +} From da3d223c45c73e5f7216eb75f1a441258be6ad64 Mon Sep 17 00:00:00 2001 From: AERDU Date: Wed, 16 Jul 2025 10:41:32 +0000 Subject: [PATCH 106/283] fallback bugfix for B_DARK_VOID_FAIL < GEN_7 (#7351) --- data/battle_scripts_1.s | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a4d3264d13..d694e47467 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2856,12 +2856,6 @@ BattleScript_MoveMissed:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_EffectDarkVoid:: -.if B_DARK_VOID_FAIL >= GEN_7 - jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus - goto BattleScript_PokemonCantUseTheMove -.endif - BattleScript_TerrainPreventsEnd2:: pause B_WAIT_TIME_SHORT printfromtable gTerrainPreventsStringIds @@ -4683,6 +4677,11 @@ BattleScript_FlatterTryConfuse:: seteffectprimary MOVE_EFFECT_CONFUSION goto BattleScript_MoveEnd +BattleScript_EffectDarkVoid:: +.if B_DARK_VOID_FAIL >= GEN_7 + jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus + goto BattleScript_PokemonCantUseTheMove +.endif BattleScript_EffectNonVolatileStatus:: attackcanceler attackstring From 67d007f4fb811b2e72a773fb282213b4dddd2741 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:29:25 +0100 Subject: [PATCH 107/283] Fixes Grassy Terrain healing when Heal Blocked/Semi-Invulnerable (#7353) --- src/battle_end_turn.c | 8 +++++++- src/battle_message.c | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 6cf45ded4d..efc790aadd 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -490,10 +490,16 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL: - if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && IsBattlerGrounded(battler)) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN + && IsBattlerAlive(battler) + && !IsBattlerAtMaxHp(battler) + && !(gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK)) + && IsBattlerGrounded(battler)) { gBattlerAttacker = battler; gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16); + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = -1; BattleScriptExecute(BattleScript_GrassyTerrainHeals); effect = TRUE; } diff --git a/src/battle_message.c b/src/battle_message.c index 350cddd374..ab1ec0659f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1205,7 +1205,8 @@ const u16 gGotBurnedStringIds[] = const u16 gGotFrostbiteStringIds[] = { - [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE + [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE, + [B_MSG_STATUSED_BY_ABILITY] = STRINGID_PKMNGOTFROSTBITE, }; const u16 gFrostbiteHealedStringIds[] = From 19c9aa508d91338ab298a7363c066895e060a5dc Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:31:06 +0100 Subject: [PATCH 108/283] Fixes shadows and mon animations for Illusioned battlers (#7347) --- src/battle_controllers.c | 10 ++++------ src/battle_gfx_sfx_util.c | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index d189c67215..dfd7138bcb 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -2172,9 +2172,7 @@ void StartSendOutAnim(u32 battler, bool32 dontClearTransform, bool32 dontClearSu ClearTemporarySpeciesSpriteData(battler, dontClearTransform, dontClearSubstituteBit); gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1]; - species = GetIllusionMonSpecies(battler); - if (species == SPECIES_NONE) - species = GetMonData(mon, MON_DATA_SPECIES); + species = GetBattlerVisualSpecies(battler); gBattleControllerData[battler] = CreateInvisibleSpriteWithCallback(SpriteCB_WaitForBattlerBallReleaseAnim); // Load sprite for opponent only, player sprite is expected to be already loaded. if (!IsOnPlayerSide(battler)) @@ -2490,7 +2488,7 @@ void BtlController_HandleSetRawMonData(u32 battler) void BtlController_HandleLoadMonSprite(u32 battler, void (*controllerCallback)(u32 battler)) { struct Pokemon *mon = GetBattlerMon(battler); - u16 species = GetMonData(mon, MON_DATA_SPECIES); + u16 species = GetBattlerVisualSpecies(battler); BattleLoadMonSpriteGfx(mon, battler); SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battler)); @@ -3153,7 +3151,7 @@ void TrySetBattlerShadowSpriteCallback(u32 battler) if (gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary].callback == SpriteCallbackDummy && (B_ENEMY_MON_SHADOW_STYLE <= GEN_3 || P_GBA_STYLE_SPECIES_GFX == TRUE || gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdSecondary].callback == SpriteCallbackDummy)) - SetBattlerShadowSpriteCallback(battler, GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)); + SetBattlerShadowSpriteCallback(battler, GetBattlerVisualSpecies(battler)); } bool32 TryShinyAnimAfterMonAnimUtil(u32 battler) @@ -3256,7 +3254,7 @@ bool32 SwitchIn_TryShinyAnimUtil(u32 battler) DestroySprite(&gSprites[gBattleControllerData[battler]]); if (GetBattlerSide(battler) == B_SIDE_OPPONENT) - SetBattlerShadowSpriteCallback(battler, GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)); + SetBattlerShadowSpriteCallback(battler, GetBattlerVisualSpecies(battler)); return TRUE; } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 3d8d2f48be..9b272a51b4 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -1168,7 +1168,7 @@ void CreateEnemyShadowSprite(u32 battler) { if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) { - u16 species = SanitizeSpeciesId(gBattleMons[battler].species); + u16 species = GetBattlerVisualSpecies(battler); u8 size = gSpeciesInfo[species].enemyShadowSize; gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow, @@ -1282,7 +1282,7 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite) } else if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) { - u16 species = SanitizeSpeciesId(gBattleMons[battler].species); + u16 species = GetBattlerVisualSpecies(battler); xOffset = gSpeciesInfo[species].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16); yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16; size = gSpeciesInfo[species].enemyShadowSize; From 0406caa687b03c2bf70acfaf7f36459f0b17dcf8 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:05:08 -0400 Subject: [PATCH 109/283] Improve AI's setup logic (#7345) --- src/battle_ai_util.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ test/battle/ai/ai.c | 22 +++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 625ea3a9e1..b9e90ee4fd 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1443,6 +1443,26 @@ bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits) return FALSE; } +// Can battler KO the target ignoring any Endure effects (Sturdy, Focus Sash, etc.) +bool32 CanBattlerKOTargetIgnoringSturdy(u32 battlerAtk, u32 battlerDef) +{ + struct AiLogicData *aiData = gAiLogicData; + s32 moveIndex, dmg; + u16 *moves = GetMovesArray(battlerAtk); + u32 moveLimitations = aiData->moveLimitations[battlerAtk]; + + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (IsMoveUnusable(moveIndex, moves[moveIndex], moveLimitations)) + continue; + dmg = AI_GetDamage(battlerAtk, battlerDef, moveIndex, AI_ATTACKING, aiData); + + if (gBattleMons[battlerDef].hp <= dmg && CanEndureHit(battlerAtk, battlerDef, moves[moveIndex])) + return TRUE; + } + return FALSE; +} + bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits) { u32 indexSlot = GetMoveSlot(GetMovesArray(battlerDef), move); @@ -4220,6 +4240,35 @@ bool32 IsRecycleEncouragedItem(u32 item) return FALSE; } +bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiIsFaster) +{ + s32 i; + u16 *moves = GetMovesArray(battlerId); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == MOVE_NONE || moves[i] == MOVE_UNAVAILABLE) + continue; + if (noOfHitsToFaint <= 2) + { + if (GetMovePriority(moves[i]) > 0) + return TRUE; + + switch (gMovesInfo[moves[i]].additionalEffects[i].moveEffect) + { + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + { + if(aiIsFaster) + return TRUE; + } + } + } + } + + return FALSE; +} + static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statId, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; @@ -4268,6 +4317,14 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, || HasBattlerSideMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_HAZE))) return NO_INCREASE; + // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs + if (CanBattlerKOTargetIgnoringSturdy(battlerAtk, battlerDef)) + return NO_INCREASE; + + // Don't increase stats if player has a move that can change the KO threshold + if (HasMoveThatChangesKOThreshold(battlerDef, noOfHitsToFaint, aiIsFaster)) + return NO_INCREASE; + // Predicting switch if (IsBattlerPredictedToSwitch(battlerDef)) { diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 7eb06dd5d4..5202afe606 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -923,3 +923,25 @@ AI_SINGLE_BATTLE_TEST("AI will prefer resisted move over failing move") TURN { MOVE(player, MOVE_ABSORB); EXPECT_MOVE(opponent, MOVE_MEGA_DRAIN);} } } + +AI_SINGLE_BATTLE_TEST("AI won't setup if it can KO through Sturdy effect") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_SKARMORY) { Ability(ABILITY_STURDY); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_MOLTRES) { Moves(MOVE_FIRE_BLAST, MOVE_AGILITY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_FIRE_BLAST); } + } +} + +AI_SINGLE_BATTLE_TEST("AI won't setup if otherwise good scenario is changed by the presence of priority") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_FLOATZEL) { Speed(2); Moves(MOVE_AQUA_JET, MOVE_SURF); } + OPPONENT(SPECIES_DONPHAN) { Speed(5); Moves(MOVE_BULK_UP, MOVE_EARTHQUAKE); } + } WHEN { + TURN { MOVE(player, MOVE_SURF); EXPECT_MOVE(opponent, MOVE_EARTHQUAKE); } + } +} From 65a63fb9f0845775e4d368817297b96ff7415cd3 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:30:51 -0400 Subject: [PATCH 110/283] Improve AI's ShouldRecover (#7342) --- include/battle_ai_util.h | 4 +-- include/config/ai.h | 2 ++ include/random.h | 1 + src/battle_ai_main.c | 27 ++++++++++++------ src/battle_ai_util.c | 61 +++++++++++++++++++++++++++++++--------- test/battle/ai/ai.c | 39 +++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 23 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index f4bd20d3d8..d4a66f2028 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -93,7 +93,7 @@ bool32 AI_CanBattlerEscape(u32 battler); bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef); s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk); -u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk); +u32 NoOfHitsForTargetToFaintBattler(u32 battlerDef, u32 battlerAtk); u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); u32 GetBestDmgFromBattler(u32 battler, u32 battlerTarget, enum DamageCalcContext calcContext); bool32 CanTargetMoveFaintAi(u32 move, u32 battlerDef, u32 battlerAtk, u32 nHits); @@ -115,7 +115,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex); u32 GetBattlerSideSpeedAverage(u32 battler); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage); -bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent, enum DamageCalcContext calcContext); +bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect); enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 moveIndex); bool32 IsRecycleEncouragedItem(u32 item); diff --git a/include/config/ai.h b/include/config/ai.h index 44d2f3236d..ec359c646d 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -56,6 +56,8 @@ // AI move scoring #define STATUS_MOVE_FOCUS_PUNCH_CHANCE 50 // Chance the AI will use a status move if the player's best move is Focus Punch #define BOOST_INTO_HAZE_CHANCE 0 // Chance the AI will use a stat boosting move if the player has used Haze +#define SHOULD_RECOVER_CHANCE 50 // Chance the AI will give recovery moves score increase if less than ENABLE_RECOVERY_THRESHOLD and in no immediate danger +#define ENABLE_RECOVERY_THRESHOLD 60 // HP percentage beneath which SHOULD_RECOVER_CHANCE is active // AI damage calc considerations #define RISKY_AI_CRIT_STAGE_THRESHOLD 2 // Stat stages at which Risky will assume it gets a crit diff --git a/include/random.h b/include/random.h index 130fb32e69..65e48e1b86 100644 --- a/include/random.h +++ b/include/random.h @@ -200,6 +200,7 @@ enum RandomTag RNG_AI_PREDICT_MOVE, RNG_AI_STATUS_FOCUS_PUNCH, RNG_AI_BOOST_INTO_HAZE, + RNG_AI_SHOULD_RECOVER, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, RNG_AI_ASSUME_STATUS_SLEEP, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 95c94eb455..5586934eea 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3897,11 +3897,22 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_DREAM_EATER: - case EFFECT_STRENGTH_SAP: case EFFECT_AQUA_RING: if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) ADJUST_SCORE(DECENT_EFFECT); break; + case EFFECT_STRENGTH_SAP: + u32 atkStat = gBattleMons[battlerDef].attack; + u32 atkStage = gBattleMons[battlerDef].statStages[STAT_ATK]; + atkStat *= gStatStageRatios[atkStage][0]; + atkStat /= gStatStageRatios[atkStage][1]; + u32 healPercent = atkStat * 100 / gBattleMons[battlerAtk].maxHP; + if (ShouldRecover(battlerAtk, battlerDef, move, healPercent)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) + ADJUST_SCORE(WEAK_EFFECT); + } case EFFECT_EXPLOSION: case EFFECT_MISTY_EXPLOSION: case EFFECT_MEMENTO: @@ -4054,7 +4065,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; } - if (ShouldRecover(battlerAtk, battlerDef, move, healPercent, AI_DEFENDING)) + if (ShouldRecover(battlerAtk, battlerDef, move, healPercent)) ADJUST_SCORE(DECENT_EFFECT); } break; @@ -4064,7 +4075,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_MORNING_SUN: case EFFECT_SYNTHESIS: case EFFECT_MOONLIGHT: - if (ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING)) + if (ShouldRecover(battlerAtk, battlerDef, move, 50)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_LIGHT_SCREEN: @@ -4082,7 +4093,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { break; } - else if (ShouldRecover(battlerAtk, battlerDef, move, 100, AI_DEFENDING)) + else if (ShouldRecover(battlerAtk, battlerDef, move, 100)) { if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_SLP || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_STATUS @@ -5044,9 +5055,9 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SHORE_UP: - if ((AI_GetWeather() & B_WEATHER_SANDSTORM) && ShouldRecover(battlerAtk, battlerDef, move, 67, AI_DEFENDING)) + if ((AI_GetWeather() & B_WEATHER_SANDSTORM) && ShouldRecover(battlerAtk, battlerDef, move, 67)) ADJUST_SCORE(DECENT_EFFECT); - else if (ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING)) + else if (ShouldRecover(battlerAtk, battlerDef, move, 50)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_ENDEAVOR: @@ -5072,8 +5083,8 @@ case EFFECT_GUARD_SPLIT: //case EFFECT_SKY_DROP //break; case EFFECT_JUNGLE_HEALING: - if (ShouldRecover(battlerAtk, battlerDef, move, 25, AI_DEFENDING) - || ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25, AI_DEFENDING) + if (ShouldRecover(battlerAtk, battlerDef, move, 25) + || ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25) || gBattleMons[battlerAtk].status1 & STATUS1_ANY || gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) ADJUST_SCORE(GOOD_EFFECT); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b9e90ee4fd..ff81162d52 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1349,7 +1349,7 @@ bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk) return FALSE; } -u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk) +u32 NoOfHitsForTargetToFaintBattler(u32 battlerDef, u32 battlerAtk) { u32 i; u32 currNumberOfHits; @@ -1367,6 +1367,32 @@ u32 NoOfHitsForTargetToFaintAI(u32 battlerDef, u32 battlerAtk) return leastNumberOfHits; } +u32 NoOfHitsForTargetToFaintBattlerWithMod(u32 battlerDef, u32 battlerAtk, s32 hpMod) +{ + u32 i; + u32 currNumberOfHits; + u32 leastNumberOfHits = UNKNOWN_NO_OF_HITS; + u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod; + u32 damageDealt = 0; + + if (hpCheck > gBattleMons[battlerAtk].maxHP) + hpCheck = gBattleMons[battlerAtk].maxHP; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + damageDealt = AI_GetDamage(battlerDef, battlerAtk, i, AI_DEFENDING, gAiLogicData); + if (damageDealt == 0) + continue; + currNumberOfHits = hpCheck / (damageDealt + 1) + 1; + if (currNumberOfHits != 0) + { + if (currNumberOfHits < leastNumberOfHits) + leastNumberOfHits = currNumberOfHits; + } + } + return leastNumberOfHits; +} + u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) { struct AiLogicData *aiData = gAiLogicData; @@ -3710,21 +3736,30 @@ bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) return FALSE; } -bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent, enum DamageCalcContext calcContext) +bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent) { - if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move)) + u32 maxHP = gBattleMons[battlerAtk].maxHP; + u32 healAmount = (healPercent * maxHP) / 100; + if (healAmount > maxHP) + healAmount = maxHP; + if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + healAmount = 0; + if (AI_IsFaster(battlerAtk, battlerDef, move)) { - // using item or user going first - s32 damage = AI_GetDamage(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, calcContext, gAiLogicData); - s32 healAmount = (healPercent * damage) / 100; - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) - healAmount = 0; - if (CanTargetFaintAi(battlerDef, battlerAtk) && !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healAmount, 0)) return TRUE; // target can faint attacker unless they heal - else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < 60 && (Random() % 3)) - return TRUE; // target can't faint attacker at all, attacker health is about half, 2/3rds rate of encouraging healing + else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < ENABLE_RECOVERY_THRESHOLD && RandomPercentage(RNG_AI_SHOULD_RECOVER, SHOULD_RECOVER_CHANCE)) + return TRUE; // target can't faint attacker at all, generally safe + } + else + { + if (!CanTargetFaintAi(battlerDef, battlerAtk) + && GetBestDmgFromBattler(battlerDef, battlerAtk, AI_DEFENDING) < healAmount + && NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk) < NoOfHitsForTargetToFaintBattlerWithMod(battlerDef, battlerAtk, healAmount)) + return TRUE; // target can't faint attacker and is dealing less damage than we're healing + else if (!CanTargetFaintAi(battlerDef, battlerAtk) && gAiLogicData->hpPercents[battlerAtk] < ENABLE_RECOVERY_THRESHOLD && RandomPercentage(RNG_AI_SHOULD_RECOVER, SHOULD_RECOVER_CHANCE)) + return TRUE; // target can't faint attacker at all, generally safe } return FALSE; } @@ -3972,7 +4007,7 @@ bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) switch (GetMoveEffect(move)) { case EFFECT_WISH: - return ShouldRecover(battlerAtk, battlerDef, move, 50, AI_DEFENDING); // Switch recovery isn't good idea in doubles + return ShouldRecover(battlerAtk, battlerDef, move, 50); // Switch recovery isn't good idea in doubles case EFFECT_HEAL_BELL: if (hasStatus) return TRUE; @@ -4272,7 +4307,7 @@ bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiI static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, enum StatChange statId, bool32 considerContrary) { enum AIScore tempScore = NO_INCREASE; - u32 noOfHitsToFaint = NoOfHitsForTargetToFaintAI(battlerDef, battlerAtk); + u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk); u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE); u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 5202afe606..bd827fe5a8 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -945,3 +945,42 @@ AI_SINGLE_BATTLE_TEST("AI won't setup if otherwise good scenario is changed by t TURN { MOVE(player, MOVE_SURF); EXPECT_MOVE(opponent, MOVE_EARTHQUAKE); } } } + +AI_SINGLE_BATTLE_TEST("AI will use Recovery move if it outheals your damage and outspeeds") +{ + PASSES_RANDOMLY(100, 100, RNG_AI_SHOULD_RECOVER); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_LINOONE) { Speed(2); Moves(MOVE_HEADBUTT); } + OPPONENT(SPECIES_GASTRODON) { Speed(5); Moves(MOVE_SCALD, MOVE_RECOVER); HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_HEADBUTT); EXPECT_MOVE(opponent, MOVE_RECOVER); } + } +} + +AI_SINGLE_BATTLE_TEST("AI will use recovery move if it outheals your damage and is outsped") +{ + u32 aiMove = MOVE_NONE; + PASSES_RANDOMLY(100, 100, RNG_AI_SHOULD_RECOVER); + PARAMETRIZE{ aiMove = MOVE_RECOVER; } + PARAMETRIZE{ aiMove = MOVE_STRENGTH_SAP; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_LINOONE) { Speed(5); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_GASTRODON) { Speed(2); Moves(MOVE_SCALD, aiMove); HP(200); MaxHP(400); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, aiMove); } + } +} + +AI_SINGLE_BATTLE_TEST("AI will use recovery move if is in no immediate danger beneath an HP threshold") +{ + PASSES_RANDOMLY(SHOULD_RECOVER_CHANCE, 100, RNG_AI_SHOULD_RECOVER); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_LINOONE) { Speed(2); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_GASTRODON) { Speed(5); Moves(MOVE_SCALD, MOVE_RECOVER); HP(200); MaxHP(400); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_RECOVER); } + } +} From 705f194d985fec9b228f1a09bd631f2d2fff98de Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 18 Jul 2025 12:28:00 +0200 Subject: [PATCH 111/283] Fixes various battler corruption during switch in ability activation (#7352) --- charmap.txt | 4 +- data/battle_scripts_1.s | 82 ++++++++++++------------------------ include/battle_message.h | 4 +- include/battle_scripts.h | 8 ++-- src/battle_message.c | 16 +++---- src/battle_script_commands.c | 7 ++- src/battle_util.c | 37 ++++++++-------- 7 files changed, 70 insertions(+), 88 deletions(-) diff --git a/charmap.txt b/charmap.txt index 34fb683d0c..2750610dc9 100644 --- a/charmap.txt +++ b/charmap.txt @@ -424,8 +424,8 @@ B_TRAINER1_NAME_WITH_CLASS = FD 42 B_TRAINER2_NAME_WITH_CLASS = FD 43 B_PARTNER_NAME_WITH_CLASS = FD 44 B_ATK_TRAINER_NAME_WITH_CLASS = FD 45 -B_SCR_TEAM1 = FD 46 -B_SCR_TEAM2 = FD 47 +B_EFF_TEAM1 = FD 46 +B_EFF_TEAM2 = FD 47 @ indicates the end of a town/city name (before " TOWN" or " CITY") NAME_END = FC 00 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d694e47467..6d36b2b530 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6763,51 +6763,40 @@ BattleScript_UltraBurst:: end3 BattleScript_GulpMissileFormChange:: - call BattleScript_AttackerFormChange + call BattleScript_BattlerFormChange goto BattleScript_FromTwoTurnMovesSecondTurnRet -BattleScript_AttackerFormChange:: +BattleScript_BattlerFormChange:: pause 5 - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting flushtextbox -BattleScript_AttackerFormChangeNoPopup:: - handleformchange BS_ATTACKER, 0 - handleformchange BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE +BattleScript_BattlerFormChangeNoPopup: + handleformchange BS_SCRIPTING, 0 + handleformchange BS_SCRIPTING, 1 + playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - handleformchange BS_ATTACKER, 2 + handleformchange BS_SCRIPTING, 2 return -BattleScript_AttackerFormChangeEnd3:: - call BattleScript_AttackerFormChange +BattleScript_BattlerFormChangeEnd3:: + call BattleScript_BattlerFormChange end3 -BattleScript_AttackerFormChangeEnd3NoPopup:: - call BattleScript_AttackerFormChangeNoPopup +BattleScript_BattlerFormChangeEnd3NoPopup:: + call BattleScript_BattlerFormChangeNoPopup end3 -BattleScript_AttackerFormChangeWithString:: +BattleScript_BattlerFormChangeWithStringEnd3:: pause 5 - copybyte gBattlerAbility, gBattlerAttacker - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting flushtextbox -BattleScript_AttackerFormChangeWithStringNoPopup:: - handleformchange BS_ATTACKER, 0 - handleformchange BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE + handleformchange BS_SCRIPTING, 0 + handleformchange BS_SCRIPTING, 1 + playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - handleformchange BS_ATTACKER, 2 + handleformchange BS_SCRIPTING, 2 printstring STRINGID_PKMNTRANSFORMED waitmessage B_WAIT_TIME_LONG - return - -BattleScript_AttackerFormChangeWithStringEnd3:: - call BattleScript_AttackerFormChangeWithString - end3 - -BattleScript_AttackerFormChangeWithStringEnd3NoPopup:: - call BattleScript_AttackerFormChangeWithStringNoPopup end3 BattleScript_AttackerFormChangeMoveEffect:: @@ -6873,19 +6862,6 @@ BattleScript_TargetFormChangeWithStringNoPopup:: waitmessage B_WAIT_TIME_LONG return -BattleScript_BattlerFormChangeWithStringEnd3:: - pause 5 - call BattleScript_AbilityPopUpScripting - flushtextbox - handleformchange BS_SCRIPTING, 0 - handleformchange BS_SCRIPTING, 1 - playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE, NULL - waitanimation - handleformchange BS_SCRIPTING, 2 - printstring STRINGID_PKMNTRANSFORMED - waitmessage B_WAIT_TIME_LONG - end3 - BattleScript_IllusionOffAndTerastallization:: call BattleScript_IllusionOff goto BattleScript_Terastallization @@ -7620,11 +7596,7 @@ BattleScript_TryIntimidateHoldEffectsRet: BattleScript_IntimidateActivates:: savetarget -.if B_ABILITY_POP_UP == TRUE - showabilitypopup BS_ATTACKER - pause B_WAIT_TIME_LONG - destroyabilitypopup -.endif + call BattleScript_AbilityPopUp setbyte gBattlerTarget, 0 BattleScript_IntimidateLoop: jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_IntimidateLoopIncrement @@ -7655,6 +7627,7 @@ BattleScript_IntimidateLoopIncrement: copybyte sBATTLER, gBattlerAttacker destroyabilitypopup restoretarget + restoreattacker pause B_WAIT_TIME_MED tryintimidateejectpack end3 @@ -7689,11 +7662,7 @@ BattleScript_IntimidateInReverse:: BattleScript_SupersweetSyrupActivates:: savetarget -.if B_ABILITY_POP_UP == TRUE - showabilitypopup BS_ATTACKER - pause B_WAIT_TIME_LONG - destroyabilitypopup -.endif + call BattleScript_AbilityPopUp printstring STRINGID_SUPERSWEETAROMAWAFTS waitmessage B_WAIT_TIME_LONG setbyte gBattlerTarget, 0 @@ -7721,6 +7690,7 @@ BattleScript_SupersweetSyrupLoopIncrement: copybyte sBATTLER, gBattlerAttacker destroyabilitypopup restoretarget + restoreattacker pause B_WAIT_TIME_MED tryintimidateejectpack end3 @@ -7877,8 +7847,8 @@ BattleScript_HospitalityActivates:: printstring STRINGID_HOSPITALITYRESTORATION waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_TARGET - datahpupdate BS_TARGET + healthbarupdate BS_EFFECT_BATTLER + datahpupdate BS_EFFECT_BATTLER end3 BattleScript_AttackWeakenedByStrongWinds:: @@ -8345,6 +8315,7 @@ BattleScript_FellStingerRaisesAtkEnd: BattleScript_AttackerAbilityStatRaiseEnd3:: call BattleScript_AttackerAbilityStatRaise + restoreattacker end3 BattleScript_SwitchInAbilityMsg:: @@ -8395,6 +8366,8 @@ BattleScript_ImposterActivates:: waitanimation printstring STRINGID_IMPOSTERTRANSFORM waitmessage B_WAIT_TIME_LONG + restoreattacker + restoretarget end3 BattleScript_HurtAttacker: @@ -9495,6 +9468,7 @@ BattleScript_PastelVeilLoopIncrement: setallytonexttarget BattleScript_PastelVeil_TryCurePoison goto BattleScript_PastelVeilEnd BattleScript_PastelVeilEnd: + restoretarget end3 BattleScript_NeutralizingGasExits:: diff --git a/include/battle_message.h b/include/battle_message.h index e9b133b656..28be583551 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -84,8 +84,8 @@ #define B_TXT_TRAINER2_NAME_WITH_CLASS 0x43 #define B_TXT_PARTNER_NAME_WITH_CLASS 0x44 #define B_TXT_ATK_TRAINER_NAME_WITH_CLASS 0x45 -#define B_TXT_SCR_TEAM1 0x46 -#define B_TXT_SCR_TEAM2 0x47 +#define B_TXT_EFF_TEAM1 0x46 +#define B_TXT_EFF_TEAM2 0x47 #define B_BUFF_STRING 0 #define B_BUFF_NUMBER 1 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index cd88a120a5..372921e8e8 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -374,10 +374,10 @@ extern const u8 BattleScript_IllusionOffEnd3[]; extern const u8 BattleScript_IllusionOffAndTerastallization[]; extern const u8 BattleScript_DancerActivates[]; extern const u8 BattleScript_AftermathDmg[]; -extern const u8 BattleScript_AttackerFormChange[]; -extern const u8 BattleScript_AttackerFormChangeEnd3[]; +extern const u8 BattleScript_BattlerFormChange[]; +extern const u8 BattleScript_BattlerFormChangeEnd3[]; extern const u8 BattleScript_AttackerFormChangeWithString[]; -extern const u8 BattleScript_AttackerFormChangeWithStringEnd3[]; +extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[]; extern const u8 BattleScript_TargetFormChange[]; extern const u8 BattleScript_AnticipationActivates[]; extern const u8 BattleScript_SlowStartEnds[]; @@ -449,7 +449,7 @@ extern const u8 BattleScript_WanderingSpiritActivates[]; extern const u8 BattleScript_MirrorArmorReflect[]; extern const u8 BattleScript_GooeyActivates[]; extern const u8 BattleScript_PastelVeilActivates[]; -extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[]; +extern const u8 BattleScript_BattlerFormChangeEnd3NoPopup[]; extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[]; extern const u8 BattleScript_AttackerFormChangeMoveEffect[]; extern const u8 BattleScript_BothCanNoLongerEscape[]; diff --git a/src/battle_message.c b/src/battle_message.c index ab1ec0659f..3c1ca4b14b 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -319,7 +319,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNENDUREDHIT] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} endured the hit!"), [STRINGID_MAGNITUDESTRENGTH] = COMPOUND_STRING("Magnitude {B_BUFF1}!"), [STRINGID_PKMNCUTHPMAXEDATTACK] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} cut its own HP and maximized its Attack!"), - [STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} copied {B_DEF_NAME_WITH_PREFIX2}'s stat changes!"), + [STRINGID_PKMNCOPIEDSTATCHANGES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} copied {B_EFF_NAME_WITH_PREFIX2}'s stat changes!"), [STRINGID_PKMNGOTFREE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} got free of {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), //not in gen 5+, generic rapid spin? [STRINGID_PKMNSHEDLEECHSEED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} shed Leech Seed!"), //not in gen 5+, generic rapid spin? [STRINGID_PKMNBLEWAWAYSPIKES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} blew away Spikes!"), //not in gen 5+, generic rapid spin? @@ -629,13 +629,13 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_ICEBODYHPGAIN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} healed it a little bit!"), //don't think this message is displayed anymore [STRINGID_SNOWWARNINGHAIL] = COMPOUND_STRING("It started to hail!"), [STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} frisked {B_DEF_NAME_WITH_PREFIX2} and found its {B_LAST_ITEM}!"), - [STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_DEF_TEAM1} team is too nervous to eat Berries!"), + [STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_EFF_TEAM1} team is too nervous to eat Berries!"), [STRINGID_HARVESTBERRY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} harvested its {B_LAST_ITEM}!"), [STRINGID_MAGICBOUNCEACTIVATES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} bounced the {B_ATK_NAME_WITH_PREFIX2} back!"), [STRINGID_PROTEANTYPECHANGE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} transformed it into the {B_BUFF1} type!"), [STRINGID_SYMBIOSISITEMPASS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} passed its {B_LAST_ITEM} to {B_EFF_NAME_WITH_PREFIX2} through {B_LAST_ABILITY}!"), [STRINGID_STEALTHROCKDMG] = COMPOUND_STRING("Pointed stones dug into {B_SCR_NAME_WITH_PREFIX2}!"), - [STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("The poison spikes disappeared from the ground around {B_SCR_TEAM2} team!"), + [STRINGID_TOXICSPIKESABSORBED] = COMPOUND_STRING("The poison spikes disappeared from the ground around {B_EFF_TEAM2} team!"), [STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was poisoned!"), [STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was badly poisoned!"), [STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was caught in a sticky web!"), @@ -857,7 +857,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SWAMPENVELOPEDSIDE] = COMPOUND_STRING("A swamp enveloped {B_DEF_TEAM2} team!"), [STRINGID_THESWAMPDISAPPEARED] = COMPOUND_STRING("The swamp around {B_ATK_TEAM2} team disappeared!"), [STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is preparing to tell a chillingly bad joke!"), - [STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_ATK_PARTNER_NAME} drank down all the matcha that {B_ATK_NAME_WITH_PREFIX2} made!"), + [STRINGID_HOSPITALITYRESTORATION] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} drank down all the matcha that {B_SCR_NAME_WITH_PREFIX2} made!"), [STRINGID_ELECTROSHOTCHARGING] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} absorbed electricity!"), [STRINGID_ITEMWASUSEDUP] = COMPOUND_STRING("The {B_LAST_ITEM} was used up…"), [STRINGID_ATTACKERLOSTITSTYPE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} lost its {B_BUFF1} type!"), @@ -3111,14 +3111,14 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) else toCpy = sText_Opposing2; break; - case B_TXT_SCR_TEAM1: - if (IsOnPlayerSide(gBattleScripting.battler)) + case B_TXT_EFF_TEAM1: + if (IsOnPlayerSide(gEffectBattler)) toCpy = sText_Your1; else toCpy = sText_Opposing1; break; - case B_TXT_SCR_TEAM2: - if (IsOnPlayerSide(gBattleScripting.battler)) + case B_TXT_EFF_TEAM2: + if (IsOnPlayerSide(gEffectBattler)) toCpy = sText_Your2; else toCpy = sText_Opposing2; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8abed761e7..fcd325305c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8325,7 +8325,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) { gSideStatuses[GetBattlerSide(battler)] &= ~SIDE_STATUS_TOXIC_SPIKES; gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0; - gBattleScripting.battler = battler; + gEffectBattler = battler; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ToxicSpikesAbsorbed; } @@ -17877,9 +17877,14 @@ void BS_TryGulpMissile(void) && (gCurrentMove == MOVE_DIVE) && (GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) + { + gBattleScripting.battler = gBattlerAttacker; gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; + } else + { gBattlescriptCurrInstr = cmd->nextInstr; + } } void BS_TryActivateGulpMissile(void) diff --git a/src/battle_util.c b/src/battle_util.c index 3e9090516e..f3972791f8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1821,7 +1821,8 @@ static inline bool32 TryFormChangeBeforeMove(void) return FALSE; BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AttackerFormChange; + gBattleScripting.battler = gBattlerAttacker; + gBattlescriptCurrInstr = BattleScript_BattlerFormChange; return TRUE; } @@ -3515,6 +3516,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON && !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER)) { + SaveBattlerAttacker(gBattlerAttacker); + SaveBattlerTarget(gBattlerTarget); gBattlerAttacker = battler; gBattlerTarget = diagonalBattler; BattleScriptPushCursorAndCallback(BattleScript_ImposterActivates); @@ -3562,7 +3565,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_UNNERVE: if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated) { - gBattlerTarget = GetOppositeBattler(battler); + gEffectBattler = GetOppositeBattler(battler); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE; gDisableStructs[battler].unnerveActivated = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -3574,7 +3577,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_AS_ONE_SHADOW_RIDER: if (!gSpecialStatuses[battler].switchInAbilityDone && !gDisableStructs[battler].unnerveActivated) { - gBattlerTarget = GetOppositeBattler(battler); + gEffectBattler = GetOppositeBattler(battler); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE; gDisableStructs[battler].unnerveActivated = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -3596,6 +3599,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_PASTEL_VEIL: if (!gSpecialStatuses[battler].switchInAbilityDone) { + SaveBattlerTarget(gBattlerTarget); gBattlerTarget = battler; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_PASTEL_VEIL; BattleScriptPushCursorAndCallback(BattleScript_PastelVeilActivates); @@ -3635,7 +3639,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_FriskActivates); // Try activate effect++; } @@ -3680,6 +3683,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)) { SET_STATCHANGER(statId, 1, FALSE); + SaveBattlerAttacker(gBattlerAttacker); gBattlerAttacker = battler; PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); BattleScriptPushCursorAndCallback(BattleScript_AttackerAbilityStatRaiseEnd3); @@ -3830,6 +3834,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_INTIMIDATE: if (!gSpecialStatuses[battler].switchInAbilityDone) { + SaveBattlerAttacker(gBattlerAttacker); gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, TRUE); @@ -3841,6 +3846,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup) { + SaveBattlerAttacker(gBattlerAttacker); gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE; @@ -3873,8 +3879,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SHIELDS_DOWN: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3); effect++; } break; @@ -4002,10 +4007,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE)) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattlerAttacker = gBattlerAbility = battler; for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i]; - gBattleScripting.battler = BATTLE_PARTNER(battler); + gEffectBattler = BATTLE_PARTNER(battler); BattleScriptPushCursorAndCallback(BattleScript_CostarActivates); effect++; } @@ -4033,8 +4037,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[partner].hp < gBattleMons[partner].maxHP && IsBattlerAlive(partner)) { - gBattlerTarget = partner; - gBattlerAttacker = battler; + gEffectBattler = partner; gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattleStruct->moveDamage[partner] = (GetNonDynamaxMaxHP(partner) / 4) * -1; BattleScriptPushCursorAndCallback(BattleScript_HospitalityActivates); @@ -4074,10 +4077,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH)) { - gBattlerAttacker = battler; gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3); + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; } break; @@ -4296,8 +4298,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SHIELDS_DOWN: if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); + gBattleScripting.battler = battler; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3); effect++; } break; @@ -4328,8 +4330,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && GetActiveGimmick(battler) != GIMMICK_TERA && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { - gBattlerAttacker = battler; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); + gBattleScripting.battler = battler; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeEnd3NoPopup); effect++; } break; @@ -4979,8 +4981,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { + gBattleScripting.battler = gBattlerAttacker; BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AttackerFormChange; + gBattlescriptCurrInstr = BattleScript_BattlerFormChange; effect++; } break; From ac69a61cb4060bcd3df09161447710b558c6818d Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:57:32 -0400 Subject: [PATCH 112/283] Fix magnet rise ai timer check (#7361) Co-authored-by: ghoulslash --- src/battle_ai_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b785180bc2..96265621b2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2769,7 +2769,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAGNET_RISE: if (gFieldStatuses & STATUS_FIELD_GRAVITY - || gDisableStructs[battlerAtk].magnetRiseTimer != 0 + || gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_IRON_BALL || gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_MAGNET_RISE | STATUS3_SMACKED_DOWN) || !IsBattlerGrounded(battlerAtk)) From 05b1db8cc64ca1fbef534511602e5f0e31062e97 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 18 Jul 2025 16:57:57 +0200 Subject: [PATCH 113/283] `trainerproc` copy other trainer party (#7251) --- docs/tutorials/how_to_trainer_party_pool.md | 5 +++ include/data.h | 1 + src/battle_main.c | 19 ++++++++- tools/trainerproc/main.c | 43 +++++++++++++++++---- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/docs/tutorials/how_to_trainer_party_pool.md b/docs/tutorials/how_to_trainer_party_pool.md index e0e7639de3..e111ba957e 100644 --- a/docs/tutorials/how_to_trainer_party_pool.md +++ b/docs/tutorials/how_to_trainer_party_pool.md @@ -52,6 +52,11 @@ By default, only `DefaultPickFunction` and `PickLowest` are implemente - `Pool Prune` (`.poolPruneIndex`) controls if members in the pool should be removed before party members are picked from the pool. By default, only `POOL_PRUNE_NONE`, which doesn't remove anything from the pool, and `POOL_PRUNE_TEST`, which removes Wobbuffet from the pool, are implemented. Must be an `enum` value in `enum PoolPruneOptions`. +## Pool copy +The `Copy Pool` option can be used to have the trainer use the party or pool from a different trainer. +If you for example want some other trainer to have the same team/pool as Tiana, you'd use `Copy Pool: TRAINER_TIANA`. +If `Party Size` isn't defined for the current trainer, it will inherit from the copied trainer. + ## Example pool ``` === TRAINER_TIANA === diff --git a/include/data.h b/include/data.h index 003d669f8e..ffa1a4cba0 100644 --- a/include/data.h +++ b/include/data.h @@ -105,6 +105,7 @@ struct Trainer /*0x22*/ u8 poolRuleIndex; /*0x23*/ u8 poolPickIndex; /*0x24*/ u8 poolPruneIndex; + /*0x25*/ u16 overrideTrainer; }; struct TrainerClass diff --git a/src/battle_main.c b/src/battle_main.c index 7ba11811f6..8c4ba46261 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2026,7 +2026,24 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir u8 retVal; if (trainerNum == TRAINER_SECRET_BASE) return 0; - retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); + if (GetTrainerStructFromId(trainerNum)->overrideTrainer) + { + struct Trainer tempTrainer; + memcpy(&tempTrainer, GetTrainerStructFromId(trainerNum), sizeof(struct Trainer)); + const struct Trainer *origTrainer = GetTrainerStructFromId(tempTrainer.overrideTrainer); + + tempTrainer.party = origTrainer->party; + + tempTrainer.poolSize = origTrainer->poolSize; + if (tempTrainer.partySize == 0) + tempTrainer.partySize = origTrainer->partySize; + + retVal = CreateNPCTrainerPartyFromTrainer(party, (const struct Trainer *)(&tempTrainer), firstTrainer, gBattleTypeFlags); + } + else + { + retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); + } return retVal; } diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 98ca8884fd..dc812cb153 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -150,6 +150,9 @@ struct Trainer struct String pool_prune; int pool_prune_line; + struct String copy_pool; + int copy_pool_line; + struct String macro; int macro_line; }; @@ -1283,6 +1286,13 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct trainer->pool_prune_line = value.location.line; trainer->pool_prune = token_string(&value); } + else if (is_literal_token(&key, "Copy Pool")) + { + if (trainer->copy_pool_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Copy Pool'"); + trainer->copy_pool_line = value.location.line; + trainer->copy_pool = token_string(&value); + } else if (is_literal_token(&key, "Macro")) { if (trainer->macro_line) @@ -1317,7 +1327,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct while (match_empty_line(p)) {} if (!parse_pokemon_header(p, &nickname, &species, &gender, &item)) { - if (i > 0 || ends_with(trainer->id, "_NONE")) + if (i > 0 || ends_with(trainer->id, "_NONE") || !is_empty_string(trainer->copy_pool)) break; if (!p->error) set_parse_error(p, p->location, "expected nickname or species"); @@ -1331,6 +1341,12 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct } trainer->pokemon_n++; + if (!is_empty_string(trainer->copy_pool)) + { + set_show_parse_error(p, p->location, "trainer is set to copy mons from other trainer, but defines their own party"); + } + + pokemon->nickname = token_string(&nickname); pokemon->species = token_string(&species); if (is_empty_token(&gender)) @@ -1529,7 +1545,7 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct } } - if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n) + if (trainer->party_size_line && trainer->party_size > trainer->pokemon_n && is_empty_string(trainer->copy_pool)) { set_show_parse_error(p, p->location, "partySize larger than supplied pool"); } @@ -1863,6 +1879,13 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, ",\n"); } + if (!is_empty_string(trainer->copy_pool)) + { + fprintf(f, "#line %d\n", trainer->copy_pool_line); + fprintf(f, " .overrideTrainer = "); + fprint_string(f, trainer->copy_pool); + fprintf(f, ",\n"); + } if (trainer->macro_line) { fprintf(f, "#line %d\n", trainer->macro_line); @@ -1875,18 +1898,21 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par { fprintf(f, "#line %d\n", trainer->party_size_line); fprintf(f, " .partySize = %d,\n", trainer->party_size); - fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n); - fprintf(f, " .party = (const struct TrainerMon[])\n"); - fprintf(f, " {\n"); + if (is_empty_string(trainer->copy_pool)) + { + fprintf(f, " .poolSize = %d,\n", trainer->pokemon_n); + fprintf(f, " .party = (const struct TrainerMon[])\n"); + fprintf(f, " {\n"); + } } - else + else if (is_empty_string(trainer->copy_pool)) { fprintf(f, " .partySize = %d,\n", trainer->pokemon_n); fprintf(f, " .party = (const struct TrainerMon[])\n"); fprintf(f, " {\n"); } - for (int j = 0; j < trainer->pokemon_n; j++) + for (int j = 0; j < trainer->pokemon_n && is_empty_string(trainer->copy_pool); j++) { struct Pokemon *pokemon = &trainer->pokemon[j]; fprintf(f, " {\n"); @@ -2049,7 +2075,8 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, " },\n"); } - fprintf(f, " },\n"); + if (is_empty_string(trainer->copy_pool)) + fprintf(f, " },\n"); fprintf(f, " },\n"); } } From 71d40cc3f1c200b2f67d47ecb3319b7858541969 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 18 Jul 2025 19:12:37 +0200 Subject: [PATCH 114/283] Convert various to callnatives (#7355) --- asm/macros/battle_script.inc | 759 +- data/battle_scripts_1.s | 194 +- data/battle_scripts_2.s | 4 +- include/constants/battle_script_commands.h | 117 +- src/battle_script_commands.c | 13241 ++++++++++--------- 5 files changed, 7111 insertions(+), 7204 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index ba4b4619aa..c906938b93 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1806,644 +1806,659 @@ .4byte \jumpInstr .endm -@ various command changed to more readable macros - .macro cancelmultiturnmoves battler:req - various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES - .endm - - .macro getifcantrunfrombattle battler:req - various \battler, VARIOUS_IS_RUNNING_IMPOSSIBLE + .macro jumpiflastuseditemholdeffect holdEffect:req, secondaryId:req, jumpInstr:req + callnative BS_JumpIfLastUsedItemHoldEffect + .byte \holdEffect + .2byte \secondaryId + .4byte \jumpInstr .endm - .macro getmovetarget battler:req - various \battler, VARIOUS_GET_MOVE_TARGET + .macro swapsidestatuses + callnative BS_CourtChangeSwapSideStatuses .endm - .macro getbattlerfainted battler:req - various \battler, VARIOUS_GET_BATTLER_FAINTED + .macro swapstats stat:req + callnative BS_SwapStats + .byte \stat .endm - .macro resetswitchinabilitybits battler:req - various \battler, VARIOUS_RESET_SWITCH_IN_ABILITY_BITS + .macro restoresavedmove + callnative BS_RestoreSavedMove .endm - .macro updatechoicemoveonlvlup battler:req - various \battler, VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP +@ helpful macros + .macro setstatchanger stat:req, stages:req, down:req + setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7 .endm - .macro resetplayerfainted - various BS_ATTACKER, VARIOUS_RESET_PLAYER_FAINTED + .macro setmoveeffect effect:req + sethword sMOVE_EFFECT, \effect + sethword sSAVED_MOVE_EFFECT, \effect .endm - .macro palaceflavortext battler:req - various \battler, VARIOUS_PALACE_FLAVOR_TEXT + .macro sethword dst:req, value:req + setbyte \dst, (\value) & 0xFF + setbyte \dst + 1, ((\value) >> 8) & 0xFF .endm - .macro arenajudgmentwindow - various BS_ATTACKER, VARIOUS_ARENA_JUDGMENT_WINDOW + .macro setword dst:req, value:req + setbyte \dst, (\value) & 0xFF + setbyte \dst + 1, ((\value) >> 8) & 0xFF + setbyte \dst + 2, ((\value) >> 16) & 0xFF + setbyte \dst + 3, ((\value) >> 24) & 0xFF .endm - .macro arenaopponentmonlost - various BS_ATTACKER, VARIOUS_ARENA_OPPONENT_MON_LOST + .macro copybyte dst:req, src:req + copyarray \dst, \src, 0x1 .endm - .macro arenaplayermonlost - various BS_ATTACKER, VARIOUS_ARENA_PLAYER_MON_LOST + .macro copyhword dst:req, src:req + copyarray \dst, \src, 0x2 .endm - .macro arenabothmonlost - various BS_ATTACKER, VARIOUS_ARENA_BOTH_MONS_LOST + .macro copyword dst:req, src:req + copyarray \dst, \src, 0x4 .endm - .macro forfeityesnobox battler:req - various \battler, VARIOUS_EMIT_YESNOBOX + .macro jumpifbytenotequal byte1:req, byte2:req, jumpInstr:req + jumpifarraynotequal \byte1, \byte2, 0x1, \jumpInstr .endm - .macro arenadrawreftextbox - various BS_ATTACKER, VARIOUS_DRAW_ARENA_REF_TEXT_BOX + .macro jumpifbyteequal byte1:req, byte2:req, jumpInstr:req + jumpifarrayequal \byte1, \byte2, 0x1, \jumpInstr .endm - .macro arenaerasereftextbox - various BS_ATTACKER, VARIOUS_ERASE_ARENA_REF_TEXT_BOX + .macro jumpifmove move:req, jumpInstr:req + jumpifhalfword CMP_EQUAL, gCurrentMove, \move, \jumpInstr .endm - .macro arenajudgmentstring id:req - various \id, VARIOUS_ARENA_JUDGMENT_STRING + .macro jumpifnotmove move:req, jumpInstr:req + jumpifhalfword CMP_NOT_EQUAL, gCurrentMove, \move, \jumpInstr .endm - .macro arenawaitmessage id:req - various \id, VARIOUS_ARENA_WAIT_STRING + .macro jumpifnotchosenmove move:req, jumpInstr:req + jumpifhalfword CMP_NOT_EQUAL, gChosenMove, \move, \jumpInstr .endm - .macro waitcry battler:req - various \battler, VARIOUS_WAIT_CRY + .macro jumpifstatus3 battler:req, flags:req, jumpInstr:req + jumpifstatus3condition \battler, \flags, FALSE, \jumpInstr .endm - .macro returnopponentmon1toball battler:req - various \battler, VARIOUS_RETURN_OPPONENT_MON1 + .macro jumpifnostatus3 battler:req, flags:req, jumpInstr:req + jumpifstatus3condition \battler, \flags, TRUE, \jumpInstr .endm - .macro returnopponentmon2toball battler:req - various \battler, VARIOUS_RETURN_OPPONENT_MON2 + .macro jumpifmovehadnoeffect jumpInstr:req + jumpifmoveresultflags MOVE_RESULT_NO_EFFECT, \jumpInstr .endm - .macro volumedown - various BS_ATTACKER, VARIOUS_VOLUME_DOWN + .macro jumpifside battler:req, side:req, equalJumpInstr:req + getbattlerside \battler + jumpifbyte CMP_EQUAL, gBattleCommunication, \side, \equalJumpInstr .endm - .macro volumeup - various BS_ATTACKER, VARIOUS_VOLUME_UP + .macro jumpifbattletype flags:req, jumpInstr:req + jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr .endm - .macro setalreadystatusedmoveattempt battler:req - various \battler, VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT + .macro jumpifnotbattletype flags:req, jumpInstr:req + jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr .endm - .macro palacetryescapestatus battler:req - various \battler, VARIOUS_PALACE_TRY_ESCAPE_STATUS + .macro dmg_1_8_targethp + manipulatedamage DMG_1_8_TARGET_HP .endm - .macro setoutcomeonteleport battler:req - various \battler, VARIOUS_SET_TELEPORT_OUTCOME + .macro dmgtomaxattackerhp + manipulatedamage DMG_FULL_ATTACKER_HP .endm - .macro playtrainerdefeatbgm battler:req - various \battler, VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC + .macro jumpifflowerveil jumpInstr:req + jumpifnottype BS_TARGET, TYPE_GRASS, 1f + jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr + 1: .endm - .macro stattextbuffer battler:req - various \battler, VARIOUS_STAT_TEXT_BUFFER + .macro jumpifflowerveilattacker jumpInstr:req + jumpifnottype BS_ATTACKER, TYPE_GRASS, 1f + jumpifability BS_ATTACKER_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr + 1: .endm - .macro switchinabilities battler:req - various \battler, VARIOUS_SWITCHIN_ABILITIES + .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req + callnative BS_JumpIfAbilityCantBeSuppressed + .byte \battler + .4byte \jumpInstr .endm - .macro instanthpdrop battler:req - various \battler, VARIOUS_INSTANT_HP_DROP + .macro tryactivateabilityshield battler:req + callnative BS_TryActivateAbilityShield + .byte \battler .endm - .macro clearstatus battler:req - various \battler, VARIOUS_CLEAR_STATUS + .macro trysynchronoise jumpInstr:req + callnative BS_TrySynchronoise + .4byte \jumpInstr .endm - .macro restorepp battler:req - various \battler, VARIOUS_RESTORE_PP + .macro jumpifroarfails jumpInstr:req + callnative BS_JumpIfRoarFails + .4byte \jumpInstr .endm - .macro tryactivatereceiver battler:req - various \battler, VARIOUS_TRY_ACTIVATE_RECEIVER + .macro jumpifabsent battler:req, jumpInstr:req + callnative BS_JumpIfAbsent + .byte \battler + .4byte \jumpInstr .endm - .macro tryactivatesoulheart - various BS_ATTACKER, VARIOUS_TRY_ACTIVATE_SOULHEART + .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req + jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE .endm - .macro playmoveanimation battler:req, move:req - various \battler, VARIOUS_PLAY_MOVE_ANIMATION - .2byte \move + .macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req, equal:req + callnative BS_JumpIfHoldEffect + .byte \battler + .byte \holdEffect + .4byte \jumpInstr + .byte \equal .endm - .macro setluckychant battler:req, failInstr:req - various \battler VARIOUS_SET_LUCKY_CHANT - .4byte \failInstr + .macro jumpifnoally battler:req, jumpInstr:req + callnative BS_JumpIfNoAlly + .byte \battler + .4byte \jumpInstr .endm - .macro suckerpunchcheck failInstr:req - various BS_ATTACKER, VARIOUS_SUCKER_PUNCH_CHECK - .4byte \failInstr + .macro infatuatewithbattler battler:req, infatuateWith:req + callnative BS_InfatuateWithBattler + .byte \battler + .byte \infatuateWith .endm - .macro setabilitysimple battler:req, failInstr:req - various \battler VARIOUS_SET_SIMPLE_BEAM - .4byte \failInstr + .macro setlastuseditem battler:req + callnative BS_SetLastUsedItem + .byte \battler .endm - .macro tryentrainment failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ENTRAINMENT + .macro trysetfairylock failInstr:req + callnative BS_TrySetFairyLock .4byte \failInstr .endm - .macro setlastusedability battler:req - various \battler, VARIOUS_SET_LAST_USED_ABILITY - .endm - - .macro tryafteryou failInstr:req - various BS_ATTACKER, VARIOUS_AFTER_YOU - .4byte \failInstr + .macro getstatvalue stat:req + callnative BS_GetStatValue + .byte \stat .endm - .macro trybestow failInstr:req - various BS_ATTACKER, VARIOUS_BESTOW - .4byte \failInstr + .macro jumpiffullhp battler:req, jumpInstr:req + callnative BS_JumpIfFullHp + .byte \battler + .4byte \jumpInstr .endm - .macro invertstatstages battler:req - various \battler, VARIOUS_INVERT_STAT_STAGES + .macro tryfriskmessage + callnative BS_TryFriskMessage .endm - .macro trymefirst failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ME_FIRST - .4byte \failInstr + .macro settracedability battler:req + callnative BS_SetTracedAbility + .byte \battler .endm - .macro jumpifbattleend jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_BATTLE_END - .4byte \jumpInstr + .macro tryillusionoff battler:req + callnative BS_TryIllusionOff + .byte \battler .endm - .macro tryelectrify failInstr:req - various BS_ATTACKER, VARIOUS_TRY_ELECTRIFY - .4byte \failInstr + .macro setspriteignore0hp ignore0HP:req + callnative BS_SetSpriteIgnore0Hp + .byte \ignore0HP .endm - .macro trysoak failInstr:req - various BS_ATTACKER, VARIOUS_TRY_SOAK - .4byte \failInstr + .macro updatenick + callnative BS_UpdateNick .endm - .macro handleformchange battler:req, case:req - various \battler, VARIOUS_HANDLE_FORM_CHANGE - .byte \case + .macro jumpifnotberry battler:req, jumpInstr:req + callnative BS_JumpIfNotBerry + .byte \battler + .4byte \jumpInstr .endm - .macro jumpifcantuselastresort battler:req, jumpInstr:req - various \battler, VARIOUS_TRY_LAST_RESORT - .4byte \jumpInstr + .macro gravityonairbornemons + callnative BS_GravityOnAirborneMons .endm - .macro tryautotomize battler:req, failInstr:req - various \battler, VARIOUS_TRY_AUTOTOMIZE + .macro tryacupressure failInstr:req + callnative BS_TryAcupressure .4byte \failInstr .endm - .macro jumpifcantusesynchronoise jumpInstr:req - various BS_ATTACKER, VARIOUS_TRY_SYNCHRONOISE - .4byte \jumpInstr + .macro cancelmultiturnmoves + callnative BS_CancelMultiTurnMoves .endm - .macro showabilitypopup battler:req - various \battler, VARIOUS_ABILITY_POPUP + .macro isrunningimpossible + callnative BS_IsRunningImpossible .endm - .macro updateabilitypopup battler:req - various \battler, VARIOUS_UPDATE_ABILITY_POPUP + .macro getmovetarget + callnative BS_GetMoveTarget .endm - .macro jumpiftargetally jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_TARGET_ALLY - .4byte \jumpInstr + @ Will jump to script pointer if the specified battler has or has not fainted. + .macro jumpiffainted battler:req, value:req, ptr:req + getbattlerfainted \battler + jumpifbyte CMP_EQUAL, gBattleCommunication, \value, \ptr .endm - .macro trypsychoshift failInstr:req sleepClauseFailInstr:req - various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT - .4byte \failInstr - .4byte \sleepClauseFailInstr + .macro getbattlerfainted battler:req + callnative BS_GetBattlerFainted + .byte \battler .endm - .macro curestatus battler:req - various \battler, VARIOUS_CURE_STATUS + .macro resetswitchinabilitybits + callnative BS_ResetSwitchInAbilityBits .endm - .macro powertrick battler:req - various \battler, VARIOUS_POWER_TRICK + .macro updatechoicemoveonlvlup + callnative BS_UpdateChoiceMoveOnLvlUp .endm - .macro jumpifnotgrounded battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_GROUNDED - .4byte \jumpInstr + .macro resetplayerfainted + callnative BS_ResetPlayerFainted .endm - .macro handletrainerslidemsg battler:req, case:req - various \battler, VARIOUS_HANDLE_TRAINER_SLIDE_MSG - .byte \case + .macro palaceflavortext + callnative BS_PalaceFlavorText .endm - .macro trytrainerslidefirstdownmsg battler:req - various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF + .macro arenajudgmentwindow + callnative BS_ArenaJudgmentWindow .endm - .macro trytrainerslidelastonmsg battler:req - various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON + .macro arenaopponentmonlost + callnative BS_ArenaOpponentMonLost .endm - .macro setauroraveil battler:req - various \battler, VARIOUS_SET_AURORA_VEIL + .macro arenaplayermonlost + callnative BS_ArenaPlayerMonLost .endm - .macro trysetthirdtype battler:req, failInstr:req - various \battler, VARIOUS_TRY_THIRD_TYPE - .4byte \failInstr + .macro arenabothmonslost + callnative BS_ArenaBothMonsLost .endm - .macro tryaccupressure battler:req, failInstr:req - various \battler, VARIOUS_ACUPRESSURE - .4byte \failInstr + .macro forfeityesnobox + callnative BS_ForfeitYesNoBox .endm - .macro bringdownairbornebattler battler:req - various \battler, VARIOUS_GRAVITY_ON_AIRBORNE_MONS + .macro drawarenareftextbox + callnative BS_DrawArenaRefTextBox .endm - .macro checkgrassyterrainheal battler:req, failInstr:req - various \battler, VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS - .4byte \failInstr + .macro erasearenareftextbox + callnative BS_EraseArenaRefTextBox .endm - .macro jumpifnotberry battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_BERRY - .4byte \jumpInstr + .macro arenajudgmentstring id:req + callnative BS_ArenaJudgmentString + .byte \id .endm - .macro jumpifroarfails jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_ROAR_FAILS - .4byte \jumpInstr + .macro arenawaitmessage id:req + callnative BS_ArenaWaitMessage + .byte \id .endm - .macro tryinstruct failInstr:req - various BS_ATTACKER, VARIOUS_TRY_INSTRUCT - .4byte \failInstr + .macro waitcry + callnative BS_WaitCry .endm - .macro settracedability battler:req - various \battler, VARIOUS_TRACE_ABILITY + .macro returnopponentmon1toball + callnative BS_ReturnOpponentMon1ToBall .endm - .macro updatenick battler:req - various \battler, VARIOUS_UPDATE_NICK + .macro returnopponentmon2toball + callnative BS_ReturnOpponentMon2ToBall .endm - .macro tryillusionoff battler:req - various \battler, VARIOUS_TRY_ILLUSION_OFF + .macro volumedown + callnative BS_VolumeDown .endm - .macro spriteignore0hp value:req - various BS_ATTACKER, VARIOUS_SET_SPRITEIGNORE0HP - .byte \value + .macro volumeup + callnative BS_VolumeUp .endm - .macro getstatvalue battler:req, stat:req - various \battler, VARIOUS_GET_STAT_VALUE - .byte \stat + .macro setalreadystatusedmoveattempt + callnative BS_SetAlreadyStatusedMoveAttempt .endm - .macro jumpiffullhp battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_FULL_HP - .4byte \jumpInstr + .macro palacetryescapestatus + callnative BS_PalaceTryEscapeStatus .endm - .macro losetype battler:req, type:req - various \battler, VARIOUS_LOSE_TYPE - .byte \type + .macro setteleportoutcome battler:req + callnative BS_SetTeleportOutcome + .byte \battler .endm - .macro tryfriskmsg battler:req - various \battler, VARIOUS_TRY_FRISK + .macro playtrainerdefeatedmusic + callnative BS_PlayTrainerDefeatedMusic .endm - .macro jumpifshieldsdown battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED - .4byte \jumpInstr + .macro stattextbuffer + callnative BS_StatTextBuffer .endm - .macro trysetfairylock failInstr:req - various BS_ATTACKER, VARIOUS_TRY_FAIRY_LOCK - .4byte \failInstr + .macro switchinabilities battler:req + callnative BS_SwitchinAbilities + .byte \battler .endm - .macro jumpifnoally battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NO_ALLY - .4byte \jumpInstr + .macro instanthpdrop + callnative BS_InstantHpDrop .endm - .macro jumpifholdeffect battler:req, holdEffect:req, jumpInstr:req, equal=TRUE - various \battler, VARIOUS_JUMP_IF_HOLD_EFFECT - .byte \holdEffect - .4byte \jumpInstr - .byte \equal + .macro clearstatus + callnative BS_ClearStatus .endm - .macro jumpifnoholdeffect battler:req, holdEffect:req, jumpInstr:req - jumpifholdeffect \battler, \holdEffect, \jumpInstr, FALSE + .macro restoremovepp + callnative BS_RestoreMovePp .endm - .macro infatuatewithbattler battler:req, infatuateWith:req - various \battler, VARIOUS_INFATUATE_WITH_BATTLER - .byte \infatuateWith + .macro tryactivatereceiver battler:req + callnative BS_TryActivateReceiver + .byte \battler .endm - .macro setlastuseditem battler:req - various \battler, VARIOUS_SET_LAST_USED_ITEM + .macro tryactivatesoulheart + callnative BS_TryActivateSoulheart .endm - .macro jumpifabsent battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_ABSENT - .4byte \jumpInstr + .macro playmoveanimation move:req + callnative BS_PlayMoveAnimation + .2byte \move .endm - .macro destroyabilitypopup - various BS_ABILITY_BATTLER, VARIOUS_DESTROY_ABILITY_POPUP + .macro setluckychant failInstr:req + callnative BS_SetLuckyChant + .4byte \failInstr .endm - .macro gettotemboost jumpInstr:req - various BS_ATTACKER, VARIOUS_TOTEM_BOOST - .4byte \jumpInstr + .macro suckerpunchcheck failInstr:req + callnative BS_SuckerPunchCheck + .4byte \failInstr .endm - .macro consumeberry battler:req, fromBattler:req - various \battler, VARIOUS_CONSUME_BERRY - .byte \fromBattler + .macro setsimplebeam failInstr:req + callnative BS_SetSimpleBeam + .4byte \failInstr .endm - .macro activateitemeffects battler:req - various \battler, VARIOUS_MOVEEND_ITEM_EFFECTS + .macro tryentrainment failInstr:req + callnative BS_TryEntrainment + .4byte \failInstr .endm - .macro pickpocketsteal - various 0, VARIOUS_PICKPOCKET + .macro setlastusedability + callnative BS_SetLastUsedAbility .endm - .macro doterrainseed battler:req, failInstr:req - various \battler, VARIOUS_TERRAIN_SEED - .4byte \failInstr + .macro invertstatstages + callnative BS_InvertStatStages .endm - .macro makeinvisible battler:req - various \battler, VARIOUS_MAKE_INVISIBLE + .macro trymefirst failInstr:req + callnative BS_TryMeFirst + .4byte \failInstr .endm - .macro tryroomservice battler:req, failInstr:req - various \battler, VARIOUS_ROOM_SERVICE + .macro tryelectrify failInstr:req + callnative BS_TryElectrify .4byte \failInstr .endm - .macro jumpifpranksterblocked battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED - .4byte \jumpInstr + .macro trysoak failInstr:req + callnative BS_TrySoak + .4byte \failInstr .endm - .macro jumpifteamhealthy battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_TEAM_HEALTHY - .4byte \jumpInstr + .macro handleformchange battler:req, case_:req + callnative BS_HandleFormChange + .byte \battler + .byte \case_ .endm - .macro tryhealquarterhealth battler:req, failInstr:req - various \battler, VARIOUS_TRY_HEAL_QUARTER_HP + .macro trylastresort failInstr:req + callnative BS_TryLastResort .4byte \failInstr .endm - .macro trytoclearprimalweather - various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER - .endm - - .macro setattackertostickywebuser - various BS_TARGET, VARIOUS_SET_ATTACKER_STICKY_WEB_USER + .macro tryautotomize failInstr:req + callnative BS_TryAutotomize + .4byte \failInstr .endm - .macro getrototillertargets failInstr:req - various BS_ATTACKER, VARIOUS_GET_ROTOTILLER_TARGETS + .macro tryinstruct failInstr:req + callnative BS_TryInstruct .4byte \failInstr .endm - .macro jumpifnotrototilleraffected battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED - .4byte \jumpInstr + .macro showabilitypopup + callnative BS_ShowAbilityPopup .endm - .macro jumpifcantreverttoprimal jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL - .4byte \jumpInstr + .macro updateabilitypopup + callnative BS_UpdateAbilityPopup .endm - .macro jumpifweatheraffected battler:req, flags:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_WEATHER_AFFECTED - .4byte \flags + .macro jumpiftargetally jumpInstr:req + callnative BS_JumpIfTargetAlly .4byte \jumpInstr .endm - .macro jumpifspecies battler:req, species:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_SPECIES - .2byte \species - .4byte \jumpInstr + .macro trypsychoshift failInstr:req sleepClauseFailInstr:req + callnative BS_TryPsychoShift + .4byte \failInstr + .4byte \sleepClauseFailInstr .endm - .macro tryendneutralizinggas battler:req - various \battler, VARIOUS_TRY_END_NEUTRALIZING_GAS + .macro curestatus battler:req + callnative BS_CureStatus + .byte \battler .endm - .macro trynoretreat battler:req, failInstr:req - various \battler, VARIOUS_TRY_NO_RETREAT - .4byte \failInstr + .macro powertrick + callnative BS_PowerTrick .endm - .macro checkpoltergeist battler:req, failInstr:req - various \battler, VARIOUS_CHECK_POLTERGEIST + .macro tryafteryou failInstr:req + callnative BS_TryAfterYou .4byte \failInstr .endm - .macro cutonethirdhpraisestats failInstr:req - various BS_ATTACKER, VARIOUS_CUT_1_3_HP_RAISE_STATS + .macro trybestow failInstr:req + callnative BS_TryBestow .4byte \failInstr .endm - .macro curecertainstatuses battler:req - various \battler, VARIOUS_CURE_CERTAIN_STATUSES + .macro handletrainerslidemsg battler:req, case_:req + callnative BS_HandleTrainerSlideMsg + .byte \battler + .byte \case_ .endm - .macro tryresetnegativestatstages battler:req - various \battler, VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES + .macro trytrainerslidemsgfirstoff battler:req + callnative BS_TryTrainerSlideMsgFirstOff + .byte \battler .endm - .macro jumpiflastuseditemberry jumpInstr:req - various BS_ATTACKER, VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY - .4byte \jumpInstr + .macro trytrainerslidemsglaston battler:req + callnative BS_TryTrainerSlideMsgLastOn + .byte \battler .endm - .macro jumpiflastuseditemholdeffect holdEffect:req, secondaryId:req, jumpInstr:req - callnative BS_JumpIfLastUsedItemHoldEffect - .byte \holdEffect - .2byte \secondaryId - .4byte \jumpInstr + .macro setauroraveil + callnative BS_SetAuroraVeil .endm - .macro savebattleritem battler:req - various \battler, VARIOUS_SAVE_BATTLER_ITEM + .macro trythirdtype failInstr:req + callnative BS_TryThirdType + .4byte \failInstr .endm - .macro restorebattleritem battler:req - various \battler, VARIOUS_RESTORE_BATTLER_ITEM + .macro destroyabilitypopup + callnative BS_DestroyAbilityPopup .endm - .macro battleritemtolastuseditem battler:req - various \battler, VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM + .macro gettotemboost jumpInstr:req + callnative BS_GetTotemBoost + .4byte \jumpInstr .endm - .macro swapsidestatuses - callnative BS_CourtChangeSwapSideStatuses + .macro activateitemeffects + callnative BS_ActivateItemEffects .endm - .macro swapstats stat:req - callnative BS_SwapStats - .byte \stat + .macro tryroomservice battler:req, failInstr:req + callnative BS_TryRoomService + .byte \battler + .4byte \failInstr .endm - .macro restoresavedmove - callnative BS_RestoreSavedMove + .macro tryterrainseed battler:req, failInstr:req + callnative BS_TryTerrainSeed + .byte \battler + .4byte \failInstr .endm -@ helpful macros - .macro setstatchanger stat:req, stages:req, down:req - setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7 + .macro makeinvisible battler:req + callnative BS_MakeInvisible + .byte \battler .endm - .macro setmoveeffect effect:req - sethword sMOVE_EFFECT, \effect - sethword sSAVED_MOVE_EFFECT, \effect + .macro jumpifteamhealthy jumpInstr:req + callnative BS_JumpIfTeamHealthy + .4byte \jumpInstr .endm - .macro sethword dst:req, value:req - setbyte \dst, (\value) & 0xFF - setbyte \dst + 1, ((\value) >> 8) & 0xFF + .macro tryhealquarterhealth battler:req, failInstr:req + callnative BS_TryHealQuarterHealth + .byte \battler + .4byte \failInstr .endm - .macro setword dst:req, value:req - setbyte \dst, (\value) & 0xFF - setbyte \dst + 1, ((\value) >> 8) & 0xFF - setbyte \dst + 2, ((\value) >> 16) & 0xFF - setbyte \dst + 3, ((\value) >> 24) & 0xFF + .macro jumpifunder200 jumpInstr:req + callnative BS_JumpIfUnder200 + .4byte \jumpInstr .endm - .macro copybyte dst:req, src:req - copyarray \dst, \src, 0x1 + .macro setskydrop + callnative BS_SetSkyDrop .endm - .macro copyhword dst:req, src:req - copyarray \dst, \src, 0x2 + .macro clearskydrop failInstr:req + callnative BS_ClearSkyDrop + .4byte \failInstr .endm - .macro copyword dst:req, src:req - copyarray \dst, \src, 0x4 + .macro skydropyawn + callnative BS_SkyDropYawn .endm - .macro jumpifbytenotequal byte1:req, byte2:req, jumpInstr:req - jumpifarraynotequal \byte1, \byte2, 0x1, \jumpInstr + .macro jumpifpranksterblocked jumpInstr:req + callnative BS_JumpIfPranksterBlocked + .4byte \jumpInstr .endm - .macro jumpifbyteequal byte1:req, byte2:req, jumpInstr:req - jumpifarrayequal \byte1, \byte2, 0x1, \jumpInstr + .macro trytoclearprimalweather + callnative BS_TryToClearPrimalWeather .endm - .macro jumpifmove move:req, jumpInstr:req - jumpifhalfword CMP_EQUAL, gCurrentMove, \move, \jumpInstr + .macro tryendneutralizinggas + callnative BS_TryEndNeutralizingGas .endm - .macro jumpifnotmove move:req, jumpInstr:req - jumpifhalfword CMP_NOT_EQUAL, gCurrentMove, \move, \jumpInstr + .macro getrototillertargets failInstr:req + callnative BS_GetRototillerTargets + .4byte \failInstr .endm - .macro jumpifnotchosenmove move:req, jumpInstr:req - jumpifhalfword CMP_NOT_EQUAL, gChosenMove, \move, \jumpInstr + .macro jumpifnotrototilleraffected jumpInstr:req + callnative BS_JumpIfNotRototillerAffected + .4byte \jumpInstr .endm - .macro jumpifstatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, FALSE, \jumpInstr + .macro consumeberry battler:req, fromBattler:req + callnative BS_ConsumeBerry + .byte \battler + .byte \fromBattler .endm - .macro jumpifnostatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, TRUE, \jumpInstr + .macro jumpifweatheraffected flags:req, jumpInstr:req + callnative BS_JumpIfWeatherAffected + .2byte \flags + .4byte \jumpInstr .endm - .macro jumpifmovehadnoeffect jumpInstr:req - jumpifmoveresultflags MOVE_RESULT_NO_EFFECT, \jumpInstr + .macro jumpifspecies species:req, jumpInstr:req + callnative BS_JumpIfSpecies + .2byte \species + .4byte \jumpInstr .endm - .macro jumpifside battler:req, side:req, equalJumpInstr:req - getbattlerside \battler - jumpifbyte CMP_EQUAL, gBattleCommunication, \side, \equalJumpInstr + .macro jumpifleafguardprotected battler:req, jumpInstr:req + callnative BS_JumpIfLeafGuardProtected + .byte \battler + .4byte \jumpInstr .endm - .macro jumpifbattletype flags:req, jumpInstr:req - jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr + .macro setattackertostickywebuser + callnative BS_SetAttackerToStickyWebUser .endm - .macro jumpifnotbattletype flags:req, jumpInstr:req - jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr + .macro cutonethirdhpandraisestats failInstr:req + callnative BS_CutOneThirdHpAndRaiseStats + .4byte \failInstr .endm - .macro dmg_1_8_targethp - manipulatedamage DMG_1_8_TARGET_HP + .macro checkpoltergeist failInstr:req + callnative BS_CheckPoltergeist + .4byte \failInstr .endm - .macro dmgtomaxattackerhp - manipulatedamage DMG_FULL_ATTACKER_HP + .macro trynoretreat failInstr:req + callnative BS_TryNoRetreat + .4byte \failInstr .endm - .macro jumpifflowerveil jumpInstr:req - jumpifnottype BS_TARGET, TYPE_GRASS, 1f - jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr - 1: + .macro curecertainstatuses + callnative BS_CureCertainStatuses .endm - .macro jumpifflowerveilattacker jumpInstr:req - jumpifnottype BS_ATTACKER, TYPE_GRASS, 1f - jumpifability BS_ATTACKER_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr - 1: + .macro tryresetnegativestatstages + callnative BS_TryResetNegativeStatStages .endm - .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req - callnative BS_JumpIfAbilityCantBeSuppressed - .byte \battler + .macro jumpiflastuseditemberry jumpInstr:req + callnative BS_JumpIfLastUsedItemBerry .4byte \jumpInstr .endm - .macro tryactivateabilityshield battler:req - callnative BS_TryActivateAbilityShield - .byte \battler + .macro savebattleritem + callnative BS_SaveBattlerItem .endm - .macro trysynchronoise jumpInstr:req - callnative BS_TrySynchronoise - .4byte \jumpInstr + .macro restorebattleritem + callnative BS_RestoreBattlerItem + .endm + + .macro battleritemtolastuseditem + callnative BS_BattlerItemToLastUsedItem .endm .macro setallytonexttarget jumpInstr:req @@ -2464,40 +2479,12 @@ goto \jumpInstr .endm - .macro jumpifleafguardprotected battler:req, jumpInstr:req - various \battler, VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED - .4byte \jumpInstr - .endm - .macro jumpifsafeguard jumpInstr:req jumpifability BS_ATTACKER, ABILITY_INFILTRATOR, 1f jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, \jumpInstr 1: .endm - @ Will jump to script pointer if the target weighs less than 200 kg, or 441 lbs. - .macro jumpifunder200 battler:req, failInstr:req - various \battler, VARIOUS_JUMP_IF_UNDER_200 - .4byte \failInstr - .endm - - @ Sets the sky drop status and does all other necessary operations - .macro setskydrop - various 0, VARIOUS_SET_SKY_DROP - .endm - - @ Clears the sky drop status and does all other necessary operations. - @ If the target fainted in before this script is called, it goes to the given script. - .macro clearskydrop failInstr:req - various 0, VARIOUS_CLEAR_SKY_DROP - .4byte \failInstr - .endm - - @ Accounts for if the target of Sky Drop was in confuse_lock when the attacker falls asleep due to Yawn. - .macro skydropyawn - various 0, VARIOUS_SKY_DROP_YAWN - .endm - @ Tries to increase or decrease a battler's stat's stat stage by a specified amount. If impossible, jumps to \script. .macro modifybattlerstatstage battler:req, stat:req, mode:req, amount:req, script:req, animation:req, customString @@ -2528,12 +2515,6 @@ waitmessage B_WAIT_TIME_LONG .endm - @ Will jump to script pointer if the specified battler has or has not fainted. - .macro jumpiffainted battler:req, value:req, ptr:req - getbattlerfainted \battler - jumpifbyte CMP_EQUAL, gBattleCommunication, \value, \ptr - .endm - .macro flushtextbox printstring STRINGID_EMPTYSTRING3 waitmessage 1 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 695535ab4f..d0a8d640ef 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -621,7 +621,7 @@ BattleScript_AffectionBasedStatus_HealFrostbiteString: printstring STRINGID_ATTACKERHEALEDITSFROSTBITE BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG - clearstatus BS_ATTACKER + clearstatus waitstate updatestatusicon BS_ATTACKER waitstate @@ -677,7 +677,7 @@ BattleScript_EffectSkyDrop:: attackstring jumpifsubstituteblocks BattleScript_ButItFailed jumpiftargetally BattleScript_ButItFailed - jumpifunder200 BS_TARGET, BattleScript_SkyDropWork + jumpifunder200 BattleScript_SkyDropWork pause B_WAIT_TIME_SHORT printstring STRINGID_TARGETTOOHEAVY waitmessage B_WAIT_TIME_LONG @@ -753,14 +753,14 @@ BattleScript_EffectFling:: jumpiflastuseditemholdeffect HOLD_EFFECT_WHITE_HERB, 0, BattleScript_FlingWhiteHerb goto BattleScript_FlingEnd BattleScript_EffectFlingConsumeBerry: - savebattleritem BS_TARGET - battleritemtolastuseditem BS_TARGET + savebattleritem + battleritemtolastuseditem setbyte sBERRY_OVERRIDE, 1 @ override the requirements for eating berries orword gHitMarker, HITMARKER_DISABLE_ANIMATION consumeberry BS_TARGET, TRUE bicword gHitMarker, HITMARKER_DISABLE_ANIMATION setbyte sBERRY_OVERRIDE, 0 - restorebattleritem BS_TARGET + restorebattleritem BattleScript_FlingEnd: tryfaintmon BS_TARGET trysymbiosis BS_ATTACKER @@ -785,7 +785,7 @@ BattleScript_FlingLightBall: seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_PARALYSIS goto BattleScript_FlingEnd BattleScript_FlingMentalHerb: - curecertainstatuses BS_TARGET + curecertainstatuses savetarget copybyte gBattlerAttacker, gBattlerTarget playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL @@ -801,7 +801,7 @@ BattleScript_FlingToxicOrb: seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_TOXIC goto BattleScript_FlingEnd BattleScript_FlingWhiteHerb: - tryresetnegativestatstages BS_TARGET + tryresetnegativestatstages swapattackerwithtarget printstring STRINGID_PKMNSTATUSNORMAL waitmessage B_WAIT_TIME_MED @@ -815,15 +815,15 @@ BattleScript_FlingMissed: goto BattleScript_MoveMissedPause BattleScript_EffectAuraWheel:: @ Aura Wheel can only be used by Morpeko - jumpifspecies BS_ATTACKER, SPECIES_MORPEKO_FULL_BELLY, BattleScript_EffectHit - jumpifspecies BS_ATTACKER, SPECIES_MORPEKO_HANGRY, BattleScript_EffectHit + jumpifspecies SPECIES_MORPEKO_FULL_BELLY, BattleScript_EffectHit + jumpifspecies SPECIES_MORPEKO_HANGRY, BattleScript_EffectHit goto BattleScript_PokemonCantUseTheMove BattleScript_EffectClangorousSoul:: attackcanceler attackstring ppreduce - cutonethirdhpraisestats BattleScript_ButItFailed + cutonethirdhpandraisestats BattleScript_ButItFailed orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_BIDE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_IGNORE_DISGUISE attackanimation waitanimation @@ -863,7 +863,7 @@ BattleScript_EffectPoltergeist:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - checkpoltergeist BS_TARGET, BattleScript_ButItFailed + checkpoltergeist BattleScript_ButItFailed printstring STRINGID_ABOUTTOUSEPOLTERGEIST waitmessage B_WAIT_TIME_LONG goto BattleScript_HitFromCritCalc @@ -892,7 +892,7 @@ BattleScript_EffectNoRetreat:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - trynoretreat BS_TARGET, BattleScript_ButItFailed + trynoretreat BattleScript_ButItFailed attackanimation waitanimation call BattleScript_AllStatsUp @@ -908,8 +908,8 @@ BattleScript_BothCanNoLongerEscape:: return BattleScript_EffectHyperspaceFury:: - jumpifspecies BS_ATTACKER, SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit - jumpifspecies BS_ATTACKER, SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt + jumpifspecies SPECIES_HOOPA_UNBOUND, BattleScript_EffectHit + jumpifspecies SPECIES_HOOPA_CONFINED, BattleScript_ButHoopaCantUseIt goto BattleScript_PokemonCantUseTheMove BattleScript_ButHoopaCantUseIt: @@ -1024,7 +1024,7 @@ BattleScript_EffectJungleHealing:: attackcanceler attackstring ppreduce - jumpifteamhealthy BS_ATTACKER, BattleScript_ButItFailed + jumpifteamhealthy BattleScript_ButItFailed attackanimation waitanimation copybyte gBattlerTarget, gBattlerAttacker @@ -1170,7 +1170,7 @@ BattleScript_EffectStrengthSap:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_StrengthSapTryLower: - getstatvalue BS_TARGET, STAT_ATK + getstatvalue STAT_ATK jumpiffullhp BS_ATTACKER, BattleScript_StrengthSapMustLower BattleScript_StrengthSapAnimation: attackanimation @@ -1274,7 +1274,7 @@ BattleScript_VCreateStatLossRet: BattleScript_SpectralThiefSteal:: setbyte sB_ANIM_TURN, 1 - playmoveanimation BS_ATTACKER, MOVE_SPECTRAL_THIEF + playmoveanimation MOVE_SPECTRAL_THIEF waitanimation setbyte sB_ANIM_TURN, 0 printstring STRINGID_SPECTRALTHIEFSTEAL @@ -1440,7 +1440,7 @@ BattleScript_EffectAcupressure:: BattleScript_EffectAcupressureTry: attackstring ppreduce - tryaccupressure BS_TARGET, BattleScript_ButItFailed + tryacupressure BattleScript_ButItFailed attackanimation waitanimation statbuffchange BS_TARGET, STAT_CHANGE_CERTAIN, BattleScript_MoveEnd @@ -1458,7 +1458,7 @@ BattleScript_EffectThirdType:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - trysetthirdtype BS_TARGET, BattleScript_ButItFailed + trythirdtype BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_THIRDTYPEADDED @@ -1516,7 +1516,7 @@ BattleScript_RototillerLoop: jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_RototillerCheckAffected jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_RototillerCantRaiseMultipleStats BattleScript_RototillerCheckAffected: - jumpifnotrototilleraffected BS_TARGET, BattleScript_RototillerNoEffect + jumpifnotrototilleraffected BattleScript_RototillerNoEffect setstatchanger STAT_ATK, 1, FALSE statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_RototillerTrySpAtk, BIT_SPATK jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_RototillerTrySpAtk @@ -1588,7 +1588,7 @@ BattleScript_EffectPowerTrick:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - powertrick BS_ATTACKER + powertrick attackanimation waitanimation printstring STRINGID_PKMNSWITCHEDATKANDDEF @@ -1723,7 +1723,7 @@ BattleScript_AutotomizePrintString:: waitmessage B_WAIT_TIME_LONG BattleScript_AutotomizeWeightLoss:: jumpifmovehadnoeffect BattleScript_MoveEnd - tryautotomize BS_ATTACKER, BattleScript_MoveEnd + tryautotomize BattleScript_MoveEnd printstring STRINGID_BECAMENIMBLE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -1877,7 +1877,7 @@ BattleScript_EffectLastResort:: attackcanceler attackstring ppreduce - jumpifcantuselastresort BS_ATTACKER, BattleScript_ButItFailed + trylastresort BattleScript_ButItFailed accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE goto BattleScript_HitFromCritCalc @@ -1890,7 +1890,7 @@ BattleScript_EffectGrowth:: BattleScript_GrowthDoMoveAnim:: attackanimation waitanimation - jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthAtk2 + jumpifweatheraffected B_WEATHER_SUN, BattleScript_GrowthAtk2 setstatchanger STAT_ATK, 1, FALSE goto BattleScript_GrowthAtk BattleScript_GrowthAtk2: @@ -1901,7 +1901,7 @@ BattleScript_GrowthAtk: printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_GrowthTrySpAtk:: - jumpifweatheraffected BS_ATTACKER, B_WEATHER_SUN, BattleScript_GrowthSpAtk2 + jumpifweatheraffected B_WEATHER_SUN, BattleScript_GrowthSpAtk2 setstatchanger STAT_SPATK, 1, FALSE goto BattleScript_GrowthSpAtk BattleScript_GrowthSpAtk2: @@ -2156,7 +2156,7 @@ BattleScript_EffectTopsyTurvy:: BattleScript_EffectTopsyTurvyWorks: attackanimation waitanimation - invertstatstages BS_TARGET + invertstatstages printstring STRINGID_TOPSYTURVYSWITCHEDSTATS waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -2210,7 +2210,7 @@ BattleScript_EffectEntrainment:: tryentrainment BattleScript_ButItFailed attackanimation waitanimation - setlastusedability BS_TARGET + setlastusedability printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -2220,7 +2220,7 @@ BattleScript_EffectSimpleBeam:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - setabilitysimple BS_TARGET, BattleScript_ButItFailed + setsimplebeam BattleScript_ButItFailed attackanimation waitanimation .if B_ABILITY_POP_UP == TRUE @@ -2233,7 +2233,7 @@ BattleScript_EffectSimpleBeam:: trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectSuckerPunch:: @@ -2246,7 +2246,7 @@ BattleScript_EffectLuckyChant:: attackcanceler attackstring ppreduce - setluckychant BS_ATTACKER, BattleScript_ButItFailed + setluckychant BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_SHIELDEDFROMCRITICALHITS @@ -2271,7 +2271,7 @@ BattleScript_EffectHealingWish:: ppreduce attackanimation waitanimation - instanthpdrop BS_ATTACKER + instanthpdrop setatkhptozero tryfaintmon BS_ATTACKER storehealingwish BS_ATTACKER @@ -2299,7 +2299,7 @@ BattleScript_HealingWishActivates:: goto BattleScript_EffectHealingWishRestore BattleScript_LunarDanceActivates:: setbyte cMULTISTRING_CHOOSER, 1 - restorepp BS_ATTACKER + restoremovepp BattleScript_EffectHealingWishRestore: printfromtable gHealingWishStringIds waitmessage B_WAIT_TIME_LONG @@ -2309,7 +2309,7 @@ BattleScript_EffectHealingWishRestore: manipulatedamage DMG_CHANGE_SIGN healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - clearstatus BS_ATTACKER + clearstatus waitstate updatestatusicon BS_ATTACKER waitstate @@ -2335,7 +2335,7 @@ BattleScript_EffectWorrySeed:: trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectPowerSplit:: @@ -2467,7 +2467,7 @@ BattleScript_EffectGastroAcid:: trytoclearprimalweather tryrevertweatherform flushtextbox - tryendneutralizinggas BS_TARGET + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectToxicSpikes:: @@ -2614,7 +2614,7 @@ BattleScript_GravityLoop: jumpifstatus3 BS_TARGET, STATUS3_ON_AIR | STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop goto BattleScript_GravityLoopEnd BattleScript_GravityLoopDrop: - bringdownairbornebattler BS_TARGET + gravityonairbornemons printstring STRINGID_GRAVITYGROUNDING waitmessage B_WAIT_TIME_LONG BattleScript_GravityLoopEnd: @@ -2742,7 +2742,7 @@ BattleScript_MoveMissed:: BattleScript_EffectDarkVoid:: .if B_DARK_VOID_FAIL >= GEN_7 - jumpifspecies BS_ATTACKER, SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus + jumpifspecies SPECIES_DARKRAI, BattleScript_EffectNonVolatileStatus goto BattleScript_PokemonCantUseTheMove .endif @@ -2831,7 +2831,7 @@ BattleScript_InsomniaProtects: goto BattleScript_MoveEnd BattleScript_AlreadyAsleep:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYASLEEP waitmessage B_WAIT_TIME_LONG @@ -3158,7 +3158,7 @@ BattleScript_RestoreHp: goto BattleScript_MoveEnd BattleScript_AlreadyPoisoned:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_LONG printstring STRINGID_PKMNALREADYPOISONED waitmessage B_WAIT_TIME_LONG @@ -3175,7 +3175,7 @@ BattleScript_EffectAuroraVeil:: attackcanceler attackstring ppreduce - setauroraveil BS_ATTACKER + setauroraveil goto BattleScript_PrintReflectLightScreenSafeguardString BattleScript_EffectLightScreen:: @@ -3213,7 +3213,7 @@ BattleScript_RestCantSleep:: goto BattleScript_MoveEnd BattleScript_RestIsAlreadyAsleep:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYASLEEP2 waitmessage B_WAIT_TIME_LONG @@ -3293,7 +3293,7 @@ BattleScript_EffectConfuse:: goto BattleScript_MoveEnd BattleScript_AlreadyConfused:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYCONFUSED waitmessage B_WAIT_TIME_LONG @@ -3395,7 +3395,7 @@ BattleScript_VoltAbsorbHeal: goto BattleScript_MoveHPDrain BattleScript_AlreadyParalyzed:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNISALREADYPARALYZED waitmessage B_WAIT_TIME_LONG @@ -3414,7 +3414,7 @@ BattleScript_EffectTwoTurnsAttack:: tryfiretwoturnmovewithoutcharging BS_ATTACKER, BattleScript_EffectHit @ e.g. Solar Beam call BattleScript_FirstChargingTurn tryfiretwoturnmoveaftercharging BS_ATTACKER, BattleScript_TwoTurnMovesSecondTurn @ e.g. Electro Shot - jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_TwoTurnMovesSecondPowerHerbActivates + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POWER_HERB, BattleScript_TwoTurnMovesSecondPowerHerbActivates, TRUE goto BattleScript_MoveEnd BattleScript_EffectGeomancy:: @@ -3515,7 +3515,7 @@ BattleScript_SubstituteString:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd BattleScript_AlreadyHasSubstitute:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNHASSUBSTITUTE waitmessage B_WAIT_TIME_LONG @@ -3870,7 +3870,7 @@ BattleScript_CurseEnd:: goto BattleScript_MoveEnd BattleScript_GhostCurse:: jumpifbytenotequal gBattlerAttacker, gBattlerTarget, BattleScript_DoGhostCurse - getmovetarget BS_ATTACKER + getmovetarget BattleScript_DoGhostCurse:: attackcanceler attackstring @@ -3944,7 +3944,7 @@ BattleScript_EffectPerishSong:: setbyte gBattlerTarget, 0 BattleScript_PerishSongLoop:: jumpifblockedbysoundproof BS_TARGET, BattleScript_PerishSongBlocked - jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected + jumpifpranksterblocked BattleScript_PerishSongNotAffected BattleScript_PerishSongLoopIncrement:: addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop @@ -4269,14 +4269,14 @@ BattleScript_EffectTeleport:: attackcanceler attackstring ppreduce - getifcantrunfrombattle BS_ATTACKER + isrunningimpossible jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective attackanimation waitanimation printstring STRINGID_PKMNFLEDFROMBATTLE waitmessage B_WAIT_TIME_LONG - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER goto BattleScript_MoveEnd BattleScript_EffectBeatUp:: @@ -4557,7 +4557,7 @@ BattleScript_EffectNonVolatileStatus:: goto BattleScript_MoveEnd BattleScript_AlreadyBurned:: - setalreadystatusedmoveattempt BS_ATTACKER + setalreadystatusedmoveattempt pause B_WAIT_TIME_SHORT printstring STRINGID_PKMNALREADYHASBURN waitmessage B_WAIT_TIME_LONG @@ -5074,7 +5074,7 @@ BattleScript_FaintAttacker:: cleareffectsonfaint BS_ATTACKER tryactivatesoulheart tryactivatereceiver BS_ATTACKER - trytrainerslidefirstdownmsg BS_ATTACKER + trytrainerslidemsgfirstoff BS_ATTACKER return BattleScript_FaintTarget:: @@ -5088,7 +5088,7 @@ BattleScript_FaintTarget:: cleareffectsonfaint BS_TARGET tryactivatesoulheart tryactivatereceiver BS_TARGET - trytrainerslidefirstdownmsg BS_TARGET + trytrainerslidemsgfirstoff BS_TARGET return BattleScript_GiveExp:: @@ -5134,7 +5134,7 @@ BattleScript_FaintedMonTryChoose: jumpifbyte CMP_EQUAL, gBattleCommunication, PARTY_SIZE, BattleScript_FaintedMonSendOutNew @ Switch Pokémon before opponent atknameinbuff1 - resetswitchinabilitybits BS_ATTACKER + resetswitchinabilitybits hpthresholds2 BS_ATTACKER printstring STRINGID_RETURNMON switchoutabilities BS_ATTACKER @@ -5164,7 +5164,7 @@ BattleScript_FaintedMonSendOutNew: switchinanim BS_FAINTED, FALSE, FALSE waitstate resetplayerfainted - trytrainerslidelastonmsg BS_FAINTED + trytrainerslidemsglaston BS_FAINTED jumpifbytenotequal sSHIFT_SWITCHED, sZero, BattleScript_FaintedMonShiftSwitched BattleScript_FaintedMonSendOutNewEnd: switchineffects BS_FAINTED @@ -5264,9 +5264,9 @@ BattleScript_CheckDomeDrew:: jumpifbyte CMP_EQUAL, gBattleOutcome, B_OUTCOME_DREW, BattleScript_LocalBattleLostEnd_ BattleScript_LocalBattleLostPrintTrainersWinText:: jumpifnotbattletype BATTLE_TYPE_TRAINER, BattleScript_LocalBattleLostPrintWhiteOut - returnopponentmon1toball BS_ATTACKER + returnopponentmon1toball waitstate - returnopponentmon2toball BS_ATTACKER + returnopponentmon2toball waitstate trainerslidein BS_OPPONENT1 waitstate @@ -5283,9 +5283,9 @@ BattleScript_LocalBattleLostEnd_:: end2 BattleScript_FrontierLinkBattleLost:: - returnopponentmon1toball BS_ATTACKER + returnopponentmon1toball waitstate - returnopponentmon2toball BS_ATTACKER + returnopponentmon2toball waitstate trainerslidein BS_OPPONENT1 waitstate @@ -5312,7 +5312,7 @@ BattleScript_LinkBattleWonOrLostWaitEnd:: end2 BattleScript_TowerLinkBattleWon:: - playtrainerdefeatbgm BS_ATTACKER + playtrainerdefeatedmusic printstring STRINGID_BATTLEEND waitmessage B_WAIT_TIME_LONG trainerslidein BS_OPPONENT1 @@ -5456,7 +5456,7 @@ BattleScript_LearnedNewMove:: fanfare MUS_LEVEL_UP printstring STRINGID_PKMNLEARNEDMOVE waitmessage B_WAIT_TIME_LONG - updatechoicemoveonlvlup BS_ATTACKER + updatechoicemoveonlvlup goto BattleScript_TryLearnMoveLoop BattleScript_LearnMoveReturn:: return @@ -5691,7 +5691,7 @@ BattleScript_RoarSuccessSwitch_Ret: BattleScript_RoarSuccessEndBattle:: call BattleScript_RoarSuccessRet setbyte sSWITCH_CASE, B_SWITCH_NORMAL - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER finishaction BattleScript_RoarSuccessRet: @@ -6661,12 +6661,12 @@ BattleScript_IllusionOffEnd3:: end3 BattleScript_IllusionOff:: - spriteignore0hp TRUE + setspriteignore0hp TRUE playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF waitanimation - updatenick BS_SCRIPTING + updatenick waitstate - spriteignore0hp FALSE + setspriteignore0hp FALSE printstring STRINGID_ILLUSIONWOREOFF waitmessage B_WAIT_TIME_LONG return @@ -6814,7 +6814,7 @@ BattleScript_MoveUsedIsParalyzed:: printstring STRINGID_PKMNISPARALYZED waitmessage B_WAIT_TIME_LONG statusanimation BS_ATTACKER - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves goto BattleScript_MoveEnd BattleScript_PowderMoveNoEffect:: @@ -6831,7 +6831,7 @@ BattleScript_PowderMoveNoEffectPrint: printstring STRINGID_ITDOESNTAFFECT BattleScript_PowderMoveNoEffectWaitMsg: waitmessage B_WAIT_TIME_LONG - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd @@ -6849,7 +6849,7 @@ BattleScript_TryActivateSteadFast: call BattleScript_AbilityPopUp statbuffchange BS_ATTACKER, STAT_CHANGE_ALLOW_PTR, BattleScript_MoveUsedFlinchedEnd setbyte gBattleCommunication STAT_SPEED - stattextbuffer BS_ATTACKER + stattextbuffer printstring STRINGID_ATTACKERABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveUsedFlinchedEnd @@ -6871,7 +6871,7 @@ BattleScript_MoveUsedIsConfused:: volatileanimation BS_ATTACKER, VOLATILE_CONFUSION jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, FALSE, BattleScript_MoveUsedIsConfusedRet BattleScript_DoSelfConfusionDmg:: - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves adjustdamage printstring STRINGID_ITHURTCONFUSION waitmessage B_WAIT_TIME_LONG @@ -6893,7 +6893,7 @@ BattleScript_MoveUsedPowder:: attackstring ppreduce pause B_WAIT_TIME_SHORT - cancelmultiturnmoves BS_ATTACKER + cancelmultiturnmoves volatileanimation BS_ATTACKER, VOLATILE_POWDER waitanimation effectivenesssound @@ -7146,7 +7146,7 @@ BattleScript_AbilityPopUpTarget:: BattleScript_AbilityPopUp:: tryactivateabilityshield BS_ABILITY_BATTLER .if B_ABILITY_POP_UP == TRUE - showabilitypopup BS_ABILITY_BATTLER + showabilitypopup pause B_WAIT_TIME_SHORT .endif recordability BS_ABILITY_BATTLER @@ -7159,10 +7159,10 @@ BattleScript_AbilityPopUpScripting: BattleScript_AbilityPopUpOverwriteThenNormal: setbyte sFIXED_ABILITY_POPUP, TRUE - showabilitypopup BS_ABILITY_BATTLER + showabilitypopup pause B_WAIT_TIME_SHORT sethword sABILITY_OVERWRITE, 0 - updateabilitypopup BS_ABILITY_BATTLER + updateabilitypopup pause B_WAIT_TIME_SHORT recordability BS_ABILITY_BATTLER destroyabilitypopup @@ -7229,7 +7229,7 @@ BattleScript_EmergencyExitWild:: .endif playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN waitanimation - setoutcomeonteleport BS_SCRIPTING + setteleportoutcome BS_SCRIPTING finishaction return @@ -7260,7 +7260,7 @@ BattleScript_EmergencyExitWildEnd2:: pause B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_SLIDE_OFFSCREEN waitanimation - setoutcomeonteleport BS_ATTACKER + setteleportoutcome BS_ATTACKER finishaction end2 @@ -7667,7 +7667,7 @@ BattleScript_ActivateTerrainEffects: setbyte gBattlerAttacker, 0 BattleScript_ActivateTerrainSeed: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 - doterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility + tryterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility removeitem BS_TARGET BattleScript_ActivateTerrainAbility: activateterrainchangeabilities BS_TARGET @@ -8118,7 +8118,7 @@ BattleScript_FriskActivates:: saveattacker savetarget copybyte gBattlerAttacker, sBATTLER - tryfriskmsg BS_SCRIPTING + tryfriskmessage restoreattacker restoretarget end3 @@ -8126,7 +8126,7 @@ BattleScript_FriskActivates:: BattleScript_ImposterActivates:: call BattleScript_AbilityPopUp transformdataexecution - playmoveanimation BS_ATTACKER, MOVE_TRANSFORM + playmoveanimation MOVE_TRANSFORM waitanimation printstring STRINGID_IMPOSTERTRANSFORM waitmessage B_WAIT_TIME_LONG @@ -8298,7 +8298,7 @@ BattleScript_MoveUsedLoafingAround:: @ Skip ahead if not the Battle Palace message jumpifbyte CMP_NOT_EQUAL, cMULTISTRING_CHOOSER, B_MSG_INCAPABLE_OF_POWER, BattleScript_MoveUsedLoafingAroundMsg setbyte gBattleCommunication, 0 - palacetryescapestatus BS_ATTACKER + palacetryescapestatus setbyte cMULTISTRING_CHOOSER, B_MSG_INCAPABLE_OF_POWER BattleScript_MoveUsedLoafingAroundMsg:: printfromtable gInobedientStringIds @@ -8669,7 +8669,7 @@ BattleScript_FlushMessageBox:: BattleScript_PalacePrintFlavorText:: setbyte gBattleCommunication + 1, 0 BattleScript_PalaceTryBattlerFlavorText:: - palaceflavortext BS_ATTACKER @ BS_ATTACKER here overwritten by gBattleCommunication + 1 + palaceflavortext jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, TRUE, BattleScript_PalaceEndFlavorText printfromtable gBattlePalaceFlavorTextTable waitmessage B_WAIT_TIME_LONG @@ -8681,16 +8681,16 @@ BattleScript_PalaceEndFlavorText:: end2 BattleScript_ArenaTurnBeginning:: - waitcry BS_ATTACKER + waitcry volumedown playse SE_ARENA_TIMEUP1 pause 8 playse SE_ARENA_TIMEUP1 - arenadrawreftextbox + drawarenareftextbox arenajudgmentstring B_MSG_REF_COMMENCE_BATTLE arenawaitmessage B_MSG_REF_COMMENCE_BATTLE pause B_WAIT_TIME_LONG - arenaerasereftextbox + erasearenareftextbox volumeup end2 @@ -8704,7 +8704,7 @@ BattleScript_ArenaDoJudgment:: pause 8 playse SE_ARENA_TIMEUP1 pause B_WAIT_TIME_LONG - arenadrawreftextbox + drawarenareftextbox arenajudgmentstring B_MSG_REF_THATS_IT arenawaitmessage B_MSG_REF_THATS_IT pause B_WAIT_TIME_LONG @@ -8727,11 +8727,11 @@ BattleScript_ArenaDoJudgment:: arenajudgmentstring B_MSG_REF_PLAYER_WON arenawaitmessage B_MSG_REF_PLAYER_WON arenajudgmentwindow - arenaerasereftextbox + erasearenareftextbox printstring STRINGID_DEFEATEDOPPONENTBYREFEREE waitmessage B_WAIT_TIME_LONG playfaintcry BS_OPPONENT1 - waitcry BS_ATTACKER + waitcry dofaintanimation BS_OPPONENT1 cleareffectsonfaint BS_OPPONENT1 arenaopponentmonlost @@ -8741,11 +8741,11 @@ BattleScript_ArenaJudgmentPlayerLoses: arenajudgmentstring B_MSG_REF_OPPONENT_WON arenawaitmessage B_MSG_REF_OPPONENT_WON arenajudgmentwindow - arenaerasereftextbox + erasearenareftextbox printstring STRINGID_LOSTTOOPPONENTBYREFEREE waitmessage B_WAIT_TIME_LONG playfaintcry BS_PLAYER1 - waitcry BS_ATTACKER + waitcry dofaintanimation BS_PLAYER1 cleareffectsonfaint BS_PLAYER1 arenaplayermonlost @@ -8755,23 +8755,23 @@ BattleScript_ArenaJudgmentDraw: arenajudgmentstring B_MSG_REF_DRAW arenawaitmessage B_MSG_REF_DRAW arenajudgmentwindow - arenaerasereftextbox + erasearenareftextbox printstring STRINGID_TIEDOPPONENTBYREFEREE waitmessage B_WAIT_TIME_LONG playfaintcry BS_PLAYER1 - waitcry BS_ATTACKER + waitcry dofaintanimation BS_PLAYER1 cleareffectsonfaint BS_PLAYER1 playfaintcry BS_OPPONENT1 - waitcry BS_ATTACKER + waitcry dofaintanimation BS_OPPONENT1 cleareffectsonfaint BS_OPPONENT1 - arenabothmonlost + arenabothmonslost end2 BattleScript_AskIfWantsToForfeitMatch:: printselectionstring STRINGID_QUESTIONFORFEITMATCH - forfeityesnobox BS_ATTACKER + forfeityesnobox endselectionscript BattleScript_PrintPlayerForfeited:: @@ -9074,7 +9074,7 @@ BattleScript_Pickpocket:: swapattackerwithtarget call BattleScript_ItemSteal swapattackerwithtarget - activateitemeffects BS_TARGET + activateitemeffects return BattleScript_PickpocketPrevented: @@ -9536,7 +9536,7 @@ BattleScript_RaiseCritAlliesEnd: goto BattleScript_MoveEnd BattleScript_EffectHealOneSixthAllies:: - jumpifteamhealthy BS_ATTACKER, BattleScript_MoveEnd + jumpifteamhealthy BattleScript_MoveEnd savetarget copybyte gBattlerTarget, gBattlerAttacker BattleScript_HealOneSixthAlliesLoop: @@ -9617,11 +9617,11 @@ BattleScript_DynamaxEnds:: BattleScript_DynamaxEnds_Ret:: flushtextbox - spriteignore0hp TRUE + setspriteignore0hp TRUE updatedynamax playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE waitanimation - spriteignore0hp FALSE + setspriteignore0hp FALSE pause B_WAIT_TIME_SHORT return @@ -9720,7 +9720,7 @@ BattleScript_SleepClausePreventsEnd:: BattleScript_QuestionForfeitBattle:: printselectionstring STRINGID_QUESTIONFORFEITBATTLE - forfeityesnobox BS_ATTACKER + forfeityesnobox endselectionscript BattleScript_ForfeitBattleGaveMoney:: diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 004b4ca8ab..0e0f43893e 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -131,7 +131,7 @@ BattleScript_PokeFluteEnd:: BattleScript_ItemSetMist:: call BattleScript_UseItemMessage setmist - playmoveanimation BS_ATTACKER, MOVE_MIST + playmoveanimation MOVE_MIST waitanimation printfromtable gMistUsedStringIds waitmessage B_WAIT_TIME_LONG @@ -142,7 +142,7 @@ BattleScript_ItemSetFocusEnergy:: jumpifvolatile BS_ATTACKER, VOLATILE_DRAGON_CHEER, BattleScript_ButItFailed jumpifvolatile BS_ATTACKER, VOLATILE_FOCUS_ENERGY, BattleScript_ButItFailed setfocusenergy BS_ATTACKER - playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY + playmoveanimation MOVE_FOCUS_ENERGY waitanimation copybyte sBATTLER, gBattlerAttacker printstring STRINGID_PKMNUSEDXTOGETPUMPED diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 02f0bc2813..2d50ec1e4f 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -88,123 +88,10 @@ #define CMP_COMMON_BITS 4 #define CMP_NO_COMMON_BITS 5 +// Veriouses have been deprecated but the enum and function will be supported for one more release cycle enum CmdVarious { - VARIOUS_CANCEL_MULTI_TURN_MOVES, - VARIOUS_IS_RUNNING_IMPOSSIBLE, - VARIOUS_GET_MOVE_TARGET, - VARIOUS_GET_BATTLER_FAINTED, - VARIOUS_RESET_SWITCH_IN_ABILITY_BITS, - VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP, - VARIOUS_RESET_PLAYER_FAINTED, - VARIOUS_PALACE_FLAVOR_TEXT, - VARIOUS_ARENA_JUDGMENT_WINDOW, - VARIOUS_ARENA_OPPONENT_MON_LOST, - VARIOUS_ARENA_PLAYER_MON_LOST, - VARIOUS_ARENA_BOTH_MONS_LOST, - VARIOUS_EMIT_YESNOBOX, - VARIOUS_DRAW_ARENA_REF_TEXT_BOX, - VARIOUS_ERASE_ARENA_REF_TEXT_BOX, - VARIOUS_ARENA_JUDGMENT_STRING, - VARIOUS_ARENA_WAIT_STRING, - VARIOUS_WAIT_CRY, - VARIOUS_RETURN_OPPONENT_MON1, - VARIOUS_RETURN_OPPONENT_MON2, - VARIOUS_VOLUME_DOWN, - VARIOUS_VOLUME_UP, - VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT, - VARIOUS_PALACE_TRY_ESCAPE_STATUS, - VARIOUS_SET_TELEPORT_OUTCOME, - VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC, - VARIOUS_STAT_TEXT_BUFFER, - VARIOUS_SWITCHIN_ABILITIES, - VARIOUS_INSTANT_HP_DROP, - VARIOUS_CLEAR_STATUS, - VARIOUS_RESTORE_PP, - VARIOUS_PLAY_MOVE_ANIMATION, - VARIOUS_SET_LUCKY_CHANT, - VARIOUS_SUCKER_PUNCH_CHECK, - VARIOUS_SET_SIMPLE_BEAM, - VARIOUS_TRY_ENTRAINMENT, - VARIOUS_SET_LAST_USED_ABILITY, - VARIOUS_INVERT_STAT_STAGES, - VARIOUS_TRY_ME_FIRST, - VARIOUS_JUMP_IF_BATTLE_END, - VARIOUS_TRY_ELECTRIFY, - VARIOUS_TRY_SOAK, - VARIOUS_TRY_LAST_RESORT, - VARIOUS_TRY_AUTOTOMIZE, - VARIOUS_ABILITY_POPUP, - VARIOUS_JUMP_IF_TARGET_ALLY, - VARIOUS_TRY_SYNCHRONOISE, - VARIOUS_PSYCHO_SHIFT, - VARIOUS_CURE_STATUS, - VARIOUS_POWER_TRICK, - VARIOUS_AFTER_YOU, - VARIOUS_BESTOW, - VARIOUS_JUMP_IF_NOT_GROUNDED, - VARIOUS_HANDLE_TRAINER_SLIDE_MSG, - VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF, - VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON, - VARIOUS_SET_AURORA_VEIL, - VARIOUS_TRY_THIRD_TYPE, - VARIOUS_ACUPRESSURE, - VARIOUS_GRAVITY_ON_AIRBORNE_MONS, - VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, - VARIOUS_JUMP_IF_ROAR_FAILS, - VARIOUS_TRY_INSTRUCT, - VARIOUS_JUMP_IF_NOT_BERRY, - VARIOUS_TRACE_ABILITY, - VARIOUS_UPDATE_NICK, - VARIOUS_TRY_ILLUSION_OFF, - VARIOUS_SET_SPRITEIGNORE0HP, - VARIOUS_HANDLE_FORM_CHANGE, - VARIOUS_GET_STAT_VALUE, - VARIOUS_JUMP_IF_FULL_HP, - VARIOUS_LOSE_TYPE, - VARIOUS_TRY_ACTIVATE_SOULHEART, - VARIOUS_TRY_ACTIVATE_RECEIVER, - VARIOUS_TRY_FRISK, - VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, - VARIOUS_TRY_FAIRY_LOCK, - VARIOUS_JUMP_IF_NO_ALLY, - VARIOUS_JUMP_IF_HOLD_EFFECT, - VARIOUS_INFATUATE_WITH_BATTLER, - VARIOUS_SET_LAST_USED_ITEM, - VARIOUS_JUMP_IF_ABSENT, - VARIOUS_DESTROY_ABILITY_POPUP, - VARIOUS_TOTEM_BOOST, - VARIOUS_MOVEEND_ITEM_EFFECTS, - VARIOUS_TERRAIN_SEED, - VARIOUS_MAKE_INVISIBLE, - VARIOUS_ROOM_SERVICE, - VARIOUS_JUMP_IF_TEAM_HEALTHY, - VARIOUS_TRY_HEAL_QUARTER_HP, - VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, - VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, - VARIOUS_GET_ROTOTILLER_TARGETS, - VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, - VARIOUS_CONSUME_BERRY, - VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, - VARIOUS_JUMP_IF_SPECIES, - VARIOUS_UPDATE_ABILITY_POPUP, - VARIOUS_JUMP_IF_WEATHER_AFFECTED, - VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED, - VARIOUS_SET_ATTACKER_STICKY_WEB_USER, - VARIOUS_TRY_NO_RETREAT, - VARIOUS_CHECK_POLTERGEIST, - VARIOUS_CUT_1_3_HP_RAISE_STATS, - VARIOUS_TRY_END_NEUTRALIZING_GAS, - VARIOUS_JUMP_IF_UNDER_200, - VARIOUS_SET_SKY_DROP, - VARIOUS_CLEAR_SKY_DROP, - VARIOUS_SKY_DROP_YAWN, - VARIOUS_CURE_CERTAIN_STATUSES, - VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES, - VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY, - VARIOUS_SAVE_BATTLER_ITEM, - VARIOUS_RESTORE_BATTLER_ITEM, - VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, + VARIOUS_NONE, }; // Cmd_manipulatedamage diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 533c25171f..7f816f1f37 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6716,7 +6716,7 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.battler = battler; - + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler)) BattleScriptCall(BattleScript_EmergencyExit); else @@ -9562,3440 +9562,3283 @@ static bool32 ChangeOrderTargetAfterAttacker(void) return TRUE; } +// will be deprecated next release cycle static void Cmd_various(void) { CMD_ARGS(u8 battler, u8 id); - struct Pokemon *mon; - s32 i; - u8 data[10]; - u32 battler, bits; - enum CmdVarious variousId = cmd->id; - if (gBattleControllerExecFlags) return; - battler = GetBattlerForBattleScript(cmd->battler); + gBattlescriptCurrInstr = cmd->nextInstr; +} - switch (variousId) - { - // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. - // Also when an opposing wild mon uses it againt its partner. - // Also when B_FLAG_NO_RUNNING is enabled. - case VARIOUS_JUMP_IF_ROAR_FAILS: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (WILD_DOUBLE_BATTLE - && IsOnPlayerSide(gBattlerAttacker) - && !IsOnPlayerSide(gBattlerTarget) - && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else if (WILD_DOUBLE_BATTLE - && !IsOnPlayerSide(gBattlerAttacker) - && !IsOnPlayerSide(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else if (FlagGet(B_FLAG_NO_RUNNING)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_ABSENT: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlive(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED: +static void TryResetProtectUseCounter(u32 battler) +{ + u32 lastMove = gLastResultingMoves[battler]; + enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove); + if (lastMove == MOVE_UNAVAILABLE + || (!gBattleMoveEffects[lastEffect].usesProtectCounter + && ((B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) + || B_ALLY_SWITCH_FAIL_CHANCE < GEN_9))) + gDisableStructs[battler].protectUses = 0; +} + +static void Cmd_setprotectlike(void) +{ + CMD_ARGS(); + + bool32 protectFails = TRUE; + bool32 notLastTurn = TRUE; + u32 protectMethod = GetMoveProtectMethod(gCurrentMove); + + TryResetProtectUseCounter(gBattlerAttacker); + + if (gCurrentTurnActionNumber == (gBattlersCount - 1)) + notLastTurn = FALSE; + + if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= Random() && notLastTurn) + || (protectMethod == PROTECT_WIDE_GUARD && B_WIDE_GUARD != GEN_5) + || (protectMethod == PROTECT_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsShieldsDownProtected(battler, GetBattlerAbility(battler))) - { - gBattlerAbility = battler; - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else + if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) { - gBattlescriptCurrInstr = cmd->nextInstr; + gProtectStructs[gBattlerAttacker].endured = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; } - return; - } - case VARIOUS_JUMP_IF_HOLD_EFFECT: - { - VARIOUS_ARGS(u8 holdEffect, const u8 *jumpInstr, u8 equal); - if ((GetBattlerHoldEffect(battler, TRUE) == cmd->holdEffect) == cmd->equal) + else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE) { - if (cmd->equal) - gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM - gBattlescriptCurrInstr = cmd->jumpInstr; + gProtectStructs[gBattlerAttacker].protected = protectMethod; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; } else { - if (!cmd->equal) - gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM - gBattlescriptCurrInstr = cmd->nextInstr; + gProtectStructs[gBattlerAttacker].protected = protectMethod; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; } - return; + + gDisableStructs[gBattlerAttacker].protectUses++; + protectFails = FALSE; } - case VARIOUS_JUMP_IF_NO_ALLY: + + if (protectFails) { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlive(BATTLE_PARTNER(battler))) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gDisableStructs[gBattlerAttacker].protectUses = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECT_FAILED; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; } - case VARIOUS_INFATUATE_WITH_BATTLER: - { - VARIOUS_ARGS(u8 infatuateWith); - gBattleScripting.battler = battler; - gBattleMons[battler].volatiles.infatuation = INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); - gBattlescriptCurrInstr = cmd->nextInstr; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_tryexplosion(void) +{ + CMD_ARGS(); + + if (gBattleControllerExecFlags) return; - } - case VARIOUS_SET_LAST_USED_ITEM: + + gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; + BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_setatkhptozero(void) +{ + CMD_ARGS(); + + if (gBattleControllerExecFlags) + return; + + gBattleMons[gBattlerAttacker].hp = 0; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].hp), &gBattleMons[gBattlerAttacker].hp); + MarkBattlerForControllerExec(gBattlerAttacker); + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_jumpifnexttargetvalid(void) +{ + CMD_ARGS(const u8 *jumpInstr); + + const u8 *jumpInstr = cmd->jumpInstr; + + for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++) { - VARIOUS_ARGS(); - gLastUsedItem = gBattleMons[battler].item; - break; + if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + continue; + if (IsBattlerAlive(gBattlerTarget)) + break; } - case VARIOUS_TRY_FAIRY_LOCK: + + if (gBattlerTarget >= gBattlersCount) { - VARIOUS_ARGS(const u8 *failInstr); - if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gFieldStatuses |= STATUS_FIELD_FAIRY_LOCK; - gFieldTimers.fairyLockTimer = gBattleTurnCounter + 2; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; + gBattlerTarget = gBattlersCount - 1; + gBattlescriptCurrInstr = cmd->nextInstr; } - case VARIOUS_GET_STAT_VALUE: + else { - VARIOUS_ARGS(u8 stat); - i = cmd->stat; - gBattleStruct->moveDamage[gBattlerAttacker] = *(u16 *)(&gBattleMons[battler].attack) + (i - 1); - gBattleStruct->moveDamage[gBattlerAttacker] *= gStatStageRatios[gBattleMons[battler].statStages[i]][0]; - gBattleStruct->moveDamage[gBattlerAttacker] /= gStatStageRatios[gBattleMons[battler].statStages[i]][1]; + gBattlescriptCurrInstr = jumpInstr; + } +} + +static void Cmd_tryhealhalfhealth(void) +{ + CMD_ARGS(const u8 *failInstr, u8 battler); + + const u8 *failInstr = cmd->failInstr; + + if (cmd->battler == BS_ATTACKER) + gBattlerTarget = gBattlerAttacker; + + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = 1; + gBattleStruct->moveDamage[gBattlerTarget] *= -1; + + if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) + gBattlescriptCurrInstr = failInstr; + else gBattlescriptCurrInstr = cmd->nextInstr; - return; +} + +static void SetMoveForMirrorMove(u32 move) +{ + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + // Edge case, we used Z Mirror Move, got the stat boost and now need to use the Z-move + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + { + gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; + gCurrentMove = GetTypeBasedZMove(move); } - case VARIOUS_JUMP_IF_FULL_HP: + else { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsBattlerAtMaxHp(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gCurrentMove = move; } - case VARIOUS_TRY_FRISK: + + gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + ResetValuesForCalledMove(); + gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); +} + +static void Cmd_trymirrormove(void) +{ + CMD_ARGS(); + + s32 i, validMovesCount; + u16 move; + u16 validMoves[MAX_BATTLERS_COUNT] = {0}; + + for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) { - VARIOUS_ARGS(); - while (gBattleStruct->friskedBattler < gBattlersCount) + if (i != gBattlerAttacker) { - gBattlerTarget = gBattleStruct->friskedBattler++; - if (!IsBattlerAlly(battler, gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattleMons[gBattlerTarget].item != ITEM_NONE) + move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; + if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) { - gLastUsedItem = gBattleMons[gBattlerTarget].item; - RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffect(gBattlerTarget, FALSE)); - // If Frisk identifies two mons' items, show the pop-up only once. - if (gBattleStruct->friskedAbility) - { - BattleScriptCall(BattleScript_FriskMsg); - } - else - { - gBattleStruct->friskedAbility = TRUE; - BattleScriptCall(BattleScript_FriskMsgWithPopup); - } - return; + validMoves[validMovesCount] = move; + validMovesCount++; } } - gBattleStruct->friskedBattler = 0; - gBattleStruct->friskedAbility = FALSE; - break; } - case VARIOUS_TRACE_ABILITY: + + move = gBattleStruct->lastTakenMove[gBattlerAttacker]; + if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) { - VARIOUS_ARGS(); - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = gBattleStruct->tracedAbility[battler]; - break; + SetMoveForMirrorMove(move); } - case VARIOUS_TRY_ILLUSION_OFF: + else if (validMovesCount != 0) { - VARIOUS_ARGS(); - if (TryClearIllusion(battler, ABILITYEFFECT_MOVE_END)) - return; - break; + SetMoveForMirrorMove(validMoves[Random() % validMovesCount]); } - case VARIOUS_SET_SPRITEIGNORE0HP: + else // no valid moves found { - VARIOUS_ARGS(bool8 ignore0HP); - gBattleStruct->spriteIgnore0Hp = cmd->ignore0HP; gBattlescriptCurrInstr = cmd->nextInstr; - return; } - case VARIOUS_UPDATE_NICK: - { - VARIOUS_ARGS(); - mon = GetBattlerMon(battler); - UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_NICK); - break; - } - case VARIOUS_JUMP_IF_NOT_BERRY: +} + +static void Cmd_setfieldweather(void) +{ + CMD_ARGS(u8 weather); + + u8 battleWeatherId = cmd->weather; + + if (!TryChangeBattleWeather(gBattlerAttacker, battleWeatherId, FALSE)) { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_FAILED; + gBattlescriptCurrInstr = cmd->nextInstr; return; } - case VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS: - { - VARIOUS_ARGS(const u8 *failInstr); - if ((gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK)) - || IsBattlerAtMaxHp(battler) - || !gBattleMons[battler].hp - || !(IsBattlerGrounded(battler))) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_GRAVITY_ON_AIRBORNE_MONS: + switch (battleWeatherId) { - VARIOUS_ARGS(); - // Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop. - if (gStatuses3[battler] & STATUS3_ON_AIR && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) - CancelMultiTurnMoves(battler, SKY_DROP_GRAVITY_ON_AIRBORNE); - - gStatuses3[battler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); + case BATTLE_WEATHER_RAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_RAIN; break; - } - case VARIOUS_ACUPRESSURE: - { - VARIOUS_ARGS(const u8 *failInstr); - bits = 0; - for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) - { - if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - bits |= 1u << i; - } - if (bits) - { - u32 statId; - do - { - statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1; - } while (!(bits & (1u << statId))); - - SET_STATCHANGER(statId, 2, FALSE); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_CANCEL_MULTI_TURN_MOVES: - { - VARIOUS_ARGS(); - const u8 *result; - result = CancelMultiTurnMoves(battler, SKY_DROP_CANCEL_MULTI_TURN_MOVES); - if (result) - { - gBattlescriptCurrInstr = result; - return; - } - break; - } - case VARIOUS_IS_RUNNING_IMPOSSIBLE: - { - VARIOUS_ARGS(); - gBattleCommunication[0] = IsRunningFromBattleImpossible(battler); + case BATTLE_WEATHER_SUN: + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SUNLIGHT; break; - } - case VARIOUS_GET_MOVE_TARGET: - { - VARIOUS_ARGS(); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + case BATTLE_WEATHER_SANDSTORM: + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SANDSTORM; break; - } - case VARIOUS_GET_BATTLER_FAINTED: - { - VARIOUS_ARGS(); - if (gHitMarker & HITMARKER_FAINTED(battler)) - gBattleCommunication[0] = TRUE; - else - gBattleCommunication[0] = FALSE; + case BATTLE_WEATHER_HAIL: + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_HAIL; break; - } - case VARIOUS_RESET_SWITCH_IN_ABILITY_BITS: - { - VARIOUS_ARGS(); - gSpecialStatuses[battler].switchInAbilityDone = FALSE; + case BATTLE_WEATHER_SNOW: + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SNOW; break; } - case VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP: - { - VARIOUS_ARGS(); - if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId || gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) - { - if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId) - battler = 0; - else - battler = 2; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[battler].moves[i] == gBattleStruct->choicedMove[battler]) - break; - } - if (i == MAX_MON_MOVES) - gBattleStruct->choicedMove[battler] = MOVE_NONE; - } - break; - } - case VARIOUS_RESET_PLAYER_FAINTED: - { - VARIOUS_ARGS(); - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE)) - && gBattleTypeFlags & BATTLE_TYPE_TRAINER - && IsBattlerAlive(B_POSITION_PLAYER_LEFT) - && IsBattlerAlive(B_POSITION_OPPONENT_LEFT)) - { - gHitMarker &= ~HITMARKER_PLAYER_FAINTED; - } - break; - } - case VARIOUS_PALACE_FLAVOR_TEXT: + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_setreflect(void) +{ + CMD_ARGS(); + if (!TrySetReflect(gBattlerAttacker)) { - VARIOUS_ARGS(); - // Try and print end-of-turn Battle Palace flavor text (e.g. "A glint appears in mon's eyes") - gBattleCommunication[0] = FALSE; // whether or not msg should be printed - gBattleScripting.battler = battler = gBattleCommunication[1]; - if (!(gBattleStruct->palaceFlags & (1u << battler)) - && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp - && IsBattlerAlive(battler) - && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) - { - gBattleStruct->palaceFlags |= 1u << battler; - gBattleCommunication[0] = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = gNaturesInfo[GetNatureFromPersonality(gBattleMons[battler].personality)].battlePalaceFlavorText; - } - break; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; } - case VARIOUS_ARENA_JUDGMENT_WINDOW: - { - VARIOUS_ARGS(); - i = BattleArena_ShowJudgmentWindow(&gBattleCommunication[0]); + gBattlescriptCurrInstr = cmd->nextInstr; +} - // BattleArena_ShowJudgmentWindow's last state was an intermediate step. - // Return without advancing the current instruction so that it will be called again. - if (i == ARENA_RESULT_RUNNING) - return; +static void Cmd_setseeded(void) +{ + CMD_ARGS(); - gBattleCommunication[1] = i; - break; - } - case VARIOUS_ARENA_OPPONENT_MON_LOST: + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED) { - VARIOUS_ARGS(); - gBattleMons[1].hp = 0; - gHitMarker |= HITMARKER_FAINTED(1); - gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; - gDisableStructs[1].truantSwitchInHack = 1; - break; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_MISS; } - case VARIOUS_ARENA_PLAYER_MON_LOST: + else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS)) { - VARIOUS_ARGS(); - gBattleMons[0].hp = 0; - gHitMarker |= HITMARKER_FAINTED(0); - gHitMarker |= HITMARKER_PLAYER_FAINTED; - gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; - gDisableStructs[0].truantSwitchInHack = 1; - break; - } - case VARIOUS_ARENA_BOTH_MONS_LOST: - { - VARIOUS_ARGS(); - gBattleMons[0].hp = 0; - gBattleMons[1].hp = 0; - gHitMarker |= HITMARKER_FAINTED(0); - gHitMarker |= HITMARKER_FAINTED(1); - gHitMarker |= HITMARKER_PLAYER_FAINTED; - gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[0]; - gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[1]; - gDisableStructs[0].truantSwitchInHack = 1; - gDisableStructs[1].truantSwitchInHack = 1; - break; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_FAIL; } - case VARIOUS_EMIT_YESNOBOX: + else { - VARIOUS_ARGS(); - BtlController_EmitYesNoBox(battler, B_COMM_TO_CONTROLLER); - MarkBattlerForControllerExec(battler); - break; + gStatuses3[gBattlerTarget] |= gBattlerAttacker; + gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_SET; } - case VARIOUS_DRAW_ARENA_REF_TEXT_BOX: + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +// TODO: Needs tests for everything +static void Cmd_manipulatedamage(void) +{ + CMD_ARGS(u8 mode); + + switch (cmd->mode) { - VARIOUS_ARGS(); - DrawArenaRefereeTextBox(); + case DMG_CHANGE_SIGN: + gBattleStruct->moveDamage[gBattlerAttacker] *= -1; break; - } - case VARIOUS_ERASE_ARENA_REF_TEXT_BOX: - { - VARIOUS_ARGS(); - EraseArenaRefereeTextBox(); + case DMG_DOUBLED: + gBattleStruct->moveDamage[gBattlerTarget] *= 2; break; - } - case VARIOUS_ARENA_JUDGMENT_STRING: - { - CMD_ARGS(u8 id, u8 _); - BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[cmd->id]); - BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGMENT_TEXT); + case DMG_1_8_TARGET_HP: + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 8; + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = 1; break; - } - case VARIOUS_ARENA_WAIT_STRING: - { - VARIOUS_ARGS(); - if (IsTextPrinterActive(ARENA_WIN_JUDGMENT_TEXT)) - return; + case DMG_FULL_ATTACKER_HP: + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker); + break; + case DMG_BIG_ROOT: + gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); break; } - case VARIOUS_WAIT_CRY: + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_trysetrest(void) +{ + CMD_ARGS(const u8 *failInstr); + + const u8 *failInstr = cmd->failInstr; + gBattlerTarget = gBattlerAttacker; + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP * (-1); + + if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) { - VARIOUS_ARGS(); - if (!IsCryFinished()) - return; - break; + gBattlescriptCurrInstr = failInstr; } - case VARIOUS_RETURN_OPPONENT_MON1: + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) { - VARIOUS_ARGS(); - battler = 1; - if (IsBattlerAlive(battler)) - { - BtlController_EmitReturnMonToBall(battler, B_COMM_TO_CONTROLLER, FALSE); - MarkBattlerForControllerExec(battler); - } - break; + gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; } - case VARIOUS_RETURN_OPPONENT_MON2: + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) { - VARIOUS_ARGS(); - if (gBattlersCount > 3) - { - battler = 3; - if (IsBattlerAlive(battler)) - { - BtlController_EmitReturnMonToBall(battler, B_COMM_TO_CONTROLLER, FALSE); - MarkBattlerForControllerExec(battler); - } - } - break; + gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; } - case VARIOUS_VOLUME_DOWN: + else { - VARIOUS_ARGS(); - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x55); - break; + if (gBattleMons[gBattlerTarget].status1 & ((u8)(~STATUS1_SLEEP))) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_REST_STATUSED; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_REST; + + gBattleMons[gBattlerTarget].status1 = STATUS1_SLEEP_TURN(3); + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + gBattlescriptCurrInstr = cmd->nextInstr; } - case VARIOUS_VOLUME_UP: +} + +static void Cmd_jumpifnotfirstturn(void) +{ + CMD_ARGS(const u8 *jumpInstr); + + const u8 *jumpInstr = cmd->jumpInstr; + + if (gDisableStructs[gBattlerAttacker].isFirstTurn && !(gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = jumpInstr; +} + +static void Cmd_setmiracleeye(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (!(gStatuses3[gBattlerTarget] & STATUS3_MIRACLE_EYED)) { - VARIOUS_ARGS(); - m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); - break; + gStatuses3[gBattlerTarget] |= STATUS3_MIRACLE_EYED; + gBattlescriptCurrInstr = cmd->nextInstr; } - case VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT: + else { - VARIOUS_ARGS(); - gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = TRUE; - break; + gBattlescriptCurrInstr = cmd->failInstr; } - case VARIOUS_PALACE_TRY_ESCAPE_STATUS: +} + +bool8 UproarWakeUpCheck(u8 battler) +{ + s32 i; + bool32 hasSoundproof = (B_UPROAR_IGNORE_SOUNDPROOF < GEN_5 && GetBattlerAbility(battler) == ABILITY_SOUNDPROOF); + + for (i = 0; i < gBattlersCount; i++) { - VARIOUS_ARGS(); - if (BattlePalace_TryEscapeStatus(battler)) - return; + if (!(gBattleMons[i].volatiles.uproarTurns) || hasSoundproof) + continue; + + gBattleScripting.battler = i; + + if (gBattlerTarget == 0xFF) + gBattlerTarget = i; + else if (gBattlerTarget == i) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_SLEEP_UPROAR; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_KEPT_AWAKE; + break; } - case VARIOUS_SET_TELEPORT_OUTCOME: + + if (i == gBattlersCount) + return FALSE; + else + return TRUE; +} + +static void Cmd_jumpifuproarwakes(void) +{ + CMD_ARGS(const u8 *jumpInstr); + + if (UproarWakeUpCheck(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_stockpile(void) +{ + CMD_ARGS(u8 id); + + switch (cmd->id) { - VARIOUS_ARGS(); - // Don't end the battle if one of the wild mons teleported from the wild double battle - // and its partner is still alive. - if (!IsOnPlayerSide(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))) - { - gAbsentBattlerFlags |= 1u << battler; - gHitMarker |= HITMARKER_FAINTED(battler); - gBattleMons[battler].hp = 0; - SetMonData(GetBattlerMon(battler), MON_DATA_HP, &gBattleMons[battler].hp); - SetHealthboxSpriteInvisible(gHealthboxSpriteIds[battler]); - FaintClearSetData(battler); - } - else if (IsOnPlayerSide(battler)) + case 0: + if (gDisableStructs[gBattlerAttacker].stockpileCounter >= 3) { - gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_STOCKPILE; } else { - gBattleOutcome = B_OUTCOME_MON_TELEPORTED; + gDisableStructs[gBattlerAttacker].stockpileCounter++; + gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; + gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STOCKPILED; } break; - } - case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC: - { - VARIOUS_ARGS(); - BtlController_EmitPlayFanfareOrBGM(battler, B_COMM_TO_CONTROLLER, MUS_VICTORY_TRAINER, TRUE); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_STAT_TEXT_BUFFER: - { - VARIOUS_ARGS(); - PREPARE_STAT_BUFFER(gBattleTextBuff1, gBattleCommunication[0]); + case 1: // Save def/sp def stats. + if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gDisableStructs[gBattlerAttacker].stockpileDef += gBattleMons[gBattlerAttacker].statStages[STAT_DEF] - gDisableStructs[gBattlerAttacker].stockpileBeforeDef; + gDisableStructs[gBattlerAttacker].stockpileSpDef += gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF] - gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef; + } break; } - case VARIOUS_SWITCHIN_ABILITIES: - { - VARIOUS_ARGS(); - gBattlescriptCurrInstr = cmd->nextInstr; - AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); - AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); - AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); - return; - } - case VARIOUS_INSTANT_HP_DROP: + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_stockpiletobasedamage(void) +{ + CMD_ARGS(const u8 *failInstr); + + const u8 *failInstr = cmd->failInstr; + if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) { - VARIOUS_ARGS(); - BtlController_EmitHealthBarUpdate(battler, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); - MarkBattlerForControllerExec(battler); - break; + gBattlescriptCurrInstr = failInstr; } - case VARIOUS_CLEAR_STATUS: + else { - VARIOUS_ARGS(); - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; + if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; + + gBattlescriptCurrInstr = cmd->nextInstr; } - case VARIOUS_RESTORE_PP: +} + +static void Cmd_stockpiletohpheal(void) +{ + CMD_ARGS(const u8 *failInstr); + + const u8 *failInstr = cmd->failInstr; + + if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) { - VARIOUS_ARGS(); - for (i = 0; i < 4; i++) - { - gBattleMons[battler].pp[i] = CalculatePPWithBonus(gBattleMons[battler].moves[i], gBattleMons[battler].ppBonuses, i); - data[i] = gBattleMons[battler].pp[i]; - } - data[i] = gBattleMons[battler].ppBonuses; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_PP_DATA_BATTLE, 0, 5, data); - MarkBattlerForControllerExec(battler); - break; + gBattlescriptCurrInstr = failInstr; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FAILED; } - case VARIOUS_TRY_ACTIVATE_RECEIVER: // Partner gets fainted's ally ability + else { - VARIOUS_ARGS(); - gBattlerAbility = BATTLE_PARTNER(battler); - i = GetBattlerAbility(gBattlerAbility); - if (IsBattlerAlive(gBattlerAbility) - && (i == ABILITY_RECEIVER || i == ABILITY_POWER_OF_ALCHEMY) - && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD - && !gAbilitiesInfo[gBattleMons[battler].ability].cantBeCopied) + if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) { - gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_ReceiverActivates; - return; + gDisableStructs[gBattlerAttacker].stockpileCounter = 0; + gBattlescriptCurrInstr = failInstr; + gBattlerTarget = gBattlerAttacker; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FULL_HP; } - break; - } - case VARIOUS_TRY_ACTIVATE_SOULHEART: - { - VARIOUS_ARGS(); - while (gBattleStruct->soulheartBattlerId < gBattlersCount) + else { - gBattleScripting.battler = gBattleStruct->soulheartBattlerId++; - if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART - && IsBattlerAlive(gBattleScripting.battler) - && !NoAliveMonsForEitherParty() - && CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) { - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); - BattleScriptCall(BattleScript_ScriptingAbilityStatRaise); - return; + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter)); + gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; + } + else // Snatched move + { + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + gBattleScripting.animTurn = 1; } + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + + gBattlescriptCurrInstr = cmd->nextInstr; + gBattlerTarget = gBattlerAttacker; } - gBattleStruct->soulheartBattlerId = 0; - break; } - case VARIOUS_PLAY_MOVE_ANIMATION: +} + +void BS_RemoveStockpileCounters(void) +{ + NATIVE_ARGS(); + + if (GetMoveEffect(gCurrentMove) == EFFECT_SWALLOW + && gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT + && IsBattlerAlive(gBattlerTarget)) { - VARIOUS_ARGS(u16 move); - BtlController_EmitMoveAnimation(battler, B_COMM_TO_CONTROLLER, cmd->move, gBattleScripting.animTurn, 0, 0, gBattleMons[battler].friendship, &gDisableStructs[battler], gMultiHitCounter); - MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; - return; } - case VARIOUS_SET_LUCKY_CHANT: + else { - VARIOUS_ARGS(const u8 *failInstr); - if (!(gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_LUCKY_CHANT)) - { - gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_LUCKY_CHANT; - gSideTimers[GetBattlerSide(battler)].luckyChantTimer = gBattleTurnCounter + 5; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; + gDisableStructs[gBattlerAttacker].stockpileCounter = 0; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_MoveEffectStockpileWoreOff; } - case VARIOUS_SUCKER_PUNCH_CHECK: +} + +// Sign change for drained HP handled in GetDrainedBigRootHp +static void Cmd_setdrainedhp(void) +{ + CMD_ARGS(); + + gBattleStruct->moveDamage[gBattlerAttacker] = (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100); + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static u16 ReverseStatChangeMoveEffect(u16 moveEffect) +{ + switch (moveEffect) { - VARIOUS_ARGS(const u8 *failInstr); - if (gProtectStructs[gBattlerTarget].protected == PROTECT_OBSTRUCT) - gBattlescriptCurrInstr = cmd->failInstr; - else if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else if (IsBattleMoveStatus(gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]) && !gProtectStructs[gBattlerTarget].noValidMoves) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; + // +1 + case MOVE_EFFECT_ATK_PLUS_1: + return MOVE_EFFECT_ATK_MINUS_1; + case MOVE_EFFECT_DEF_PLUS_1: + return MOVE_EFFECT_DEF_MINUS_1; + case MOVE_EFFECT_SPD_PLUS_1: + return MOVE_EFFECT_SPD_MINUS_1; + case MOVE_EFFECT_SP_ATK_PLUS_1: + return MOVE_EFFECT_SP_ATK_MINUS_1; + case MOVE_EFFECT_SP_DEF_PLUS_1: + return MOVE_EFFECT_SP_DEF_MINUS_1; + case MOVE_EFFECT_ACC_PLUS_1: + return MOVE_EFFECT_ACC_MINUS_1; + case MOVE_EFFECT_EVS_PLUS_1: + return MOVE_EFFECT_EVS_MINUS_1; + // -1 + case MOVE_EFFECT_ATK_MINUS_1: + return MOVE_EFFECT_ATK_PLUS_1; + case MOVE_EFFECT_DEF_MINUS_1: + return MOVE_EFFECT_DEF_PLUS_1; + case MOVE_EFFECT_SPD_MINUS_1: + return MOVE_EFFECT_SPD_PLUS_1; + case MOVE_EFFECT_SP_ATK_MINUS_1: + return MOVE_EFFECT_SP_ATK_PLUS_1; + case MOVE_EFFECT_SP_DEF_MINUS_1: + return MOVE_EFFECT_SP_DEF_PLUS_1; + case MOVE_EFFECT_ACC_MINUS_1: + return MOVE_EFFECT_ACC_PLUS_1; + case MOVE_EFFECT_EVS_MINUS_1: + // +2 + case MOVE_EFFECT_ATK_PLUS_2: + return MOVE_EFFECT_ATK_MINUS_2; + case MOVE_EFFECT_DEF_PLUS_2: + return MOVE_EFFECT_DEF_MINUS_2; + case MOVE_EFFECT_SPD_PLUS_2: + return MOVE_EFFECT_SPD_MINUS_2; + case MOVE_EFFECT_SP_ATK_PLUS_2: + return MOVE_EFFECT_SP_ATK_MINUS_2; + case MOVE_EFFECT_SP_DEF_PLUS_2: + return MOVE_EFFECT_SP_DEF_MINUS_2; + case MOVE_EFFECT_ACC_PLUS_2: + return MOVE_EFFECT_ACC_MINUS_2; + case MOVE_EFFECT_EVS_PLUS_2: + return MOVE_EFFECT_EVS_MINUS_2; + // -2 + case MOVE_EFFECT_ATK_MINUS_2: + return MOVE_EFFECT_ATK_PLUS_2; + case MOVE_EFFECT_DEF_MINUS_2: + return MOVE_EFFECT_DEF_PLUS_2; + case MOVE_EFFECT_SPD_MINUS_2: + return MOVE_EFFECT_SPD_PLUS_2; + case MOVE_EFFECT_SP_ATK_MINUS_2: + return MOVE_EFFECT_SP_ATK_PLUS_2; + case MOVE_EFFECT_SP_DEF_MINUS_2: + return MOVE_EFFECT_SP_DEF_PLUS_2; + case MOVE_EFFECT_ACC_MINUS_2: + return MOVE_EFFECT_ACC_PLUS_2; + case MOVE_EFFECT_EVS_MINUS_2: + return MOVE_EFFECT_EVS_PLUS_2; + default: + return 0; } - case VARIOUS_SET_SIMPLE_BEAM: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten - || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) - gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; +} - gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_ENTRAINMENT: +static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 statValue, u32 statId, bool32 certain) +{ + u32 currStat = 0; + u32 changeableStatsCount = 1; // current stat is counted automatically + u32 statAnimId = statId; + bool32 statChangeByTwo = statValue > 1 || statValue < -1; + + if (statValue <= -1) // goes down { - VARIOUS_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeCopied - || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; - } + if (statChangeByTwo) + statAnimId += STAT_ANIM_MINUS2; else + statAnimId += STAT_ANIM_MINUS1; + + while (stats != 0) { - if (gBattleMons[gBattlerTarget].ability == gBattleMons[gBattlerAttacker].ability - || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else + if (stats & 1) { - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; - gBattlescriptCurrInstr = cmd->nextInstr; + if (certain) + { + if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE) + { + changeableStatsCount++; + break; + } + } + else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC) + && !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) + && !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK) + && !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF)) + { + if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE) + { + changeableStatsCount++; + break; + } + } } + stats >>= 1, currStat++; } - return; - } - case VARIOUS_SET_LAST_USED_ABILITY: - { - VARIOUS_ARGS(); - gLastUsedAbility = gBattleMons[battler].ability; - break; - } - case VARIOUS_INVERT_STAT_STAGES: - { - VARIOUS_ARGS(); - for (i = 0; i < NUM_BATTLE_STATS; i++) + + if (changeableStatsCount > 1) // more than one stat, so the color is gray { - if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) // Negative becomes positive. - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE + (DEFAULT_STAT_STAGE - gBattleMons[battler].statStages[i]); - else if (gBattleMons[battler].statStages[i] > DEFAULT_STAT_STAGE) // Positive becomes negative. - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE - (gBattleMons[battler].statStages[i] - DEFAULT_STAT_STAGE); + if (statChangeByTwo) + statAnimId = STAT_ANIM_MULTIPLE_MINUS2; + else + statAnimId = STAT_ANIM_MULTIPLE_MINUS1; } - break; } - case VARIOUS_TRY_ME_FIRST: + else // goes up { - VARIOUS_ARGS(const u8 *failInstr); - u16 move = gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]; - if (IsBattleMoveStatus(move) || IsMoveMeFirstBanned(move) - || GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; + if (statChangeByTwo) + statAnimId += STAT_ANIM_PLUS2; else + statAnimId += STAT_ANIM_PLUS1; + + while (stats != 0) { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + if (stats & 1 && gBattleMons[battler].statStages[currStat] < MAX_STAT_STAGE) { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCalledMove = GetTypeBasedZMove(move); - } - else - { - gCalledMove = move; + changeableStatsCount++; + break; } - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_BATTLE_END: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (NoAliveMonsForEitherParty()) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_ELECTRIFY: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->failInstr; + stats >>= 1, currStat++; } - else + + if (changeableStatsCount > 1) // more than one stat, so the color is gray { - gStatuses4[gBattlerTarget] |= STATUS4_ELECTRIFIED; - gBattlescriptCurrInstr = cmd->nextInstr; + if (statChangeByTwo) + statAnimId = STAT_ANIM_MULTIPLE_PLUS2; + else + statAnimId = STAT_ANIM_MULTIPLE_PLUS1; } - return; } - case VARIOUS_TRY_SOAK: + + if (!gBattleScripting.statAnimPlayed) { - VARIOUS_ARGS(const u8 *failInstr); - u32 types[3]; - GetBattlerTypes(gBattlerTarget, FALSE, types); - u32 typeToSet = GetMoveArgType(gCurrentMove); - if ((types[0] == typeToSet && types[1] == typeToSet) - || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - SET_BATTLER_TYPE(gBattlerTarget, typeToSet); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, typeToSet); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; + BtlController_EmitBattleAnimation(battler, B_COMM_TO_CONTROLLER, B_ANIM_STATS_CHANGE, &gDisableStructs[battler], statAnimId); + MarkBattlerForControllerExec(battler); + if (changeableStatsCount > 1) + gBattleScripting.statAnimPlayed = TRUE; } - case VARIOUS_HANDLE_FORM_CHANGE: + else if (changeableStatsCount == 1) // final stat that can be changed { - VARIOUS_ARGS(u8 case_); - mon = GetBattlerMon(battler); + gBattleScripting.statAnimPlayed = FALSE; + } +} - // Change species. - if (cmd->case_ == 0) - { - /* What was the idea here? - if (!gBattleTextBuff1) - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battler].species); - */ - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); - MarkBattlerForControllerExec(battler); - } - // Change stats. - else if (cmd->case_ == 1) - { - RecalcBattlerStats(battler, mon, FALSE); - } - // Update healthbox. - else +static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr) +{ + u32 index, battlerAbility; + enum ItemHoldEffect battlerHoldEffect; + battlerAbility = GetBattlerAbility(battler); + battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); + gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker; + + if (battlerAbility == ABILITY_CONTRARY) + { + statValue ^= STAT_BUFF_NEGATIVE; + if (!flags.onlyChecking) { - UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); + gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE; + RecordAbilityBattle(battler, battlerAbility); + if (flags.updateMoveEffect) + gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect); } - gBattlescriptCurrInstr = cmd->nextInstr; - return; } - case VARIOUS_TRY_LAST_RESORT: + else if (battlerAbility == ABILITY_SIMPLE && !flags.onlyChecking) { - VARIOUS_ARGS(const u8 *failInstr); - if (CanUseLastResort(battler)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->failInstr; - return; + statValue = (SET_STAT_BUFF_VALUE(GET_STAT_BUFF_VALUE(statValue) * 2)) | ((statValue <= -1) ? STAT_BUFF_NEGATIVE : 0); + RecordAbilityBattle(battler, battlerAbility); } - case VARIOUS_TRY_AUTOTOMIZE: + + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); + + if (statValue <= -1) // Stat decrease. { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerWeight(battler) > 1) + if (gSideTimers[GetBattlerSide(battler)].mistTimer + && !flags.certain && gCurrentMove != MOVE_CURSE + && !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR)) { - gDisableStructs[battler].autotomizeCount++; - gBattlescriptCurrInstr = cmd->nextInstr; + if (flags.allowPtr) + { + if (gSpecialStatuses[battler].statLowered) + { + gBattlescriptCurrInstr = BS_ptr; + } + else + { + BattleScriptPush(BS_ptr); + gBattleScripting.battler = battler; + gBattlescriptCurrInstr = BattleScript_MistProtected; + gSpecialStatuses[battler].statLowered = TRUE; + } + } + return STAT_CHANGE_DIDNT_WORK; } - else + else if (gCurrentMove != MOVE_CURSE + && !flags.notProtectAffected && JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, BattleScript_ButItFailed)) { - gBattlescriptCurrInstr = cmd->failInstr; + return STAT_CHANGE_DIDNT_WORK; } - return; - } - case VARIOUS_TRY_INSTRUCT: - { - VARIOUS_ARGS(const u8 *failInstr); - u16 move = gLastPrintedMoves[gBattlerTarget]; - if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasAdditionalEffectSelf(move, MOVE_EFFECT_RECHARGE) - || IsMoveInstructBanned(move) - || gBattleMoveEffects[GetMoveEffect(move)].twoTurnEffect - || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) - || IsZMove(move) - || IsMaxMove(move)) + else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || CanAbilityPreventStatLoss(battlerAbility)) + && (flags.statDropPrevention || gBattlerAttacker != gBattlerTarget || flags.mirrorArmored) && !flags.certain && gCurrentMove != MOVE_CURSE) { - gBattlescriptCurrInstr = cmd->failInstr; + if (flags.allowPtr) + { + if (gSpecialStatuses[battler].statLowered) + { + gBattlescriptCurrInstr = BS_ptr; + } + else + { + gBattleScripting.battler = battler; + if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) + { + gLastUsedItem = gBattleMons[battler].item; + BattleScriptPush(BS_ptr); + gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; + RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); + } + else + { + gBattlerAbility = battler; + BattleScriptPush(BS_ptr); + gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss; + gLastUsedAbility = battlerAbility; + RecordAbilityBattle(battler, gLastUsedAbility); + } + gSpecialStatuses[battler].statLowered = TRUE; + } + } + return STAT_CHANGE_DIDNT_WORK; } - else + else if ((index = IsFlowerVeilProtected(battler)) && !flags.certain) { - gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4; - gCalledMove = move; - for (i = 0; i < MAX_MON_MOVES; i++) + if (flags.allowPtr) { - if (gBattleMons[gBattlerTarget].moves[i] == gCalledMove) + if (gSpecialStatuses[battler].statLowered) { - gCurrMovePos = i; - i = 4; - break; + gBattlescriptCurrInstr = BS_ptr; + } + else + { + BattleScriptPush(BS_ptr); + gBattleScripting.battler = battler; + gBattlerAbility = index - 1; + gBattlescriptCurrInstr = BattleScript_FlowerVeilProtectsRet; + gLastUsedAbility = ABILITY_FLOWER_VEIL; + gSpecialStatuses[battler].statLowered = TRUE; } } - if (i != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) - gBattlescriptCurrInstr = cmd->failInstr; - else + return STAT_CHANGE_DIDNT_WORK; + } + else if (!flags.certain + && (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC) + || (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) + || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK) + || (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF))) + { + if (flags.allowPtr) { - gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget]; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, battler, gBattlerPartyIndexes[battler]); - gBattlescriptCurrInstr = cmd->nextInstr; + BattleScriptPush(BS_ptr); + gBattleScripting.battler = battler; + gBattlerAbility = battler; + gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss; + gLastUsedAbility = battlerAbility; + RecordAbilityBattle(battler, gLastUsedAbility); } + return STAT_CHANGE_DIDNT_WORK; } - return; - } - case VARIOUS_ABILITY_POPUP: - { - VARIOUS_ARGS(); - CreateAbilityPopUp(battler, gBattleMons[battler].ability, (IsDoubleBattle()) != 0); - break; - } - case VARIOUS_UPDATE_ABILITY_POPUP: - { - VARIOUS_ARGS(); - UpdateAbilityPopup(battler); - break; - } - case VARIOUS_JUMP_IF_TARGET_ALLY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; - return; - } - case VARIOUS_TRY_SYNCHRONOISE: - { - VARIOUS_ARGS(const u8 *failInstr); - if (!DoBattlersShareType(gBattlerAttacker, gBattlerTarget)) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_LOSE_TYPE: - { - VARIOUS_ARGS(u8 type); - RemoveBattlerType(battler, cmd->type); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_PSYCHO_SHIFT: + else if (battlerAbility == ABILITY_MIRROR_ARMOR && !flags.mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget) { - VARIOUS_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr); - u32 targetAbility = GetBattlerAbility(gBattlerTarget); - // Psycho shift works - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_TOXIC_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 1; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_BURN) && CanBeBurned(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 2; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 3; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerAttacker, gBattlerTarget, targetAbility, BLOCKED_BY_SLEEP_CLAUSE)) - gBattleCommunication[MULTISTRING_CHOOSER] = 4; - else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerAttacker, gBattlerTarget, targetAbility)) - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) + if (flags.allowPtr) { - gBattlescriptCurrInstr = cmd->sleepClauseFailInstr; - return; + SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE); + BattleScriptPush(BS_ptr); + gBattleScripting.battler = battler; + gBattlerAbility = battler; + gBattlescriptCurrInstr = BattleScript_MirrorArmorReflect; + RecordAbilityBattle(battler, gBattleMons[battler].ability); } - else + return STAT_CHANGE_DIDNT_WORK; + } + else // try to decrease + { + statValue = -GET_STAT_BUFF_VALUE(statValue); + if (gBattleMons[battler].statStages[statId] == 1) + statValue = -1; + else if (gBattleMons[battler].statStages[statId] == 2 && statValue < -2) + statValue = -2; + gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; + index = 1; + if (statValue == -2) { - gBattlescriptCurrInstr = cmd->failInstr; - return; + gBattleTextBuff2[1] = B_BUFF_STRING; + gBattleTextBuff2[2] = STRINGID_STATHARSHLY; + gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8; + index = 4; } - gBattleMons[gBattlerTarget].status1 = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; - battler = gBattlerTarget; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - gBattlescriptCurrInstr = cmd->nextInstr; - TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); - return; - } - case VARIOUS_CURE_STATUS: - { - VARIOUS_ARGS(); + else if (statValue <= -3) + { + gBattleTextBuff2[1] = B_BUFF_STRING; + gBattleTextBuff2[2] = STRINGID_SEVERELY & 0xFF; + gBattleTextBuff2[3] = STRINGID_SEVERELY >> 8; + index = 4; + } + gBattleTextBuff2[index++] = B_BUFF_STRING; + gBattleTextBuff2[index++] = STRINGID_STATFELL; + gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8; + gBattleTextBuff2[index] = B_BUFF_EOS; - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_POWER_TRICK: - { - VARIOUS_ARGS(); - gStatuses3[battler] ^= STATUS3_POWER_TRICK; - SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, i); - break; - } - case VARIOUS_AFTER_YOU: - { - VARIOUS_ARGS(const u8 *failInstr); - if (ChangeOrderTargetAfterAttacker()) - { - gSpecialStatuses[gBattlerTarget].afterYou = 1; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; - } - case VARIOUS_BESTOW: - { - VARIOUS_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerAttacker].item == ITEM_NONE - || gBattleMons[gBattlerTarget].item != ITEM_NONE - || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) - || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) - || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - BestowItem(gBattlerAttacker, gBattlerTarget); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_JUMP_IF_NOT_GROUNDED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (!IsBattlerGrounded(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_HANDLE_TRAINER_SLIDE_MSG: - { - VARIOUS_ARGS(u8 case_); - if (cmd->case_ == PRINT_SLIDE_MESSAGE) - { - BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, STRINGID_TRAINERSLIDE); - MarkBattlerForControllerExec(battler); - } - else if (cmd->case_ == RESTORE_BATTLER_SLIDE_CONTROL) - { - if (IsBattlerAlive(battler)) + if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE) { - SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species); - BattleLoadMonSpriteGfx(GetBattlerMon(battler), battler); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE; } - i = BATTLE_PARTNER(battler); - if (IsBattlerAlive(i)) + else if (!flags.onlyChecking) { - SetBattlerShadowSpriteCallback(i, gBattleMons[i].species); - BattleLoadMonSpriteGfx(GetBattlerMon(i), i); + gProtectStructs[battler].tryEjectPack = TRUE; + gProtectStructs[battler].lashOutAffected = TRUE; } } - gBattlescriptCurrInstr = cmd->nextInstr; - return; } - case VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF: + else // stat increase { - VARIOUS_ARGS(); - if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN))) + statValue = GET_STAT_BUFF_VALUE(statValue); + if (gBattleMons[battler].statStages[statId] == 11) + statValue = 1; + else if (gBattleMons[battler].statStages[statId] == 10 && statValue > 2) + statValue = 2; + gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; + index = 1; + if (statValue == 2) { - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - return; + gBattleTextBuff2[1] = B_BUFF_STRING; + gBattleTextBuff2[2] = STRINGID_STATSHARPLY; + gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; + index = 4; } - break; - } - case VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON: - { - VARIOUS_ARGS(); - if ((i = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_LAST_SWITCHIN))) + else if (statValue >= 3) { - gBattleScripting.battler = battler; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - return; + gBattleTextBuff2[1] = B_BUFF_STRING; + gBattleTextBuff2[2] = STRINGID_DRASTICALLY & 0xFF; + gBattleTextBuff2[3] = STRINGID_DRASTICALLY >> 8; + index = 4; } - break; - } - case VARIOUS_SET_AURORA_VEIL: - { - VARIOUS_ARGS(); - if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_AURORA_VEIL - || !(HasWeatherEffect() && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + gBattleTextBuff2[index++] = B_BUFF_STRING; + gBattleTextBuff2[index++] = STRINGID_STATROSE; + gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8; + gBattleTextBuff2[index] = B_BUFF_EOS; + + gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE + + if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE; } - else + else if (!flags.onlyChecking) { - gSideStatuses[GetBattlerSide(battler)] |= SIDE_STATUS_AURORA_VEIL; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LIGHT_CLAY) - gSideTimers[GetBattlerSide(battler)].auroraVeilTimer = gBattleTurnCounter + 8; + u32 statIncrease; + if ((statValue + gBattleMons[battler].statStages[statId]) > MAX_STAT_STAGE) + statIncrease = MAX_STAT_STAGE - gBattleMons[battler].statStages[statId]; else - gSideTimers[GetBattlerSide(battler)].auroraVeilTimer = gBattleTurnCounter + 5; + statIncrease = statValue; - if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - else - gBattleCommunication[MULTISTRING_CHOOSER] = 5; - } - break; - } - case VARIOUS_TRY_THIRD_TYPE: - { - VARIOUS_ARGS(const u8 *failInstr); - u32 type = GetMoveArgType(gCurrentMove); - if (IS_BATTLER_OF_TYPE(battler, type) || GetActiveGimmick(battler) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleMons[battler].types[2] = type; - PREPARE_TYPE_BUFFER(gBattleTextBuff1, type); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_DESTROY_ABILITY_POPUP: - { - VARIOUS_ARGS(); - for (u32 i = 0; i < gBattlersCount; i++) - { - DestroyAbilityPopUp(i); - } - break; - } - case VARIOUS_TOTEM_BOOST: - { - VARIOUS_ARGS(const u8 *jumpInstr); - battler = gBattlerAttacker; - if (gQueuedStatBoosts[battler].stats == 0) - { - gBattlescriptCurrInstr = cmd->nextInstr; // stats done, exit - } - else - { - for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) + gProtectStructs[battler].statRaised = TRUE; + + if (statIncrease) { - if (gQueuedStatBoosts[battler].stats & (1 << i)) + // Check Mirror Herb / Opportunist + for (index = 0; index < gBattlersCount; index++) { - if (gQueuedStatBoosts[battler].statChanges[i] <= -1) - SET_STATCHANGER(i + 1, abs(gQueuedStatBoosts[battler].statChanges[i]), TRUE); - else - SET_STATCHANGER(i + 1, gQueuedStatBoosts[battler].statChanges[i], FALSE); + if (IsBattlerAlly(index, battler)) + continue; // Only triggers on opposing side - gQueuedStatBoosts[battler].stats &= ~(1 << i); - gBattleScripting.battler = battler; - gBattlerTarget = battler; - if (gQueuedStatBoosts[battler].stats & 0x80) + if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST + && gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises { - gQueuedStatBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag - gBattlescriptCurrInstr = BattleScript_TotemFlaredToLife; + gProtectStructs[index].activateOpportunist = 2; // set stats to copy } - else + if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB) { - gBattlescriptCurrInstr = cmd->jumpInstr; // do boost + gProtectStructs[index].eatMirrorHerb = 1; + } + + if (gProtectStructs[index].activateOpportunist == 2 || gProtectStructs[index].eatMirrorHerb == 1) + { + gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk + gQueuedStatBoosts[index].statChanges[statId - 1] += statIncrease; } - return; } } - gBattlescriptCurrInstr = cmd->nextInstr; // exit if loop failed (failsafe) } - return; - } - case VARIOUS_MOVEEND_ITEM_EFFECTS: - { - VARIOUS_ARGS(); - if (ItemBattleEffects(ITEMEFFECT_NORMAL, battler)) - return; - break; } - case VARIOUS_ROOM_SERVICE: + + if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE) // same as B_MSG_STAT_WONT_DECREASE { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(battler)) - { - BattleScriptCall(BattleScript_ConsumableStatRaiseRet); - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - return; + if (!flags.allowPtr) + return STAT_CHANGE_DIDNT_WORK; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + return STAT_CHANGE_WORKED; } - case VARIOUS_TERRAIN_SEED: - { - VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS) - { - enum ItemEffect effect = ITEM_NO_EFFECT; - u16 item = gBattleMons[battler].item; - switch (GetBattlerHoldEffectParam(battler)) - { - case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_MISTY_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: - effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); - break; - } - if (effect != ITEM_NO_EFFECT) - return; - } - gBattlescriptCurrInstr = cmd->failInstr; - return; - } - case VARIOUS_MAKE_INVISIBLE: - { - VARIOUS_ARGS(); - if (gBattleControllerExecFlags) - break; + if (flags.onlyChecking) + return STAT_CHANGE_WORKED; - BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); - MarkBattlerForControllerExec(battler); - break; - } - case VARIOUS_JUMP_IF_TEAM_HEALTHY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if ((IsDoubleBattle()) && IsBattlerAlive(BATTLE_PARTNER(battler))) - { - u8 partner = BATTLE_PARTNER(battler); - if ((gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) - && (gBattleMons[partner].hp == gBattleMons[partner].maxHP && !(gBattleMons[partner].status1 & STATUS1_ANY))) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } - else // single battle - { - if (gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_TRY_HEAL_QUARTER_HP: - { - VARIOUS_ARGS(const u8 *failInstr); - gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; - if (gBattleStruct->moveDamage[battler] == 0) - gBattleStruct->moveDamage[battler] = 1; - gBattleStruct->moveDamage[battler] *= -1; + gBattleMons[battler].statStages[statId] += statValue; + if (gBattleMons[battler].statStages[statId] < MIN_STAT_STAGE) + gBattleMons[battler].statStages[statId] = MIN_STAT_STAGE; + if (gBattleMons[battler].statStages[statId] > MAX_STAT_STAGE) + gBattleMons[battler].statStages[statId] = MAX_STAT_STAGE; - if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) - gBattlescriptCurrInstr = cmd->failInstr; // fail - else - gBattlescriptCurrInstr = cmd->nextInstr; // can heal - return; - } - case VARIOUS_JUMP_IF_UNDER_200: - { - VARIOUS_ARGS(const u8 *jumpInstr); - // If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail. - if (GetBattlerWeight(gBattlerTarget) < 2000) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SET_SKY_DROP: - { - VARIOUS_ARGS(); - gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR); - /* skyDropTargets holds the information of who is in a particular instance of Sky Drop. - This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if - the target of a Sky Drop faints while in the air.*/ - gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget; - gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker; + if (ShouldDefiantCompetitiveActivate(battler, battlerAbility)) + stats = 0; // use single stat animations when Defiant/Competitive activate + else + stats &= ~(1u << statId); + + TryPlayStatChangeAnimation(battler, battlerAbility, stats, statValue, statId, flags.certain); + + return STAT_CHANGE_WORKED; +} - // End any multiturn effects caused by the target except VOLATILE_LOCK_CONFUSE - gBattleMons[gBattlerTarget].volatiles.multipleTurns = 0; - gBattleMons[gBattlerTarget].volatiles.uproarTurns= 0; - gBattleMons[gBattlerTarget].volatiles.bideTurns = 0; - gDisableStructs[gBattlerTarget].rolloutTimer = 0; - gDisableStructs[gBattlerTarget].furyCutterCounter = 0; +static void Cmd_statbuffchange(void) +{ + CMD_ARGS(u8 battler, u16 flags, const u8 *failInstr, u8 stats); - // End any Follow Me/Rage Powder effects caused by the target - if (gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer != 0 && gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget == gBattlerTarget) - gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 0; + u16 flags = cmd->flags; + u32 stats = cmd->stats; + const u8 *ptrBefore = gBattlescriptCurrInstr; + const u8 *failInstr = cmd->failInstr; - break; - } - case VARIOUS_CLEAR_SKY_DROP: + if (ChangeStatBuffs( + GetBattlerForBattleScript(cmd->battler), + GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), + GET_STAT_BUFF_ID(gBattleScripting.statChanger), + flags, + stats, + failInstr) == STAT_CHANGE_WORKED) + gBattlescriptCurrInstr = cmd->nextInstr; + else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping. + gBattlescriptCurrInstr = failInstr; +} + +bool32 TryResetBattlerStatChanges(u8 battler) +{ + u32 j; + bool32 ret = FALSE; + + gDisableStructs[battler].stockpileDef = 0; + gDisableStructs[battler].stockpileSpDef = 0; + for (j = 0; j < NUM_BATTLE_STATS; j++) { - VARIOUS_ARGS(const u8 *failInstr); - // Check to see if the initial target of this Sky Drop fainted before the 2nd turn of Sky Drop. - // If so, make the move fail. If not, clear all of the statuses and continue the move. - if (gBattleStruct->skyDropTargets[gBattlerAttacker] == SKY_DROP_NO_TARGET) - gBattlescriptCurrInstr = cmd->failInstr; - else - { - gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET; - gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET; - gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); - gBattlescriptCurrInstr = cmd->nextInstr; - } + if (gBattleMons[battler].statStages[j] != DEFAULT_STAT_STAGE) + ret = TRUE; // returns TRUE if any stat was reset - // Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted. - if (gBattleMons[gBattlerTarget].volatiles.lockConfusionTurns) - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; - return; + gBattleMons[battler].statStages[j] = DEFAULT_STAT_STAGE; } - case VARIOUS_SKY_DROP_YAWN: // If the mon that's sleeping due to Yawn was holding a Pokemon in Sky Drop, release the target and clear Sky Drop data. - { - VARIOUS_ARGS(); - if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED)) - { - // Set the target of Sky Drop as gEffectBattler - gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler]; - // Clear skyDropTargets data - gBattleStruct->skyDropTargets[gBattleStruct->skyDropTargets[gEffectBattler]] = SKY_DROP_NO_TARGET; - gBattleStruct->skyDropTargets[gEffectBattler] = SKY_DROP_NO_TARGET; + return ret; +} - // If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation - if (gBattleMons[gEffectBattler].volatiles.lockConfusionTurns && CanBeConfused(gEffectBattler)) - { - gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; - gBattlerAttacker = gEffectBattler; - gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; - gBattlescriptCurrInstr = BattleScript_ThrashConfuses; - return; - } - } - break; - } - case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: +// Haze +static void Cmd_normalisebuffs(void) +{ + CMD_ARGS(); + + s32 i; + + for (i = 0; i < gBattlersCount; i++) + TryResetBattlerStatChanges(i); + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_setbide(void) +{ + CMD_ARGS(); + + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; + gLockedMoves[gBattlerAttacker] = gCurrentMove; + gBideDmg[gBattlerAttacker] = 0; + gBattleMons[gBattlerAttacker].volatiles.bideTurns = 2; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_twoturnmoveschargestringandanimation(void) +{ + CMD_ARGS(const u8 *animationThenStringPtr); + + gBattleScripting.savedStringId = GetMoveTwoTurnAttackStringId(gCurrentMove); + if (B_UPDATED_MOVE_DATA < GEN_5 || MoveHasChargeTurnAdditionalEffect(gCurrentMove)) + gBattlescriptCurrInstr = cmd->animationThenStringPtr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_trynonvolatilestatus(void) +{ + CMD_ARGS(); + bool32 canInflictStatus = TRUE; + + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + GetMoveNonVolatileStatus(gCurrentMove), + RUN_SCRIPT)) + canInflictStatus = FALSE; + + if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { - VARIOUS_ARGS(const u8 *jumpInstr); - if (BlocksPrankster(gCurrentMove, gBattlerAttacker, battler, TRUE)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; + canInflictStatus = FALSE; + gBattlescriptCurrInstr = BattleScript_ButItFailed; } - case VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER: - { - bool8 shouldNotClear = FALSE; - for (i = 0; i < gBattlersCount; i++) + if (canInflictStatus) + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_initmultihitstring(void) +{ + CMD_ARGS(); + + PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) + + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_forcerandomswitch(void) +{ + CMD_ARGS(const u8 *failInstr); + + s32 battler1PartyId = 0; + s32 battler2PartyId = 0; + + s32 firstMonId; + s32 lastMonId = 0; // + 1 + struct Pokemon *party = NULL; + u8 validMons[PARTY_SIZE]; + s32 validMonsCount = 0; + + bool32 redCardForcedSwitch = FALSE; + + // Red card checks against wild pokemon. If we have reached here, the player has a mon to switch into + // Red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF... + if (gBattleScripting.switchCase == B_SWITCH_RED_CARD + && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && !IsOnPlayerSide(gBattlerAttacker)) // Check opponent's red card activating + { + if (!WILD_DOUBLE_BATTLE) { - u32 ability = GetBattlerAbility(i); - if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) - || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) - || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) - && IsBattlerAlive(i)) - shouldNotClear = TRUE; + // Wild mon with red card will end single battle + gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; + return; } - if (gBattleWeather & B_WEATHER_SUN_PRIMAL && !shouldNotClear) + else { - gBattleWeather &= ~B_WEATHER_SUN_PRIMAL; - PrepareStringBattle(STRINGID_EXTREMESUNLIGHTFADED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; + // Wild double battle, wild mon red card activation on player + if (IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) + { + // Both player's battlers are alive + redCardForcedSwitch = FALSE; + } + else + { + // Player has only one mon alive -> force red card switch before manually switching to other mon + redCardForcedSwitch = TRUE; + } } - else if (gBattleWeather & B_WEATHER_RAIN_PRIMAL && !shouldNotClear) + } + + // Swapping pokemon happens in: + // trainer battles + // wild double battles when an opposing pokemon uses it against one of the two alive player mons + // wild double battle when a player pokemon uses it against its partner + if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + || (WILD_DOUBLE_BATTLE + && !IsOnPlayerSide(gBattlerAttacker) + && IsOnPlayerSide(gBattlerTarget) + && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) + || (WILD_DOUBLE_BATTLE + && IsOnPlayerSide(gBattlerAttacker) + && IsOnPlayerSide(gBattlerTarget)) + || redCardForcedSwitch + ) + { + party = GetBattlerParty(gBattlerTarget); + + if (BATTLE_TWO_VS_ONE_OPPONENT && !IsOnPlayerSide(gBattlerTarget)) { - gBattleWeather &= ~B_WEATHER_RAIN_PRIMAL; - PrepareStringBattle(STRINGID_HEAVYRAINLIFTED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; + firstMonId = 0; + lastMonId = 6; + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; + battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } - else if (gBattleWeather & B_WEATHER_STRONG_WINDS && !shouldNotClear) + else if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_LINK) + || (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) + || (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)) { - gBattleWeather &= ~B_WEATHER_STRONG_WINDS; - PrepareStringBattle(STRINGID_STRONGWINDSDISSIPATED, battler); - gBattleCommunication[MSG_DISPLAY] = 1; + if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT) + { + firstMonId = PARTY_SIZE / 2; + lastMonId = PARTY_SIZE; + } + else + { + firstMonId = 0; + lastMonId = PARTY_SIZE / 2; + } + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; + battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } - break; - } - case VARIOUS_TRY_END_NEUTRALIZING_GAS: - { - VARIOUS_ARGS(); - if (gSpecialStatuses[battler].neutralizingGasRemoved) + else if ((gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK) + || (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK)) { - gSpecialStatuses[battler].neutralizingGasRemoved = FALSE; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; - return; + if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(gBattlerTarget)) == B_FLANK_RIGHT) + { + firstMonId = PARTY_SIZE / 2; + lastMonId = PARTY_SIZE; + } + else + { + firstMonId = 0; + lastMonId = PARTY_SIZE / 2; + } + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; + battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } - break; - } - case VARIOUS_GET_ROTOTILLER_TARGETS: - { - VARIOUS_ARGS(const u8 *failInstr); - // Gets the battlers to be affected by rototiller. If there are none, print 'But it failed!' + else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { - u32 count = 0; - for (i = 0; i < gBattlersCount; i++) + if (IsOnPlayerSide(gBattlerTarget)) { - gSpecialStatuses[i].rototillerAffected = FALSE; - if (IsRototillerAffected(i)) + firstMonId = 0; + lastMonId = PARTY_SIZE; + } + else + { + if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT) + { + firstMonId = PARTY_SIZE / 2; + lastMonId = PARTY_SIZE; + } + else { - gSpecialStatuses[i].rototillerAffected = TRUE; - count++; + firstMonId = 0; + lastMonId = PARTY_SIZE / 2; } } - - if (count == 0) - gBattlescriptCurrInstr = cmd->failInstr; // Rototiller fails - else - gBattlescriptCurrInstr = cmd->nextInstr; + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; + battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } - return; - } - case VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (gSpecialStatuses[battler].rototillerAffected) + else if (IsDoubleBattle()) { - gSpecialStatuses[battler].rototillerAffected = FALSE; - gBattlescriptCurrInstr = cmd->nextInstr; + firstMonId = 0; + lastMonId = PARTY_SIZE; + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; + battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } else { - gBattlescriptCurrInstr = cmd->jumpInstr; // Unaffected by rototiller - print STRINGID_NOEFFECTONTARGET + firstMonId = 0; + lastMonId = PARTY_SIZE; + battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; // there is only one Pokémon out in single battles + battler1PartyId = gBattlerPartyIndexes[gBattlerTarget]; } - return; - } - case VARIOUS_CONSUME_BERRY: - { - VARIOUS_ARGS(bool8 fromBattler); - if (gBattleScripting.overrideBerryRequirements == 2) + + for (u32 i = firstMonId; i < lastMonId; i++) { - gBattlescriptCurrInstr = cmd->nextInstr; - return; + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0 + && i != battler1PartyId + && i != battler2PartyId) + { + validMons[validMonsCount++] = i; + } } - if (cmd->fromBattler) - gLastUsedItem = gBattleMons[battler].item; - - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; - gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID - if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) - return; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == gBattleMons[battler].species) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_WEATHER_AFFECTED: + if (validMonsCount == 0) { - VARIOUS_ARGS(u32 flags, const u8 *jumpInstr); - u32 flags = cmd->flags; - if (IsBattlerWeatherAffected(battler, flags)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gBattlescriptCurrInstr = cmd->failInstr; } - case VARIOUS_JUMP_IF_SPECIES: - { - VARIOUS_ARGS(u16 species, const u8 *jumpInstr); - if (gBattleMons[battler].species == cmd->species) - gBattlescriptCurrInstr = cmd->jumpInstr; else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (IsLeafGuardProtected(battler, GetBattlerAbility(battler))) { - gBattlerAbility = battler; - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - } - case VARIOUS_SET_ATTACKER_STICKY_WEB_USER: - { - VARIOUS_ARGS(); - // For Mirror Armor: "If the Pokémon with this Ability is affected by Sticky Web, the effect is reflected back to the Pokémon which set it up. - // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." - gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition - SET_STATCHANGER(STAT_SPEED, 1, TRUE); - if (gSideTimers[GetBattlerSide(battler)].stickyWebBattlerId != 0xFF) - gBattlerAttacker = gSideTimers[GetBattlerSide(battler)].stickyWebBattlerId; - break; - } - case VARIOUS_CUT_1_3_HP_RAISE_STATS: - { - VARIOUS_ARGS(const u8 *failInstr); + gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget]; + gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; + gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE; + gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)]; - bool8 atLeastOneStatBoosted = FALSE; - u16 hpFraction = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); + if (!IsMultiBattle()) + SwitchPartyOrder(gBattlerTarget); - for (i = 1; i < NUM_STATS; i++) - { - if (CompareStat(gBattlerAttacker, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - atLeastOneStatBoosted = TRUE; - break; - } - } - if (atLeastOneStatBoosted && gBattleMons[gBattlerAttacker].hp > hpFraction) - { - gBattleStruct->moveDamage[gBattlerAttacker] = hpFraction; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else + if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + || (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI) + || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) + || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - gBattlescriptCurrInstr = cmd->failInstr; + SwitchPartyOrderLinkMulti(gBattlerTarget, gBattleStruct->monToSwitchIntoId[gBattlerTarget], 0); + SwitchPartyOrderLinkMulti(BATTLE_PARTNER(gBattlerTarget), gBattleStruct->monToSwitchIntoId[gBattlerTarget], 1); } - return; + + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + SwitchPartyOrderInGameMulti(gBattlerTarget, gBattleStruct->monToSwitchIntoId[gBattlerTarget]); } - case VARIOUS_CHECK_POLTERGEIST: + } + else { - VARIOUS_ARGS(const u8 *failInstr); - if (gBattleMons[battler].item == ITEM_NONE - || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM - || GetBattlerAbility(battler) == ABILITY_KLUTZ) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + // In normal wild doubles, Roar will always fail if the user's level is less than the target's. + if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) + gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; else - { - PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[battler].item); - gLastUsedItem = gBattleMons[battler].item; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +static void Cmd_tryconversiontypechange(void) +{ + CMD_ARGS(const u8 *failInstr); + + u8 validMoves = 0; + u8 moveChecked = 0; + u8 moveType = 0; + + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; return; } - case VARIOUS_TRY_NO_RETREAT: + + if (B_UPDATED_CONVERSION >= GEN_6) { - VARIOUS_ARGS(const u8 *failInstr); - if (gDisableStructs[battler].noRetreat) + // Changes user's type to its first move's type + for (moveChecked = 0; moveChecked < MAX_MON_MOVES; moveChecked++) + { + if (gBattleMons[gBattlerAttacker].moves[moveChecked] != MOVE_NONE) + { + moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); + break; + } + } + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - if (!gBattleMons[battler].volatiles.escapePrevention) - gDisableStructs[battler].noRetreat = TRUE; + SET_BATTLER_TYPE(gBattlerAttacker, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); gBattlescriptCurrInstr = cmd->nextInstr; } - return; } - case VARIOUS_CURE_CERTAIN_STATUSES: + else { - VARIOUS_ARGS(); - // Check infatuation - if (gBattleMons[battler].volatiles.infatuation) - { - gBattleMons[battler].volatiles.infatuation = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - } - // Check taunt - if (gDisableStructs[battler].tauntTimer != 0) - { - gDisableStructs[battler].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - } - // Check encore - if (gDisableStructs[battler].encoreTimer != 0) - { - gDisableStructs[battler].encoredMove = 0; - gDisableStructs[battler].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - } - // Check torment - if (gBattleMons[battler].volatiles.torment == TRUE) + // Randomly changes user's type to one of its moves' type + while (validMoves < MAX_MON_MOVES) { - gBattleMons[battler].volatiles.torment = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; + if (gBattleMons[gBattlerAttacker].moves[validMoves] == MOVE_NONE) + break; + + validMoves++; } - // Check heal block - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + + for (moveChecked = 0; moveChecked < validMoves; moveChecked++) { - gStatuses3[battler] &= ~(STATUS3_HEAL_BLOCK); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; + moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); + + if (moveType == TYPE_MYSTERY) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + moveType = TYPE_GHOST; + else + moveType = TYPE_NORMAL; + } + if (moveType != gBattleMons[gBattlerAttacker].types[0] + && moveType != gBattleMons[gBattlerAttacker].types[1] + && moveType != gBattleMons[gBattlerAttacker].types[2]) + { + break; + } } - // Check disable - if (gDisableStructs[battler].disableTimer != 0) + + if (moveChecked == validMoves) { - gDisableStructs[battler].disableTimer = 0; - gDisableStructs[battler].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; + gBattlescriptCurrInstr = cmd->failInstr; } - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES: - { - VARIOUS_ARGS(); - battler = gBattlerTarget; - for (i = 0; i < NUM_BATTLE_STATS; i++) - if (gBattleMons[battler].statStages[i] < DEFAULT_STAT_STAGE) - gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY: - { - VARIOUS_ARGS(const u8 *jumpInstr); - if (GetItemPocket(gLastUsedItem) == POCKET_BERRIES) - gBattlescriptCurrInstr = cmd->jumpInstr; else - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - case VARIOUS_SAVE_BATTLER_ITEM: - { - VARIOUS_ARGS(); - gBattleHistory->heldItems[battler] = gBattleMons[battler].item; - break; - } - case VARIOUS_RESTORE_BATTLER_ITEM: - { - VARIOUS_ARGS(); - gBattleMons[battler].item = gBattleHistory->heldItems[battler]; - break; - } - case VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM: - { - VARIOUS_ARGS(); - gBattleMons[battler].item = gLastUsedItem; - break; - } - } // End of switch (cmd->id) - - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void TryResetProtectUseCounter(u32 battler) -{ - u32 lastMove = gLastResultingMoves[battler]; - enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove); - if (lastMove == MOVE_UNAVAILABLE - || (!gBattleMoveEffects[lastEffect].usesProtectCounter - && ((B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) - || B_ALLY_SWITCH_FAIL_CHANCE < GEN_9))) - gDisableStructs[battler].protectUses = 0; -} - -static void Cmd_setprotectlike(void) -{ - CMD_ARGS(); + { + do + { + while ((moveChecked = MOD(Random(), MAX_MON_MOVES)) >= validMoves); - bool32 protectFails = TRUE; - bool32 notLastTurn = TRUE; - u32 protectMethod = GetMoveProtectMethod(gCurrentMove); + moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); - TryResetProtectUseCounter(gBattlerAttacker); + if (moveType == TYPE_MYSTERY) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + moveType = TYPE_GHOST; + else + moveType = TYPE_NORMAL; + } + } + while (moveType == gBattleMons[gBattlerAttacker].types[0] || moveType == gBattleMons[gBattlerAttacker].types[1] || moveType == gBattleMons[gBattlerAttacker].types[2]); - if (gCurrentTurnActionNumber == (gBattlersCount - 1)) - notLastTurn = FALSE; + SET_BATTLER_TYPE(gBattlerAttacker, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= Random() && notLastTurn) - || (protectMethod == PROTECT_WIDE_GUARD && B_WIDE_GUARD != GEN_5) - || (protectMethod == PROTECT_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) - { - if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) - { - gProtectStructs[gBattlerAttacker].endured = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; - } - else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE) - { - gProtectStructs[gBattlerAttacker].protected = protectMethod; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; - } - else - { - gProtectStructs[gBattlerAttacker].protected = protectMethod; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; + gBattlescriptCurrInstr = cmd->nextInstr; } - - gDisableStructs[gBattlerAttacker].protectUses++; - protectFails = FALSE; - } - - if (protectFails) - { - gDisableStructs[gBattlerAttacker].protectUses = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECT_FAILED; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; } - - gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_tryexplosion(void) +static void Cmd_givepaydaymoney(void) { CMD_ARGS(); - if (gBattleControllerExecFlags) - return; + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) && gPaydayMoney != 0) + { + u32 bonusMoney = gPaydayMoney * gBattleStruct->moneyMultiplier; + AddMoney(&gSaveBlock1Ptr->money, bonusMoney); - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; - BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); - MarkBattlerForControllerExec(gBattlerAttacker); - gBattlescriptCurrInstr = cmd->nextInstr; + PREPARE_HWORD_NUMBER_BUFFER(gBattleTextBuff1, 5, bonusMoney) + + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_PrintPayDayMoneyString; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_setatkhptozero(void) +static void Cmd_setlightscreen(void) { CMD_ARGS(); - if (gBattleControllerExecFlags) - return; - - gBattleMons[gBattlerAttacker].hp = 0; - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].hp), &gBattleMons[gBattlerAttacker].hp); - MarkBattlerForControllerExec(gBattlerAttacker); + if (!TrySetLightScreen(gBattlerAttacker)) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; + } gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifnexttargetvalid(void) +#define NOT_ENDURED 0 +#define FOCUS_SASHED 1 +#define FOCUS_BANDED 2 +#define AFFECTION_ENDURED 3 +static void Cmd_tryKO(void) { - CMD_ARGS(const u8 *jumpInstr); + CMD_ARGS(const u8 *failInstr); - const u8 *jumpInstr = cmd->jumpInstr; + bool32 lands = FALSE; + enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE); + u16 targetAbility = GetBattlerAbility(gBattlerTarget); + u32 rand = Random() % 100; + u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); + u32 endured = NOT_ENDURED; - for (gBattlerTarget++; gBattlerTarget < gBattlersCount; gBattlerTarget++) + // Dynamaxed Pokemon cannot be hit by OHKO moves. + if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { - if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) - continue; - if (IsBattlerAlive(gBattlerTarget)) - break; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED; + gBattlescriptCurrInstr = cmd->failInstr; + return; } - if (gBattlerTarget >= gBattlersCount) + gPotentialItemEffectBattler = gBattlerTarget; + if (holdEffect == HOLD_EFFECT_FOCUS_BAND + && (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget)) { - gBattlerTarget = gBattlersCount - 1; - gBattlescriptCurrInstr = cmd->nextInstr; + endured = FOCUS_BANDED; + RecordItemEffectBattle(gBattlerTarget, holdEffect); + } + else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget)) + { + endured = FOCUS_SASHED; + RecordItemEffectBattle(gBattlerTarget, holdEffect); + } + else if (B_AFFECTION_MECHANICS == TRUE && IsOnPlayerSide(gBattlerTarget) && affectionScore >= AFFECTION_THREE_HEARTS) + { + if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20) + || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) + || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) + endured = AFFECTION_ENDURED; + } + + if (targetAbility == ABILITY_STURDY) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gLastUsedAbility = ABILITY_STURDY; + gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO; + gBattlerAbility = gBattlerTarget; } else { - gBattlescriptCurrInstr = jumpInstr; + if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level + && ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS + && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) + || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) + || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))) + { + lands = TRUE; + } + else + { + u16 odds = GetMoveAccuracy(gCurrentMove) + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level); + if (B_SHEER_COLD_ACC >= GEN_7 && effect == EFFECT_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) + odds -= 10; + if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) + lands = TRUE; + } + + if (lands) + { + if (gProtectStructs[gBattlerTarget].endured) + { + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED; + } + else if (endured == FOCUS_BANDED || endured == FOCUS_SASHED) + { + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_HUNG_ON; + gLastUsedItem = gBattleMons[gBattlerTarget].item; + } + else if (endured == AFFECTION_ENDURED) + { + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; + } + else + { + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_ONE_HIT_KO; + } + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_MISS; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED; + gBattlescriptCurrInstr = cmd->failInstr; + } } } +#undef NOT_ENDURED +#undef FOCUS_SASHED +#undef FOCUS_BANDED +#undef AFFECTION_ENDURED -static void Cmd_tryhealhalfhealth(void) +static void Cmd_checknonvolatiletrigger(void) { - CMD_ARGS(const u8 *failInstr, u8 battler); - - const u8 *failInstr = cmd->failInstr; - - if (cmd->battler == BS_ATTACKER) - gBattlerTarget = gBattlerAttacker; - - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; + CMD_ARGS(u16 nonVolatile, const u8 *failInstr); - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - gBattlescriptCurrInstr = failInstr; + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + cmd->nonVolatile, + CHECK_TRIGGER)) + gBattlescriptCurrInstr = cmd->failInstr; + else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + gBattlescriptCurrInstr = cmd->failInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -static void SetMoveForMirrorMove(u32 move) +static void Cmd_copybidedmg(void) { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - // Edge case, we used Z Mirror Move, got the stat boost and now need to use the Z-move - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + CMD_ARGS(); + gBattleStruct->moveDamage[gBattlerTarget] = gBideDmg[gBattlerAttacker] * 2; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_unused_96(void) +{ +} + +static void Cmd_tryinfatuating(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - gCurrentMove = GetTypeBasedZMove(move); + gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; + gLastUsedAbility = ABILITY_OBLIVIOUS; + RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); } else { - gCurrentMove = move; + if (gBattleMons[gBattlerTarget].volatiles.infatuation + || !AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; + } } - - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); } -static void Cmd_trymirrormove(void) +static void Cmd_updatestatusicon(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler); + u32 battler; - s32 i, validMovesCount; - u16 move; - u16 validMoves[MAX_BATTLERS_COUNT] = {0}; + if (gBattleControllerExecFlags) + return; - for (validMovesCount = 0, i = 0; i < gBattlersCount; i++) + if (cmd->battler == BS_PLAYER2) { - if (i != gBattlerAttacker) + for (battler = gBattleControllerExecFlags; battler < gBattlersCount; battler++) { - move = gBattleStruct->lastTakenMoveFrom[gBattlerAttacker][i]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) + if (!(gAbsentBattlerFlags & (1u << battler))) { - validMoves[validMovesCount] = move; - validMovesCount++; + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); } } + gBattlescriptCurrInstr = cmd->nextInstr; } - - move = gBattleStruct->lastTakenMove[gBattlerAttacker]; - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE) - { - SetMoveForMirrorMove(move); - } - else if (validMovesCount != 0) + else if (cmd->battler == BS_ATTACKER_WITH_PARTNER) { - SetMoveForMirrorMove(validMoves[Random() % validMovesCount]); + battler = gBattlerAttacker; + if (!(gAbsentBattlerFlags & (1u << battler))) + { + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + } + if ((IsDoubleBattle())) + { + battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); + if (!(gAbsentBattlerFlags & (1u << battler))) + { + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + } + } + gBattlescriptCurrInstr = cmd->nextInstr; } - else // no valid moves found + else { + battler = GetBattlerForBattleScript(cmd->battler); + BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setfieldweather(void) +static void Cmd_setmist(void) { - CMD_ARGS(u8 weather); - - u8 battleWeatherId = cmd->weather; + CMD_ARGS(); - if (!TryChangeBattleWeather(gBattlerAttacker, battleWeatherId, FALSE)) + if (gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_FAILED; - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MIST_FAILED; } - - switch (battleWeatherId) + else { - case BATTLE_WEATHER_RAIN: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_RAIN; - break; - case BATTLE_WEATHER_SUN: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SUNLIGHT; - break; - case BATTLE_WEATHER_SANDSTORM: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SANDSTORM; - break; - case BATTLE_WEATHER_HAIL: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_HAIL; - break; - case BATTLE_WEATHER_SNOW: - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SNOW; - break; + gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer = gBattleTurnCounter + 5; + gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_MIST; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MIST; } - gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setreflect(void) +static void Cmd_setfocusenergy(void) { - CMD_ARGS(); - if (!TrySetReflect(gBattlerAttacker)) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; - } + CMD_ARGS(u8 battler); + u8 battler = GetBattlerForBattleScript(cmd->battler); + enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_setseeded(void) -{ - CMD_ARGS(); - - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED) + if ((effect == EFFECT_DRAGON_CHEER && (!(IsDoubleBattle()) || (gAbsentBattlerFlags & (1u << battler)))) + || gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_MISS; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED; } - else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS)) + else if (effect == EFFECT_DRAGON_CHEER && !IS_BATTLER_OF_TYPE(battler, TYPE_DRAGON)) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_FAIL; + gBattleMons[battler].volatiles.dragonCheer = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } else { - gStatuses3[gBattlerTarget] |= gBattlerAttacker; - gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_SET; + if (GetGenConfig(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3) + gBattleMons[battler].volatiles.focusEnergy = TRUE; + else + gBattleMons[battler].volatiles.dragonCheer = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; } - gBattlescriptCurrInstr = cmd->nextInstr; } -// TODO: Needs tests for everything -static void Cmd_manipulatedamage(void) +static void Cmd_transformdataexecution(void) { - CMD_ARGS(u8 mode); + CMD_ARGS(); - switch (cmd->mode) + gChosenMove = MOVE_UNAVAILABLE; + gBattlescriptCurrInstr = cmd->nextInstr; + if (gBattleMons[gBattlerTarget].volatiles.transformed + || gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON + || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER) { - case DMG_CHANGE_SIGN: - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - break; - case DMG_DOUBLED: - gBattleStruct->moveDamage[gBattlerTarget] *= 2; - break; - case DMG_1_8_TARGET_HP: - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 8; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - break; - case DMG_FULL_ATTACKER_HP: - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker); - break; - case DMG_BIG_ROOT: - gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); - break; + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORM_FAILED; } + else + { + s32 i; + u8 *battleMonAttacker, *battleMonTarget; + u8 timesGotHit; - gBattlescriptCurrInstr = cmd->nextInstr; -} + gBattleMons[gBattlerAttacker].volatiles.transformed = TRUE; + gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; + gDisableStructs[gBattlerAttacker].disableTimer = 0; + gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; + gDisableStructs[gBattlerAttacker].transformedMonShininess = gBattleMons[gBattlerTarget].isShiny; + gDisableStructs[gBattlerAttacker].mimickedMoves = 0; + gDisableStructs[gBattlerAttacker].usedMoves = 0; -static void Cmd_trysetrest(void) -{ - CMD_ARGS(const u8 *failInstr); + timesGotHit = gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]; + gBattleStruct->timesGotHit[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = timesGotHit; - const u8 *failInstr = cmd->failInstr; - gBattlerTarget = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP * (-1); + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].species) - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - { - gBattlescriptCurrInstr = failInstr; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) - { - gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) - { - gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; - } - else - { - if (gBattleMons[gBattlerTarget].status1 & ((u8)(~STATUS1_SLEEP))) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_REST_STATUSED; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_REST; + battleMonAttacker = (u8 *)(&gBattleMons[gBattlerAttacker]); + battleMonTarget = (u8 *)(&gBattleMons[gBattlerTarget]); - gBattleMons[gBattlerTarget].status1 = STATUS1_SLEEP_TURN(3); - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = cmd->nextInstr; + for (i = 0; i < offsetof(struct BattlePokemon, pp); i++) + battleMonAttacker[i] = battleMonTarget[i]; + + gDisableStructs[gBattlerAttacker].overwrittenAbility = GetBattlerAbility(gBattlerTarget); + for (i = 0; i < MAX_MON_MOVES; i++) + { + u32 pp = GetMovePP(gBattleMons[gBattlerAttacker].moves[i]); + if (pp < 5) + gBattleMons[gBattlerAttacker].pp[i] = pp; + else + gBattleMons[gBattlerAttacker].pp[i] = 5; + } + + // update AI knowledge + RecordAllMoves(gBattlerAttacker); + RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); + + BtlController_EmitResetActionMoveSelection(gBattlerAttacker, B_COMM_TO_CONTROLLER, RESET_MOVE_SELECTION); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORMED; } } -static void Cmd_jumpifnotfirstturn(void) +static void Cmd_setsubstitute(void) { - CMD_ARGS(const u8 *jumpInstr); + CMD_ARGS(); - const u8 *jumpInstr = cmd->jumpInstr; + u32 factor = GetMoveEffect(gCurrentMove) == EFFECT_SHED_TAIL ? 2 : 4; + u32 hp; - if (gDisableStructs[gBattlerAttacker].isFirstTurn && !(gSpecialStatuses[gBattlerAttacker].instructedChosenTarget)) - gBattlescriptCurrInstr = cmd->nextInstr; + if (factor == 2) + hp = (GetNonDynamaxMaxHP(gBattlerAttacker)+1) / factor; // shed tail rounds up else - gBattlescriptCurrInstr = jumpInstr; -} + hp = GetNonDynamaxMaxHP(gBattlerAttacker) / factor; // one bit value will only work for Pokémon which max hp can go to 1020(which is more than possible in games) -static void Cmd_setmiracleeye(void) -{ - CMD_ARGS(const u8 *failInstr); + if (hp == 0) + hp = 1; - if (!(gStatuses3[gBattlerTarget] & STATUS3_MIRACLE_EYED)) + if (gBattleMons[gBattlerAttacker].hp <= hp) { - gStatuses3[gBattlerTarget] |= STATUS3_MIRACLE_EYED; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleStruct->moveDamage[gBattlerAttacker] = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SUBSTITUTE_FAILED; } else { - gBattlescriptCurrInstr = cmd->failInstr; - } -} - -bool8 UproarWakeUpCheck(u8 battler) -{ - s32 i; - bool32 hasSoundproof = (B_UPROAR_IGNORE_SOUNDPROOF < GEN_5 && GetBattlerAbility(battler) == ABILITY_SOUNDPROOF); - - for (i = 0; i < gBattlersCount; i++) - { - if (!(gBattleMons[i].volatiles.uproarTurns) || hasSoundproof) - continue; - - gBattleScripting.battler = i; + gBattleStruct->moveDamage[gBattlerAttacker] = hp; // one bit value will only work for Pokémon which max hp can go to 1020(which is more than possible in games) + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; - if (gBattlerTarget == 0xFF) - gBattlerTarget = i; - else if (gBattlerTarget == i) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_SLEEP_UPROAR; + gBattleMons[gBattlerAttacker].volatiles.substitute = TRUE; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; + if (factor == 2) + gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker] / 2; else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_UPROAR_KEPT_AWAKE; - - break; + gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker]; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SUBSTITUTE; + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE; } - if (i == gBattlersCount) - return FALSE; - else - return TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifuproarwakes(void) +static void Cmd_mimicattackcopy(void) { - CMD_ARGS(const u8 *jumpInstr); + CMD_ARGS(const u8 *failInstr); - if (UproarWakeUpCheck(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; + if ((IsMoveMimicBanned(gLastMoves[gBattlerTarget])) + || (gBattleMons[gBattlerAttacker].volatiles.transformed) + || gLastMoves[gBattlerTarget] == MOVE_NONE + || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_stockpile(void) -{ - CMD_ARGS(u8 id); - - switch (cmd->id) { - case 0: - if (gDisableStructs[gBattlerAttacker].stockpileCounter >= 3) + int i; + + for (i = 0; i < MAX_MON_MOVES; i++) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_STOCKPILE; + if (gBattleMons[gBattlerAttacker].moves[i] == gLastMoves[gBattlerTarget]) + break; } - else + + if (i == MAX_MON_MOVES) { - gDisableStructs[gBattlerAttacker].stockpileCounter++; - gDisableStructs[gBattlerAttacker].stockpileBeforeDef = gBattleMons[gBattlerAttacker].statStages[STAT_DEF]; - gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef = gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF]; - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBattlerAttacker].stockpileCounter); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STOCKPILED; + gChosenMove = 0xFFFF; + gBattleMons[gBattlerAttacker].moves[gCurrMovePos] = gLastMoves[gBattlerTarget]; + u32 pp = GetMovePP(gLastMoves[gBattlerTarget]); + if (pp < 5) + gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = pp; + else + gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = 5; + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) + + gDisableStructs[gBattlerAttacker].mimickedMoves |= 1u << gCurrMovePos; + gBattlescriptCurrInstr = cmd->nextInstr; } - break; - case 1: // Save def/sp def stats. - if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + else { - gDisableStructs[gBattlerAttacker].stockpileDef += gBattleMons[gBattlerAttacker].statStages[STAT_DEF] - gDisableStructs[gBattlerAttacker].stockpileBeforeDef; - gDisableStructs[gBattlerAttacker].stockpileSpDef += gBattleMons[gBattlerAttacker].statStages[STAT_SPDEF] - gDisableStructs[gBattlerAttacker].stockpileBeforeSpDef; + gBattlescriptCurrInstr = cmd->failInstr; } - break; } +} - gBattlescriptCurrInstr = cmd->nextInstr; +static bool32 InvalidMetronomeMove(u32 move) +{ + return GetMoveEffect(move) == EFFECT_PLACEHOLDER + || IsMoveMetronomeBanned(move); } -static void Cmd_stockpiletobasedamage(void) +static void Cmd_metronome(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - const u8 *failInstr = cmd->failInstr; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) +#if B_METRONOME_MOVES >= GEN_9 + u32 moveCount = MOVES_COUNT_GEN9; +#elif B_METRONOME_MOVES >= GEN_8 + u32 moveCount = MOVES_COUNT_GEN8; +#elif B_METRONOME_MOVES >= GEN_7 + u32 moveCount = MOVES_COUNT_GEN7; +#elif B_METRONOME_MOVES >= GEN_6 + u32 moveCount = MOVES_COUNT_GEN6; +#elif B_METRONOME_MOVES >= GEN_5 + u32 moveCount = MOVES_COUNT_GEN5; +#elif B_METRONOME_MOVES >= GEN_4 + u32 moveCount = MOVES_COUNT_GEN4; +#elif B_METRONOME_MOVES >= GEN_3 + u32 moveCount = MOVES_COUNT_GEN3; +#elif B_METRONOME_MOVES >= GEN_2 + u32 moveCount = MOVES_COUNT_GEN2; +#else + u32 moveCount = MOVES_COUNT_GEN1; +#endif + + gCurrentMove = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); + PrepareStringBattle(STRINGID_WAGGLINGAFINGER, gBattlerAttacker); + gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); + gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + ResetValuesForCalledMove(); +} + +static void Cmd_unused_0x9f(void) +{ +} + +static void Cmd_unused_0xA0(void) +{ +} + +static void Cmd_counterdamagecalculator(void) +{ + CMD_ARGS(const u8 *failInstr); + + u8 sideAttacker = GetBattlerSide(gBattlerAttacker); + u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId); + + if (gProtectStructs[gBattlerAttacker].physicalDmg + && sideAttacker != sideTarget + && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - gBattlescriptCurrInstr = failInstr; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; + + if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) + gBattlerTarget = gSideTimers[sideTarget].followmeTarget; + else + gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + + gBattlescriptCurrInstr = cmd->nextInstr; } else { - if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +// A copy of Cmd with the physical -> special field changes +static void Cmd_mirrorcoatdamagecalculator(void) +{ + CMD_ARGS(const u8 *failInstr); + + u8 sideAttacker = GetBattlerSide(gBattlerAttacker); + u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId); + + if (gProtectStructs[gBattlerAttacker].specialDmg + && sideAttacker != sideTarget + && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) + { + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; + + if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) + gBattlerTarget = gSideTimers[sideTarget].followmeTarget; + else + gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; gBattlescriptCurrInstr = cmd->nextInstr; } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } } -static void Cmd_stockpiletohpheal(void) +static void Cmd_disablelastusedattack(void) { CMD_ARGS(const u8 *failInstr); - const u8 *failInstr = cmd->failInstr; + s32 i; - if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0 && !gBattleStruct->snatchedMoveIsUsed) + for (i = 0; i < MAX_MON_MOVES; i++) { - gBattlescriptCurrInstr = failInstr; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FAILED; + if (gBattleMons[gBattlerTarget].moves[i] == gLastMoves[gBattlerTarget]) + break; + } + if (gDisableStructs[gBattlerTarget].disabledMove == MOVE_NONE + && i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) + { + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].moves[i]) + + gDisableStructs[gBattlerTarget].disabledMove = gBattleMons[gBattlerTarget].moves[i]; + if (B_DISABLE_TURNS >= GEN_5) + gDisableStructs[gBattlerTarget].disableTimer = 4; + else if (B_DISABLE_TURNS >= GEN_4) + gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 4; // 4-7 turns + else + gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 2; // 2-5 turns + gBattlescriptCurrInstr = cmd->nextInstr; } else { - if (gBattleMons[gBattlerAttacker].maxHP == gBattleMons[gBattlerAttacker].hp) + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +static void Cmd_trysetencore(void) +{ + CMD_ARGS(const u8 *failInstr); + + s32 i; + + if (IsMaxMove(gLastMoves[gBattlerTarget]) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) + { + for (i = 0; i < MAX_MON_MOVES; i++) { - gDisableStructs[gBattlerAttacker].stockpileCounter = 0; - gBattlescriptCurrInstr = failInstr; - gBattlerTarget = gBattlerAttacker; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWALLOW_FULL_HP; + if (gBattleMons[gBattlerTarget].moves[i] == gBattleStruct->dynamax.baseMoves[gBattlerTarget]) + break; } - else + } + else + { + for (i = 0; i < MAX_MON_MOVES; i++) { - if (gDisableStructs[gBattlerAttacker].stockpileCounter > 0) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (1 << (3 - gDisableStructs[gBattlerAttacker].stockpileCounter)); - gBattleScripting.animTurn = gDisableStructs[gBattlerAttacker].stockpileCounter; - } - else // Snatched move - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - gBattleScripting.animTurn = 1; - } - - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - - gBattlescriptCurrInstr = cmd->nextInstr; - gBattlerTarget = gBattlerAttacker; + if (gBattleMons[gBattlerTarget].moves[i] == gLastMoves[gBattlerTarget]) + break; } } -} -void BS_RemoveStockpileCounters(void) -{ - NATIVE_ARGS(); + if ((IsMoveEncoreBanned(gLastMoves[gBattlerTarget])) + || gLastMoves[gBattlerTarget] == MOVE_NONE + || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) + { + i = MAX_MON_MOVES; + } - if (GetMoveEffect(gCurrentMove) == EFFECT_SWALLOW - && gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT - && IsBattlerAlive(gBattlerTarget)) + if (gDisableStructs[gBattlerTarget].encoredMove == MOVE_NONE + && i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) { + gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; + gDisableStructs[gBattlerTarget].encoredMovePos = i; + // Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn. + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + gDisableStructs[gBattlerTarget].encoreTimer = 4; + else + gDisableStructs[gBattlerTarget].encoreTimer = 3; gBattlescriptCurrInstr = cmd->nextInstr; } else { - gDisableStructs[gBattlerAttacker].stockpileCounter = 0; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_MoveEffectStockpileWoreOff; + gBattlescriptCurrInstr = cmd->failInstr; } } -// Sign change for drained HP handled in GetDrainedBigRootHp -static void Cmd_setdrainedhp(void) +static void Cmd_painsplitdmgcalc(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *failInstr); - gBattleStruct->moveDamage[gBattlerAttacker] = (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100); + if (!(DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) + { + s32 hpDiff = (gBattleMons[gBattlerAttacker].hp + GetNonDynamaxHP(gBattlerTarget)) / 2; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - hpDiff; + gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp - hpDiff; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } } -static u16 ReverseStatChangeMoveEffect(u16 moveEffect) +// Conversion 2 +static void Cmd_settypetorandomresistance(void) { - switch (moveEffect) + CMD_ARGS(const u8 *failInstr); + + // Before Gen 5 Conversion 2 only worked on a move the attacker was actually hit by. + // This changed later to the last move used by the selected target. + if (B_UPDATED_CONVERSION_2 < GEN_5) { - // +1 - case MOVE_EFFECT_ATK_PLUS_1: - return MOVE_EFFECT_ATK_MINUS_1; - case MOVE_EFFECT_DEF_PLUS_1: - return MOVE_EFFECT_DEF_MINUS_1; - case MOVE_EFFECT_SPD_PLUS_1: - return MOVE_EFFECT_SPD_MINUS_1; - case MOVE_EFFECT_SP_ATK_PLUS_1: - return MOVE_EFFECT_SP_ATK_MINUS_1; - case MOVE_EFFECT_SP_DEF_PLUS_1: - return MOVE_EFFECT_SP_DEF_MINUS_1; - case MOVE_EFFECT_ACC_PLUS_1: - return MOVE_EFFECT_ACC_MINUS_1; - case MOVE_EFFECT_EVS_PLUS_1: - return MOVE_EFFECT_EVS_MINUS_1; - // -1 - case MOVE_EFFECT_ATK_MINUS_1: - return MOVE_EFFECT_ATK_PLUS_1; - case MOVE_EFFECT_DEF_MINUS_1: - return MOVE_EFFECT_DEF_PLUS_1; - case MOVE_EFFECT_SPD_MINUS_1: - return MOVE_EFFECT_SPD_PLUS_1; - case MOVE_EFFECT_SP_ATK_MINUS_1: - return MOVE_EFFECT_SP_ATK_PLUS_1; - case MOVE_EFFECT_SP_DEF_MINUS_1: - return MOVE_EFFECT_SP_DEF_PLUS_1; - case MOVE_EFFECT_ACC_MINUS_1: - return MOVE_EFFECT_ACC_PLUS_1; - case MOVE_EFFECT_EVS_MINUS_1: - // +2 - case MOVE_EFFECT_ATK_PLUS_2: - return MOVE_EFFECT_ATK_MINUS_2; - case MOVE_EFFECT_DEF_PLUS_2: - return MOVE_EFFECT_DEF_MINUS_2; - case MOVE_EFFECT_SPD_PLUS_2: - return MOVE_EFFECT_SPD_MINUS_2; - case MOVE_EFFECT_SP_ATK_PLUS_2: - return MOVE_EFFECT_SP_ATK_MINUS_2; - case MOVE_EFFECT_SP_DEF_PLUS_2: - return MOVE_EFFECT_SP_DEF_MINUS_2; - case MOVE_EFFECT_ACC_PLUS_2: - return MOVE_EFFECT_ACC_MINUS_2; - case MOVE_EFFECT_EVS_PLUS_2: - return MOVE_EFFECT_EVS_MINUS_2; - // -2 - case MOVE_EFFECT_ATK_MINUS_2: - return MOVE_EFFECT_ATK_PLUS_2; - case MOVE_EFFECT_DEF_MINUS_2: - return MOVE_EFFECT_DEF_PLUS_2; - case MOVE_EFFECT_SPD_MINUS_2: - return MOVE_EFFECT_SPD_PLUS_2; - case MOVE_EFFECT_SP_ATK_MINUS_2: - return MOVE_EFFECT_SP_ATK_PLUS_2; - case MOVE_EFFECT_SP_DEF_MINUS_2: - return MOVE_EFFECT_SP_DEF_PLUS_2; - case MOVE_EFFECT_ACC_MINUS_2: - return MOVE_EFFECT_ACC_PLUS_2; - case MOVE_EFFECT_EVS_MINUS_2: - return MOVE_EFFECT_EVS_PLUS_2; - default: - return 0; - } -} + if (gLastLandedMoves[gBattlerAttacker] == MOVE_NONE + || gLastLandedMoves[gBattlerAttacker] == MOVE_UNAVAILABLE) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gBattleMoveEffects[GetMoveEffect(gLastLandedMoves[gBattlerAttacker])].twoTurnEffect + && gBattleMons[gLastHitBy[gBattlerAttacker]].volatiles.multipleTurns) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + u32 i, resistTypes = 0; + u32 hitByType = gLastHitByType[gBattlerAttacker]; -static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 statValue, u32 statId, bool32 certain) -{ - u32 currStat = 0; - u32 changeableStatsCount = 1; // current stat is counted automatically - u32 statAnimId = statId; - bool32 statChangeByTwo = statValue > 1 || statValue < -1; + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. + { + switch (GetTypeModifier(hitByType, i)) + { + case UQ_4_12(0): + case UQ_4_12(0.5): + resistTypes |= 1u << i; + break; + } + } - if (statValue <= -1) // goes down + while (resistTypes != 0) + { + i = Random() % NUMBER_OF_MON_TYPES; + if (resistTypes & 1u << i) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) + { + resistTypes &= ~(1u << i); // Type resists, but the user is already of this type. + } + else + { + SET_BATTLER_TYPE(gBattlerAttacker, i); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + } + } + + gBattlescriptCurrInstr = cmd->failInstr; + } + } + else { - if (statChangeByTwo) - statAnimId += STAT_ANIM_MINUS2; + if (gLastResultingMoves[gBattlerTarget] == MOVE_NONE + || gLastResultingMoves[gBattlerTarget] == MOVE_UNAVAILABLE + || gLastResultingMoves[gBattlerTarget] == MOVE_STRUGGLE) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gLastUsedMoveType[gBattlerTarget] == TYPE_NONE || gLastUsedMoveType[gBattlerTarget] == TYPE_STELLAR || gLastUsedMoveType[gBattlerTarget] == TYPE_MYSTERY) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else - statAnimId += STAT_ANIM_MINUS1; - - while (stats != 0) { - if (stats & 1) + u32 i, resistTypes = 0; + + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. { - if (certain) + switch (GetTypeModifier(gLastUsedMoveType[gBattlerTarget], i)) { - if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE) - { - changeableStatsCount++; - break; - } + case UQ_4_12(0): + case UQ_4_12(0.5): + resistTypes |= 1u << i; + break; } - else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC) - && !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) - && !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK) - && !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF)) + } + + while (resistTypes != 0) + { + i = Random() % NUMBER_OF_MON_TYPES; + if (resistTypes & 1u << i) { - if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE) + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) { - changeableStatsCount++; - break; + resistTypes &= ~(1u << i); // Type resists, but the user is already of this type. + } + else + { + SET_BATTLER_TYPE(gBattlerAttacker, i); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); + gBattlescriptCurrInstr = cmd->nextInstr; + return; } } } - stats >>= 1, currStat++; - } - if (changeableStatsCount > 1) // more than one stat, so the color is gray - { - if (statChangeByTwo) - statAnimId = STAT_ANIM_MULTIPLE_MINUS2; - else - statAnimId = STAT_ANIM_MULTIPLE_MINUS1; + gBattlescriptCurrInstr = cmd->failInstr; } } - else // goes up +} + +static void Cmd_setalwayshitflag(void) +{ + CMD_ARGS(); + + gStatuses3[gBattlerTarget] &= ~STATUS3_ALWAYS_HITS; + gStatuses3[gBattlerTarget] |= STATUS3_ALWAYS_HITS_TURN(2); + gDisableStructs[gBattlerTarget].battlerWithSureHit = gBattlerAttacker; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +// Sketch +static void Cmd_copymovepermanently(void) +{ + CMD_ARGS(const u8 *failInstr); + + gChosenMove = MOVE_UNAVAILABLE; + + if (!(gBattleMons[gBattlerAttacker].volatiles.transformed) + && gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE + && !IsMoveSketchBanned(gLastPrintedMoves[gBattlerTarget])) { - if (statChangeByTwo) - statAnimId += STAT_ANIM_PLUS2; - else - statAnimId += STAT_ANIM_PLUS1; + s32 i; - while (stats != 0) + for (i = 0; i < MAX_MON_MOVES; i++) { - if (stats & 1 && gBattleMons[battler].statStages[currStat] < MAX_STAT_STAGE) - { - changeableStatsCount++; + if (GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i]) == EFFECT_SKETCH) + continue; + if (gBattleMons[gBattlerAttacker].moves[i] == gLastPrintedMoves[gBattlerTarget]) break; - } - stats >>= 1, currStat++; } - if (changeableStatsCount > 1) // more than one stat, so the color is gray + if (i != MAX_MON_MOVES) { - if (statChangeByTwo) - statAnimId = STAT_ANIM_MULTIPLE_PLUS2; - else - statAnimId = STAT_ANIM_MULTIPLE_PLUS1; + gBattlescriptCurrInstr = cmd->failInstr; } - } + else // sketch worked + { + struct MovePpInfo movePpData; - if (!gBattleScripting.statAnimPlayed) - { - BtlController_EmitBattleAnimation(battler, B_COMM_TO_CONTROLLER, B_ANIM_STATS_CHANGE, &gDisableStructs[battler], statAnimId); - MarkBattlerForControllerExec(battler); - if (changeableStatsCount > 1) - gBattleScripting.statAnimPlayed = TRUE; + gBattleMons[gBattlerAttacker].moves[gCurrMovePos] = gLastPrintedMoves[gBattlerTarget]; + gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = GetMovePP(gLastPrintedMoves[gBattlerTarget]); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + movePpData.moves[i] = gBattleMons[gBattlerAttacker].moves[i]; + movePpData.pp[i] = gBattleMons[gBattlerAttacker].pp[i]; + } + movePpData.ppBonuses = gBattleMons[gBattlerAttacker].ppBonuses; + + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_MOVES_PP_BATTLE, 0, sizeof(movePpData), &movePpData); + MarkBattlerForControllerExec(gBattlerAttacker); + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastPrintedMoves[gBattlerTarget]) + + gBattlescriptCurrInstr = cmd->nextInstr; + } } - else if (changeableStatsCount == 1) // final stat that can be changed + else { - gBattleScripting.statAnimPlayed = FALSE; + gBattlescriptCurrInstr = cmd->failInstr; } } -static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr) +static void Cmd_trychoosesleeptalkmove(void) { - u32 index, battlerAbility; - enum ItemHoldEffect battlerHoldEffect; - battlerAbility = GetBattlerAbility(battler); - battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); - gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker; + CMD_ARGS(const u8 *failInstr); - if (battlerAbility == ABILITY_CONTRARY) + u32 i, unusableMovesBits = 0, movePosition; + + for (i = 0; i < MAX_MON_MOVES; i++) { - statValue ^= STAT_BUFF_NEGATIVE; - if (!flags.onlyChecking) + if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) + || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) { - gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE; - RecordAbilityBattle(battler, battlerAbility); - if (flags.updateMoveEffect) - gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect); + unusableMovesBits |= (1 << (i)); } } - else if (battlerAbility == ABILITY_SIMPLE && !flags.onlyChecking) + + unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); + if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen { - statValue = (SET_STAT_BUFF_VALUE(GET_STAT_BUFF_VALUE(statValue) * 2)) | ((statValue <= -1) ? STAT_BUFF_NEGATIVE : 0); - RecordAbilityBattle(battler, battlerAbility); + gBattlescriptCurrInstr = cmd->nextInstr; } - - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - - if (statValue <= -1) // Stat decrease. + else // at least one move can be chosen { - if (gSideTimers[GetBattlerSide(battler)].mistTimer - && !flags.certain && gCurrentMove != MOVE_CURSE - && !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR)) + // Set Sleep Talk as used move, so it works with Last Resort. + gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; + do { - if (flags.allowPtr) - { - if (gSpecialStatuses[battler].statLowered) - { - gBattlescriptCurrInstr = BS_ptr; - } - else - { - BattleScriptPush(BS_ptr); - gBattleScripting.battler = battler; - gBattlescriptCurrInstr = BattleScript_MistProtected; - gSpecialStatuses[battler].statLowered = TRUE; - } - } - return STAT_CHANGE_DIDNT_WORK; - } - else if (gCurrentMove != MOVE_CURSE - && !flags.notProtectAffected && JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, BattleScript_ButItFailed)) + movePosition = MOD(Random(), MAX_MON_MOVES); + } while ((1u << movePosition) & unusableMovesBits); + + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gBattleMons[gBattlerAttacker].moves[movePosition])) { - return STAT_CHANGE_DIDNT_WORK; + gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gBattleMons[gBattlerAttacker].moves[movePosition]; + gCalledMove = GetTypeBasedZMove(gBattleMons[gBattlerAttacker].moves[movePosition]); } - else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || CanAbilityPreventStatLoss(battlerAbility)) - && (flags.statDropPrevention || gBattlerAttacker != gBattlerTarget || flags.mirrorArmored) && !flags.certain && gCurrentMove != MOVE_CURSE) + else { - if (flags.allowPtr) - { - if (gSpecialStatuses[battler].statLowered) - { - gBattlescriptCurrInstr = BS_ptr; - } - else - { - gBattleScripting.battler = battler; - if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) - { - gLastUsedItem = gBattleMons[battler].item; - BattleScriptPush(BS_ptr); - gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; - RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); - } - else - { - gBattlerAbility = battler; - BattleScriptPush(BS_ptr); - gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss; - gLastUsedAbility = battlerAbility; - RecordAbilityBattle(battler, gLastUsedAbility); - } - gSpecialStatuses[battler].statLowered = TRUE; - } - } - return STAT_CHANGE_DIDNT_WORK; + gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition]; } - else if ((index = IsFlowerVeilProtected(battler)) && !flags.certain) + gCurrMovePos = movePosition; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +static inline bool32 IsDanamaxMonPresent(void) +{ + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (battler == gBattlerAttacker) + continue; + + if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX) + return TRUE; + } + + return FALSE; +} + +static void Cmd_trysetdestinybond(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (IsDanamaxMonPresent()) + { + gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; + } + else if (DoesDestinyBondFail(gBattlerAttacker)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerAttacker].volatiles.destinyBond = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +static void TrySetDestinyBondToHappen(void) +{ + if (gBattleMons[gBattlerTarget].volatiles.destinyBond + && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) + && !(gHitMarker & HITMARKER_GRUDGE)) + { + gHitMarker |= HITMARKER_DESTINYBOND; + } +} + +static void Cmd_trysetdestinybondtohappen(void) +{ + CMD_ARGS(); + + TrySetDestinyBondToHappen(); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_settailwind(void) +{ + CMD_ARGS(const u8 *failInstr); + + u8 side = GetBattlerSide(gBattlerAttacker); + + if (!(gSideStatuses[side] & SIDE_STATUS_TAILWIND)) + { + gSideStatuses[side] |= SIDE_STATUS_TAILWIND; + gSideTimers[side].tailwindTimer = gBattleTurnCounter + (B_TAILWIND_TURNS >= GEN_5 ? 4 : 3); + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +static void Cmd_tryspiteppreduce(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (gLastMoves[gBattlerTarget] != MOVE_NONE + && gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE) + { + s32 i; + + // Get move slot to reduce PP. + if (IsMaxMove(gLastMoves[gBattlerTarget])) { - if (flags.allowPtr) + for (i = 0; i < MAX_MON_MOVES; i++) { - if (gSpecialStatuses[battler].statLowered) - { - gBattlescriptCurrInstr = BS_ptr; - } - else - { - BattleScriptPush(BS_ptr); - gBattleScripting.battler = battler; - gBattlerAbility = index - 1; - gBattlescriptCurrInstr = BattleScript_FlowerVeilProtectsRet; - gLastUsedAbility = ABILITY_FLOWER_VEIL; - gSpecialStatuses[battler].statLowered = TRUE; - } + if (gBattleStruct->dynamax.baseMoves[gBattlerTarget] == gBattleMons[gBattlerTarget].moves[i]) + break; } - return STAT_CHANGE_DIDNT_WORK; } - else if (!flags.certain - && (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC) - || (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) - || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK) - || (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF))) + else { - if (flags.allowPtr) + for (i = 0; i < MAX_MON_MOVES; i++) { - BattleScriptPush(BS_ptr); - gBattleScripting.battler = battler; - gBattlerAbility = battler; - gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss; - gLastUsedAbility = battlerAbility; - RecordAbilityBattle(battler, gLastUsedAbility); + if (gLastMoves[gBattlerTarget] == gBattleMons[gBattlerTarget].moves[i]) + break; } - return STAT_CHANGE_DIDNT_WORK; } - else if (battlerAbility == ABILITY_MIRROR_ARMOR && !flags.mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget) + + if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] > (B_CAN_SPITE_FAIL >= GEN_4 ? 0 : 1)) { - if (flags.allowPtr) + s32 ppToDeduct = B_PP_REDUCED_BY_SPITE >= GEN_4 ? 4 : (Random() & 3) + 2; + // G-Max Depletion only deducts 2 PP. + if (IsMaxMove(gCurrentMove) && MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_SPITE)) + ppToDeduct = 2; + + if (gBattleMons[gBattlerTarget].pp[i] < ppToDeduct) + ppToDeduct = gBattleMons[gBattlerTarget].pp[i]; + + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) + + ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); + + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) + + gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; + + // if (MOVE_IS_PERMANENT(gBattlerTarget, i)), but backwards + if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) + && !(gBattleMons[gBattlerTarget].volatiles.transformed)) { - SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE); - BattleScriptPush(BS_ptr); - gBattleScripting.battler = battler; - gBattlerAbility = battler; - gBattlescriptCurrInstr = BattleScript_MirrorArmorReflect; - RecordAbilityBattle(battler, gBattleMons[battler].ability); + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); + MarkBattlerForControllerExec(gBattlerTarget); } - return STAT_CHANGE_DIDNT_WORK; + + gBattlescriptCurrInstr = cmd->nextInstr; + + // Don't cut off Sky Drop if pp is brought to zero. + if (gBattleMons[gBattlerTarget].pp[i] == 0 && gBattleStruct->skyDropTargets[gBattlerTarget] == SKY_DROP_NO_TARGET) + CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_IGNORE); } - else // try to decrease + else { - statValue = -GET_STAT_BUFF_VALUE(statValue); - if (gBattleMons[battler].statStages[statId] == 1) - statValue = -1; - else if (gBattleMons[battler].statStages[statId] == 2 && statValue < -2) - statValue = -2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; - if (statValue == -2) - { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATHARSHLY; - gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8; - index = 4; - } - else if (statValue <= -3) - { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_SEVERELY & 0xFF; - gBattleTextBuff2[3] = STRINGID_SEVERELY >> 8; - index = 4; - } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATFELL; - gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; + gBattlescriptCurrInstr = cmd->failInstr; + } + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL +static void Cmd_healpartystatus(void) +{ + CMD_ARGS(); - if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE; - } - else if (!flags.onlyChecking) - { - gProtectStructs[battler].tryEjectPack = TRUE; - gProtectStructs[battler].lashOutAffected = TRUE; - } - } + u32 i = 0; + u32 zero = 0; + u32 toHeal = 0; + u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + bool32 isSoundMove = IsSoundMove(gCurrentMove); + + if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 + || !(isSoundMove && GetBattlerAbility(gBattlerAttacker) == ABILITY_SOUNDPROOF)) + { + if (isSoundMove) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL; + else + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA; + gBattleMons[gBattlerAttacker].status1 = 0; + gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; } - else // stat increase + else { - statValue = GET_STAT_BUFF_VALUE(statValue); - if (gBattleMons[battler].statStages[statId] == 11) - statValue = 1; - else if (gBattleMons[battler].statStages[statId] == 10 && statValue > 2) - statValue = 2; - gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN; - index = 1; - if (statValue == 2) + RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_ATTACKER; + } + + gBattleScripting.battler = partner; + + if (IsBattlerAlive(partner)) + { + if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF)) { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_STATSHARPLY; - gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8; - index = 4; + gBattleMons[partner].status1 = 0; + gBattleMons[partner].volatiles.nightmare = FALSE; } - else if (statValue >= 3) + else { - gBattleTextBuff2[1] = B_BUFF_STRING; - gBattleTextBuff2[2] = STRINGID_DRASTICALLY & 0xFF; - gBattleTextBuff2[3] = STRINGID_DRASTICALLY >> 8; - index = 4; + RecordAbilityBattle(partner, gBattleMons[partner].ability); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_PARTNER; } - gBattleTextBuff2[index++] = B_BUFF_STRING; - gBattleTextBuff2[index++] = STRINGID_STATROSE; - gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8; - gBattleTextBuff2[index] = B_BUFF_EOS; + } - gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE + // Because the above MULTISTRING_CHOOSER are ORd, if both are set then it will be B_MSG_BELL_BOTH_SOUNDPROOF - if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE; - } - else if (!flags.onlyChecking) - { - u32 statIncrease; - if ((statValue + gBattleMons[battler].statStages[statId]) > MAX_STAT_STAGE) - statIncrease = MAX_STAT_STAGE - gBattleMons[battler].statStages[statId]; - else - statIncrease = statValue; + for (i = 0; i < PARTY_SIZE; i++) + { + u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + u8 abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM); - gProtectStructs[battler].statRaised = TRUE; + if (species != SPECIES_NONE && species != SPECIES_EGG) + { + u16 ability; + bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i; + bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner); - if (statIncrease) + if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 + || (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker)) + ability = ABILITY_NONE; + else if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner) + ability = ABILITY_NONE; + else if (isAttacker) + ability = GetBattlerAbility(gBattlerAttacker); + else if (isDoublesPartner) + ability = GetBattlerAbility(partner); + else { - // Check Mirror Herb / Opportunist - for (index = 0; index < gBattlersCount; index++) + ability = GetAbilityBySpecies(species, abilityNum); + #if TESTING + if (gTestRunnerEnabled) { - if (IsBattlerAlly(index, battler)) - continue; // Only triggers on opposing side - - if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST - && gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises - { - gProtectStructs[index].activateOpportunist = 2; // set stats to copy - } - if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB) - { - gProtectStructs[index].eatMirrorHerb = 1; - } - - if (gProtectStructs[index].activateOpportunist == 2 || gProtectStructs[index].eatMirrorHerb == 1) - { - gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk - gQueuedStatBoosts[index].statChanges[statId - 1] += statIncrease; - } + u32 side = GetBattlerSide(gBattlerAttacker); + if (TestRunner_Battle_GetForcedAbility(side, i)) + ability = TestRunner_Battle_GetForcedAbility(side, i); } + #endif + } + + if (!(isSoundMove && ability == ABILITY_SOUNDPROOF)) + { + toHeal |= (1 << i); + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i); } } } - if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE) // same as B_MSG_STAT_WONT_DECREASE + if (toHeal) { - if (!flags.allowPtr) - return STAT_CHANGE_DIDNT_WORK; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - return STAT_CHANGE_WORKED; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, toHeal, sizeof(zero), &zero); + MarkBattlerForControllerExec(gBattlerAttacker); } - if (flags.onlyChecking) - return STAT_CHANGE_WORKED; + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleMons[battler].statStages[statId] += statValue; - if (gBattleMons[battler].statStages[statId] < MIN_STAT_STAGE) - gBattleMons[battler].statStages[statId] = MIN_STAT_STAGE; - if (gBattleMons[battler].statStages[statId] > MAX_STAT_STAGE) - gBattleMons[battler].statStages[statId] = MAX_STAT_STAGE; +static void Cmd_cursetarget(void) +{ + CMD_ARGS(const u8 *failInstr); - if (ShouldDefiantCompetitiveActivate(battler, battlerAbility)) - stats = 0; // use single stat animations when Defiant/Competitive activate + if (gBattleMons[gBattlerTarget].volatiles.cursed) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else - stats &= ~(1u << statId); - - TryPlayStatChangeAnimation(battler, battlerAbility, stats, statValue, statId, flags.certain); + { + gBattleMons[gBattlerTarget].volatiles.cursed = TRUE; + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; - return STAT_CHANGE_WORKED; + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_statbuffchange(void) +static void Cmd_trysetspikes(void) { - CMD_ARGS(u8 battler, u16 flags, const u8 *failInstr, u8 stats); + CMD_ARGS(const u8 *failInstr); - u16 flags = cmd->flags; - u32 stats = cmd->stats; - const u8 *ptrBefore = gBattlescriptCurrInstr; - const u8 *failInstr = cmd->failInstr; + u8 targetSide = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); - if (ChangeStatBuffs( - GetBattlerForBattleScript(cmd->battler), - GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), - GET_STAT_BUFF_ID(gBattleScripting.statChanger), - flags, - stats, - failInstr) == STAT_CHANGE_WORKED) + if (gSideTimers[targetSide].spikesAmount == 3) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (gSideTimers[targetSide].spikesAmount == 0) // Add only once to the queue + PushHazardTypeToQueue(targetSide, HAZARDS_SPIKES); + gSideTimers[targetSide].spikesAmount++; gBattlescriptCurrInstr = cmd->nextInstr; - else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping. - gBattlescriptCurrInstr = failInstr; + } } -bool32 TryResetBattlerStatChanges(u8 battler) +static void Cmd_setvolatile(void) { - u32 j; - bool32 ret = FALSE; - - gDisableStructs[battler].stockpileDef = 0; - gDisableStructs[battler].stockpileSpDef = 0; - for (j = 0; j < NUM_BATTLE_STATS; j++) - { - if (gBattleMons[battler].statStages[j] != DEFAULT_STAT_STAGE) - ret = TRUE; // returns TRUE if any stat was reset - - gBattleMons[battler].statStages[j] = DEFAULT_STAT_STAGE; - } + CMD_ARGS(u8 battler, u8 _volatile, u8 value); - return ret; + SetMonVolatile(GetBattlerForBattleScript(cmd->battler), cmd->_volatile, cmd->value); + gBattlescriptCurrInstr = cmd->nextInstr; } -// Haze -static void Cmd_normalisebuffs(void) +static void Cmd_trysetperishsong(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *failInstr); s32 i; + s32 notAffectedCount = 0; for (i = 0; i < gBattlersCount; i++) - TryResetBattlerStatChanges(i); + { + if (gStatuses3[i] & STATUS3_PERISH_SONG + || GetBattlerAbility(i) == ABILITY_SOUNDPROOF + || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE) + || gStatuses3[i] & STATUS3_COMMANDER) + { + notAffectedCount++; + } + else + { + gStatuses3[i] |= STATUS3_PERISH_SONG; + gDisableStructs[i].perishSongTimer = 3; + } + } - gBattlescriptCurrInstr = cmd->nextInstr; + if (notAffectedCount == gBattlersCount) + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setbide(void) +static void Cmd_handlerollout(void) { CMD_ARGS(); - gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; - gLockedMoves[gBattlerAttacker] = gCurrentMove; - gBideDmg[gBattlerAttacker] = 0; - gBattleMons[gBattlerAttacker].volatiles.bideTurns = 2; - - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_twoturnmoveschargestringandanimation(void) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + { + CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_IGNORE); + gBattlescriptCurrInstr = BattleScript_MoveMissedPause; + } + else + { + if (!(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) // First hit. + { + gDisableStructs[gBattlerAttacker].rolloutTimer = 5; + gDisableStructs[gBattlerAttacker].rolloutTimerStartValue = 5; + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; + gLockedMoves[gBattlerAttacker] = gCurrentMove; + } + if (--gDisableStructs[gBattlerAttacker].rolloutTimer == 0) // Last hit. + { + gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; + } + + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +static void Cmd_jumpifconfusedandstatmaxed(void) { - CMD_ARGS(const u8 *animationThenStringPtr); + CMD_ARGS(u8 stat, const u8 *jumpInstr); - gBattleScripting.savedStringId = GetMoveTwoTurnAttackStringId(gCurrentMove); - if (B_UPDATED_MOVE_DATA < GEN_5 || MoveHasChargeTurnAdditionalEffect(gCurrentMove)) - gBattlescriptCurrInstr = cmd->animationThenStringPtr; + if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0 + && !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised else gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trynonvolatilestatus(void) +static void Cmd_handlefurycutter(void) { CMD_ARGS(); - bool32 canInflictStatus = TRUE; - - if (!CanSetNonVolatileStatus( - gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - GetBattlerAbility(gBattlerTarget), - GetMoveNonVolatileStatus(gCurrentMove), - RUN_SCRIPT)) - canInflictStatus = FALSE; - if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) { - canInflictStatus = FALSE; - gBattlescriptCurrInstr = BattleScript_ButItFailed; + gDisableStructs[gBattlerAttacker].furyCutterCounter = 0; + gBattlescriptCurrInstr = BattleScript_MoveMissedPause; } + else + { + u32 max; - if (canInflictStatus) - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_initmultihitstring(void) -{ - CMD_ARGS(); + if (B_UPDATED_MOVE_DATA >= GEN_6) + max = 3; + else if (B_UPDATED_MOVE_DATA == GEN_5) + max = 4; + else + max = 5; - PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) + if (gDisableStructs[gBattlerAttacker].furyCutterCounter < max + && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT) // Don't increment counter on second hit + gDisableStructs[gBattlerAttacker].furyCutterCounter++; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_forcerandomswitch(void) +static void Cmd_setembargo(void) { CMD_ARGS(const u8 *failInstr); - s32 battler1PartyId = 0; - s32 battler2PartyId = 0; - - s32 firstMonId; - s32 lastMonId = 0; // + 1 - struct Pokemon *party = NULL; - u8 validMons[PARTY_SIZE]; - s32 validMonsCount = 0; - - bool32 redCardForcedSwitch = FALSE; - - // Red card checks against wild pokemon. If we have reached here, the player has a mon to switch into - // Red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF... - if (gBattleScripting.switchCase == B_SWITCH_RED_CARD - && !(gBattleTypeFlags & BATTLE_TYPE_TRAINER) - && !IsOnPlayerSide(gBattlerAttacker)) // Check opponent's red card activating + if (gStatuses3[gBattlerTarget] & STATUS3_EMBARGO) { - if (!WILD_DOUBLE_BATTLE) - { - // Wild mon with red card will end single battle - gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; - return; - } - else - { - // Wild double battle, wild mon red card activation on player - if (IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) - { - // Both player's battlers are alive - redCardForcedSwitch = FALSE; - } - else - { - // Player has only one mon alive -> force red card switch before manually switching to other mon - redCardForcedSwitch = TRUE; - } - } + gBattlescriptCurrInstr = cmd->failInstr; } - - // Swapping pokemon happens in: - // trainer battles - // wild double battles when an opposing pokemon uses it against one of the two alive player mons - // wild double battle when a player pokemon uses it against its partner - if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) - || (WILD_DOUBLE_BATTLE - && !IsOnPlayerSide(gBattlerAttacker) - && IsOnPlayerSide(gBattlerTarget) - && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) - || (WILD_DOUBLE_BATTLE - && IsOnPlayerSide(gBattlerAttacker) - && IsOnPlayerSide(gBattlerTarget)) - || redCardForcedSwitch - ) + else { - party = GetBattlerParty(gBattlerTarget); + gStatuses3[gBattlerTarget] |= STATUS3_EMBARGO; + gDisableStructs[gBattlerTarget].embargoTimer = gBattleTurnCounter + 5; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} - if (BATTLE_TWO_VS_ONE_OPPONENT && !IsOnPlayerSide(gBattlerTarget)) - { - firstMonId = 0; - lastMonId = 6; - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; - battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; - } - else if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_LINK) - || (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) - || (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)) - { - if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT) - { - firstMonId = PARTY_SIZE / 2; - lastMonId = PARTY_SIZE; - } - else - { - firstMonId = 0; - lastMonId = PARTY_SIZE / 2; - } - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; - battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; - } - else if ((gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK) - || (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK)) +static void Cmd_presentdamagecalculation(void) +{ + CMD_ARGS(); + + u32 rand = Random() & 0xFF; + + /* Don't reroll present effect/power for the second hit of Parental Bond. + * Not sure if this is the correct behaviour, but bulbapedia states + * that if present heals the foe, it doesn't strike twice, and if it deals + * damage, the second strike will always deal damage too. This is a simple way + * to replicate that effect. + */ + if (gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT) + { + if (rand < 102) { - if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(gBattlerTarget)) == B_FLANK_RIGHT) - { - firstMonId = PARTY_SIZE / 2; - lastMonId = PARTY_SIZE; - } - else - { - firstMonId = 0; - lastMonId = PARTY_SIZE / 2; - } - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; - battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; + gBattleStruct->presentBasePower = 40; } - else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + else if (rand < 178) { - if (IsOnPlayerSide(gBattlerTarget)) - { - firstMonId = 0; - lastMonId = PARTY_SIZE; - } - else - { - if ((gBattlerTarget & BIT_FLANK) != B_FLANK_LEFT) - { - firstMonId = PARTY_SIZE / 2; - lastMonId = PARTY_SIZE; - } - else - { - firstMonId = 0; - lastMonId = PARTY_SIZE / 2; - } - } - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; - battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; + gBattleStruct->presentBasePower = 80; } - else if (IsDoubleBattle()) + else if (rand < 204) { - firstMonId = 0; - lastMonId = PARTY_SIZE; - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; - battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; + gBattleStruct->presentBasePower = 120; } else { - firstMonId = 0; - lastMonId = PARTY_SIZE; - battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; // there is only one Pokémon out in single battles - battler1PartyId = gBattlerPartyIndexes[gBattlerTarget]; + // TODO: Check if this is correct + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 4; + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = 1; + gBattleStruct->moveDamage[gBattlerTarget] *= -1; + gBattleStruct->presentBasePower = 0; } + } - for (u32 i = firstMonId; i < lastMonId; i++) - { - if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[i], MON_DATA_IS_EGG) - && GetMonData(&party[i], MON_DATA_HP) != 0 - && i != battler1PartyId - && i != battler2PartyId) - { - validMons[validMonsCount++] = i; - } - } + if (gBattleStruct->presentBasePower) + { + gBattlescriptCurrInstr = BattleScript_HitFromCritCalc; + } + else if (gBattleMons[gBattlerTarget].maxHP == gBattleMons[gBattlerTarget].hp) + { + gBattlescriptCurrInstr = BattleScript_AlreadyAtFullHp; + } + else + { + gBattleStruct->moveResultFlags[gBattlerTarget] &= ~MOVE_RESULT_DOESNT_AFFECT_FOE; + gBattlescriptCurrInstr = BattleScript_PresentHealTarget; + } +} - if (validMonsCount == 0) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget]; - gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; - gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE; - gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)]; - - if (!IsMultiBattle()) - SwitchPartyOrder(gBattlerTarget); - - if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) - || (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI) - || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) - || (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)) - { - SwitchPartyOrderLinkMulti(gBattlerTarget, gBattleStruct->monToSwitchIntoId[gBattlerTarget], 0); - SwitchPartyOrderLinkMulti(BATTLE_PARTNER(gBattlerTarget), gBattleStruct->monToSwitchIntoId[gBattlerTarget], 1); - } +static void Cmd_setsafeguard(void) +{ + CMD_ARGS(); - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - SwitchPartyOrderInGameMulti(gBattlerTarget, gBattleStruct->monToSwitchIntoId[gBattlerTarget]); - } + if (gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_SAFEGUARD) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; } else { - // In normal wild doubles, Roar will always fail if the user's level is less than the target's. - if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) - gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle; - else - gBattlescriptCurrInstr = cmd->failInstr; + gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_SAFEGUARD; + gSideTimers[GetBattlerSide(gBattlerAttacker)].safeguardTimer = gBattleTurnCounter + 5; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; } + + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_tryconversiontypechange(void) +static void Cmd_magnitudedamagecalculation(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - u8 validMoves = 0; - u8 moveChecked = 0; - u8 moveType = 0; + u32 magnitude = Random() % 100; - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) + if (magnitude < 5) { - gBattlescriptCurrInstr = cmd->failInstr; - return; + gBattleStruct->magnitudeBasePower = 10; + magnitude = 4; } - - if (B_UPDATED_CONVERSION >= GEN_6) + else if (magnitude < 15) { - // Changes user's type to its first move's type - for (moveChecked = 0; moveChecked < MAX_MON_MOVES; moveChecked++) - { - if (gBattleMons[gBattlerAttacker].moves[moveChecked] != MOVE_NONE) - { - moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); - break; - } - } - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - SET_BATTLER_TYPE(gBattlerAttacker, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattleStruct->magnitudeBasePower = 30; + magnitude = 5; + } + else if (magnitude < 35) + { + gBattleStruct->magnitudeBasePower = 50; + magnitude = 6; + } + else if (magnitude < 65) + { + gBattleStruct->magnitudeBasePower = 70; + magnitude = 7; + } + else if (magnitude < 85) + { + gBattleStruct->magnitudeBasePower = 90; + magnitude = 8; + } + else if (magnitude < 95) + { + gBattleStruct->magnitudeBasePower = 110; + magnitude = 9; } else { - // Randomly changes user's type to one of its moves' type - while (validMoves < MAX_MON_MOVES) - { - if (gBattleMons[gBattlerAttacker].moves[validMoves] == MOVE_NONE) - break; + gBattleStruct->magnitudeBasePower = 150; + magnitude = 10; + } - validMoves++; - } + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 2, magnitude) - for (moveChecked = 0; moveChecked < validMoves; moveChecked++) - { - moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); + for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) + { + if (gBattlerTarget == gBattlerAttacker) + continue; + if (!(gAbsentBattlerFlags & (1u << gBattlerTarget))) // A valid target was found. + break; + } - if (moveType == TYPE_MYSTERY) - { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - moveType = TYPE_GHOST; - else - moveType = TYPE_NORMAL; - } - if (moveType != gBattleMons[gBattlerAttacker].types[0] - && moveType != gBattleMons[gBattlerAttacker].types[1] - && moveType != gBattleMons[gBattlerAttacker].types[2]) - { - break; - } - } + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (moveChecked == validMoves) +static bool32 SetTargetToNextPursuiter(u32 battlerDef) +{ + u32 i; + for (i = gCurrentTurnActionNumber + 1; i < gBattlersCount; i++) + { + u32 battler = gBattlerByTurnOrder[i]; + if (gChosenActionByBattler[battler] == B_ACTION_USE_MOVE + && GetMoveEffect(gChosenMoveByBattler[battler]) == EFFECT_PURSUIT + && IsBattlerAlive(battlerDef) + && IsBattlerAlive(battler) + && !IsBattlerAlly(battler, battlerDef) + && (B_PURSUIT_TARGET >= GEN_4 || gBattleStruct->moveTarget[battler] == battlerDef) + && !IsGimmickSelected(battler, GIMMICK_Z_MOVE) + && !IsGimmickSelected(battler, GIMMICK_DYNAMAX) + && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) { - gBattlescriptCurrInstr = cmd->failInstr; + gBattlerTarget = battler; + return TRUE; } - else - { - do - { - while ((moveChecked = MOD(Random(), MAX_MON_MOVES)) >= validMoves); - - moveType = GetMoveType(gBattleMons[gBattlerAttacker].moves[moveChecked]); + } + return FALSE; +} - if (moveType == TYPE_MYSTERY) - { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - moveType = TYPE_GHOST; - else - moveType = TYPE_NORMAL; - } - } - while (moveType == gBattleMons[gBattlerAttacker].types[0] || moveType == gBattleMons[gBattlerAttacker].types[1] || moveType == gBattleMons[gBattlerAttacker].types[2]); +static void Cmd_jumpifnopursuitswitchdmg(void) +{ + CMD_ARGS(const u8 *jumpInstr); - SET_BATTLER_TYPE(gBattlerAttacker, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + u32 savedTarget = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; - } + if (SetTargetToNextPursuiter(gBattlerAttacker)) + { + ChangeOrderTargetAfterAttacker(); + gBattleStruct->battlerState[gBattlerAttacker].pursuitTarget = TRUE; + gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker]; + gBattleStruct->moveTarget[gBattlerTarget] = gBattlerAttacker; + gBattlerTarget = savedTarget; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->jumpInstr; } } -static void Cmd_givepaydaymoney(void) +static void Cmd_tryrestorehpberry(void) { CMD_ARGS(); + if (TryRestoreHPBerries(gBattlerAttacker, ITEMEFFECT_TRY_HEALING)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) && gPaydayMoney != 0) - { - u32 bonusMoney = gPaydayMoney * gBattleStruct->moneyMultiplier; - AddMoney(&gSaveBlock1Ptr->money, bonusMoney); +// Belly Drum, Fillet Away +static void Cmd_halvehp(void) +{ + CMD_ARGS(const u8 *failInstr); - PREPARE_HWORD_NUMBER_BUFFER(gBattleTextBuff1, 5, bonusMoney) + u32 halfHp = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_PrintPayDayMoneyString; + if (!(GetNonDynamaxMaxHP(gBattlerAttacker) / 2)) + halfHp = 1; + + if (gBattleMons[gBattlerAttacker].hp > halfHp) + { + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + + gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } } -static void Cmd_setlightscreen(void) +// Psych Up +static void Cmd_copyfoestats(void) { CMD_ARGS(); - if (!TrySetLightScreen(gBattlerAttacker)) + s32 i; + + for (i = 0; i < NUM_BATTLE_STATS; i++) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; + gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i]; } + gBattleScripting.battler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; } -#define NOT_ENDURED 0 -#define FOCUS_SASHED 1 -#define FOCUS_BANDED 2 -#define AFFECTION_ENDURED 3 -static void Cmd_tryKO(void) +static void Cmd_rapidspinfree(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - bool32 lands = FALSE; - enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE); - u16 targetAbility = GetBattlerAbility(gBattlerTarget); - u32 rand = Random() % 100; - u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); - u32 endured = NOT_ENDURED; + u8 atkSide = GetBattlerSide(gBattlerAttacker); - // Dynamaxed Pokemon cannot be hit by OHKO moves. - if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) + if (gBattleMons[gBattlerAttacker].volatiles.wrapped) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED; - gBattlescriptCurrInstr = cmd->failInstr; - return; + gBattleScripting.battler = gBattlerTarget; + gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; + gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker]; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); + BattleScriptCall(BattleScript_WrapFree); } - - gPotentialItemEffectBattler = gBattlerTarget; - if (holdEffect == HOLD_EFFECT_FOCUS_BAND - && (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget)) + else if (gStatuses3[gBattlerAttacker] & STATUS3_LEECHSEED) { - endured = FOCUS_BANDED; - RecordItemEffectBattle(gBattlerTarget, holdEffect); + gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED; + gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED_BATTLER; + BattleScriptCall(BattleScript_LeechSeedFree); } - else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget)) + else if (AreAnyHazardsOnSide(atkSide)) { - endured = FOCUS_SASHED; - RecordItemEffectBattle(gBattlerTarget, holdEffect); + for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) + { + if (IsHazardOnSideAndClear(atkSide, hazardType)) + { + gBattleStruct->numHazards[atkSide]--; + gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; + BattleScriptCall(BattleScript_SpinHazardsAway); + return; + } + } } - else if (B_AFFECTION_MECHANICS == TRUE && IsOnPlayerSide(gBattlerTarget) && affectionScore >= AFFECTION_THREE_HEARTS) + else { - if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20) - || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) - || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) - endured = AFFECTION_ENDURED; + gBattlescriptCurrInstr = cmd->nextInstr; } +} - if (targetAbility == ABILITY_STURDY) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gLastUsedAbility = ABILITY_STURDY; - gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO; - gBattlerAbility = gBattlerTarget; - } - else +static void Cmd_unused_0xBF(void) +{ +} + +static void Cmd_recoverbasedonsunlight(void) +{ + CMD_ARGS(const u8 *failInstr); + + gBattlerTarget = gBattlerAttacker; + if (gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP) { - if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level - && ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS - && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) - || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) - || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))) + if (GetMoveEffect(gCurrentMove) == EFFECT_SHORE_UP) { - lands = TRUE; + if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) + gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; + else + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; } - else + else if (GetGenConfig(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2) { - u16 odds = GetMoveAccuracy(gCurrentMove) + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level); - if (B_SHEER_COLD_ACC >= GEN_7 && effect == EFFECT_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) - odds -= 10; - if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) - lands = TRUE; + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + else if (gBattleWeather & B_WEATHER_SUN) + gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; + else // not sunny weather + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; } - - if (lands) + else // B_TIME_OF_DAY_HEALING_MOVES == GEN_2 { - if (gProtectStructs[gBattlerTarget].endured) - { - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED; - } - else if (endured == FOCUS_BANDED || endured == FOCUS_SASHED) - { - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_HUNG_ON; - gLastUsedItem = gBattleMons[gBattlerTarget].item; - } - else if (endured == AFFECTION_ENDURED) - { - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; - } - else + u32 healingModifier = 1; + u32 time = GetTimeOfDay(); + + switch (GetMoveEffect(gCurrentMove)) { - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp; - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_ONE_HIT_KO; + case EFFECT_MOONLIGHT: + if (time == TIME_NIGHT || time == TIME_EVENING) + healingModifier = 2; + break; + case EFFECT_MORNING_SUN: + if ((OW_TIMES_OF_DAY == GEN_3 && time == TIME_DAY) // Gen 3 doesn't have morning + || (OW_TIMES_OF_DAY != GEN_3 && time == TIME_MORNING)) + healingModifier = 2; + break; + case EFFECT_SYNTHESIS: + if (time == TIME_DAY) + healingModifier = 2; + break; + default: + healingModifier = 1; + break; } - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_MISS; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_KO_UNAFFECTED; - gBattlescriptCurrInstr = cmd->failInstr; + + if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) + gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + else if (gBattleWeather & B_WEATHER_SUN) + gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + else // not sunny weather + gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8; + } + + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; } } -#undef NOT_ENDURED -#undef FOCUS_SASHED -#undef FOCUS_BANDED -#undef AFFECTION_ENDURED -static void Cmd_checknonvolatiletrigger(void) +static void Cmd_setstickyweb(void) { - CMD_ARGS(u16 nonVolatile, const u8 *failInstr); + CMD_ARGS(const u8 *failInstr); - if (!CanSetNonVolatileStatus( - gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - GetBattlerAbility(gBattlerTarget), - cmd->nonVolatile, - CHECK_TRIGGER)) - gBattlescriptCurrInstr = cmd->failInstr; - else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + u8 targetSide = GetBattlerSide(gBattlerTarget); + + if (IsHazardOnSide(targetSide, HAZARDS_STICKY_WEB)) + { gBattlescriptCurrInstr = cmd->failInstr; + } else + { + PushHazardTypeToQueue(targetSide, HAZARDS_STICKY_WEB); + gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor + gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_copybidedmg(void) +static void Cmd_selectfirstvalidtarget(void) { CMD_ARGS(); - gBattleStruct->moveDamage[gBattlerTarget] = gBideDmg[gBattlerAttacker] * 2; - gBattlescriptCurrInstr = cmd->nextInstr; -} -static void Cmd_unused_96(void) -{ + for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) + { + if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) + continue; + if (IsBattlerAlive(gBattlerTarget)) + break; + } + if (gBattlerTarget >= gBattlersCount) + gBattlerTarget = 0; + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_tryinfatuating(void) +static void Cmd_trysetfutureattack(void) { CMD_ARGS(const u8 *failInstr); - if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) + if (gWishFutureKnock.futureSightCounter[gBattlerTarget] > gBattleTurnCounter) { - gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; - gLastUsedAbility = ABILITY_OBLIVIOUS; - RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); + gBattlescriptCurrInstr = cmd->failInstr; } else { - if (gBattleMons[gBattlerTarget].volatiles.infatuation - || !AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + gSideStatuses[GetBattlerSide(gBattlerTarget)] |= SIDE_STATUS_FUTUREATTACK; + gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; + gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; + gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; + gWishFutureKnock.futureSightCounter[gBattlerTarget] = gBattleTurnCounter + 3; + + if (gCurrentMove == MOVE_DOOM_DESIRE) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; else - { - gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; + + gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_updatestatusicon(void) +static void Cmd_trydobeatup(void) { - CMD_ARGS(u8 battler); - u32 battler; +#if B_BEAT_UP >= GEN_5 + CMD_ARGS(); - if (gBattleControllerExecFlags) - return; + gBattleStruct->beatUpSlot++; + gBattlescriptCurrInstr = cmd->nextInstr; +#else + CMD_ARGS(const u8 *endInstr, const u8 *failInstr); + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - if (cmd->battler == BS_PLAYER2) + if (!IsBattlerAlive(gBattlerTarget)) { - for (battler = gBattleControllerExecFlags; battler < gBattlersCount; battler++) - { - if (!(gAbsentBattlerFlags & (1u << battler))) - { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } - } - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->endInstr; } - else if (cmd->battler == BS_ATTACKER_WITH_PARTNER) + else { - battler = gBattlerAttacker; - if (!(gAbsentBattlerFlags & (1u << battler))) + u8 beforeLoop = gBattleCommunication[0]; + for (;gBattleCommunication[0] < PARTY_SIZE; gBattleCommunication[0]++) { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); + if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP) + && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE + && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG + && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS)) + break; } - if ((IsDoubleBattle())) + + if (gBattleCommunication[0] < PARTY_SIZE) { - battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (!(gAbsentBattlerFlags & (1u << battler))) - { - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - } + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleCommunication[0]) + + gBattlescriptCurrInstr = cmd->nextInstr; + + gBattleStruct->moveDamage[gBattlerTarget] = GetSpeciesBaseAttack(GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)); + gBattleStruct->moveDamage[gBattlerTarget] *= GetMovePower(gCurrentMove); + gBattleStruct->moveDamage[gBattlerTarget] *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2); + gBattleStruct->moveDamage[gBattlerTarget] /= GetSpeciesBaseDefense(gBattleMons[gBattlerTarget].species); + gBattleStruct->moveDamage[gBattlerTarget] = (gBattleStruct->moveDamage[gBattlerTarget] / 50) + 2; + if (gProtectStructs[gBattlerAttacker].helpingHand) + gBattleStruct->moveDamage[gBattlerTarget] = gBattleStruct->moveDamage[gBattlerTarget] * 15 / 10; + + gBattleCommunication[0]++; + } + else if (beforeLoop != 0) + { + gBattlescriptCurrInstr = cmd->endInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; } - gBattlescriptCurrInstr = cmd->nextInstr; } - else +#endif +} + +static void Cmd_setsemiinvulnerablebit(void) +{ + CMD_ARGS(bool8 clear); + + if (gBattleMoveEffects[GetMoveEffect(gCurrentMove)].semiInvulnerableEffect == TRUE) { - battler = GetBattlerForBattleScript(cmd->battler); - BtlController_EmitStatusIconUpdate(battler, B_COMM_TO_CONTROLLER, gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - gBattlescriptCurrInstr = cmd->nextInstr; + u32 semiInvulnerableEffect = GetMoveTwoTurnAttackStatus(gCurrentMove); + if (cmd->clear) + gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect; + else + gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect; } + + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setmist(void) +static bool32 CheckIfCanFireTwoTurnMoveNow(u8 battler, bool8 checkChargeTurnEffects) { - CMD_ARGS(); + // Semi-invulnerable moves cannot skip their charge turn (except with Power Herb) + if (gBattleMoveEffects[GetMoveEffect(gCurrentMove)].semiInvulnerableEffect == TRUE) + return FALSE; - if (gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer) + // If this move has charge turn effects, it must charge, activate them, then try to fire + if (checkChargeTurnEffects && MoveHasChargeTurnAdditionalEffect(gCurrentMove)) + return FALSE; + + // Insert custom conditions here + + // Certain two-turn moves may fire on the first turn in the right weather (Solar Beam, Electro Shot) + // By default, all two-turn moves have the option of adding weather to their argument + if (IsBattlerWeatherAffected(battler, GetMoveTwoTurnAttackWeather(gCurrentMove))) + return TRUE; + + return FALSE; +} + +static void Cmd_tryfiretwoturnmovenowbyeffect(void) +{ + CMD_ARGS(u8 battler, bool8 checkChargeTurnEffects, const u8 *jumpInstr); + + if (CheckIfCanFireTwoTurnMoveNow(cmd->battler, cmd->checkChargeTurnEffects) == TRUE) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MIST_FAILED; + gBattleScripting.animTurn = 1; + gBattlescriptCurrInstr = cmd->jumpInstr; } else - { - gSideTimers[GetBattlerSide(gBattlerAttacker)].mistTimer = gBattleTurnCounter + 5; - gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_MIST; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MIST; - } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_setminimize(void) +{ + CMD_ARGS(); + + if (gHitMarker & HITMARKER_OBEYS) + gStatuses3[gBattlerAttacker] |= STATUS3_MINIMIZED; + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setfocusenergy(void) +static void Cmd_unused_c8(void) { - CMD_ARGS(u8 battler); - u8 battler = GetBattlerForBattleScript(cmd->battler); - enum BattleMoveEffects effect = GetMoveEffect(gCurrentMove); +} - if ((effect == EFFECT_DRAGON_CHEER && (!(IsDoubleBattle()) || (gAbsentBattlerFlags & (1u << battler)))) - || gBattleMons[battler].volatiles.dragonCheer || gBattleMons[battler].volatiles.focusEnergy) +static void Cmd_trymemento(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (B_MEMENTO_FAIL >= GEN_4 + && (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED + || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE + || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) + || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FOCUS_ENERGY_FAILED; + // Failed, target was protected. + gBattlescriptCurrInstr = cmd->failInstr; } - else if (effect == EFFECT_DRAGON_CHEER && !IS_BATTLER_OF_TYPE(battler, TYPE_DRAGON)) + else if (B_MEMENTO_FAIL < GEN_4 + && gBattleMons[gBattlerTarget].statStages[STAT_ATK] == MIN_STAT_STAGE + && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] == MIN_STAT_STAGE + && gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) { - gBattleMons[battler].volatiles.dragonCheer = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; + // Failed, unprotected target already has minimum Attack and Special Attack. + gBattlescriptCurrInstr = cmd->failInstr; } else { - if (GetGenConfig(GEN_CONFIG_FOCUS_ENERGY_CRIT_RATIO) >= GEN_3) - gBattleMons[battler].volatiles.focusEnergy = TRUE; - else - gBattleMons[battler].volatiles.dragonCheer = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_GETTING_PUMPED; + // Success, drop user's HP bar to 0 + gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; + BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; } - gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_transformdataexecution(void) +// Follow Me +static void Cmd_setforcedtarget(void) { CMD_ARGS(); - gChosenMove = MOVE_UNAVAILABLE; + gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 1; + gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget = gBattlerTarget; + gSideTimers[GetBattlerSide(gBattlerTarget)].followmePowder = IsPowderMove(gCurrentMove); gBattlescriptCurrInstr = cmd->nextInstr; - if (gBattleMons[gBattlerTarget].volatiles.transformed - || gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORM_FAILED; - } +} + +static void Cmd_setcharge(void) +{ + CMD_ARGS(u8 battler); + + u8 battler = GetBattlerForBattleScript(cmd->battler); + gStatuses3[battler] |= STATUS3_CHARGED_UP; + if (B_CHARGE < GEN_9) + gDisableStructs[battler].chargeTimer = 2; else - { - s32 i; - u8 *battleMonAttacker, *battleMonTarget; - u8 timesGotHit; + gDisableStructs[battler].chargeTimer = 0; + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleMons[gBattlerAttacker].volatiles.transformed = TRUE; - gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; - gDisableStructs[gBattlerAttacker].disableTimer = 0; - gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; - gDisableStructs[gBattlerAttacker].transformedMonShininess = gBattleMons[gBattlerTarget].isShiny; - gDisableStructs[gBattlerAttacker].mimickedMoves = 0; - gDisableStructs[gBattlerAttacker].usedMoves = 0; +// Nature Power +static void Cmd_callenvironmentattack(void) +{ + CMD_ARGS(); - timesGotHit = gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]; - gBattleStruct->timesGotHit[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = timesGotHit; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gCurrentMove = GetNaturePowerMove(gBattlerAttacker); + gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + BattleScriptPush(GetMoveBattleScript(gCurrentMove)); + gBattlescriptCurrInstr = cmd->nextInstr; +} - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].species) +u32 GetNaturePowerMove(u32 battler) +{ + u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + move = MOVE_MOONBLAST; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + move = MOVE_THUNDERBOLT; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + move = MOVE_ENERGY_BALL; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + move = MOVE_PSYCHIC; + else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) + move = MOVE_TRI_ATTACK; - battleMonAttacker = (u8 *)(&gBattleMons[gBattlerAttacker]); - battleMonTarget = (u8 *)(&gBattleMons[gBattlerTarget]); + if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE) + { + gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; + move = GetTypeBasedZMove(move); + } - for (i = 0; i < offsetof(struct BattlePokemon, pp); i++) - battleMonAttacker[i] = battleMonTarget[i]; + return move; +} - gDisableStructs[gBattlerAttacker].overwrittenAbility = GetBattlerAbility(gBattlerTarget); - for (i = 0; i < MAX_MON_MOVES; i++) - { - u32 pp = GetMovePP(gBattleMons[gBattlerAttacker].moves[i]); - if (pp < 5) - gBattleMons[gBattlerAttacker].pp[i] = pp; - else - gBattleMons[gBattlerAttacker].pp[i] = 5; - } +static void Cmd_curestatuswithmove(void) +{ + CMD_ARGS(const u8 *failInstr); + u32 shouldHeal; - // update AI knowledge - RecordAllMoves(gBattlerAttacker); - RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); + if (GetMoveEffect(gCurrentMove) == EFFECT_REFRESH) + shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_CAN_MOVE; + else // Take Heart + shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; - BtlController_EmitResetActionMoveSelection(gBattlerAttacker, B_COMM_TO_CONTROLLER, RESET_MOVE_SELECTION); + if (shouldHeal) + { + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); + + gBattleMons[gBattlerAttacker].status1 = 0; + gBattlescriptCurrInstr = cmd->nextInstr; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].status1), &gBattleMons[gBattlerAttacker].status1); MarkBattlerForControllerExec(gBattlerAttacker); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORMED; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; } } -static void Cmd_setsubstitute(void) +static void Cmd_settorment(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *failInstr); - u32 factor = GetMoveEffect(gCurrentMove) == EFFECT_SHED_TAIL ? 2 : 4; - u32 hp; - - if (factor == 2) - hp = (GetNonDynamaxMaxHP(gBattlerAttacker)+1) / factor; // shed tail rounds up - else - hp = GetNonDynamaxMaxHP(gBattlerAttacker) / factor; // one bit value will only work for Pokémon which max hp can go to 1020(which is more than possible in games) - - if (hp == 0) - hp = 1; - - if (gBattleMons[gBattlerAttacker].hp <= hp) + if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE + || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { - gBattleStruct->moveDamage[gBattlerAttacker] = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SUBSTITUTE_FAILED; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleStruct->moveDamage[gBattlerAttacker] = hp; // one bit value will only work for Pokémon which max hp can go to 1020(which is more than possible in games) - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - - gBattleMons[gBattlerAttacker].volatiles.substitute = TRUE; - gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; - if (factor == 2) - gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker] / 2; - else - gDisableStructs[gBattlerAttacker].substituteHP = gBattleStruct->moveDamage[gBattlerAttacker]; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SUBSTITUTE; - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE; + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; } +} - gBattlescriptCurrInstr = cmd->nextInstr; +static void Cmd_jumpifnodamage(void) +{ + CMD_ARGS(const u8 *jumpInstr); + + if (gProtectStructs[gBattlerAttacker].physicalDmg || gProtectStructs[gBattlerAttacker].specialDmg) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; } -static void Cmd_mimicattackcopy(void) +static void Cmd_settaunt(void) { CMD_ARGS(const u8 *failInstr); - if ((IsMoveMimicBanned(gLastMoves[gBattlerTarget])) - || (gBattleMons[gBattlerAttacker].volatiles.transformed) - || gLastMoves[gBattlerTarget] == MOVE_NONE - || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) + if (B_OBLIVIOUS_TAUNT >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) { - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; + gLastUsedAbility = ABILITY_OBLIVIOUS; + RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); } - else + else if (gDisableStructs[gBattlerTarget].tauntTimer == 0) { - int i; - - for (i = 0; i < MAX_MON_MOVES; i++) + u8 turns; + if (B_TAUNT_TURNS >= GEN_5) { - if (gBattleMons[gBattlerAttacker].moves[i] == gLastMoves[gBattlerTarget]) - break; + turns = 4; + if (GetBattlerTurnOrderNum(gBattlerTarget) > GetBattlerTurnOrderNum(gBattlerAttacker)) + turns--; // If the target hasn't yet moved this turn, Taunt lasts for only three turns (source: Bulbapedia) } - - if (i == MAX_MON_MOVES) + else if (B_TAUNT_TURNS >= GEN_4) { - gChosenMove = 0xFFFF; - gBattleMons[gBattlerAttacker].moves[gCurrMovePos] = gLastMoves[gBattlerTarget]; - u32 pp = GetMovePP(gLastMoves[gBattlerTarget]); - if (pp < 5) - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = pp; - else - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = 5; - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) - - gDisableStructs[gBattlerAttacker].mimickedMoves |= 1u << gCurrMovePos; - gBattlescriptCurrInstr = cmd->nextInstr; + turns = (Random() & 2) + 3; } else { - gBattlescriptCurrInstr = cmd->failInstr; + turns = 2; } - } -} - -static bool32 InvalidMetronomeMove(u32 move) -{ - return GetMoveEffect(move) == EFFECT_PLACEHOLDER - || IsMoveMetronomeBanned(move); -} - -static void Cmd_metronome(void) -{ - CMD_ARGS(); - -#if B_METRONOME_MOVES >= GEN_9 - u32 moveCount = MOVES_COUNT_GEN9; -#elif B_METRONOME_MOVES >= GEN_8 - u32 moveCount = MOVES_COUNT_GEN8; -#elif B_METRONOME_MOVES >= GEN_7 - u32 moveCount = MOVES_COUNT_GEN7; -#elif B_METRONOME_MOVES >= GEN_6 - u32 moveCount = MOVES_COUNT_GEN6; -#elif B_METRONOME_MOVES >= GEN_5 - u32 moveCount = MOVES_COUNT_GEN5; -#elif B_METRONOME_MOVES >= GEN_4 - u32 moveCount = MOVES_COUNT_GEN4; -#elif B_METRONOME_MOVES >= GEN_3 - u32 moveCount = MOVES_COUNT_GEN3; -#elif B_METRONOME_MOVES >= GEN_2 - u32 moveCount = MOVES_COUNT_GEN2; -#else - u32 moveCount = MOVES_COUNT_GEN1; -#endif - - gCurrentMove = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); - PrepareStringBattle(STRINGID_WAGGLINGAFINGER, gBattlerAttacker); - gBattlescriptCurrInstr = GetMoveBattleScript(gCurrentMove); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - ResetValuesForCalledMove(); -} - -static void Cmd_unused_0x9f(void) -{ -} - -static void Cmd_unused_0xA0(void) -{ -} - -static void Cmd_counterdamagecalculator(void) -{ - CMD_ARGS(const u8 *failInstr); - - u8 sideAttacker = GetBattlerSide(gBattlerAttacker); - u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId); - - if (gProtectStructs[gBattlerAttacker].physicalDmg - && sideAttacker != sideTarget - && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) - { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; - - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) - gBattlerTarget = gSideTimers[sideTarget].followmeTarget; - else - gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + gDisableStructs[gBattlerTarget].tauntTimer = turns; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13004,25 +12847,18 @@ static void Cmd_counterdamagecalculator(void) } } -// A copy of Cmd with the physical -> special field changes -static void Cmd_mirrorcoatdamagecalculator(void) +static void Cmd_trysethelpinghand(void) { CMD_ARGS(const u8 *failInstr); - u8 sideAttacker = GetBattlerSide(gBattlerAttacker); - u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId); + gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (gProtectStructs[gBattlerAttacker].specialDmg - && sideAttacker != sideTarget - && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) + if (IsDoubleBattle() + && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) + && !gProtectStructs[gBattlerAttacker].helpingHand + && !gProtectStructs[gBattlerTarget].helpingHand) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; - - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) - gBattlerTarget = gSideTimers[sideTarget].followmeTarget; - else - gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; - + gProtectStructs[gBattlerTarget].helpingHand = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13031,284 +12867,153 @@ static void Cmd_mirrorcoatdamagecalculator(void) } } -static void Cmd_disablelastusedattack(void) +// Trick +static void Cmd_tryswapitems(void) { CMD_ARGS(const u8 *failInstr); - s32 i; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[gBattlerTarget].moves[i] == gLastMoves[gBattlerTarget]) - break; - } - if (gDisableStructs[gBattlerTarget].disabledMove == MOVE_NONE - && i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) + // opponent can't swap items with player in regular battles + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL + || (!IsOnPlayerSide(gBattlerAttacker) + && !(gBattleTypeFlags & (BATTLE_TYPE_LINK + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_SECRET_BASE + | BATTLE_TYPE_RECORDED_LINK + | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) + )))) { - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].moves[i]) - - gDisableStructs[gBattlerTarget].disabledMove = gBattleMons[gBattlerTarget].moves[i]; - if (B_DISABLE_TURNS >= GEN_5) - gDisableStructs[gBattlerTarget].disableTimer = 4; - else if (B_DISABLE_TURNS >= GEN_4) - gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 4; // 4-7 turns - else - gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 2; // 2-5 turns - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattlescriptCurrInstr = cmd->failInstr; - } -} - -static void Cmd_trysetencore(void) -{ - CMD_ARGS(const u8 *failInstr); - - s32 i; + u8 sideAttacker = GetBattlerSide(gBattlerAttacker); + u8 sideTarget = GetBattlerSide(gBattlerTarget); - if (IsMaxMove(gLastMoves[gBattlerTarget]) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) - { - for (i = 0; i < MAX_MON_MOVES; i++) + // You can't swap items if they were knocked off in regular battles + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_SECRET_BASE + | BATTLE_TYPE_RECORDED_LINK)) + && (gWishFutureKnock.knockedOffMons[sideAttacker] & (1u << gBattlerPartyIndexes[gBattlerAttacker]) + || gWishFutureKnock.knockedOffMons[sideTarget] & (1u << gBattlerPartyIndexes[gBattlerTarget]))) { - if (gBattleMons[gBattlerTarget].moves[i] == gBattleStruct->dynamax.baseMoves[gBattlerTarget]) - break; + gBattlescriptCurrInstr = cmd->failInstr; } - } - else - { - for (i = 0; i < MAX_MON_MOVES; i++) + // can't swap if two Pokémon don't have an item + // or if either of them is an enigma berry or a mail + else if ((gBattleMons[gBattlerAttacker].item == ITEM_NONE && gBattleMons[gBattlerTarget].item == ITEM_NONE) + || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) + || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerTarget].item) + || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) + || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item)) { - if (gBattleMons[gBattlerTarget].moves[i] == gLastMoves[gBattlerTarget]) - break; + gBattlescriptCurrInstr = cmd->failInstr; } - } + // check if ability prevents swapping + else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + { + gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + } + // took a while, but all checks passed and items can be safely swapped + else + { + u16 oldItemAtk, *newItemAtk; - if ((IsMoveEncoreBanned(gLastMoves[gBattlerTarget])) - || gLastMoves[gBattlerTarget] == MOVE_NONE - || gLastMoves[gBattlerTarget] == MOVE_UNAVAILABLE) - { - i = MAX_MON_MOVES; - } + newItemAtk = &gBattleStruct->changedItems[gBattlerAttacker]; + oldItemAtk = gBattleMons[gBattlerAttacker].item; + *newItemAtk = gBattleMons[gBattlerTarget].item; - if (gDisableStructs[gBattlerTarget].encoredMove == MOVE_NONE - && i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) - { - gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; - gDisableStructs[gBattlerTarget].encoredMovePos = i; - // Encore always lasts 3 turns, but we need to account for a scenario where Encore changes the move during the same turn. - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) - gDisableStructs[gBattlerTarget].encoreTimer = 4; - else - gDisableStructs[gBattlerTarget].encoreTimer = 3; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } -} + gBattleMons[gBattlerAttacker].item = ITEM_NONE; + gBattleMons[gBattlerTarget].item = oldItemAtk; -static void Cmd_painsplitdmgcalc(void) -{ - CMD_ARGS(const u8 *failInstr); + RecordItemEffectBattle(gBattlerAttacker, 0); + RecordItemEffectBattle(gBattlerTarget, GetItemHoldEffect(oldItemAtk)); - if (!(DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) - { - s32 hpDiff = (gBattleMons[gBattlerAttacker].hp + GetNonDynamaxHP(gBattlerTarget)) / 2; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(*newItemAtk), newItemAtk); + MarkBattlerForControllerExec(gBattlerAttacker); - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - hpDiff; - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp - hpDiff; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); + MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } -} + gBattleStruct->choicedMove[gBattlerTarget] = MOVE_NONE; + gBattleStruct->choicedMove[gBattlerAttacker] = MOVE_NONE; -// Conversion 2 -static void Cmd_settypetorandomresistance(void) -{ - CMD_ARGS(const u8 *failInstr); + gBattlescriptCurrInstr = cmd->nextInstr; - // Before Gen 5 Conversion 2 only worked on a move the attacker was actually hit by. - // This changed later to the last move used by the selected target. - if (B_UPDATED_CONVERSION_2 < GEN_5) - { - if (gLastLandedMoves[gBattlerAttacker] == MOVE_NONE - || gLastLandedMoves[gBattlerAttacker] == MOVE_UNAVAILABLE) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gBattleMoveEffects[GetMoveEffect(gLastLandedMoves[gBattlerAttacker])].twoTurnEffect - && gBattleMons[gLastHitBy[gBattlerAttacker]].volatiles.multipleTurns) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gLastHitByType[gBattlerAttacker] == TYPE_STELLAR || gLastHitByType[gBattlerAttacker] == TYPE_MYSTERY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - u32 i, resistTypes = 0; - u32 hitByType = gLastHitByType[gBattlerAttacker]; + PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk) + PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk) - for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. + if (!(sideAttacker == sideTarget && IsPartnerMonFromSameTrainer(gBattlerAttacker))) { - switch (GetTypeModifier(hitByType, i)) - { - case UQ_4_12(0): - case UQ_4_12(0.5): - resistTypes |= 1u << i; - break; - } + // if targeting your own side and you aren't in a multi battle, don't save items as stolen + if (IsOnPlayerSide(gBattlerAttacker)) + TrySaveExchangedItem(gBattlerAttacker, oldItemAtk); + if (IsOnPlayerSide(gBattlerTarget)) + TrySaveExchangedItem(gBattlerTarget, *newItemAtk); } - while (resistTypes != 0) + if (oldItemAtk != ITEM_NONE && *newItemAtk != ITEM_NONE) { - i = Random() % NUMBER_OF_MON_TYPES; - if (resistTypes & 1u << i) - { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) - { - resistTypes &= ~(1u << i); // Type resists, but the user is already of this type. - } - else - { - SET_BATTLER_TYPE(gBattlerAttacker, i); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - } + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_BOTH; // attacker's item -> <- target's item } - - gBattlescriptCurrInstr = cmd->failInstr; - } - } - else - { - if (gLastResultingMoves[gBattlerTarget] == MOVE_NONE - || gLastResultingMoves[gBattlerTarget] == MOVE_UNAVAILABLE - || gLastResultingMoves[gBattlerTarget] == MOVE_STRUGGLE) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gLastUsedMoveType[gBattlerTarget] == TYPE_NONE || gLastUsedMoveType[gBattlerTarget] == TYPE_STELLAR || gLastUsedMoveType[gBattlerTarget] == TYPE_MYSTERY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - u32 i, resistTypes = 0; - - for (i = 0; i < NUMBER_OF_MON_TYPES; i++) // Find all types that resist. + else if (oldItemAtk == ITEM_NONE && *newItemAtk != ITEM_NONE) { - switch (GetTypeModifier(gLastUsedMoveType[gBattlerTarget], i)) - { - case UQ_4_12(0): - case UQ_4_12(0.5): - resistTypes |= 1u << i; - break; - } - } + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNBURDEN && gDisableStructs[gBattlerAttacker].unburdenActive) + gDisableStructs[gBattlerAttacker].unburdenActive = FALSE; - while (resistTypes != 0) + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_TAKEN; // nothing -> <- target's item + } + else { - i = Random() % NUMBER_OF_MON_TYPES; - if (resistTypes & 1u << i) - { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, i)) - { - resistTypes &= ~(1u << i); // Type resists, but the user is already of this type. - } - else - { - SET_BATTLER_TYPE(gBattlerAttacker, i); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, i); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } - } + CheckSetUnburden(gBattlerAttacker); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_GIVEN; // attacker's item -> <- nothing } - - gBattlescriptCurrInstr = cmd->failInstr; } } } -static void Cmd_setalwayshitflag(void) +// Role Play, Doodle +static void Cmd_trycopyability(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler, const u8 *failInstr); - gStatuses3[gBattlerTarget] &= ~STATUS3_ALWAYS_HITS; - gStatuses3[gBattlerTarget] |= STATUS3_ALWAYS_HITS_TURN(2); - gDisableStructs[gBattlerTarget].battlerWithSureHit = gBattlerAttacker; - gBattlescriptCurrInstr = cmd->nextInstr; + u32 battler = GetBattlerForBattleScript(cmd->battler); + u16 defAbility = gBattleMons[gBattlerTarget].ability; + + if (gBattleMons[battler].ability == defAbility + || defAbility == ABILITY_NONE + || gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed + || (IsBattlerAlive(BATTLE_PARTNER(battler)) && gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE) + || gAbilitiesInfo[defAbility].cantBeCopied) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = defAbility; + gLastUsedAbility = defAbility; + gBattlescriptCurrInstr = cmd->nextInstr; + } } -// Sketch -static void Cmd_copymovepermanently(void) +static void Cmd_trywish(void) { CMD_ARGS(const u8 *failInstr); - gChosenMove = MOVE_UNAVAILABLE; - - if (!(gBattleMons[gBattlerAttacker].volatiles.transformed) - && gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE - && !IsMoveSketchBanned(gLastPrintedMoves[gBattlerTarget])) + if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) { - s32 i; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i]) == EFFECT_SKETCH) - continue; - if (gBattleMons[gBattlerAttacker].moves[i] == gLastPrintedMoves[gBattlerTarget]) - break; - } - - if (i != MAX_MON_MOVES) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else // sketch worked - { - struct MovePpInfo movePpData; - - gBattleMons[gBattlerAttacker].moves[gCurrMovePos] = gLastPrintedMoves[gBattlerTarget]; - gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = GetMovePP(gLastPrintedMoves[gBattlerTarget]); - - for (i = 0; i < MAX_MON_MOVES; i++) - { - movePpData.moves[i] = gBattleMons[gBattlerAttacker].moves[i]; - movePpData.pp[i] = gBattleMons[gBattlerAttacker].pp[i]; - } - movePpData.ppBonuses = gBattleMons[gBattlerAttacker].ppBonuses; - - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_MOVES_PP_BATTLE, 0, sizeof(movePpData), &movePpData); - MarkBattlerForControllerExec(gBattlerAttacker); - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastPrintedMoves[gBattlerTarget]) - - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (gWishFutureKnock.wishCounter[gBattlerAttacker] <= gBattleTurnCounter) + { + gWishFutureKnock.wishCounter[gBattlerAttacker] = gBattleTurnCounter + 2; + gWishFutureKnock.wishPartyId[gBattlerAttacker] = gBattlerPartyIndexes[gBattlerAttacker]; + gBattlescriptCurrInstr = cmd->nextInstr; } else { @@ -13316,765 +13021,631 @@ static void Cmd_copymovepermanently(void) } } -static void Cmd_trychoosesleeptalkmove(void) +static void Cmd_settoxicspikes(void) { CMD_ARGS(const u8 *failInstr); - u32 i, unusableMovesBits = 0, movePosition; - - for (i = 0; i < MAX_MON_MOVES; i++) + u8 targetSide = GetBattlerSide(gBattlerTarget); + if (gSideTimers[targetSide].toxicSpikesAmount >= 2) { - if (IsMoveSleepTalkBanned(gBattleMons[gBattlerAttacker].moves[i]) - || gBattleMoveEffects[GetMoveEffect(gBattleMons[gBattlerAttacker].moves[i])].twoTurnEffect) - { - unusableMovesBits |= (1 << (i)); - } + gBattlescriptCurrInstr = cmd->failInstr; } - - unusableMovesBits = CheckMoveLimitations(gBattlerAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP | MOVE_LIMITATION_CHOICE_ITEM)); - if (unusableMovesBits == ALL_MOVES_MASK) // all 4 moves cannot be chosen + else { + if (gSideTimers[targetSide].toxicSpikesAmount == 0) + PushHazardTypeToQueue(targetSide, HAZARDS_TOXIC_SPIKES); + gSideTimers[targetSide].toxicSpikesAmount++; gBattlescriptCurrInstr = cmd->nextInstr; } - else // at least one move can be chosen - { - // Set Sleep Talk as used move, so it works with Last Resort. - gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; - do - { - movePosition = MOD(Random(), MAX_MON_MOVES); - } while ((1u << movePosition) & unusableMovesBits); - - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gBattleMons[gBattlerAttacker].moves[movePosition])) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gBattleMons[gBattlerAttacker].moves[movePosition]; - gCalledMove = GetTypeBasedZMove(gBattleMons[gBattlerAttacker].moves[movePosition]); - } - else - { - gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition]; - } - gCurrMovePos = movePosition; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->failInstr; - } } -static inline bool32 IsDanamaxMonPresent(void) +static void Cmd_setgastroacid(void) { - for (u32 battler = 0; battler < gBattlersCount; battler++) - { - if (battler == gBattlerAttacker) - continue; + CMD_ARGS(const u8 *failInstr); - if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX) - return TRUE; + if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeSuppressed) + { + gBattlescriptCurrInstr = cmd->failInstr; } + else + { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - return FALSE; + gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_trysetdestinybond(void) +static void Cmd_setyawn(void) { CMD_ARGS(const u8 *failInstr); - if (IsDanamaxMonPresent()) + if (gStatuses3[gBattlerTarget] & STATUS3_YAWN + || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) { - gBattlescriptCurrInstr = BattleScript_MoveBlockedByDynamax; + gBattlescriptCurrInstr = cmd->failInstr; } - else if (DoesDestinyBondFail(gBattlerAttacker)) + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + // When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: + // "But it failed" will display first. + gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; + } + else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) + { + // When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: + // "But it failed" will display first. + gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; + } + else + { + gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +static void Cmd_setdamagetohealthdifference(void) +{ + CMD_ARGS(const u8 *failInstr); + + if (GetNonDynamaxHP(gBattlerTarget) <= gBattleMons[gBattlerAttacker].hp) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerAttacker].volatiles.destinyBond = TRUE; + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - gBattleMons[gBattlerAttacker].hp; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void TrySetDestinyBondToHappen(void) +static void HandleRoomMove(u32 statusFlag, u16 *timer, u8 stringId) { - if (gBattleMons[gBattlerTarget].volatiles.destinyBond - && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) - && !(gHitMarker & HITMARKER_GRUDGE)) + if (gFieldStatuses & statusFlag) { - gHitMarker |= HITMARKER_DESTINYBOND; + gFieldStatuses &= ~statusFlag; + gBattleCommunication[MULTISTRING_CHOOSER] = stringId + 1; + } + else + { + gFieldStatuses |= statusFlag; + *timer = gBattleTurnCounter + 5; + gBattleCommunication[MULTISTRING_CHOOSER] = stringId; } } -static void Cmd_trysetdestinybondtohappen(void) +static void Cmd_setroom(void) { CMD_ARGS(); - TrySetDestinyBondToHappen(); + switch (GetMoveEffect(gCurrentMove)) + { + case EFFECT_TRICK_ROOM: + HandleRoomMove(STATUS_FIELD_TRICK_ROOM, &gFieldTimers.trickRoomTimer, 0); + break; + case EFFECT_WONDER_ROOM: + HandleRoomMove(STATUS_FIELD_WONDER_ROOM, &gFieldTimers.wonderRoomTimer, 2); + break; + case EFFECT_MAGIC_ROOM: + HandleRoomMove(STATUS_FIELD_MAGIC_ROOM, &gFieldTimers.magicRoomTimer, 4); + break; + default: + gBattleCommunication[MULTISTRING_CHOOSER] = 6; + break; + } gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_settailwind(void) +// Skill Swap +static void Cmd_tryswapabilities(void) { CMD_ARGS(const u8 *failInstr); - u8 side = GetBattlerSide(gBattlerAttacker); - - if (!(gSideStatuses[side] & SIDE_STATUS_TAILWIND)) + if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped + || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeSwapped) { - gSideStatuses[side] |= SIDE_STATUS_TAILWIND; - gSideTimers[side].tailwindTimer = gBattleTurnCounter + (B_TAILWIND_TURNS >= GEN_5 ? 4 : 3); - gBattlescriptCurrInstr = cmd->nextInstr; + RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); + gBattlescriptCurrInstr = cmd->failInstr; } - else + else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); gBattlescriptCurrInstr = cmd->failInstr; } -} - -static void Cmd_tryspiteppreduce(void) -{ - CMD_ARGS(const u8 *failInstr); - - if (gLastMoves[gBattlerTarget] != MOVE_NONE - && gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE) + else { - s32 i; - - // Get move slot to reduce PP. - if (IsMaxMove(gLastMoves[gBattlerTarget])) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleStruct->dynamax.baseMoves[gBattlerTarget] == gBattleMons[gBattlerTarget].moves[i]) - break; - } + gBattlescriptCurrInstr = cmd->failInstr; } else { - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gLastMoves[gBattlerTarget] == gBattleMons[gBattlerTarget].moves[i]) - break; - } - } - - if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] > (B_CAN_SPITE_FAIL >= GEN_4 ? 0 : 1)) - { - s32 ppToDeduct = B_PP_REDUCED_BY_SPITE >= GEN_4 ? 4 : (Random() & 3) + 2; - // G-Max Depletion only deducts 2 PP. - if (IsMaxMove(gCurrentMove) && MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_SPITE)) - ppToDeduct = 2; - - if (gBattleMons[gBattlerTarget].pp[i] < ppToDeduct) - ppToDeduct = gBattleMons[gBattlerTarget].pp[i]; - - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastMoves[gBattlerTarget]) - - ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, STR_CONV_MODE_LEFT_ALIGN, 1); - - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct) - - gBattleMons[gBattlerTarget].pp[i] -= ppToDeduct; - - // if (MOVE_IS_PERMANENT(gBattlerTarget, i)), but backwards - if (!(gDisableStructs[gBattlerTarget].mimickedMoves & (1u << i)) - && !(gBattleMons[gBattlerTarget].volatiles.transformed)) - { - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_PPMOVE1_BATTLE + i, 0, sizeof(gBattleMons[gBattlerTarget].pp[i]), &gBattleMons[gBattlerTarget].pp[i]); - MarkBattlerForControllerExec(gBattlerTarget); - } + if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; + gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gLastUsedAbility; gBattlescriptCurrInstr = cmd->nextInstr; - - // Don't cut off Sky Drop if pp is brought to zero. - if (gBattleMons[gBattlerTarget].pp[i] == 0 && gBattleStruct->skyDropTargets[gBattlerTarget] == SKY_DROP_NO_TARGET) - CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_IGNORE); - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; } } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } } -static void Cmd_healpartystatus(void) +static void Cmd_tryimprison(void) { - CMD_ARGS(); - - u32 i = 0; - u32 zero = 0; - u32 toHeal = 0; - u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - bool32 isSoundMove = IsSoundMove(gCurrentMove); + CMD_ARGS(const u8 *failInstr); - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 - || !(isSoundMove && GetBattlerAbility(gBattlerAttacker) == ABILITY_SOUNDPROOF)) + if ((gStatuses3[gBattlerAttacker] & STATUS3_IMPRISONED_OTHERS)) { - if (isSoundMove) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA; - gBattleMons[gBattlerAttacker].status1 = 0; - gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; + gBattlescriptCurrInstr = cmd->failInstr; } - else + else if (B_IMPRISON >= GEN_5) { - RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_ATTACKER; + gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattlescriptCurrInstr = cmd->nextInstr; } - - gBattleScripting.battler = partner; - - if (IsBattlerAlive(partner)) + else { - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || !(isSoundMove && GetBattlerAbility(partner) == ABILITY_SOUNDPROOF)) - { - gBattleMons[partner].status1 = 0; - gBattleMons[partner].volatiles.nightmare = FALSE; - } - else + u8 battler; + + for (battler = 0; battler < gBattlersCount; battler++) { - RecordAbilityBattle(partner, gBattleMons[partner].ability); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL_SOUNDPROOF_PARTNER; - } - } - - // Because the above MULTISTRING_CHOOSER are ORd, if both are set then it will be B_MSG_BELL_BOTH_SOUNDPROOF - - for (i = 0; i < PARTY_SIZE; i++) - { - u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); - u8 abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM); - - if (species != SPECIES_NONE && species != SPECIES_EGG) - { - u16 ability; - bool32 isAttacker = gBattlerPartyIndexes[gBattlerAttacker] == i; - bool32 isDoublesPartner = gBattlerPartyIndexes[partner] == i && IsBattlerAlive(partner); - - if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5 - || (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8 && isAttacker)) - ability = ABILITY_NONE; - else if (GetGenConfig(GEN_CONFIG_HEAL_BELL_SOUNDPROOF) > GEN_5 && !isAttacker && !isDoublesPartner) - ability = ABILITY_NONE; - else if (isAttacker) - ability = GetBattlerAbility(gBattlerAttacker); - else if (isDoublesPartner) - ability = GetBattlerAbility(partner); - else + if (!IsBattlerAlly(gBattlerAttacker, battler)) { - ability = GetAbilityBySpecies(species, abilityNum); - #if TESTING - if (gTestRunnerEnabled) + s32 attackerMoveId; + for (attackerMoveId = 0; attackerMoveId < MAX_MON_MOVES; attackerMoveId++) { - u32 side = GetBattlerSide(gBattlerAttacker); - if (TestRunner_Battle_GetForcedAbility(side, i)) - ability = TestRunner_Battle_GetForcedAbility(side, i); + s32 i; + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (gBattleMons[gBattlerAttacker].moves[attackerMoveId] == gBattleMons[battler].moves[i] + && gBattleMons[gBattlerAttacker].moves[attackerMoveId] != MOVE_NONE) + break; + } + if (i != MAX_MON_MOVES) + break; + } + if (attackerMoveId != MAX_MON_MOVES) + { + gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattlescriptCurrInstr = cmd->nextInstr; + break; } - #endif - } - - if (!(isSoundMove && ability == ABILITY_SOUNDPROOF)) - { - toHeal |= (1 << i); - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i); } } + if (battler == gBattlersCount) // In Generation 3 games, Imprison fails if the user doesn't share any moves with any of the foes. + gBattlescriptCurrInstr = cmd->failInstr; } - - if (toHeal) - { - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, toHeal, sizeof(zero), &zero); - MarkBattlerForControllerExec(gBattlerAttacker); - } - - gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_cursetarget(void) +static void Cmd_setstealthrock(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].volatiles.cursed) + u8 targetSide = GetBattlerSide(gBattlerTarget); + if (IsHazardOnSide(targetSide, HAZARDS_STEALTH_ROCK)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].volatiles.cursed = TRUE; - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - + PushHazardTypeToQueue(targetSide, HAZARDS_STEALTH_ROCK); gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_trysetspikes(void) +static void Cmd_setuserstatus3(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(u32 flags, const u8 *failInstr); - u8 targetSide = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); + u32 flags = cmd->flags; - if (gSideTimers[targetSide].spikesAmount == 3) + if (gStatuses3[gBattlerAttacker] & flags) { gBattlescriptCurrInstr = cmd->failInstr; } else { - if (gSideTimers[targetSide].spikesAmount == 0) // Add only once to the queue - PushHazardTypeToQueue(targetSide, HAZARDS_SPIKES); - gSideTimers[targetSide].spikesAmount++; + gStatuses3[gBattlerAttacker] |= flags; + if (flags & STATUS3_MAGNET_RISE) + gDisableStructs[gBattlerAttacker].magnetRiseTimer = gBattleTurnCounter + 5; + if (flags & STATUS3_LASER_FOCUS) + gDisableStructs[gBattlerAttacker].laserFocusTimer = gBattleTurnCounter + 2; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setvolatile(void) -{ - CMD_ARGS(u8 battler, u8 _volatile, u8 value); - - SetMonVolatile(GetBattlerForBattleScript(cmd->battler), cmd->_volatile, cmd->value); - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_trysetperishsong(void) +static void Cmd_assistattackselect(void) { CMD_ARGS(const u8 *failInstr); - s32 i; - s32 notAffectedCount = 0; + s32 chooseableMovesNo = 0; + struct Pokemon *party; + s32 monId, moveId; + u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); - for (i = 0; i < gBattlersCount; i++) + if (validMoves != NULL) { - if (gStatuses3[i] & STATUS3_PERISH_SONG - || GetBattlerAbility(i) == ABILITY_SOUNDPROOF - || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE) - || gStatuses3[i] & STATUS3_COMMANDER) - { - notAffectedCount++; - } - else + party = GetBattlerParty(gBattlerAttacker); + + for (monId = 0; monId < PARTY_SIZE; monId++) { - gStatuses3[i] |= STATUS3_PERISH_SONG; - gDisableStructs[i].perishSongTimer = 3; - } - } + if (monId == gBattlerPartyIndexes[gBattlerAttacker]) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) + continue; + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + continue; - if (notAffectedCount == gBattlersCount) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} + for (moveId = 0; moveId < MAX_MON_MOVES; moveId++) + { + u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); -static void Cmd_handlerollout(void) -{ - CMD_ARGS(); + if (IsMoveAssistBanned(move)) + continue; - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + validMoves[chooseableMovesNo++] = move; + } + } + } + + if (chooseableMovesNo) { - CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_IGNORE); - gBattlescriptCurrInstr = BattleScript_MoveMissedPause; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gCalledMove = validMoves[Random() % chooseableMovesNo]; + gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gBattlescriptCurrInstr = cmd->nextInstr; } else { - if (!(gBattleMons[gBattlerAttacker].volatiles.multipleTurns)) // First hit. - { - gDisableStructs[gBattlerAttacker].rolloutTimer = 5; - gDisableStructs[gBattlerAttacker].rolloutTimerStartValue = 5; - gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE; - gLockedMoves[gBattlerAttacker] = gCurrentMove; - } - if (--gDisableStructs[gBattlerAttacker].rolloutTimer == 0) // Last hit. - { - gBattleMons[gBattlerAttacker].volatiles.multipleTurns = FALSE; - } - - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } -} -static void Cmd_jumpifconfusedandstatmaxed(void) -{ - CMD_ARGS(u8 stat, const u8 *jumpInstr); - - if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0 - && !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN)) - gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised - else - gBattlescriptCurrInstr = cmd->nextInstr; + TRY_FREE_AND_SET_NULL(validMoves); } -static void Cmd_handlefurycutter(void) +static void Cmd_trysetmagiccoat(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *failInstr); - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn { - gDisableStructs[gBattlerAttacker].furyCutterCounter = 0; - gBattlescriptCurrInstr = BattleScript_MoveMissedPause; + gBattlescriptCurrInstr = cmd->failInstr; } else { - u32 max; - - if (B_UPDATED_MOVE_DATA >= GEN_6) - max = 3; - else if (B_UPDATED_MOVE_DATA == GEN_5) - max = 4; - else - max = 5; - - if (gDisableStructs[gBattlerAttacker].furyCutterCounter < max - && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT) // Don't increment counter on second hit - gDisableStructs[gBattlerAttacker].furyCutterCounter++; - + gProtectStructs[gBattlerAttacker].bounceMove = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setembargo(void) +// Snatch +static void Cmd_trysetsnatch(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_EMBARGO) + if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_EMBARGO; - gDisableStructs[gBattlerTarget].embargoTimer = gBattleTurnCounter + 5; + gProtectStructs[gBattlerAttacker].stealMove = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_presentdamagecalculation(void) +static void Cmd_unused2(void) { - CMD_ARGS(); +} - u32 rand = Random() & 0xFF; +static void Cmd_switchoutabilities(void) +{ + CMD_ARGS(u8 battler); - /* Don't reroll present effect/power for the second hit of Parental Bond. - * Not sure if this is the correct behaviour, but bulbapedia states - * that if present heals the foe, it doesn't strike twice, and if it deals - * damage, the second strike will always deal damage too. This is a simple way - * to replicate that effect. - */ - if (gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_2ND_HIT) + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS) { - if (rand < 102) - { - gBattleStruct->presentBasePower = 40; - } - else if (rand < 178) - { - gBattleStruct->presentBasePower = 80; - } - else if (rand < 204) - { - gBattleStruct->presentBasePower = 120; - } - else + gBattleMons[battler].ability = ABILITY_NONE; + BattleScriptPush(gBattlescriptCurrInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + } + else + { + switch (GetBattlerAbility(battler)) { - // TODO: Check if this is correct - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerTarget) / 4; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; - gBattleStruct->presentBasePower = 0; + case ABILITY_NATURAL_CURE: + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); + + gBattleMons[battler].status1 = 0; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, + 1u << gBattleStruct->battlerPartyIndexes[battler], + sizeof(gBattleMons[battler].status1), + &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); + break; + case ABILITY_REGENERATOR: + { + u32 regenerate = GetNonDynamaxMaxHP(battler) / 3; + regenerate += gBattleMons[battler].hp; + if (regenerate > gBattleMons[battler].maxHP) + regenerate = gBattleMons[battler].maxHP; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, + 1u << gBattleStruct->battlerPartyIndexes[battler], + sizeof(regenerate), + ®enerate); + MarkBattlerForControllerExec(battler); + break; + } } - } - if (gBattleStruct->presentBasePower) - { - gBattlescriptCurrInstr = BattleScript_HitFromCritCalc; - } - else if (gBattleMons[gBattlerTarget].maxHP == gBattleMons[gBattlerTarget].hp) - { - gBattlescriptCurrInstr = BattleScript_AlreadyAtFullHp; - } - else - { - gBattleStruct->moveResultFlags[gBattlerTarget] &= ~MOVE_RESULT_DOESNT_AFFECT_FOE; - gBattlescriptCurrInstr = BattleScript_PresentHealTarget; + gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setsafeguard(void) +static void Cmd_jumpifhasnohp(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler, const u8 *jumpInstr); - if (gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_SAFEGUARD) - { - gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SIDE_STATUS_FAILED; - } - else - { - gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_SAFEGUARD; - gSideTimers[GetBattlerSide(gBattlerAttacker)].safeguardTimer = gBattleTurnCounter + 5; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; - } + u32 battler = GetBattlerForBattleScript(cmd->battler); - gBattlescriptCurrInstr = cmd->nextInstr; + if (!IsBattlerAlive(battler)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_magnitudedamagecalculation(void) +static void Cmd_jumpifnotcurrentmoveargtype(void) { - CMD_ARGS(); + CMD_ARGS(u8 battler, const u8 *failInstr); - u32 magnitude = Random() % 100; + u8 battler = GetBattlerForBattleScript(cmd->battler); + const u8 *failInstr = cmd->failInstr; + u32 type = GetMoveArgType(gCurrentMove); - if (magnitude < 5) - { - gBattleStruct->magnitudeBasePower = 10; - magnitude = 4; - } - else if (magnitude < 15) - { - gBattleStruct->magnitudeBasePower = 30; - magnitude = 5; - } - else if (magnitude < 35) - { - gBattleStruct->magnitudeBasePower = 50; - magnitude = 6; - } - else if (magnitude < 65) - { - gBattleStruct->magnitudeBasePower = 70; - magnitude = 7; - } - else if (magnitude < 85) - { - gBattleStruct->magnitudeBasePower = 90; - magnitude = 8; - } - else if (magnitude < 95) - { - gBattleStruct->magnitudeBasePower = 110; - magnitude = 9; - } + if (!IS_BATTLER_OF_TYPE(battler, type)) + gBattlescriptCurrInstr = failInstr; else - { - gBattleStruct->magnitudeBasePower = 150; - magnitude = 10; - } - - PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 2, magnitude) - - for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) - { - if (gBattlerTarget == gBattlerAttacker) - continue; - if (!(gAbsentBattlerFlags & (1u << gBattlerTarget))) // A valid target was found. - break; - } - - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->nextInstr; } -static bool32 SetTargetToNextPursuiter(u32 battlerDef) +static void Cmd_pickup(void) { - u32 i; - for (i = gCurrentTurnActionNumber + 1; i < gBattlersCount; i++) + CMD_ARGS(); + + u32 i, j; + u16 species, heldItem, ability; + u8 lvlDivBy10; + + if (!InBattlePike()) // No items in Battle Pike. { - u32 battler = gBattlerByTurnOrder[i]; - if (gChosenActionByBattler[battler] == B_ACTION_USE_MOVE - && GetMoveEffect(gChosenMoveByBattler[battler]) == EFFECT_PURSUIT - && IsBattlerAlive(battlerDef) - && IsBattlerAlive(battler) - && !IsBattlerAlly(battler, battlerDef) - && (B_PURSUIT_TARGET >= GEN_4 || gBattleStruct->moveTarget[battler] == battlerDef) - && !IsGimmickSelected(battler, GIMMICK_Z_MOVE) - && !IsGimmickSelected(battler, GIMMICK_DYNAMAX) - && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) + bool32 isInPyramid = InBattlePyramid_(); + for (i = 0; i < PARTY_SIZE; i++) { - gBattlerTarget = battler; - return TRUE; - } - } - return FALSE; -} + species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG); + heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + lvlDivBy10 = (GetMonData(&gPlayerParty[i], MON_DATA_LEVEL)-1) / 10; //Moving this here makes it easier to add in abilities like Honey Gather. + if (lvlDivBy10 > 9) + lvlDivBy10 = 9; -static void Cmd_jumpifnopursuitswitchdmg(void) -{ - CMD_ARGS(const u8 *jumpInstr); + ability = GetSpeciesAbility(species, GetMonData(&gPlayerParty[i], MON_DATA_ABILITY_NUM)); - u32 savedTarget = gBattlerTarget; + if (ability == ABILITY_PICKUP + && species != SPECIES_NONE + && species != SPECIES_EGG + && heldItem == ITEM_NONE + && (Random() % 10) == 0) + { + if (isInPyramid) + { + heldItem = GetBattlePyramidPickupItemId(); + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); + } + else + { + u32 rand = Random() % 100; + u32 percentTotal = 0; - if (SetTargetToNextPursuiter(gBattlerAttacker)) - { - ChangeOrderTargetAfterAttacker(); - gBattleStruct->battlerState[gBattlerAttacker].pursuitTarget = TRUE; - gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker]; - gBattleStruct->moveTarget[gBattlerTarget] = gBattlerAttacker; - gBattlerTarget = savedTarget; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->jumpInstr; + for (j = 0; j < ARRAY_COUNT(sPickupTable); j++) + { + percentTotal += sPickupTable[j].percentage[lvlDivBy10]; + if (rand < percentTotal) + { + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sPickupTable[j].itemId); + break; + } + } + } + } + else if (ability == ABILITY_HONEY_GATHER + && species != 0 + && species != SPECIES_EGG + && heldItem == ITEM_NONE) + { + if ((lvlDivBy10 + 1 ) * 5 > Random() % 100) + { + heldItem = ITEM_HONEY; + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); + } + } + else if (P_SHUCKLE_BERRY_JUICE == GEN_2 + && species == SPECIES_SHUCKLE + && heldItem == ITEM_ORAN_BERRY + && (Random() % 16) == 0) + { + heldItem = ITEM_BERRY_JUICE; + SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); + } + } } -} -static void Cmd_tryrestorehpberry(void) -{ - CMD_ARGS(); - if (TryRestoreHPBerries(gBattlerAttacker, ITEMEFFECT_TRY_HEALING)) - return; gBattlescriptCurrInstr = cmd->nextInstr; } -// Belly Drum, Fillet Away -static void Cmd_halvehp(void) +static void Cmd_unused_0xE6(void) { - CMD_ARGS(const u8 *failInstr); - - u32 halfHp = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - - if (!(GetNonDynamaxMaxHP(gBattlerAttacker) / 2)) - halfHp = 1; - - if (gBattleMons[gBattlerAttacker].hp > halfHp) - { - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; +} - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } +static void Cmd_unused_0xE7(void) +{ } -// Psych Up -static void Cmd_copyfoestats(void) +// Water and Mud Sport +static void Cmd_settypebasedhalvers(void) { - CMD_ARGS(); + CMD_ARGS(const u8 *failInstr); - s32 i; + bool8 worked = FALSE; - for (i = 0; i < NUM_BATTLE_STATS; i++) + if (GetMoveEffect(gCurrentMove) == EFFECT_MUD_SPORT) { - gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i]; + if (B_SPORT_TURNS >= GEN_6) + { + if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT)) + { + gFieldStatuses |= STATUS_FIELD_MUDSPORT; + gFieldTimers.mudSportTimer = gBattleTurnCounter + 5; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; + worked = TRUE; + } + } + else + { + if (!gBattleMons[gBattlerAttacker].volatiles.waterSport) + { + gBattleMons[gBattlerAttacker].volatiles.waterSport = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; + worked = TRUE; + } + } + } + else // Water Sport + { + if (B_SPORT_TURNS >= GEN_6) + { + if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT)) + { + gFieldStatuses |= STATUS_FIELD_WATERSPORT; + gFieldTimers.waterSportTimer = gBattleTurnCounter + 5; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; + worked = TRUE; + } + } + else + { + if (!gBattleMons[gBattlerAttacker].volatiles.mudSport) + { + gBattleMons[gBattlerAttacker].volatiles.mudSport = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; + worked = TRUE; + } + } } - gBattleScripting.battler = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; + if (worked) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->failInstr; } -static void Cmd_rapidspinfree(void) +bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) { - CMD_ARGS(); + if (!gBattleMons[battlerDef].volatiles.substitute) + return FALSE; + else if (MoveIgnoresSubstitute(move)) + return FALSE; + else if (IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_INFILTRATOR)) + return FALSE; + else + return TRUE; +} - u8 atkSide = GetBattlerSide(gBattlerAttacker); +bool32 DoesDisguiseBlockMove(u32 battler, u32 move) +{ + if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) + || gBattleMons[battler].volatiles.transformed + || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + || gHitMarker & HITMARKER_IGNORE_DISGUISE + || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) + return FALSE; + else + return TRUE; +} - if (gBattleMons[gBattlerAttacker].volatiles.wrapped) - { - gBattleScripting.battler = gBattlerTarget; - gBattleMons[gBattlerAttacker].volatiles.wrapped = FALSE; - gBattlerTarget = gBattleStruct->wrappedBy[gBattlerAttacker]; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); - BattleScriptCall(BattleScript_WrapFree); - } - else if (gStatuses3[gBattlerAttacker] & STATUS3_LEECHSEED) - { - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED; - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED_BATTLER; - BattleScriptCall(BattleScript_LeechSeedFree); - } - else if (AreAnyHazardsOnSide(atkSide)) +static void Cmd_jumpifsubstituteblocks(void) +{ + CMD_ARGS(const u8 *jumpInstr); + + if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +static void Cmd_tryrecycleitem(void) +{ + CMD_ARGS(const u8 *failInstr); + + u16 *usedHeldItem; + + if (gCurrentMove == MOVE_NONE && GetBattlerAbility(gBattlerAttacker) == ABILITY_PICKUP) + usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + else + usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; + if (*usedHeldItem != ITEM_NONE && gBattleMons[gBattlerAttacker].item == ITEM_NONE) { - for (u32 hazardType = HAZARDS_NONE + 1; hazardType < HAZARDS_MAX_COUNT; hazardType++) - { - if (IsHazardOnSideAndClear(atkSide, hazardType)) - { - gBattleStruct->numHazards[atkSide]--; - gBattleCommunication[MULTISTRING_CHOOSER] = hazardType; - BattleScriptCall(BattleScript_SpinHazardsAway); - return; - } - } + gLastUsedItem = *usedHeldItem; + *usedHeldItem = ITEM_NONE; + gBattleMons[gBattlerAttacker].item = gLastUsedItem; + + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].item), &gBattleMons[gBattlerAttacker].item); + MarkBattlerForControllerExec(gBattlerAttacker); + + gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } } -static void Cmd_unused_0xBF(void) +bool32 CanCamouflage(u8 battler) { + if (IS_BATTLER_OF_TYPE(battler, gBattleEnvironmentInfo[gBattleEnvironment].camouflageType)) + return FALSE; + return TRUE; } -static void Cmd_recoverbasedonsunlight(void) +static void Cmd_settypetoenvironment(void) { CMD_ARGS(const u8 *failInstr); - gBattlerTarget = gBattlerAttacker; - if (gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP) + u8 environmentType; + switch(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { - if (GetMoveEffect(gCurrentMove) == EFFECT_SHORE_UP) - { - if (HasWeatherEffect() && gBattleWeather & B_WEATHER_SANDSTORM) - gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; - else - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - } - else if (GetGenConfig(GEN_CONFIG_TIME_OF_DAY_HEALING_MOVES) != GEN_2) - { - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - else if (gBattleWeather & B_WEATHER_SUN) - gBattleStruct->moveDamage[gBattlerAttacker] = 20 * GetNonDynamaxMaxHP(gBattlerAttacker) / 30; - else // not sunny weather - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - } - else // B_TIME_OF_DAY_HEALING_MOVES == GEN_2 - { - u32 healingModifier = 1; - u32 time = GetTimeOfDay(); - - switch (GetMoveEffect(gCurrentMove)) - { - case EFFECT_MOONLIGHT: - if (time == TIME_NIGHT || time == TIME_EVENING) - healingModifier = 2; - break; - case EFFECT_MORNING_SUN: - if ((OW_TIMES_OF_DAY == GEN_3 && time == TIME_DAY) // Gen 3 doesn't have morning - || (OW_TIMES_OF_DAY != GEN_3 && time == TIME_MORNING)) - healingModifier = 2; - break; - case EFFECT_SYNTHESIS: - if (time == TIME_DAY) - healingModifier = 2; - break; - default: - healingModifier = 1; - break; - } - - if (!(gBattleWeather & B_WEATHER_ANY) || !HasWeatherEffect() || GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_UTILITY_UMBRELLA) - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - else if (gBattleWeather & B_WEATHER_SUN) - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - else // not sunny weather - gBattleStruct->moveDamage[gBattlerAttacker] = healingModifier * GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - - } + case STATUS_FIELD_ELECTRIC_TERRAIN: + environmentType = TYPE_ELECTRIC; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + environmentType = TYPE_GRASS; + break; + case STATUS_FIELD_MISTY_TERRAIN: + environmentType = TYPE_FAIRY; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + environmentType = TYPE_PSYCHIC; + break; + default: + environmentType = gBattleEnvironmentInfo[gBattleEnvironment].camouflageType; + break; + } - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - gBattleStruct->moveDamage[gBattlerAttacker] *= -1; + if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, environmentType) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_TERA) + { + SET_BATTLER_TYPE(gBattlerAttacker, environmentType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, environmentType); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -14084,660 +13655,947 @@ static void Cmd_recoverbasedonsunlight(void) } } -static void Cmd_setstickyweb(void) +// Unused +static void Cmd_pursuitdoubles(void) { CMD_ARGS(const u8 *failInstr); - u8 targetSide = GetBattlerSide(gBattlerTarget); + u32 battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); - if (IsHazardOnSide(targetSide, HAZARDS_STICKY_WEB)) + if (IsDoubleBattle() + && !(gAbsentBattlerFlags & (1u << battler)) + && gChosenActionByBattler[battler] == B_ACTION_USE_MOVE + && GetMoveEffect(gChosenMoveByBattler[battler]) == EFFECT_PURSUIT) { - gBattlescriptCurrInstr = cmd->failInstr; + gActionsByTurnOrder[battler] = B_ACTION_TRY_FINISH; + gCurrentMove = gChosenMoveByBattler[battler]; + gBattlescriptCurrInstr = cmd->nextInstr; + gBattleScripting.animTurn = 1; + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battler; } else { - PushHazardTypeToQueue(targetSide, HAZARDS_STICKY_WEB); - gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor - gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } } -static void Cmd_selectfirstvalidtarget(void) +static void Cmd_snatchsetbattlers(void) { CMD_ARGS(); - for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) - { - if (gBattlerTarget == gBattlerAttacker && !(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove) & MOVE_TARGET_USER)) - continue; - if (IsBattlerAlive(gBattlerTarget)) - break; - } - if (gBattlerTarget >= gBattlersCount) - gBattlerTarget = 0; + gEffectBattler = gBattlerAttacker; + + if (gBattlerAttacker == gBattlerTarget) + gBattlerAttacker = gBattlerTarget = gBattleScripting.battler; + else + gBattlerTarget = gBattleScripting.battler; + + gBattleScripting.battler = gEffectBattler; gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trysetfutureattack(void) +static void Cmd_removescreens(void) { - CMD_ARGS(const u8 *failInstr); - - if (gWishFutureKnock.futureSightCounter[gBattlerTarget] > gBattleTurnCounter) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gSideStatuses[GetBattlerSide(gBattlerTarget)] |= SIDE_STATUS_FUTUREATTACK; - gWishFutureKnock.futureSightMove[gBattlerTarget] = gCurrentMove; - gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; - gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; - gWishFutureKnock.futureSightCounter[gBattlerTarget] = gBattleTurnCounter + 3; - - if (gCurrentMove == MOVE_DOOM_DESIRE) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FUTURE_SIGHT; - - gBattlescriptCurrInstr = cmd->nextInstr; - } -} - -static void Cmd_trydobeatup(void) -{ -#if B_BEAT_UP >= GEN_5 CMD_ARGS(); - gBattleStruct->beatUpSlot++; - gBattlescriptCurrInstr = cmd->nextInstr; -#else - CMD_ARGS(const u8 *endInstr, const u8 *failInstr); - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + u8 side; + bool32 failed; - if (!IsBattlerAlive(gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->endInstr; - } + if (B_BRICK_BREAK >= GEN_4) + side = GetBattlerSide(gBattlerTarget); // From Gen 4 onwards, Brick Break can remove screens on the user's side if used on an ally else - { - u8 beforeLoop = gBattleCommunication[0]; - for (;gBattleCommunication[0] < PARTY_SIZE; gBattleCommunication[0]++) - { - if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP) - && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG - && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS)) - break; - } - - if (gBattleCommunication[0] < PARTY_SIZE) - { - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattleCommunication[0]) - - gBattlescriptCurrInstr = cmd->nextInstr; - - gBattleStruct->moveDamage[gBattlerTarget] = GetSpeciesBaseAttack(GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)); - gBattleStruct->moveDamage[gBattlerTarget] *= GetMovePower(gCurrentMove); - gBattleStruct->moveDamage[gBattlerTarget] *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2); - gBattleStruct->moveDamage[gBattlerTarget] /= GetSpeciesBaseDefense(gBattleMons[gBattlerTarget].species); - gBattleStruct->moveDamage[gBattlerTarget] = (gBattleStruct->moveDamage[gBattlerTarget] / 50) + 2; - if (gProtectStructs[gBattlerAttacker].helpingHand) - gBattleStruct->moveDamage[gBattlerTarget] = gBattleStruct->moveDamage[gBattlerTarget] * 15 / 10; - - gBattleCommunication[0]++; - } - else if (beforeLoop != 0) - { - gBattlescriptCurrInstr = cmd->endInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } - } -#endif -} - -static void Cmd_setsemiinvulnerablebit(void) -{ - CMD_ARGS(bool8 clear); - - if (gBattleMoveEffects[GetMoveEffect(gCurrentMove)].semiInvulnerableEffect == TRUE) - { - u32 semiInvulnerableEffect = GetMoveTwoTurnAttackStatus(gCurrentMove); - if (cmd->clear) - gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect; - else - gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect; - } - - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static bool32 CheckIfCanFireTwoTurnMoveNow(u8 battler, bool8 checkChargeTurnEffects) -{ - // Semi-invulnerable moves cannot skip their charge turn (except with Power Herb) - if (gBattleMoveEffects[GetMoveEffect(gCurrentMove)].semiInvulnerableEffect == TRUE) - return FALSE; - - // If this move has charge turn effects, it must charge, activate them, then try to fire - if (checkChargeTurnEffects && MoveHasChargeTurnAdditionalEffect(gCurrentMove)) - return FALSE; - - // Insert custom conditions here - - // Certain two-turn moves may fire on the first turn in the right weather (Solar Beam, Electro Shot) - // By default, all two-turn moves have the option of adding weather to their argument - if (IsBattlerWeatherAffected(battler, GetMoveTwoTurnAttackWeather(gCurrentMove))) - return TRUE; - - return FALSE; -} - -static void Cmd_tryfiretwoturnmovenowbyeffect(void) -{ - CMD_ARGS(u8 battler, bool8 checkChargeTurnEffects, const u8 *jumpInstr); + side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; - if (CheckIfCanFireTwoTurnMoveNow(cmd->battler, cmd->checkChargeTurnEffects) == TRUE) - { - gBattleScripting.animTurn = 1; - gBattlescriptCurrInstr = cmd->jumpInstr; - } + if (B_BRICK_BREAK >= GEN_5) + failed = gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT; else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_setminimize(void) -{ - CMD_ARGS(); - - if (gHitMarker & HITMARKER_OBEYS) - gStatuses3[gBattlerAttacker] |= STATUS3_MINIMIZED; - - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_unused_c8(void) -{ -} - -static void Cmd_trymemento(void) -{ - CMD_ARGS(const u8 *failInstr); + failed = FALSE; - if (B_MEMENTO_FAIL >= GEN_4 - && (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE - || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) - || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) - { - // Failed, target was protected. - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (B_MEMENTO_FAIL < GEN_4 - && gBattleMons[gBattlerTarget].statStages[STAT_ATK] == MIN_STAT_STAGE - && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] == MIN_STAT_STAGE - && gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) + if (!failed && gSideStatuses[side] & SIDE_STATUS_SCREEN_ANY) { - // Failed, unprotected target already has minimum Attack and Special Attack. - gBattlescriptCurrInstr = cmd->failInstr; + gSideStatuses[side] &= ~SIDE_STATUS_SCREEN_ANY; + gBattleScripting.animTurn = 1; + gBattleScripting.animTargetsHit = 1; } else { - // Success, drop user's HP bar to 0 - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp; - BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); - MarkBattlerForControllerExec(gBattlerAttacker); - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleScripting.animTurn = 0; + gBattleScripting.animTargetsHit = 0; } -} - -// Follow Me -static void Cmd_setforcedtarget(void) -{ - CMD_ARGS(); - gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 1; - gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget = gBattlerTarget; - gSideTimers[GetBattlerSide(gBattlerTarget)].followmePowder = IsPowderMove(gCurrentMove); gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setcharge(void) +u8 GetCatchingBattler(void) { - CMD_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses3[battler] |= STATUS3_CHARGED_UP; - if (B_CHARGE < GEN_9) - gDisableStructs[battler].chargeTimer = 2; + if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))) + return GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); else - gDisableStructs[battler].chargeTimer = 0; - gBattlescriptCurrInstr = cmd->nextInstr; + return GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); } -// Nature Power -static void Cmd_callenvironmentattack(void) +static void Cmd_handleballthrow(void) { CMD_ARGS(); - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCurrentMove = GetNaturePowerMove(gBattlerAttacker); - gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - BattleScriptPush(GetMoveBattleScript(gCurrentMove)); - gBattlescriptCurrInstr = cmd->nextInstr; -} + u16 ballMultiplier = 100; + s8 ballAddition = 0; -u32 GetNaturePowerMove(u32 battler) -{ - u32 move = gBattleEnvironmentInfo[gBattleEnvironment].naturePower; - if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) - move = MOVE_MOONBLAST; - else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) - move = MOVE_THUNDERBOLT; - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) - move = MOVE_ENERGY_BALL; - else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) - move = MOVE_PSYCHIC; - else if (gBattleEnvironmentInfo[gBattleEnvironment].naturePower == MOVE_NONE) - move = MOVE_TRI_ATTACK; + if (gBattleControllerExecFlags) + return; - if (GetActiveGimmick(battler) == GIMMICK_Z_MOVE) + gBattlerTarget = GetCatchingBattler(); + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; - move = GetTypeBasedZMove(move); + BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_TRAINER_BLOCK); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_TrainerBallBlock; } - - return move; -} - -static void Cmd_curestatuswithmove(void) -{ - CMD_ARGS(const u8 *failInstr); - u32 shouldHeal; - - if (GetMoveEffect(gCurrentMove) == EFFECT_REFRESH) - shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_CAN_MOVE; - else // Take Heart - shouldHeal = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; - - if (shouldHeal) + else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) { - if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) - TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]); - - gBattleMons[gBattlerAttacker].status1 = 0; - gBattlescriptCurrInstr = cmd->nextInstr; - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].status1), &gBattleMons[gBattlerAttacker].status1); + BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = BattleScript_WallyBallThrow; } else { - gBattlescriptCurrInstr = cmd->failInstr; - } -} - -static void Cmd_settorment(void) + u32 odds, i; + u32 catchRate; + u32 ballId = ItemIdToBallId(gLastUsedItem); + + gBallToDisplay = gLastThrownBall = gLastUsedItem; + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + catchRate = gBattleStruct->safariCatchFactor * 1275 / 100; + else + catchRate = gSpeciesInfo[gBattleMons[gBattlerTarget].species].catchRate; + + if (gSpeciesInfo[gBattleMons[gBattlerTarget].species].isUltraBeast) + { + if (ballId == BALL_BEAST) + ballMultiplier = 500; + else + ballMultiplier = 10; + } + else + { + switch (ballId) + { + case BALL_ULTRA: + ballMultiplier = 200; + break; + case BALL_SPORT: + if (B_SPORT_BALL_MODIFIER <= GEN_7) + ballMultiplier = 150; + break; + case BALL_GREAT: + ballMultiplier = 150; + break; + case BALL_SAFARI: + if (B_SAFARI_BALL_MODIFIER <= GEN_7) + ballMultiplier = 150; + break; + case BALL_NET: + if (IS_BATTLER_ANY_TYPE(gBattlerTarget, TYPE_WATER, TYPE_BUG)) + ballMultiplier = B_NET_BALL_MODIFIER >= GEN_7 ? 350 : 300; + break; + case BALL_DIVE: + if (GetCurrentMapType() == MAP_TYPE_UNDERWATER + || (B_DIVE_BALL_MODIFIER >= GEN_4 && (gIsFishingEncounter || gIsSurfingEncounter))) + ballMultiplier = 350; + break; + case BALL_NEST: + if (B_NEST_BALL_MODIFIER >= GEN_6) + { + //((41 - Pokémon's level) ÷ 10)× if Pokémon's level is between 1 and 29, 1× otherwise. + if (gBattleMons[gBattlerTarget].level < 30) + ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10); + } + else if (B_NEST_BALL_MODIFIER >= GEN_5) + { + //((41 - Pokémon's level) ÷ 10)×, minimum 1× + if (gBattleMons[gBattlerTarget].level < 31) + ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10); + } + else if (gBattleMons[gBattlerTarget].level < 40) + { + //((40 - Pokémon's level) ÷ 10)×, minimum 1× + ballMultiplier = 400 - (gBattleMons[gBattlerTarget].level * 10); + if (ballMultiplier <= 90) + ballMultiplier = 100; + } + break; + case BALL_REPEAT: + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT)) + ballMultiplier = (B_REPEAT_BALL_MODIFIER >= GEN_7 ? 350 : 300); + break; + case BALL_TIMER: + ballMultiplier = 100 + (gBattleResults.battleTurnCounter * (B_TIMER_BALL_MODIFIER >= GEN_5 ? 30 : 10)); + if (ballMultiplier > 400) + ballMultiplier = 400; + break; + case BALL_DUSK: + i = GetTimeOfDay(); + if (i == TIME_EVENING || i == TIME_NIGHT || gMapHeader.cave || gMapHeader.mapType == MAP_TYPE_UNDERGROUND) + ballMultiplier = (B_DUSK_BALL_MODIFIER >= GEN_7 ? 300 : 350); + break; + case BALL_QUICK: + if (gBattleResults.battleTurnCounter == 0) + ballMultiplier = (B_QUICK_BALL_MODIFIER >= GEN_5 ? 500 : 400); + break; + case BALL_LEVEL: + if (gBattleMons[gBattlerAttacker].level >= 4 * gBattleMons[gBattlerTarget].level) + ballMultiplier = 800; + else if (gBattleMons[gBattlerAttacker].level > 2 * gBattleMons[gBattlerTarget].level) + ballMultiplier = 400; + else if (gBattleMons[gBattlerAttacker].level > gBattleMons[gBattlerTarget].level) + ballMultiplier = 200; + break; + case BALL_LURE: + if (gIsFishingEncounter) + { + if (B_LURE_BALL_MODIFIER >= GEN_8) + ballMultiplier = 400; + else if (B_LURE_BALL_MODIFIER >= GEN_7) + ballMultiplier = 500; + else + ballMultiplier = 300; + } + break; + case BALL_MOON: + { + const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerTarget].species); + if (evolutions == NULL) + break; + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) + { + if (evolutions[i].method == EVO_ITEM + && evolutions[i].param == ITEM_MOON_STONE) + ballMultiplier = 400; + } + } + break; + case BALL_LOVE: + if (gBattleMons[gBattlerTarget].species == gBattleMons[gBattlerAttacker].species) + { + u8 gender1 = GetMonGender(GetBattlerMon(gBattlerTarget)); + u8 gender2 = GetMonGender(GetBattlerMon(gBattlerAttacker)); + + if (gender1 != gender2 && gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS) + ballMultiplier = 800; + } + break; + case BALL_FAST: + if (GetSpeciesBaseSpeed(gBattleMons[gBattlerTarget].species) >= 100) + ballMultiplier = 400; + break; + case BALL_HEAVY: + i = GetSpeciesWeight(gBattleMons[gBattlerTarget].species); + if (B_HEAVY_BALL_MODIFIER >= GEN_7) + { + if (i < 1000) + ballAddition = -20; + else if (i < 2000) + ballAddition = 0; + else if (i < 3000) + ballAddition = 20; + else + ballAddition = 30; + } + else if (B_HEAVY_BALL_MODIFIER >= GEN_4) + { + if (i < 2048) + ballAddition = -20; + else if (i < 3072) + ballAddition = 20; + else if (i < 4096) + ballAddition = 30; + else + ballAddition = 40; + } + else + { + if (i < 1024) + ballAddition = -20; + else if (i < 2048) + ballAddition = 0; + else if (i < 3072) + ballAddition = 20; + else if (i < 4096) + ballAddition = 30; + else + ballAddition = 40; + } + break; + case BALL_DREAM: + if (B_DREAM_BALL_MODIFIER >= GEN_8 && (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP || GetBattlerAbility(gBattlerTarget) == ABILITY_COMATOSE)) + ballMultiplier = 400; + break; + case BALL_BEAST: + ballMultiplier = 10; + break; + } + } + + // catchRate is unsigned, which means that it may potentially overflow if sum is applied directly. + if (catchRate < 21 && ballAddition == -20) + catchRate = 1; + else + catchRate = catchRate + ballAddition; + + odds = (catchRate * ballMultiplier / 100) + * (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2) + / (3 * gBattleMons[gBattlerTarget].maxHP); + + if (gBattleMons[gBattlerTarget].status1 & STATUS1_INCAPACITATED) + odds *= 2; + if (gBattleMons[gBattlerTarget].status1 & STATUS1_CAN_MOVE) + odds = (odds * 15) / 10; + + if (gBattleResults.catchAttempts[ballId] < 255) + gBattleResults.catchAttempts[ballId]++; + + if (odds > 254) // mon caught + { + BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS); + MarkBattlerForControllerExec(gBattlerAttacker); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); + gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; + struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); + SetMonData(caughtMon, MON_DATA_POKEBALL, &ballId); + + if (CalculatePlayerPartyCount() == PARTY_SIZE) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + + if (ballId == BALL_HEAL) + { + MonRestorePP(caughtMon); + HealStatusConditions(caughtMon, STATUS1_ANY, gBattlerTarget); + gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; + SetMonData(caughtMon, MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); + } + else if (ballId == BALL_FRIEND) + { + u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); + SetMonData(caughtMon, MON_DATA_FRIENDSHIP, &friendship); + } + } + else // mon may be caught, calculate shakes + { + u8 shakes; + u8 maxShakes; + + gBattleSpritesDataPtr->animationData->isCriticalCapture = FALSE; + gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = FALSE; + + if (CriticalCapture(odds)) + { + maxShakes = BALL_1_SHAKE; // critical capture doesn't guarantee capture + gBattleSpritesDataPtr->animationData->isCriticalCapture = TRUE; + } + else + { + maxShakes = BALL_3_SHAKES_SUCCESS; + } + + if (ballId == BALL_MASTER) + { + shakes = maxShakes; + } + else + { + odds = Sqrt(Sqrt(16711680 / odds)); + odds = 1048560 / odds; + for (shakes = 0; shakes < maxShakes && Random() < odds; shakes++); + } + + BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, shakes); + MarkBattlerForControllerExec(gBattlerAttacker); + + if (shakes == maxShakes) // mon caught, copy of the code above + { + if (IsCriticalCapture()) + gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; + + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); + gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; + struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); + SetMonData(caughtMon, MON_DATA_POKEBALL, &ballId); + + if (CalculatePlayerPartyCount() == PARTY_SIZE) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + + if (ballId == BALL_HEAL) + { + MonRestorePP(caughtMon); + HealStatusConditions(caughtMon, STATUS1_ANY, gBattlerTarget); + gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; + SetMonData(caughtMon, MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); + } + else if (ballId == BALL_FRIEND) + { + u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); + SetMonData(caughtMon, MON_DATA_FRIENDSHIP, &friendship); + } + } + else // not caught + { + if (!gHasFetchedBall) + gLastUsedBall = gLastUsedItem; + + if (IsCriticalCapture()) + gBattleCommunication[MULTISTRING_CHOOSER] = BALL_3_SHAKES_FAIL; + else + gBattleCommunication[MULTISTRING_CHOOSER] = shakes; + + gBattlescriptCurrInstr = BattleScript_ShakeBallThrow; + } + } + } +} + +static void Cmd_givecaughtmon(void) +{ + CMD_ARGS(const u8 *passInstr); + enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE]; + // Restore players party in order to handle properly the case when a wild mon is caught. + if (IsNPCFollowerWildBattle()) + LoadPlayerParty(); + + switch (state) + { + case GIVECAUGHTMON_CHECK_PARTY_SIZE: + if (CalculatePlayerPartyCount() == PARTY_SIZE && B_CATCH_SWAP_INTO_PARTY >= GEN_7) + { + PrepareStringBattle(STRINGID_SENDCAUGHTMONPARTYORBOX, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_ASK_ADD_TO_PARTY; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NO_MESSSAGE_SKIP; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + break; + case GIVECAUGHTMON_ASK_ADD_TO_PARTY: + HandleBattleWindow(YESNOBOX_X_Y, 0); + BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_INPUT; + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); + break; + case GIVECAUGHTMON_HANDLE_INPUT: + if (JOY_NEW(DPAD_UP) && gBattleCommunication[CURSOR_POSITION] != 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); + } + if (JOY_NEW(DPAD_DOWN) && gBattleCommunication[CURSOR_POSITION] == 0) + { + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 1; + BattleCreateYesNoCursorAt(1); + } + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if (gBattleCommunication[CURSOR_POSITION] == 0) + { + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_DO_CHOOSE_MON; + } + else + { + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + break; + case GIVECAUGHTMON_DO_CHOOSE_MON: + if (!gPaletteFade.active) + { + BtlController_EmitChoosePokemon(gBattlerAttacker, B_COMM_TO_CONTROLLER, PARTY_ACTION_SEND_MON_TO_BOX, PARTY_SIZE, ABILITY_NONE, 0, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_CHOSEN_MON; + } + break; + case GIVECAUGHTMON_HANDLE_CHOSEN_MON: + if (gSelectedMonPartyId != PARTY_SIZE) + { + if (gSelectedMonPartyId > PARTY_SIZE) + { + // Choosing Pokemon was cancelled + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + else + { + // Mon chosen, try to put it in the PC + if (CopyMonToPC(&gPlayerParty[gSelectedMonPartyId]) == MON_GIVEN_TO_PC) + { + GetMonNickname(&gPlayerParty[gSelectedMonPartyId], gStringVar2); + StringCopy(gStringVar1, GetBoxNamePtr(GetPCBoxToSendMon())); + ZeroMonData(&gPlayerParty[gSelectedMonPartyId]); + gBattleStruct->itemLost[B_SIDE_PLAYER][gSelectedMonPartyId].originalItem = ITEM_NONE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWAPPED_INTO_PARTY; + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + else + { + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + } + } + } + break; + case GIVECAUGHTMON_GIVE_AND_SHOW_MSG: + { + struct Pokemon *caughtMon = GetBattlerMon(GetCatchingBattler()); + if (B_RESTORE_HELD_BATTLE_ITEMS >= GEN_9) + { + u16 lostItem = gBattleStruct->itemLost[B_SIDE_OPPONENT][gBattlerPartyIndexes[GetCatchingBattler()]].originalItem; + if (lostItem != ITEM_NONE && GetItemPocket(lostItem) != POCKET_BERRIES) + SetMonData(caughtMon, MON_DATA_HELD_ITEM, &lostItem); // Restore non-berry items + } + + if (GiveMonToPlayer(caughtMon) != MON_GIVEN_TO_PARTY + && gBattleCommunication[MULTISTRING_CHOOSER] != B_MSG_SWAPPED_INTO_PARTY) + { + if (!ShouldShowBoxWasFullMessage()) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SENT_SOMEONES_PC; + StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); + GetMonData(caughtMon, MON_DATA_NICKNAME, gStringVar2); + } + else + { + StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); // box the mon was sent to + GetMonData(caughtMon, MON_DATA_NICKNAME, gStringVar2); + StringCopy(gStringVar3, GetBoxNamePtr(GetPCBoxToSendMon())); //box the mon was going to be sent to + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOMEONES_BOX_FULL; + } + + // Change to B_MSG_SENT_LANETTES_PC or B_MSG_LANETTES_BOX_FULL + if (FlagGet(FLAG_SYS_PC_LANETTE)) + gBattleCommunication[MULTISTRING_CHOOSER]++; + } + + gBattleResults.caughtMonSpecies = GetMonData(caughtMon, MON_DATA_SPECIES, NULL); + GetMonData(caughtMon, MON_DATA_NICKNAME, gBattleResults.caughtMonNick); + gBattleResults.caughtMonBall = GetMonData(caughtMon, MON_DATA_POKEBALL, NULL); + + gSelectedMonPartyId = PARTY_SIZE; + gBattleCommunication[MULTIUSE_STATE] = 0; + + if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_NO_MESSSAGE_SKIP) + gBattlescriptCurrInstr = cmd->passInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + } + } + // Save the player's party again to not interferes with RestorePartyAfterFollowerNPCBattle() called after battle. + if (IsNPCFollowerWildBattle()) + SavePlayerParty(); +} + +static void Cmd_trysetcaughtmondexflags(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE - || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) + struct Pokemon *caughtMon = GetBattlerMon(GetCatchingBattler()); + u32 species = GetMonData(caughtMon, MON_DATA_SPECIES, NULL); + u32 personality = GetMonData(caughtMon, MON_DATA_PERSONALITY, NULL); + + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattleMons[gBattlerTarget].volatiles.torment = TRUE; + HandleSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_SET_CAUGHT, personality); gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_jumpifnodamage(void) +static void Cmd_displaydexinfo(void) { - CMD_ARGS(const u8 *jumpInstr); - - if (gProtectStructs[gBattlerAttacker].physicalDmg || gProtectStructs[gBattlerAttacker].specialDmg) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; -} + CMD_ARGS(); -static void Cmd_settaunt(void) -{ - CMD_ARGS(const u8 *failInstr); + struct Pokemon *mon = GetBattlerMon(GetCatchingBattler()); + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); - if (B_OBLIVIOUS_TAUNT >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) - { - gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; - gLastUsedAbility = ABILITY_OBLIVIOUS; - RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); - } - else if (gDisableStructs[gBattlerTarget].tauntTimer == 0) + switch (gBattleCommunication[0]) { - u8 turns; - if (B_TAUNT_TURNS >= GEN_5) + case 0: + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); + gBattleCommunication[0]++; + break; + case 1: + if (!gPaletteFade.active) { - turns = 4; - if (GetBattlerTurnOrderNum(gBattlerTarget) > GetBattlerTurnOrderNum(gBattlerAttacker)) - turns--; // If the target hasn't yet moved this turn, Taunt lasts for only three turns (source: Bulbapedia) + FreeAllWindowBuffers(); + gBattleCommunication[TASK_ID] = DisplayCaughtMonDexPage(species, + GetMonData(mon, MON_DATA_IS_SHINY), + GetMonData(mon, MON_DATA_PERSONALITY)); + gBattleCommunication[0]++; } - else if (B_TAUNT_TURNS >= GEN_4) + break; + case 2: + if (!gPaletteFade.active + && gMain.callback2 == BattleMainCB2 + && !gTasks[gBattleCommunication[TASK_ID]].isActive) { - turns = (Random() & 2) + 3; + SetVBlankCallback(VBlankCB_Battle); + gBattleCommunication[0]++; } - else + break; + case 3: + InitBattleBgsVideo(); + LoadBattleTextboxAndBackground(); + gBattle_BG3_X = 256; + gBattleCommunication[0]++; + break; + case 4: + if (!IsDma3ManagerBusyWithBgCopy()) { - turns = 2; + BeginNormalPaletteFade(PALETTES_BG, 0, 16, 0, RGB_BLACK); + ShowBg(0); + ShowBg(3); + gBattleCommunication[0]++; } - - gDisableStructs[gBattlerTarget].tauntTimer = turns; - gBattlescriptCurrInstr = cmd->nextInstr; + break; + case 5: + if (!gPaletteFade.active) + { + gBattlescriptCurrInstr = cmd->nextInstr; + } + break; } - else +} + +void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags) +{ + s32 destY, destX, bgId; + u16 var = 0; + + for (destY = yStart; destY <= yEnd; destY++) { - gBattlescriptCurrInstr = cmd->failInstr; + for (destX = xStart; destX <= xEnd; destX++) + { + if (destY == yStart) + { + if (destX == xStart) + var = 0x1022; + else if (destX == xEnd) + var = 0x1024; + else + var = 0x1023; + } + else if (destY == yEnd) + { + if (destX == xStart) + var = 0x1028; + else if (destX == xEnd) + var = 0x102A; + else + var = 0x1029; + } + else + { + if (destX == xStart) + var = 0x1025; + else if (destX == xEnd) + var = 0x1027; + else + var = 0x1026; + } + + if (flags & WINDOW_CLEAR) + var = 0; + + bgId = (flags & WINDOW_BG1) ? 1 : 0; + CopyToBgTilemapBufferRect_ChangePalette(bgId, &var, destX, destY, 1, 1, 0x11); + } } } -static void Cmd_trysethelpinghand(void) +void BattleCreateYesNoCursorAt(u8 cursorPosition) { - CMD_ARGS(const u8 *failInstr); + u16 src[2]; + src[0] = 1; + src[1] = 2; - gBattlerTarget = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); + CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); +} - if (IsDoubleBattle() - && !(gAbsentBattlerFlags & (1u << gBattlerTarget)) - && !gProtectStructs[gBattlerAttacker].helpingHand - && !gProtectStructs[gBattlerTarget].helpingHand) - { - gProtectStructs[gBattlerTarget].helpingHand = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } +void BattleDestroyYesNoCursorAt(u8 cursorPosition) +{ + u16 src[2]; + src[0] = 0x1016; + src[1] = 0x1016; + + CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11); + CopyBgTilemapBufferToVram(0); } -// Trick -static void Cmd_tryswapitems(void) +static void Cmd_trygivecaughtmonnick(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(); - // opponent can't swap items with player in regular battles - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL - || (!IsOnPlayerSide(gBattlerAttacker) - && !(gBattleTypeFlags & (BATTLE_TYPE_LINK - | BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_SECRET_BASE - | BATTLE_TYPE_RECORDED_LINK - | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) - )))) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else + switch (gBattleCommunication[MULTIUSE_STATE]) { - u8 sideAttacker = GetBattlerSide(gBattlerAttacker); - u8 sideTarget = GetBattlerSide(gBattlerTarget); - - // You can't swap items if they were knocked off in regular battles - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK - | BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_SECRET_BASE - | BATTLE_TYPE_RECORDED_LINK)) - && (gWishFutureKnock.knockedOffMons[sideAttacker] & (1u << gBattlerPartyIndexes[gBattlerAttacker]) - || gWishFutureKnock.knockedOffMons[sideTarget] & (1u << gBattlerPartyIndexes[gBattlerTarget]))) + case 0: + HandleBattleWindow(YESNOBOX_X_Y, 0); + BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); + gBattleCommunication[MULTIUSE_STATE]++; + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); + break; + case 1: + if (JOY_NEW(DPAD_UP) && gBattleCommunication[CURSOR_POSITION] != 0) { - gBattlescriptCurrInstr = cmd->failInstr; + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 0; + BattleCreateYesNoCursorAt(0); } - // can't swap if two Pokémon don't have an item - // or if either of them is an enigma berry or a mail - else if ((gBattleMons[gBattlerAttacker].item == ITEM_NONE && gBattleMons[gBattlerTarget].item == ITEM_NONE) - || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) - || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerTarget].item) - || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) - || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item)) + if (JOY_NEW(DPAD_DOWN) && gBattleCommunication[CURSOR_POSITION] == 0) { - gBattlescriptCurrInstr = cmd->failInstr; + PlaySE(SE_SELECT); + BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); + gBattleCommunication[CURSOR_POSITION] = 1; + BattleCreateYesNoCursorAt(1); } - // check if ability prevents swapping - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD) + if (JOY_NEW(A_BUTTON)) { - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - gLastUsedAbility = gBattleMons[gBattlerTarget].ability; - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + PlaySE(SE_SELECT); + if (gBattleCommunication[CURSOR_POSITION] == 0) + { + gBattleCommunication[MULTIUSE_STATE]++; + BeginFastPaletteFade(3); + } + else + { + gBattleCommunication[MULTIUSE_STATE] = 4; + } } - // took a while, but all checks passed and items can be safely swapped - else + else if (JOY_NEW(B_BUTTON)) { - u16 oldItemAtk, *newItemAtk; - - newItemAtk = &gBattleStruct->changedItems[gBattlerAttacker]; - oldItemAtk = gBattleMons[gBattlerAttacker].item; - *newItemAtk = gBattleMons[gBattlerTarget].item; - - gBattleMons[gBattlerAttacker].item = ITEM_NONE; - gBattleMons[gBattlerTarget].item = oldItemAtk; - - RecordItemEffectBattle(gBattlerAttacker, 0); - RecordItemEffectBattle(gBattlerTarget, GetItemHoldEffect(oldItemAtk)); + PlaySE(SE_SELECT); + gBattleCommunication[MULTIUSE_STATE] = 4; + } + break; + case 2: + if (!gPaletteFade.active) + { + struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); + GetMonData(caughtMon, MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); + FreeAllWindowBuffers(); + MainCallback callback = CalculatePlayerPartyCount() == PARTY_SIZE ? ReshowBlankBattleScreenAfterMenu : BattleMainCB2; - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(*newItemAtk), newItemAtk); - MarkBattlerForControllerExec(gBattlerAttacker); + DoNamingScreen(NAMING_SCREEN_CAUGHT_MON, gBattleStruct->caughtMonNick, + GetMonData(caughtMon, MON_DATA_SPECIES), + GetMonGender(caughtMon), + GetMonData(caughtMon, MON_DATA_PERSONALITY, NULL), + callback); - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); - MarkBattlerForControllerExec(gBattlerTarget); + gBattleCommunication[MULTIUSE_STATE]++; + } + break; + case 3: + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + SetMonData(GetBattlerMon(gBattlerTarget), MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); + gBattleCommunication[MULTIUSE_STATE]++; + } + break; + case 4: + gBattleCommunication[MULTIUSE_STATE] = 0; + gBattlescriptCurrInstr = cmd->nextInstr; + break; + } +} - gBattleStruct->choicedMove[gBattlerTarget] = MOVE_NONE; - gBattleStruct->choicedMove[gBattlerAttacker] = MOVE_NONE; +static void Cmd_subattackerhpbydmg(void) +{ + CMD_ARGS(); - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleMons[gBattlerAttacker].hp -= gBattleStruct->moveDamage[gBattlerTarget]; + gBattlescriptCurrInstr = cmd->nextInstr; +} - PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk) - PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk) +static void Cmd_removeattackerstatus1(void) +{ + CMD_ARGS(); - if (!(sideAttacker == sideTarget && IsPartnerMonFromSameTrainer(gBattlerAttacker))) - { - // if targeting your own side and you aren't in a multi battle, don't save items as stolen - if (IsOnPlayerSide(gBattlerAttacker)) - TrySaveExchangedItem(gBattlerAttacker, oldItemAtk); - if (IsOnPlayerSide(gBattlerTarget)) - TrySaveExchangedItem(gBattlerTarget, *newItemAtk); - } + gBattleMons[gBattlerAttacker].status1 = 0; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (oldItemAtk != ITEM_NONE && *newItemAtk != ITEM_NONE) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_BOTH; // attacker's item -> <- target's item - } - else if (oldItemAtk == ITEM_NONE && *newItemAtk != ITEM_NONE) - { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNBURDEN && gDisableStructs[gBattlerAttacker].unburdenActive) - gDisableStructs[gBattlerAttacker].unburdenActive = FALSE; +// CMD_ARGS is not needed for these functions as they end the script execution. +static void Cmd_finishaction(void) +{ + gCurrentActionFuncId = B_ACTION_FINISHED; +} - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_TAKEN; // nothing -> <- target's item - } - else - { - CheckSetUnburden(gBattlerAttacker); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_GIVEN; // attacker's item -> <- nothing - } - } - } +static void Cmd_finishturn(void) +{ + gCurrentActionFuncId = B_ACTION_FINISHED; + gCurrentTurnActionNumber = gBattlersCount; } -// Role Play, Doodle -static void Cmd_trycopyability(void) +static void Cmd_trainerslideout(void) { - CMD_ARGS(u8 battler, const u8 *failInstr); + CMD_ARGS(u8 position); - u32 battler = GetBattlerForBattleScript(cmd->battler); - u16 defAbility = gBattleMons[gBattlerTarget].ability; + u32 battler = GetBattlerForBattleScript(cmd->position); + BtlController_EmitTrainerSlideBack(battler, B_COMM_TO_CONTROLLER); + MarkBattlerForControllerExec(battler); - if (gBattleMons[battler].ability == defAbility - || defAbility == ABILITY_NONE - || gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed - || (IsBattlerAlive(BATTLE_PARTNER(battler)) && gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE) - || gAbilitiesInfo[defAbility].cantBeCopied) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = defAbility; - gLastUsedAbility = defAbility; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trywish(void) +static const u16 sTelekinesisBanList[] = { - CMD_ARGS(const u8 *failInstr); + SPECIES_DIGLETT, + SPECIES_DUGTRIO, + SPECIES_DIGLETT_ALOLA, + SPECIES_DUGTRIO_ALOLA, + SPECIES_SANDYGAST, + SPECIES_PALOSSAND, + SPECIES_GENGAR_MEGA, +}; - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (gWishFutureKnock.wishCounter[gBattlerAttacker] <= gBattleTurnCounter) - { - gWishFutureKnock.wishCounter[gBattlerAttacker] = gBattleTurnCounter + 2; - gWishFutureKnock.wishPartyId[gBattlerAttacker] = gBattlerPartyIndexes[gBattlerAttacker]; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else +bool32 IsTelekinesisBannedSpecies(u16 species) +{ + u32 i; + + for (i = 0; i < ARRAY_COUNT(sTelekinesisBanList); i++) { - gBattlescriptCurrInstr = cmd->failInstr; + if (species == sTelekinesisBanList[i]) + return TRUE; } + return FALSE; } -static void Cmd_settoxicspikes(void) +static void Cmd_settelekinesis(void) { CMD_ARGS(const u8 *failInstr); - u8 targetSide = GetBattlerSide(gBattlerTarget); - if (gSideTimers[targetSide].toxicSpikesAmount >= 2) + if (gStatuses3[gBattlerTarget] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) + || gFieldStatuses & STATUS_FIELD_GRAVITY + || IsTelekinesisBannedSpecies(gBattleMons[gBattlerTarget].species)) { gBattlescriptCurrInstr = cmd->failInstr; } else { - if (gSideTimers[targetSide].toxicSpikesAmount == 0) - PushHazardTypeToQueue(targetSide, HAZARDS_TOXIC_SPIKES); - gSideTimers[targetSide].toxicSpikesAmount++; + gStatuses3[gBattlerTarget] |= STATUS3_TELEKINESIS; + gDisableStructs[gBattlerTarget].telekinesisTimer = gBattleTurnCounter + 3; gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setgastroacid(void) +static void Cmd_swapstatstages(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(u8 stat); - if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeSuppressed) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) - gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + u8 stat = cmd->stat; + s8 atkStatStage = gBattleMons[gBattlerAttacker].statStages[stat]; + s8 defStatStage = gBattleMons[gBattlerTarget].statStages[stat]; - gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattleMons[gBattlerAttacker].statStages[stat] = defStatStage; + gBattleMons[gBattlerTarget].statStages[stat] = atkStatStage; + + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setyawn(void) +static u16 *GetBattlerStat(struct BattlePokemon *battler, u32 stat) { - CMD_ARGS(const u8 *failInstr); - - if (gStatuses3[gBattlerTarget] & STATUS3_YAWN - || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) - { - // When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: - // "But it failed" will display first. - gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents; - } - else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN)) - { - // When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn: - // "But it failed" will display first. - gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents; - } - else + switch (stat) { - gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); - gBattlescriptCurrInstr = cmd->nextInstr; + case STAT_ATK: return &battler->attack; + case STAT_DEF: return &battler->defense; + case STAT_SPATK: return &battler->spAttack; + case STAT_SPDEF: return &battler->spDefense; + default: return NULL; } } -static void Cmd_setdamagetohealthdifference(void) +static void Cmd_averagestats(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(u8 stat); - if (GetNonDynamaxHP(gBattlerTarget) <= gBattleMons[gBattlerAttacker].hp) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - gBattleMons[gBattlerAttacker].hp; - gBattlescriptCurrInstr = cmd->nextInstr; - } + u16 *stat1 = GetBattlerStat(&gBattleMons[gBattlerAttacker], cmd->stat); + u16 *stat2 = GetBattlerStat(&gBattleMons[gBattlerTarget], cmd->stat); + u16 avg = (*stat1 + *stat2) / 2; + *stat1 = *stat2 = avg; + + gBattlescriptCurrInstr = cmd->nextInstr; } -static void HandleRoomMove(u32 statusFlag, u16 *timer, u8 stringId) +static void Cmd_jumpifcaptivateaffected(void) { - if (gFieldStatuses & statusFlag) + CMD_ARGS(const u8 *jumpInstr); + + if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) { - gFieldStatuses &= ~statusFlag; - gBattleCommunication[MULTISTRING_CHOOSER] = stringId + 1; + gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; + gLastUsedAbility = ABILITY_OBLIVIOUS; + RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); + } + else if (AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->jumpInstr; } else { - gFieldStatuses |= statusFlag; - *timer = gBattleTurnCounter + 5; - gBattleCommunication[MULTISTRING_CHOOSER] = stringId; + gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_setroom(void) +static void Cmd_setnonvolatilestatus(void) { - CMD_ARGS(); + CMD_ARGS(u8 trigger); + gBattlescriptCurrInstr = cmd->nextInstr - 1; - switch (GetMoveEffect(gCurrentMove)) + switch (cmd->trigger) { - case EFFECT_TRICK_ROOM: - HandleRoomMove(STATUS_FIELD_TRICK_ROOM, &gFieldTimers.trickRoomTimer, 0); - break; - case EFFECT_WONDER_ROOM: - HandleRoomMove(STATUS_FIELD_WONDER_ROOM, &gFieldTimers.wonderRoomTimer, 2); + case TRIGGER_ON_ABILITY: + if (gBattleScripting.moveEffect == MOVE_EFFECT_CONFUSION) + SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); + else + SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); break; - case EFFECT_MAGIC_ROOM: - HandleRoomMove(STATUS_FIELD_MAGIC_ROOM, &gFieldTimers.magicRoomTimer, 4); + case TRIGGER_ON_MOVE: + SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); break; - default: - gBattleCommunication[MULTISTRING_CHOOSER] = 6; + case TRIGGER_ON_PROTECT: + SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); break; } - gBattlescriptCurrInstr = cmd->nextInstr; } -// Skill Swap -static void Cmd_tryswapabilities(void) +static void Cmd_tryworryseed(void) { CMD_ARGS(const u8 *failInstr); - if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped - || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeSwapped) + if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten + || gBattleMons[gBattlerTarget].ability == ABILITY_INSOMNIA) { RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; @@ -14749,3393 +14607,3665 @@ static void Cmd_tryswapabilities(void) } else { - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) - gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; - gLastUsedAbility = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; - gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gLastUsedAbility; + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; + gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_tryimprison(void) +static void Cmd_callnative(void) { - CMD_ARGS(const u8 *failInstr); + CMD_ARGS(void (*func)(void)); + void (*func)(void) = cmd->func; + func(); +} - if ((gStatuses3[gBattlerAttacker] & STATUS3_IMPRISONED_OTHERS)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (B_IMPRISON >= GEN_5) - { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; - gBattlescriptCurrInstr = cmd->nextInstr; - } +// Callnative Funcs + +void SaveBattlerTarget(u32 battler) +{ + if (gBattleStruct->savedTargetCount < NELEMS(gBattleStruct->savedBattlerTarget)) + gBattleStruct->savedBattlerTarget[gBattleStruct->savedTargetCount++] = battler; else - { - u8 battler; + DebugPrintfLevel(MGBA_LOG_WARN, "Attempting to exceed savedBattlerTarget array size!"); +} - for (battler = 0; battler < gBattlersCount; battler++) - { - if (!IsBattlerAlly(gBattlerAttacker, battler)) - { - s32 attackerMoveId; - for (attackerMoveId = 0; attackerMoveId < MAX_MON_MOVES; attackerMoveId++) - { - s32 i; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[gBattlerAttacker].moves[attackerMoveId] == gBattleMons[battler].moves[i] - && gBattleMons[gBattlerAttacker].moves[attackerMoveId] != MOVE_NONE) - break; - } - if (i != MAX_MON_MOVES) - break; - } - if (attackerMoveId != MAX_MON_MOVES) - { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; - gBattlescriptCurrInstr = cmd->nextInstr; - break; - } - } - } - if (battler == gBattlersCount) // In Generation 3 games, Imprison fails if the user doesn't share any moves with any of the foes. - gBattlescriptCurrInstr = cmd->failInstr; - } +void SaveBattlerAttacker(u32 battler) +{ + if (gBattleStruct->savedAttackerCount < NELEMS(gBattleStruct->savedBattlerAttacker)) + gBattleStruct->savedBattlerAttacker[gBattleStruct->savedAttackerCount++] = battler; + else + DebugPrintfLevel(MGBA_LOG_WARN, "Attempting to exceed savedBattlerAttacker array size!"); } -static void Cmd_setstealthrock(void) +void BS_SaveTarget(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(); + SaveBattlerTarget(gBattlerTarget); + gBattlescriptCurrInstr = cmd->nextInstr; +} - u8 targetSide = GetBattlerSide(gBattlerTarget); - if (IsHazardOnSide(targetSide, HAZARDS_STEALTH_ROCK)) +void BS_RestoreTarget(void) +{ + NATIVE_ARGS(); + if (gBattleStruct->savedTargetCount > 0) { - gBattlescriptCurrInstr = cmd->failInstr; + gBattleStruct->savedTargetCount--; + gBattlerTarget = gBattleStruct->savedBattlerTarget[gBattleStruct->savedTargetCount]; } else { - PushHazardTypeToQueue(targetSide, HAZARDS_STEALTH_ROCK); - gBattlescriptCurrInstr = cmd->nextInstr; + // #if TESTING + // Test_ExitWithResult(TEST_RESULT_ERROR, "BS_RestoreTarget attempting to restore an empty target!"); + // #else + DebugPrintfLevel(MGBA_LOG_WARN, "BS_RestoreTarget attempting to restore an empty target!"); + // #endif } + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setuserstatus3(void) +void BS_SaveAttacker(void) { - CMD_ARGS(u32 flags, const u8 *failInstr); - - u32 flags = cmd->flags; + NATIVE_ARGS(); + SaveBattlerAttacker(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (gStatuses3[gBattlerAttacker] & flags) +void BS_RestoreAttacker(void) +{ + NATIVE_ARGS(); + if (gBattleStruct->savedAttackerCount > 0) { - gBattlescriptCurrInstr = cmd->failInstr; + gBattleStruct->savedAttackerCount--; + gBattlerAttacker = gBattleStruct->savedBattlerAttacker[gBattleStruct->savedAttackerCount]; } else { - gStatuses3[gBattlerAttacker] |= flags; - if (flags & STATUS3_MAGNET_RISE) - gDisableStructs[gBattlerAttacker].magnetRiseTimer = gBattleTurnCounter + 5; - if (flags & STATUS3_LASER_FOCUS) - gDisableStructs[gBattlerAttacker].laserFocusTimer = gBattleTurnCounter + 2; - gBattlescriptCurrInstr = cmd->nextInstr; + // #if TESTING + // Test_ExitWithResult(TEST_RESULT_ERROR, "BS_RestoreAttacker attempting to restore an empty attacker!"); + // #else + DebugPrintfLevel(MGBA_LOG_WARN, "BS_RestoreAttacker attempting to restore an empty attacker!"); + // #endif } + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_assistattackselect(void) +void BS_CalcMetalBurstDmg(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(const u8 *failInstr); - s32 chooseableMovesNo = 0; - struct Pokemon *party; - s32 monId, moveId; - u16 *validMoves = Alloc(sizeof(u16) * PARTY_SIZE * MAX_MON_MOVES); + u8 sideAttacker = GetBattlerSide(gBattlerAttacker); + u8 sideTarget = 0; - if (validMoves != NULL) + if (gProtectStructs[gBattlerAttacker].physicalDmg + && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId)) + && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - party = GetBattlerParty(gBattlerAttacker); - - for (monId = 0; monId < PARTY_SIZE; monId++) - { - if (monId == gBattlerPartyIndexes[gBattlerAttacker]) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) - continue; - - for (moveId = 0; moveId < MAX_MON_MOVES; moveId++) - { - u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId); + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; - if (IsMoveAssistBanned(move)) - continue; + if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) + gBattlerTarget = gSideTimers[sideTarget].followmeTarget; + else + gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; - validMoves[chooseableMovesNo++] = move; - } - } + gBattlescriptCurrInstr = cmd->nextInstr; } - - if (chooseableMovesNo) + else if (gProtectStructs[gBattlerAttacker].specialDmg + && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId)) + && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gCalledMove = validMoves[Random() % chooseableMovesNo]; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; + + if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) + gBattlerTarget = gSideTimers[sideTarget].followmeTarget; + else + gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + gBattlescriptCurrInstr = cmd->nextInstr; } else { gBattlescriptCurrInstr = cmd->failInstr; } - - TRY_FREE_AND_SET_NULL(validMoves); } -static void Cmd_trysetmagiccoat(void) +void BS_JumpIfCantFling(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn - { - gBattlescriptCurrInstr = cmd->failInstr; - } + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (!CanFling(battler)) + gBattlescriptCurrInstr = cmd->jumpInstr; else - { - gProtectStructs[gBattlerAttacker].bounceMove = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; - } } -// Snatch -static void Cmd_trysetsnatch(void) +void BS_JumpIfMoreThanHalfHP(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn - { - gBattlescriptCurrInstr = cmd->failInstr; - } + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (gBattleMons[battler].hp > (gBattleMons[battler].maxHP + 1) / 2) + gBattlescriptCurrInstr = cmd->jumpInstr; else - { - gProtectStructs[gBattlerAttacker].stealMove = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; - } } -static void Cmd_unused2(void) -{ -} - -static void Cmd_switchoutabilities(void) +void BS_DoStockpileStatChangesWearOff(void) { - CMD_ARGS(u8 battler); + NATIVE_ARGS(u8 battler, const u8 *statChangeInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS) + if (gDisableStructs[battler].stockpileDef != 0) { - gBattleMons[battler].ability = ABILITY_NONE; - BattleScriptPush(gBattlescriptCurrInstr); - gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + SET_STATCHANGER(STAT_DEF, abs(gDisableStructs[battler].stockpileDef), TRUE); + gDisableStructs[battler].stockpileDef = 0; + BattleScriptCall(cmd->statChangeInstr); + } + else if (gDisableStructs[battler].stockpileSpDef) + { + SET_STATCHANGER(STAT_SPDEF, abs(gDisableStructs[battler].stockpileSpDef), TRUE); + gDisableStructs[battler].stockpileSpDef = 0; + BattleScriptCall(cmd->statChangeInstr); } else { - switch (GetBattlerAbility(battler)) - { - case ABILITY_NATURAL_CURE: - if (gBattleMons[battler].status1 & STATUS1_SLEEP) - TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - - gBattleMons[battler].status1 = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, - 1u << gBattleStruct->battlerPartyIndexes[battler], - sizeof(gBattleMons[battler].status1), - &gBattleMons[battler].status1); - MarkBattlerForControllerExec(battler); - break; - case ABILITY_REGENERATOR: - { - u32 regenerate = GetNonDynamaxMaxHP(battler) / 3; - regenerate += gBattleMons[battler].hp; - if (regenerate > gBattleMons[battler].maxHP) - regenerate = gBattleMons[battler].maxHP; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, - 1u << gBattleStruct->battlerPartyIndexes[battler], - sizeof(regenerate), - ®enerate); - MarkBattlerForControllerExec(battler); - break; - } - } - gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_jumpifhasnohp(void) +static bool32 CriticalCapture(u32 odds) { - CMD_ARGS(u8 battler, const u8 *jumpInstr); + u32 numCaught; + u32 totalDexCount; - u32 battler = GetBattlerForBattleScript(cmd->battler); + if (B_CRITICAL_CAPTURE == FALSE) + return FALSE; - if (!IsBattlerAlive(battler)) - gBattlescriptCurrInstr = cmd->jumpInstr; + if (B_CRITICAL_CAPTURE_LOCAL_DEX == TRUE) + totalDexCount = HOENN_DEX_COUNT; else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -static void Cmd_jumpifnotcurrentmoveargtype(void) -{ - CMD_ARGS(u8 battler, const u8 *failInstr); + totalDexCount = NATIONAL_DEX_COUNT; - u8 battler = GetBattlerForBattleScript(cmd->battler); - const u8 *failInstr = cmd->failInstr; - u32 type = GetMoveArgType(gCurrentMove); + numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); - if (!IS_BATTLER_OF_TYPE(battler, type)) - gBattlescriptCurrInstr = failInstr; + if (numCaught <= (totalDexCount * 30) / 650) + odds = 0; + else if (numCaught <= (totalDexCount * 150) / 650) + odds /= 2; + else if (numCaught <= (totalDexCount * 300) / 650) + ; // odds = (odds * 100) / 100; + else if (numCaught <= (totalDexCount * 450) / 650) + odds = (odds * 150) / 100; + else if (numCaught <= (totalDexCount * 600) / 650) + odds *= 2; else - gBattlescriptCurrInstr = cmd->nextInstr; + odds = (odds * 250) / 100; + + if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1)) + odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100; + + odds /= 6; + + if ((Random() % 255) < odds) + return TRUE; + + return FALSE; } -static void Cmd_pickup(void) +bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) { - CMD_ARGS(); + if (move != MOVE_NONE && move != MOVE_UNAVAILABLE && move != MOVE_STRUGGLE + && !IsMoveParentalBondBanned(move) + && GetMoveCategory(move) != DAMAGE_CATEGORY_STATUS + && GetMoveStrikeCount(move) < 2 + && GetMoveEffect(move) != EFFECT_SEMI_INVULNERABLE + && GetMoveEffect(move) != EFFECT_TWO_TURNS_ATTACK + && GetMoveEffect(move) != EFFECT_MULTI_HIT) + { + if (IsDoubleBattle()) + { + switch (GetBattlerMoveTargetType(battler, move)) + { + // Both foes are alive, spread move strikes once + case MOVE_TARGET_BOTH: + if (CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) >= 2) + return FALSE; + break; + // Either both foes or one foe and its ally are alive; spread move strikes once + case MOVE_TARGET_FOES_AND_ALLY: + if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker) >= 2) + return FALSE; + break; + default: + break; + } + } + return TRUE; + } + return FALSE; +} - u32 i, j; - u16 species, heldItem, ability; - u8 lvlDivBy10; +static bool8 IsFinalStrikeEffect(enum BattleMoveEffects moveEffect) +{ + u32 i; - if (!InBattlePike()) // No items in Battle Pike. + for (i = 0; i < ARRAY_COUNT(sFinalStrikeOnlyEffects); i++) { - bool32 isInPyramid = InBattlePyramid_(); - for (i = 0; i < PARTY_SIZE; i++) - { - species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG); - heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); - lvlDivBy10 = (GetMonData(&gPlayerParty[i], MON_DATA_LEVEL)-1) / 10; //Moving this here makes it easier to add in abilities like Honey Gather. - if (lvlDivBy10 > 9) - lvlDivBy10 = 9; + if (moveEffect == sFinalStrikeOnlyEffects[i]) + return TRUE; + } + return FALSE; +} - ability = GetSpeciesAbility(species, GetMonData(&gPlayerParty[i], MON_DATA_ABILITY_NUM)); +static bool32 CanAbilityPreventStatLoss(u32 abilityDef) +{ + switch (abilityDef) + { + case ABILITY_CLEAR_BODY: + case ABILITY_FULL_METAL_BODY: + case ABILITY_WHITE_SMOKE: + return TRUE; + } + return FALSE; +} - if (ability == ABILITY_PICKUP - && species != SPECIES_NONE - && species != SPECIES_EGG - && heldItem == ITEM_NONE - && (Random() % 10) == 0) - { - if (isInPyramid) - { - heldItem = GetBattlePyramidPickupItemId(); - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); - } - else - { - u32 rand = Random() % 100; - u32 percentTotal = 0; +bool32 CanBurnHitThaw(u16 move) +{ + u8 i; - for (j = 0; j < ARRAY_COUNT(sPickupTable); j++) - { - percentTotal += sPickupTable[j].percentage[lvlDivBy10]; - if (rand < percentTotal) - { - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sPickupTable[j].itemId); - break; - } - } - } - } - else if (ability == ABILITY_HONEY_GATHER - && species != 0 - && species != SPECIES_EGG - && heldItem == ITEM_NONE) - { - if ((lvlDivBy10 + 1 ) * 5 > Random() % 100) - { - heldItem = ITEM_HONEY; - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); - } - } - else if (P_SHUCKLE_BERRY_JUICE == GEN_2 - && species == SPECIES_SHUCKLE - && heldItem == ITEM_ORAN_BERRY - && (Random() % 16) == 0) - { - heldItem = ITEM_BERRY_JUICE; - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem); - } + if (B_BURN_HIT_THAW >= GEN_6) + { + u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move); + for (i = 0; i < numAdditionalEffects; i++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + if (additionalEffect->moveEffect == MOVE_EFFECT_BURN) + return TRUE; } } + return FALSE; +} - gBattlescriptCurrInstr = cmd->nextInstr; +void BS_CheckParentalBondCounter(void) +{ + NATIVE_ARGS(u8 counter, const u8 *jumpInstr); + // Some effects should only happen on the first or second strike of Parental Bond, + // so a way to check this in battle scripts is useful + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == cmd->counter && IsBattlerAlive(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_unused_0xE6(void) +void BS_JumpIfCantLoseItem(void) { + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u8 battler = GetBattlerForBattleScript(cmd->battler); + u16 item = gBattleMons[battler].item; + + if (item == ITEM_NONE || !CanBattlerGetOrLoseItem(battler, item)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_unused_0xE7(void) +void BS_GetBattlerSide(void) { + NATIVE_ARGS(u8 battler); + gBattleCommunication[0] = GetBattlerSide(GetBattlerForBattleScript(cmd->battler)); + gBattlescriptCurrInstr = cmd->nextInstr; } -// Water and Mud Sport -static void Cmd_settypebasedhalvers(void) +void BS_TrySymbiosis(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + //called by Bestow, Fling, and Bug Bite, which don't work with Cmd_removeitem. + u32 partner = BATTLE_PARTNER(battler); + if (TryTriggerSymbiosis(battler, partner)) + { + BestowItem(partner, battler); + gLastUsedAbility = gBattleMons[partner].ability; + gBattleScripting.battler = gBattlerAbility = partner; + gEffectBattler = battler; + BattleScriptCall(BattleScript_SymbiosisActivates); + return; + } - bool8 worked = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (GetMoveEffect(gCurrentMove) == EFFECT_MUD_SPORT) +void BS_SetZEffect(void) +{ + SetZEffect(); // Handles battle script jumping internally +} + +static void TryUpdateRoundTurnOrder(void) +{ + if (IsDoubleBattle()) { - if (B_SPORT_TURNS >= GEN_6) + u32 i; + u32 j = 0; + u32 k = 0; + u32 currRounder = 0; + u8 roundUsers[3] = {0xFF, 0xFF, 0xFF}; + u8 nonRoundUsers[3] = {0xFF, 0xFF, 0xFF}; + for (i = 0; i < gBattlersCount; i++) { - if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT)) + if (gBattlerByTurnOrder[i] == gBattlerAttacker) { - gFieldStatuses |= STATUS_FIELD_MUDSPORT; - gFieldTimers.mudSportTimer = gBattleTurnCounter + 5; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; - worked = TRUE; + currRounder = i + 1; // Current battler going after attacker + break; } } - else + + // Get battlers after attacker using round + for (i = currRounder; i < gBattlersCount; i++) { - if (!gBattleMons[gBattlerAttacker].volatiles.waterSport) - { - gBattleMons[gBattlerAttacker].volatiles.waterSport = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; - worked = TRUE; - } + if (gChosenMoveByBattler[gBattlerByTurnOrder[i]] == MOVE_ROUND) + roundUsers[j++] = gBattlerByTurnOrder[i]; + else + nonRoundUsers[k++] = gBattlerByTurnOrder[i]; + } + + // update turn order for round users + for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) + { + gBattlerByTurnOrder[currRounder] = roundUsers[i]; + gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again + currRounder++; + } + + // Update turn order for non-round users + for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) + { + gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; + currRounder++; } } - else // Water Sport +} + +u8 GetFirstFaintedPartyIndex(u8 battler) +{ + u32 i; + u32 start = 0; + u32 end = PARTY_SIZE; + struct Pokemon *party = GetBattlerParty(battler); + + // Check whether partner is separate trainer. + if ((IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + || (!IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) { - if (B_SPORT_TURNS >= GEN_6) + if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT + || GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) { - if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT)) - { - gFieldStatuses |= STATUS_FIELD_WATERSPORT; - gFieldTimers.waterSportTimer = gBattleTurnCounter + 5; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; - worked = TRUE; - } + end = PARTY_SIZE / 2; } else { - if (!gBattleMons[gBattlerAttacker].volatiles.mudSport) - { - gBattleMons[gBattlerAttacker].volatiles.mudSport = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; - worked = TRUE; - } + start = PARTY_SIZE / 2; } } - if (worked) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->failInstr; -} + // Loop through to find fainted battler. + for (i = start; i < end; ++i) + { + u32 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(&party[i], MON_DATA_HP) == 0) + { + return i; + } + } -bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) -{ - if (!gBattleMons[battlerDef].volatiles.substitute) - return FALSE; - else if (MoveIgnoresSubstitute(move)) - return FALSE; - else if (IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_INFILTRATOR)) - return FALSE; - else - return TRUE; + // Returns PARTY_SIZE if none found. + return PARTY_SIZE; } -bool32 DoesDisguiseBlockMove(u32 battler, u32 move) +void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler) { - if (!(gBattleMons[battler].species == SPECIES_MIMIKYU_DISGUISED || gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) - || gBattleMons[battler].volatiles.transformed - || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE)) - || gHitMarker & HITMARKER_IGNORE_DISGUISE - || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) - return FALSE; - else - return TRUE; + enum ItemHoldEffect holdEffect = GetMonHoldEffect(&gPlayerParty[expGetterMonId]); + + if (IsTradedMon(&gPlayerParty[expGetterMonId])) + *expAmount = (*expAmount * 150) / 100; + if (holdEffect == HOLD_EFFECT_LUCKY_EGG) + *expAmount = (*expAmount * 150) / 100; + if (B_UNEVOLVED_EXP_MULTIPLIER >= GEN_6 && IsMonPastEvolutionLevel(&gPlayerParty[expGetterMonId])) + *expAmount = (*expAmount * 4915) / 4096; + if (B_AFFECTION_MECHANICS == TRUE && GetMonAffectionHearts(&gPlayerParty[expGetterMonId]) >= AFFECTION_FOUR_HEARTS) + *expAmount = (*expAmount * 4915) / 4096; + if (CheckBagHasItem(ITEM_EXP_CHARM, 1)) //is also for other exp boosting Powers if/when implemented + *expAmount = (*expAmount * 150) / 100; + + if (B_SCALED_EXP >= GEN_5 && B_SCALED_EXP != GEN_6) + { + // Note: There is an edge case where if a pokemon receives a large amount of exp, it wouldn't be properly calculated + // because of multiplying by scaling factor(the value would simply be larger than an u32 can hold). Hence u64 is needed. + u64 value = *expAmount; + u8 faintedLevel = gBattleMons[faintedBattler].level; + u8 expGetterLevel = GetMonData(&gPlayerParty[expGetterMonId], MON_DATA_LEVEL); + + value *= sExperienceScalingFactors[(faintedLevel * 2) + 10]; + value /= sExperienceScalingFactors[faintedLevel + expGetterLevel + 10]; + + *expAmount = value + 1; + } } -static void Cmd_jumpifsubstituteblocks(void) +void BS_ItemRestoreHP(void) { - CMD_ARGS(const u8 *jumpInstr); + NATIVE_ARGS(const u8 *alreadyMaxHpInstr, const u8 *restoreBattlerInstr); + u16 healAmount; + u32 battler = MAX_BATTLERS_COUNT; + u32 healParam = GetItemEffect(gLastUsedItem)[6]; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP); + u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP); + gBattleCommunication[MULTIUSE_STATE] = 0; - if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - gBattlescriptCurrInstr = cmd->jumpInstr; + if (hp == maxHP) + { + gBattlescriptCurrInstr = cmd->alreadyMaxHpInstr; + } else - gBattlescriptCurrInstr = cmd->nextInstr; + { + // Track the number of Revives used in a battle. + if (hp == 0 && IsOnPlayerSide(gBattlerAttacker) && gBattleResults.numRevivesUsed < 255) + gBattleResults.numRevivesUsed++; + + // Check if the recipient is an active battler. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + battler = gBattlerAttacker; + else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + battler = BATTLE_PARTNER(gBattlerAttacker); + + // Get amount to heal. + switch (healParam) + { + case ITEM6_HEAL_HP_FULL: + healAmount = maxHP; + break; + case ITEM6_HEAL_HP_HALF: + healAmount = maxHP / 2; + break; + case ITEM6_HEAL_HP_QUARTER: + healAmount = maxHP / 4; + break; + default: + healAmount = healParam; + break; + } + if (hp + healAmount > maxHP) + healAmount = maxHP - hp; + + gBattleScripting.battler = battler; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + + // Heal is applied as move damage if battler is active. + if (battler != MAX_BATTLERS_COUNT && hp != 0) + { + gBattleStruct->moveDamage[battler] = -healAmount; + gBattlescriptCurrInstr = cmd->restoreBattlerInstr; + } + else + { + hp += healAmount; + SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp); + + // Revived battlers on the field need to be brought back. + if (IsDoubleBattle() && battler != MAX_BATTLERS_COUNT) + { + gAbsentBattlerFlags &= ~(1u << battler); + gBattleMons[battler].hp = hp; + gBattleCommunication[MULTIUSE_STATE] = TRUE; + } + gBattlescriptCurrInstr = cmd->nextInstr; + } + } } -static void Cmd_tryrecycleitem(void) +void BS_ItemCureStatus(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(const u8 *noStatusInstr); + u32 battler = gBattlerAttacker; + bool32 statusChanged = FALSE; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - u16 *usedHeldItem; + // Heal volatile conditions if battler is active. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + statusChanged = ItemHealMonVolatile(battler, gLastUsedItem); + else if (IsDoubleBattle() + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem); - if (gCurrentMove == MOVE_NONE && GetBattlerAbility(gBattlerAttacker) == ABILITY_PICKUP) - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; - else - usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerAttacker]][GetBattlerSide(gBattlerAttacker)]; - if (*usedHeldItem != ITEM_NONE && gBattleMons[gBattlerAttacker].item == ITEM_NONE) + // Heal Status1 conditions. + if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler)) { - gLastUsedItem = *usedHeldItem; - *usedHeldItem = ITEM_NONE; - gBattleMons[gBattlerAttacker].item = gLastUsedItem; - - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].item), &gBattleMons[gBattlerAttacker].item); - MarkBattlerForControllerExec(gBattlerAttacker); + statusChanged = TRUE; + if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) + gBattleMons[battler].volatiles.nightmare = FALSE; + if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) + gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + } + if (statusChanged) + { + gBattleScripting.battler = battler; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = cmd->noStatusInstr; } } -bool32 CanCamouflage(u8 battler) +void BS_ItemIncreaseStat(void) { - if (IS_BATTLER_OF_TYPE(battler, gBattleEnvironmentInfo[gBattleEnvironment].camouflageType)) - return FALSE; - return TRUE; + NATIVE_ARGS(); + u16 statId = GetItemEffect(gLastUsedItem)[1]; + u16 stages = GetItemHoldEffectParam(gLastUsedItem); + SET_STATCHANGER(statId, stages, FALSE); + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_settypetoenvironment(void) +void BS_ItemRestorePP(void) { - CMD_ARGS(const u8 *failInstr); - - u8 environmentType; - switch(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) - { - case STATUS_FIELD_ELECTRIC_TERRAIN: - environmentType = TYPE_ELECTRIC; - break; - case STATUS_FIELD_GRASSY_TERRAIN: - environmentType = TYPE_GRASS; - break; - case STATUS_FIELD_MISTY_TERRAIN: - environmentType = TYPE_FAIRY; - break; - case STATUS_FIELD_PSYCHIC_TERRAIN: - environmentType = TYPE_PSYCHIC; - break; - default: - environmentType = gBattleEnvironmentInfo[gBattleEnvironment].camouflageType; - break; - } + NATIVE_ARGS(); + const u8 *effect = GetItemEffect(gLastUsedItem); + u32 i, pp, maxPP, moveId, loopEnd; + u32 battler = MAX_BATTLERS_COUNT; + struct Pokemon *mon = (IsOnPlayerSide(gBattlerAttacker)) ? &gPlayerParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]] : &gEnemyParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]]; - if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, environmentType) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_TERA) + // Check whether to apply to all moves. + if (effect[4] & ITEM4_HEAL_PP_ONE) { - SET_BATTLER_TYPE(gBattlerAttacker, environmentType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, environmentType); - - gBattlescriptCurrInstr = cmd->nextInstr; + i = gBattleStruct->itemMoveIndex[gBattlerAttacker]; + loopEnd = i + 1; } else { - gBattlescriptCurrInstr = cmd->failInstr; + i = 0; + loopEnd = MAX_MON_MOVES; } -} - -// Unused -static void Cmd_pursuitdoubles(void) -{ - CMD_ARGS(const u8 *failInstr); - u32 battler = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker))); + // Check if the recipient is an active battler. + if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) + battler = gBattlerAttacker; + else if (IsDoubleBattle() + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) + battler = BATTLE_PARTNER(gBattlerAttacker); - if (IsDoubleBattle() - && !(gAbsentBattlerFlags & (1u << battler)) - && gChosenActionByBattler[battler] == B_ACTION_USE_MOVE - && GetMoveEffect(gChosenMoveByBattler[battler]) == EFFECT_PURSUIT) + // Heal PP! + for (; i < loopEnd; i++) { - gActionsByTurnOrder[battler] = B_ACTION_TRY_FINISH; - gCurrentMove = gChosenMoveByBattler[battler]; - gBattlescriptCurrInstr = cmd->nextInstr; - gBattleScripting.animTurn = 1; - gBattleScripting.savedBattler = gBattlerAttacker; - gBattlerAttacker = battler; + pp = GetMonData(mon, MON_DATA_PP1 + i, NULL); + moveId = GetMonData(mon, MON_DATA_MOVE1 + i, NULL); + maxPP = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), i); + if (pp != maxPP) + { + pp += effect[6]; + if (pp > maxPP) + pp = maxPP; + SetMonData(mon, MON_DATA_PP1 + i, &pp); + + // Update battler PP if needed. + if (battler != MAX_BATTLERS_COUNT + && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[battler] + && MOVE_IS_PERMANENT(battler, i)) + { + gBattleMons[battler].pp[i] = pp; + } + } } - else + gBattleScripting.battler = battler; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES)); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryRevertWeatherForm(void) +{ + NATIVE_ARGS(); + if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_WEATHER)) { - gBattlescriptCurrInstr = cmd->failInstr; + gBattleScripting.battler = gBattlerTarget; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_TargetFormChangeWithStringNoPopup; + return; } + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_snatchsetbattlers(void) +void BS_HandleMegaEvolution(void) { - CMD_ARGS(); + NATIVE_ARGS(u8 battler, u8 caseId); - gEffectBattler = gBattlerAttacker; + u8 battler = GetBattlerForBattleScript(cmd->battler); + HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_MEGA_EVOLUTION); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (gBattlerAttacker == gBattlerTarget) - gBattlerAttacker = gBattlerTarget = gBattleScripting.battler; - else - gBattlerTarget = gBattleScripting.battler; +void BS_HandlePrimalReversion(void) +{ + NATIVE_ARGS(u8 battler, u8 caseId); - gBattleScripting.battler = gEffectBattler; + u8 battler = GetBattlerForBattleScript(cmd->battler); + HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_PRIMAL_REVERSION); gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_removescreens(void) +void BS_HandleUltraBurst(void) { - CMD_ARGS(); + NATIVE_ARGS(u8 battler, u8 caseId); - u8 side; - bool32 failed; + u8 battler = GetBattlerForBattleScript(cmd->battler); + HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_ULTRA_BURST); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (B_BRICK_BREAK >= GEN_4) - side = GetBattlerSide(gBattlerTarget); // From Gen 4 onwards, Brick Break can remove screens on the user's side if used on an ally - else - side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; +void BS_JumpIfShellTrap(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - if (B_BRICK_BREAK >= GEN_5) - failed = gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT; + u8 battler = GetBattlerForBattleScript(cmd->battler); + if (gProtectStructs[battler].shellTrap) + gBattlescriptCurrInstr = cmd->jumpInstr; else - failed = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (!failed && gSideStatuses[side] & SIDE_STATUS_SCREEN_ANY) - { - gSideStatuses[side] &= ~SIDE_STATUS_SCREEN_ANY; - gBattleScripting.animTurn = 1; - gBattleScripting.animTargetsHit = 1; - } +void BS_JumpIfElectricAbilityAffected(void) +{ + NATIVE_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (IsElectricAbilityAffected(battler, cmd->ability)) + gBattlescriptCurrInstr = cmd->jumpInstr; else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ApplySaltCure(void) +{ + NATIVE_ARGS(u8 battler); + + u8 battler = GetBattlerForBattleScript(cmd->battler); + gStatuses4[battler] |= STATUS4_SALT_CURE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SetTerrain(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + u32 statusFlag = 0; + + switch (GetMoveEffect(gCurrentMove)) { - gBattleScripting.animTurn = 0; - gBattleScripting.animTargetsHit = 0; + case EFFECT_MISTY_TERRAIN: + statusFlag = STATUS_FIELD_MISTY_TERRAIN; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; + break; + case EFFECT_GRASSY_TERRAIN: + statusFlag = STATUS_FIELD_GRASSY_TERRAIN; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY; + break; + case EFFECT_ELECTRIC_TERRAIN: + statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; + break; + case EFFECT_PSYCHIC_TERRAIN: + statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; + break; + case EFFECT_HIT_SET_TERRAIN: + statusFlag = GetMoveTerrainFlag(gCurrentMove); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; + break; + default: + break; } + enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; + gFieldStatuses |= statusFlag; + gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; gBattlescriptCurrInstr = cmd->nextInstr; } -u8 GetCatchingBattler(void) +void BS_JumpIfTerrainAffected(void) { - if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))) - return GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (IsBattlerTerrainAffected(battler, cmd->flags)) + gBattlescriptCurrInstr = cmd->jumpInstr; else - return GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_handleballthrow(void) +void BS_TryReflectType(void) { - CMD_ARGS(); - - u16 ballMultiplier = 100; - s8 ballAddition = 0; - - if (gBattleControllerExecFlags) - return; - - gBattlerTarget = GetCatchingBattler(); + NATIVE_ARGS(const u8 *failInstr); + u16 targetBaseSpecies = GET_BASE_SPECIES_ID(gBattleMons[gBattlerTarget].species); + u32 targetTypes[3]; + GetBattlerTypes(gBattlerTarget, FALSE, targetTypes); - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + if (targetBaseSpecies == SPECIES_ARCEUS || targetBaseSpecies == SPECIES_SILVALLY) { - BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_TRAINER_BLOCK); - MarkBattlerForControllerExec(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_TrainerBallBlock; + gBattlescriptCurrInstr = cmd->failInstr; } - else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) + else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) { - BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS); - MarkBattlerForControllerExec(gBattlerAttacker); - gBattlescriptCurrInstr = BattleScript_WallyBallThrow; + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (IS_BATTLER_TYPELESS(gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (targetTypes[0] == TYPE_MYSTERY && targetTypes[1] == TYPE_MYSTERY && targetTypes[2] != TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].types[0] = TYPE_NORMAL; + gBattleMons[gBattlerAttacker].types[1] = TYPE_NORMAL; + gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else if (targetTypes[0] == TYPE_MYSTERY && targetTypes[1] != TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].types[0] = targetTypes[1]; + gBattleMons[gBattlerAttacker].types[1] = targetTypes[1]; + gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else if (targetTypes[0] != TYPE_MYSTERY && targetTypes[1] == TYPE_MYSTERY) + { + gBattleMons[gBattlerAttacker].types[0] = targetTypes[0]; + gBattleMons[gBattlerAttacker].types[1] = targetTypes[0]; + gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - u32 odds, i; - u32 catchRate; - u32 ballId = ItemIdToBallId(gLastUsedItem); - - gBallToDisplay = gLastThrownBall = gLastUsedItem; - if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) - catchRate = gBattleStruct->safariCatchFactor * 1275 / 100; - else - catchRate = gSpeciesInfo[gBattleMons[gBattlerTarget].species].catchRate; + gBattleMons[gBattlerAttacker].types[0] = targetTypes[0]; + gBattleMons[gBattlerAttacker].types[1] = targetTypes[1]; + gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} - if (gSpeciesInfo[gBattleMons[gBattlerTarget].species].isUltraBeast) - { - if (ballId == BALL_BEAST) - ballMultiplier = 500; - else - ballMultiplier = 10; - } - else - { - switch (ballId) - { - case BALL_ULTRA: - ballMultiplier = 200; - break; - case BALL_SPORT: - if (B_SPORT_BALL_MODIFIER <= GEN_7) - ballMultiplier = 150; - break; - case BALL_GREAT: - ballMultiplier = 150; - break; - case BALL_SAFARI: - if (B_SAFARI_BALL_MODIFIER <= GEN_7) - ballMultiplier = 150; - break; - case BALL_NET: - if (IS_BATTLER_ANY_TYPE(gBattlerTarget, TYPE_WATER, TYPE_BUG)) - ballMultiplier = B_NET_BALL_MODIFIER >= GEN_7 ? 350 : 300; - break; - case BALL_DIVE: - if (GetCurrentMapType() == MAP_TYPE_UNDERWATER - || (B_DIVE_BALL_MODIFIER >= GEN_4 && (gIsFishingEncounter || gIsSurfingEncounter))) - ballMultiplier = 350; - break; - case BALL_NEST: - if (B_NEST_BALL_MODIFIER >= GEN_6) - { - //((41 - Pokémon's level) ÷ 10)× if Pokémon's level is between 1 and 29, 1× otherwise. - if (gBattleMons[gBattlerTarget].level < 30) - ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10); - } - else if (B_NEST_BALL_MODIFIER >= GEN_5) - { - //((41 - Pokémon's level) ÷ 10)×, minimum 1× - if (gBattleMons[gBattlerTarget].level < 31) - ballMultiplier = 410 - (gBattleMons[gBattlerTarget].level * 10); - } - else if (gBattleMons[gBattlerTarget].level < 40) - { - //((40 - Pokémon's level) ÷ 10)×, minimum 1× - ballMultiplier = 400 - (gBattleMons[gBattlerTarget].level * 10); - if (ballMultiplier <= 90) - ballMultiplier = 100; - } - break; - case BALL_REPEAT: - if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT)) - ballMultiplier = (B_REPEAT_BALL_MODIFIER >= GEN_7 ? 350 : 300); - break; - case BALL_TIMER: - ballMultiplier = 100 + (gBattleResults.battleTurnCounter * (B_TIMER_BALL_MODIFIER >= GEN_5 ? 30 : 10)); - if (ballMultiplier > 400) - ballMultiplier = 400; - break; - case BALL_DUSK: - i = GetTimeOfDay(); - if (i == TIME_EVENING || i == TIME_NIGHT || gMapHeader.cave || gMapHeader.mapType == MAP_TYPE_UNDERGROUND) - ballMultiplier = (B_DUSK_BALL_MODIFIER >= GEN_7 ? 300 : 350); - break; - case BALL_QUICK: - if (gBattleResults.battleTurnCounter == 0) - ballMultiplier = (B_QUICK_BALL_MODIFIER >= GEN_5 ? 500 : 400); - break; - case BALL_LEVEL: - if (gBattleMons[gBattlerAttacker].level >= 4 * gBattleMons[gBattlerTarget].level) - ballMultiplier = 800; - else if (gBattleMons[gBattlerAttacker].level > 2 * gBattleMons[gBattlerTarget].level) - ballMultiplier = 400; - else if (gBattleMons[gBattlerAttacker].level > gBattleMons[gBattlerTarget].level) - ballMultiplier = 200; - break; - case BALL_LURE: - if (gIsFishingEncounter) - { - if (B_LURE_BALL_MODIFIER >= GEN_8) - ballMultiplier = 400; - else if (B_LURE_BALL_MODIFIER >= GEN_7) - ballMultiplier = 500; - else - ballMultiplier = 300; - } - break; - case BALL_MOON: - { - const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerTarget].species); - if (evolutions == NULL) - break; - for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) - { - if (evolutions[i].method == EVO_ITEM - && evolutions[i].param == ITEM_MOON_STONE) - ballMultiplier = 400; - } - } - break; - case BALL_LOVE: - if (gBattleMons[gBattlerTarget].species == gBattleMons[gBattlerAttacker].species) - { - u8 gender1 = GetMonGender(GetBattlerMon(gBattlerTarget)); - u8 gender2 = GetMonGender(GetBattlerMon(gBattlerAttacker)); +void BS_TrySetOctolock(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gender1 != gender2 && gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS) - ballMultiplier = 800; - } - break; - case BALL_FAST: - if (GetSpeciesBaseSpeed(gBattleMons[gBattlerTarget].species) >= 100) - ballMultiplier = 400; - break; - case BALL_HEAVY: - i = GetSpeciesWeight(gBattleMons[gBattlerTarget].species); - if (B_HEAVY_BALL_MODIFIER >= GEN_7) - { - if (i < 1000) - ballAddition = -20; - else if (i < 2000) - ballAddition = 0; - else if (i < 3000) - ballAddition = 20; - else - ballAddition = 30; - } - else if (B_HEAVY_BALL_MODIFIER >= GEN_4) - { - if (i < 2048) - ballAddition = -20; - else if (i < 3072) - ballAddition = 20; - else if (i < 4096) - ballAddition = 30; - else - ballAddition = 40; - } - else - { - if (i < 1024) - ballAddition = -20; - else if (i < 2048) - ballAddition = 0; - else if (i < 3072) - ballAddition = 20; - else if (i < 4096) - ballAddition = 30; - else - ballAddition = 40; - } - break; - case BALL_DREAM: - if (B_DREAM_BALL_MODIFIER >= GEN_8 && (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP || GetBattlerAbility(gBattlerTarget) == ABILITY_COMATOSE)) - ballMultiplier = 400; - break; - case BALL_BEAST: - ballMultiplier = 10; - break; - } - } + if (gDisableStructs[battler].octolock) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gDisableStructs[battler].octolock = TRUE; + gBattleMons[battler].volatiles.escapePrevention = TRUE; + gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; + gBattlescriptCurrInstr = cmd->nextInstr; + } +} - // catchRate is unsigned, which means that it may potentially overflow if sum is applied directly. - if (catchRate < 21 && ballAddition == -20) - catchRate = 1; - else - catchRate = catchRate + ballAddition; +void BS_SetGlaiveRush(void) +{ + NATIVE_ARGS(); + gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH; + gBattlescriptCurrInstr = cmd->nextInstr; +} - odds = (catchRate * ballMultiplier / 100) - * (gBattleMons[gBattlerTarget].maxHP * 3 - gBattleMons[gBattlerTarget].hp * 2) - / (3 * gBattleMons[gBattlerTarget].maxHP); +void BS_SetPledge(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); - if (gBattleMons[gBattlerTarget].status1 & STATUS1_INCAPACITATED) - odds *= 2; - if (gBattleMons[gBattlerTarget].status1 & STATUS1_CAN_MOVE) - odds = (odds * 15) / 10; + u32 partner = BATTLE_PARTNER(gBattlerAttacker); + u32 partnerMove = gBattleMons[partner].moves[gBattleStruct->chosenMovePositions[partner]]; + u32 i = 0; + u32 k = 0; - if (gBattleResults.catchAttempts[ballId] < 255) - gBattleResults.catchAttempts[ballId]++; + if (gBattleStruct->pledgeMove && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)) + { + PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); + gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - if (odds > 254) // mon caught + if ((gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_WATER_PLEDGE) + || (gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)) { - BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, BALL_3_SHAKES_SUCCESS); - MarkBattlerForControllerExec(gBattlerAttacker); - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); - gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; - struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); - SetMonData(caughtMon, MON_DATA_POKEBALL, &ballId); + gCurrentMove = MOVE_GRASS_PLEDGE; + gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Grass; + } + else if ((gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE) + || (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE)) + { + gCurrentMove = MOVE_FIRE_PLEDGE; + gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Fire; + } + else if ((gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE) + || (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_WATER_PLEDGE)) + { + gCurrentMove = MOVE_WATER_PLEDGE; + gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Water; + } - if (CalculatePlayerPartyCount() == PARTY_SIZE) - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - else - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleCommunication[MSG_DISPLAY] = 0; + } + else if ((gChosenActionByBattler[partner] == B_ACTION_USE_MOVE) + && IsDoubleBattle() + && IsBattlerAlive(partner) + && GetBattlerTurnOrderNum(gBattlerAttacker) < GetBattlerTurnOrderNum(partner) + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && gCurrentMove != partnerMove + && GetMoveEffect(partnerMove) == EFFECT_PLEDGE) + { + u32 currPledgeUser = 0; + u32 newTurnOrder[] = {0xFF, 0xFF}; - if (ballId == BALL_HEAL) + for (i = 0; i < gBattlersCount; i++) + { + if (gBattlerByTurnOrder[i] == gBattlerAttacker) { - MonRestorePP(caughtMon); - HealStatusConditions(caughtMon, STATUS1_ANY, gBattlerTarget); - gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; - SetMonData(caughtMon, MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); + currPledgeUser = i + 1; // Current battler going after attacker + break; } - else if (ballId == BALL_FRIEND) + } + for (i = currPledgeUser; i < gBattlersCount; i++) + { + if (gBattlerByTurnOrder[i] != partner) { - u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); - SetMonData(caughtMon, MON_DATA_FRIENDSHIP, &friendship); + newTurnOrder[k] = gBattlerByTurnOrder[i]; + k++; } } - else // mon may be caught, calculate shakes + + gBattlerByTurnOrder[currPledgeUser] = partner; + currPledgeUser++; + + for (i = 0; newTurnOrder[i] != 0xFF && i < 2; i++) { - u8 shakes; - u8 maxShakes; + gBattlerByTurnOrder[currPledgeUser] = newTurnOrder[i]; + currPledgeUser++; + } - gBattleSpritesDataPtr->animationData->isCriticalCapture = FALSE; - gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = FALSE; + gBattleStruct->pledgeMove = TRUE; + gBattleScripting.battler = partner; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattleStruct->pledgeMove = FALSE; + gBattlescriptCurrInstr = cmd->jumpInstr; + } +} - if (CriticalCapture(odds)) - { - maxShakes = BALL_1_SHAKE; // critical capture doesn't guarantee capture - gBattleSpritesDataPtr->animationData->isCriticalCapture = TRUE; - } - else - { - maxShakes = BALL_3_SHAKES_SUCCESS; - } +void BS_SetPledgeStatus(void) +{ + NATIVE_ARGS(u8 battler, u32 sideStatus); - if (ballId == BALL_MASTER) - { - shakes = maxShakes; - } - else - { - odds = Sqrt(Sqrt(16711680 / odds)); - odds = 1048560 / odds; - for (shakes = 0; shakes < maxShakes && Random() < odds; shakes++); - } + u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 side = GetBattlerSide(battler); - BtlController_EmitBallThrowAnim(gBattlerAttacker, B_COMM_TO_CONTROLLER, shakes); - MarkBattlerForControllerExec(gBattlerAttacker); + gBattleStruct->pledgeMove = FALSE; + if (!(gSideStatuses[side] & cmd->sideStatus)) + { + gSideStatuses[side] |= cmd->sideStatus; - if (shakes == maxShakes) // mon caught, copy of the code above - { - if (IsCriticalCapture()) - gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; + switch (cmd->sideStatus) + { + case SIDE_STATUS_RAINBOW: + gSideTimers[side].rainbowTimer = gBattleTurnCounter + 4; + break; + case SIDE_STATUS_SEA_OF_FIRE: + gSideTimers[side].seaOfFireTimer = gBattleTurnCounter + 4; + break; + case SIDE_STATUS_SWAMP: + gSideTimers[side].swampTimer = gBattleTurnCounter + 4; + } - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); - gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; - struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); - SetMonData(caughtMon, MON_DATA_POKEBALL, &ballId); + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + gBattlescriptCurrInstr = BattleScript_MoveEnd; +} - if (CalculatePlayerPartyCount() == PARTY_SIZE) - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - else - gBattleCommunication[MULTISTRING_CHOOSER] = 1; +void BS_TryTrainerSlideZMoveMsg(void) +{ + NATIVE_ARGS(); + s32 shouldSlide; - if (ballId == BALL_HEAL) - { - MonRestorePP(caughtMon); - HealStatusConditions(caughtMon, STATUS1_ANY, gBattlerTarget); - gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; - SetMonData(caughtMon, MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); - } - else if (ballId == BALL_FRIEND) - { - u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); - SetMonData(caughtMon, MON_DATA_FRIENDSHIP, &friendship); - } - } - else // not caught - { - if (!gHasFetchedBall) - gLastUsedBall = gLastUsedItem; + if ((shouldSlide = ShouldDoTrainerSlide(gBattlerAttacker, TRAINER_SLIDE_Z_MOVE))) + { + gBattleScripting.battler = gBattlerAttacker; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (IsCriticalCapture()) - gBattleCommunication[MULTISTRING_CHOOSER] = BALL_3_SHAKES_FAIL; - else - gBattleCommunication[MULTISTRING_CHOOSER] = shakes; +void BS_TryTrainerSlideMegaEvolutionMsg(void) +{ + NATIVE_ARGS(); + s32 shouldSlide; - gBattlescriptCurrInstr = BattleScript_ShakeBallThrow; - } - } + if ((shouldSlide = ShouldDoTrainerSlide(gBattlerAttacker, TRAINER_SLIDE_MEGA_EVOLUTION))) + { + gBattleScripting.battler = gBattlerAttacker; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryTrainerSlideDynamaxMsg(void) +{ + NATIVE_ARGS(); + s32 shouldSlide; + + if ((shouldSlide = ShouldDoTrainerSlide(gBattleScripting.battler, TRAINER_SLIDE_DYNAMAX))) + { + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryHealPulse(void) +{ + NATIVE_ARGS(const u8 *failInstr); + + if (IsBattlerAtMaxHp(gBattlerTarget)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_MEGA_LAUNCHER && IsPulseMove(gCurrentMove)) + gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 75 / 100); + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && GetMoveEffectArg_MoveProperty(gCurrentMove) == MOVE_EFFECT_FLORAL_HEALING) + gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 2 / 3); + else + gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) / 2); + + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = -1; + gBattlescriptCurrInstr = cmd->nextInstr; } } -static void Cmd_givecaughtmon(void) +void BS_TryCopycat(void) { - CMD_ARGS(const u8 *passInstr); - enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE]; - // Restore players party in order to handle properly the case when a wild mon is caught. - if (IsNPCFollowerWildBattle()) - LoadPlayerParty(); + NATIVE_ARGS(const u8 *failInstr); - switch (state) + if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || IsMoveCopycatBanned(gLastUsedMove) || IsZMove(gLastUsedMove)) { - case GIVECAUGHTMON_CHECK_PARTY_SIZE: - if (CalculatePlayerPartyCount() == PARTY_SIZE && B_CATCH_SWAP_INTO_PARTY >= GEN_7) - { - PrepareStringBattle(STRINGID_SENDCAUGHTMONPARTYORBOX, gBattlerAttacker); - gBattleCommunication[MSG_DISPLAY] = 1; - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_ASK_ADD_TO_PARTY; - } - else - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NO_MESSSAGE_SKIP; - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; - } - break; - case GIVECAUGHTMON_ASK_ADD_TO_PARTY: - HandleBattleWindow(YESNOBOX_X_Y, 0); - BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_INPUT; - gBattleCommunication[CURSOR_POSITION] = 0; - BattleCreateYesNoCursorAt(0); - break; - case GIVECAUGHTMON_HANDLE_INPUT: - if (JOY_NEW(DPAD_UP) && gBattleCommunication[CURSOR_POSITION] != 0) - { - PlaySE(SE_SELECT); - BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); - gBattleCommunication[CURSOR_POSITION] = 0; - BattleCreateYesNoCursorAt(0); - } - if (JOY_NEW(DPAD_DOWN) && gBattleCommunication[CURSOR_POSITION] == 0) + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gLastUsedMove)) { - PlaySE(SE_SELECT); - BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); - gBattleCommunication[CURSOR_POSITION] = 1; - BattleCreateYesNoCursorAt(1); + gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gLastUsedMove; + gCalledMove = GetTypeBasedZMove(gLastUsedMove); } - if (JOY_NEW(A_BUTTON)) + else if (IsMaxMove(gLastUsedMove)) { - PlaySE(SE_SELECT); - if (gBattleCommunication[CURSOR_POSITION] == 0) - { - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_DO_CHOOSE_MON; - } - else - { - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; - } + gCalledMove = gBattleStruct->dynamax.lastUsedBaseMove; } - else if (JOY_NEW(B_BUTTON)) + else { - PlaySE(SE_SELECT); - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; + gCalledMove = gLastUsedMove; } - break; - case GIVECAUGHTMON_DO_CHOOSE_MON: - if (!gPaletteFade.active) + + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryDefog(void) +{ + NATIVE_ARGS(u8 clear, const u8 *failInstr); + + if (cmd->clear) + { + if (TryDefogClear(gEffectBattler, TRUE)) + return; + else + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + if (TryDefogClear(gBattlerAttacker, FALSE)) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_TryUpperHand(void) +{ + NATIVE_ARGS(const u8 *failInstr); + + u32 abilityDef = GetBattlerAbility(gBattlerTarget); + u32 prio = GetChosenMovePriority(gBattlerTarget, abilityDef); + + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) + || gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE + || IsBattleMoveStatus(gChosenMoveByBattler[gBattlerTarget]) + || prio < 1 + || prio > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryTriggerStatusForm(void) +{ + NATIVE_ARGS(); + if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_STATUS)) + { + gBattleScripting.battler = gBattlerTarget; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_TargetFormChangeWithStringNoPopup; + return; + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_AllySwitchSwapBattler(void) +{ + NATIVE_ARGS(); + + gBattleScripting.battler = gBattlerAttacker; + gBattlerAttacker ^= BIT_FLANK; + gProtectStructs[gBattlerAttacker].usedAllySwitch = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryAllySwitch(void) +{ + NATIVE_ARGS(const u8 *failInstr); + + if (!IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) + || (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + || (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9) + { + TryResetProtectUseCounter(gBattlerAttacker); + if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random()) { - BtlController_EmitChoosePokemon(gBattlerAttacker, B_COMM_TO_CONTROLLER, PARTY_ACTION_SEND_MON_TO_BOX, PARTY_SIZE, ABILITY_NONE, 0, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); - MarkBattlerForControllerExec(gBattlerAttacker); - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_HANDLE_CHOSEN_MON; + gDisableStructs[gBattlerAttacker].protectUses = 0; + gBattlescriptCurrInstr = cmd->failInstr; } - break; - case GIVECAUGHTMON_HANDLE_CHOSEN_MON: - if (gSelectedMonPartyId != PARTY_SIZE) + else { - if (gSelectedMonPartyId > PARTY_SIZE) - { - // Choosing Pokemon was cancelled - gSelectedMonPartyId = PARTY_SIZE; - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; - } - else - { - // Mon chosen, try to put it in the PC - if (CopyMonToPC(&gPlayerParty[gSelectedMonPartyId]) == MON_GIVEN_TO_PC) - { - GetMonNickname(&gPlayerParty[gSelectedMonPartyId], gStringVar2); - StringCopy(gStringVar1, GetBoxNamePtr(GetPCBoxToSendMon())); - ZeroMonData(&gPlayerParty[gSelectedMonPartyId]); - gBattleStruct->itemLost[B_SIDE_PLAYER][gSelectedMonPartyId].originalItem = ITEM_NONE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWAPPED_INTO_PARTY; - gSelectedMonPartyId = PARTY_SIZE; - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; - } - else - { - gSelectedMonPartyId = PARTY_SIZE; - gBattleCommunication[MULTIUSE_STATE] = GIVECAUGHTMON_GIVE_AND_SHOW_MSG; - } - } + gDisableStructs[gBattlerAttacker].protectUses++; + gBattlescriptCurrInstr = cmd->nextInstr; } - break; - case GIVECAUGHTMON_GIVE_AND_SHOW_MSG: + } + else { - struct Pokemon *caughtMon = GetBattlerMon(GetCatchingBattler()); - if (B_RESTORE_HELD_BATTLE_ITEMS >= GEN_9) - { - u16 lostItem = gBattleStruct->itemLost[B_SIDE_OPPONENT][gBattlerPartyIndexes[GetCatchingBattler()]].originalItem; - if (lostItem != ITEM_NONE && GetItemPocket(lostItem) != POCKET_BERRIES) - SetMonData(caughtMon, MON_DATA_HELD_ITEM, &lostItem); // Restore non-berry items - } + gBattlescriptCurrInstr = cmd->nextInstr; + } +} - if (GiveMonToPlayer(caughtMon) != MON_GIVEN_TO_PARTY - && gBattleCommunication[MULTISTRING_CHOOSER] != B_MSG_SWAPPED_INTO_PARTY) +void BS_RunStatChangeItems(void) +{ + NATIVE_ARGS(u8 battler); + + // Change instruction before calling ItemBattleEffects. + gBattlescriptCurrInstr = cmd->nextInstr; + ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler)); +} + +static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove) +{ + u32 i, j; + + if (IsOnPlayerSide(gBattlerAttacker) + && !(gBattleTypeFlags & (BATTLE_TYPE_LINK + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_RECORDED_LINK + | BATTLE_TYPE_TRAINER_HILL + | BATTLE_TYPE_FRONTIER))) + { + const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerAttacker].species); + if (evolutions == NULL) + return; + + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) { - if (!ShouldShowBoxWasFullMessage()) - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SENT_SOMEONES_PC; - StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); - GetMonData(caughtMon, MON_DATA_NICKNAME, gStringVar2); - } - else + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) + continue; + if (evolutions[i].params == NULL) + continue; + + for (j = 0; evolutions[i].params[j].condition != CONDITIONS_END; j++) { - StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_PC_BOX_TO_SEND_MON))); // box the mon was sent to - GetMonData(caughtMon, MON_DATA_NICKNAME, gStringVar2); - StringCopy(gStringVar3, GetBoxNamePtr(GetPCBoxToSendMon())); //box the mon was going to be sent to - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOMEONES_BOX_FULL; + if (evolutions[i].params[j].condition == evolutionCondition) + { + struct Pokemon *monAtk = GetBattlerMon(gBattlerAttacker); + struct Pokemon *monDef = GetBattlerMon(gBattlerTarget); + // We only have 10 bits to use + u16 val = min(1023, GetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER) + upAmount); + // Reset progress if you faint for the recoil method. + switch (evolutionCondition) + { + case IF_USED_MOVE_X_TIMES: + if (evolutions[i].params[j].arg1 == usedMove) + SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); + break; + case IF_RECOIL_DAMAGE_GE: + if (gBattleMons[gBattlerAttacker].hp == 0) + val = 0; + SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); + break; + case IF_DEFEAT_X_WITH_ITEMS: + if (GetMonData(monDef, MON_DATA_SPECIES) == evolutions[i].params[j].arg1 + && GetMonData(monDef, MON_DATA_HELD_ITEM) == evolutions[i].params[j].arg2) + SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); + break; + } + return; + } } - - // Change to B_MSG_SENT_LANETTES_PC or B_MSG_LANETTES_BOX_FULL - if (FlagGet(FLAG_SYS_PC_LANETTE)) - gBattleCommunication[MULTISTRING_CHOOSER]++; } + } +} - gBattleResults.caughtMonSpecies = GetMonData(caughtMon, MON_DATA_SPECIES, NULL); - GetMonData(caughtMon, MON_DATA_NICKNAME, gBattleResults.caughtMonNick); - gBattleResults.caughtMonBall = GetMonData(caughtMon, MON_DATA_POKEBALL, NULL); +void BS_TryUpdateRecoilTracker(void) +{ + NATIVE_ARGS(); + TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->moveDamage[gBattlerAttacker], MOVE_NONE); + gBattlescriptCurrInstr = cmd->nextInstr; +} - gSelectedMonPartyId = PARTY_SIZE; - gBattleCommunication[MULTIUSE_STATE] = 0; +void BS_TryUpdateLeadersCrestTracker(void) +{ + NATIVE_ARGS(); + TryUpdateEvolutionTracker(IF_DEFEAT_X_WITH_ITEMS, 1, MOVE_NONE); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_NO_MESSSAGE_SKIP) - gBattlescriptCurrInstr = cmd->passInstr; +void BS_TryTidyUp(void) +{ + NATIVE_ARGS(u8 clear, const u8 *jumpInstr); + + if (cmd->clear) + { + if (TryTidyUpClear(gEffectBattler, TRUE)) + return; else gBattlescriptCurrInstr = cmd->nextInstr; - break; } + else + { + if (TryTidyUpClear(gBattlerAttacker, FALSE)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } - // Save the player's party again to not interferes with RestorePartyAfterFollowerNPCBattle() called after battle. - if (IsNPCFollowerWildBattle()) - SavePlayerParty(); } -static void Cmd_trysetcaughtmondexflags(void) +void BS_TryGulpMissile(void) { - CMD_ARGS(const u8 *failInstr); - - struct Pokemon *caughtMon = GetBattlerMon(GetCatchingBattler()); - u32 species = GetMonData(caughtMon, MON_DATA_SPECIES, NULL); - u32 personality = GetMonData(caughtMon, MON_DATA_PERSONALITY, NULL); + NATIVE_ARGS(); - if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) + && (gCurrentMove == MOVE_DIVE) + && GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE + && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) + gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; else - { - HandleSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_SET_CAUGHT, personality); gBattlescriptCurrInstr = cmd->nextInstr; - } } -static void Cmd_displaydexinfo(void) +void BS_TryActivateGulpMissile(void) { - CMD_ARGS(); - - struct Pokemon *mon = GetBattlerMon(GetCatchingBattler()); - u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + NATIVE_ARGS(); - switch (gBattleCommunication[0]) + if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg + && IsBattlerAlive(gBattlerAttacker) + && IsBattlerTurnDamaged(gBattlerTarget) + && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT + && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) { - case 0: - BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); - gBattleCommunication[0]++; - break; - case 1: - if (!gPaletteFade.active) - { - FreeAllWindowBuffers(); - gBattleCommunication[TASK_ID] = DisplayCaughtMonDexPage(species, - GetMonData(mon, MON_DATA_IS_SHINY), - GetMonData(mon, MON_DATA_PERSONALITY)); - gBattleCommunication[0]++; - } - break; - case 2: - if (!gPaletteFade.active - && gMain.callback2 == BattleMainCB2 - && !gTasks[gBattleCommunication[TASK_ID]].isActive) - { - SetVBlankCallback(VBlankCB_Battle); - gBattleCommunication[0]++; - } - break; - case 3: - InitBattleBgsVideo(); - LoadBattleTextboxAndBackground(); - gBattle_BG3_X = 256; - gBattleCommunication[0]++; - break; - case 4: - if (!IsDma3ManagerBusyWithBgCopy()) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { - BeginNormalPaletteFade(PALETTES_BG, 0, 16, 0, RGB_BLACK); - ShowBg(0); - ShowBg(3); - gBattleCommunication[0]++; + gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = 1; } - break; - case 5: - if (!gPaletteFade.active) + + switch(gBattleMons[gBattlerTarget].species) { - gBattlescriptCurrInstr = cmd->nextInstr; + case SPECIES_CRAMORANT_GORGING: + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptCall(BattleScript_GulpMissileGorging); + return; + case SPECIES_CRAMORANT_GULPING: + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptCall(BattleScript_GulpMissileGulping); + return; } - break; } + gBattlescriptCurrInstr = cmd->nextInstr; } -void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags) +void BS_TryQuash(void) { - s32 destY, destX, bgId; - u16 var = 0; + NATIVE_ARGS(const u8 *failInstr); + u32 i, j; - for (destY = yStart; destY <= yEnd; destY++) + // It's true if foe is faster, has a bigger priority, or switches + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) { - for (destX = xStart; destX <= xEnd; destX++) - { - if (destY == yStart) - { - if (destX == xStart) - var = 0x1022; - else if (destX == xEnd) - var = 0x1024; - else - var = 0x1023; - } - else if (destY == yEnd) - { - if (destX == xStart) - var = 0x1028; - else if (destX == xEnd) - var = 0x102A; - else - var = 0x1029; - } - else - { - if (destX == xStart) - var = 0x1025; - else if (destX == xEnd) - var = 0x1027; - else - var = 0x1026; - } - - if (flags & WINDOW_CLEAR) - var = 0; - - bgId = (flags & WINDOW_BG1) ? 1 : 0; - CopyToBgTilemapBufferRect_ChangePalette(bgId, &var, destX, destY, 1, 1, 0x11); - } + gBattlescriptCurrInstr = cmd->failInstr; + return; } -} - -void BattleCreateYesNoCursorAt(u8 cursorPosition) -{ - u16 src[2]; - src[0] = 1; - src[1] = 2; - - CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11); - CopyBgTilemapBufferToVram(0); -} -void BattleDestroyYesNoCursorAt(u8 cursorPosition) -{ - u16 src[2]; - src[0] = 0x1016; - src[1] = 0x1016; + // If the above condition is not true, it means we are faster than the foe, so we can set the quash bit + gProtectStructs[gBattlerTarget].quash = TRUE; - CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11); - CopyBgTilemapBufferToVram(0); + // this implementation assumes turn order is correct when using Quash + i = GetBattlerTurnOrderNum(gBattlerTarget); + for (j = i + 1; j < gBattlersCount; j++) + { + // Gen 7- config makes target go last so that the order of quash targets is kept for the correct turn order + // Gen 8+ config alters Turn Order of the target according to speed, dynamic speed should handle the rest + if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) + SwapTurnOrder(i, j); + else + break; + i++; + } + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_trygivecaughtmonnick(void) +void BS_CopyFoesStatIncrease(void) { - CMD_ARGS(); - - switch (gBattleCommunication[MULTIUSE_STATE]) - { - case 0: - HandleBattleWindow(YESNOBOX_X_Y, 0); - BattlePutTextOnWindow(gText_BattleYesNoChoice, B_WIN_YESNO); - gBattleCommunication[MULTIUSE_STATE]++; - gBattleCommunication[CURSOR_POSITION] = 0; - BattleCreateYesNoCursorAt(0); - break; - case 1: - if (JOY_NEW(DPAD_UP) && gBattleCommunication[CURSOR_POSITION] != 0) - { - PlaySE(SE_SELECT); - BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); - gBattleCommunication[CURSOR_POSITION] = 0; - BattleCreateYesNoCursorAt(0); - } - if (JOY_NEW(DPAD_DOWN) && gBattleCommunication[CURSOR_POSITION] == 0) + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 stat = 0; + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gQueuedStatBoosts[battler].stats == 0) + { + for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++) { - PlaySE(SE_SELECT); - BattleDestroyYesNoCursorAt(gBattleCommunication[CURSOR_POSITION]); - gBattleCommunication[CURSOR_POSITION] = 1; - BattleCreateYesNoCursorAt(1); + if (gQueuedStatBoosts[battler].statChanges[stat] != 0) + gQueuedStatBoosts[battler].stats |= (1 << stat); } - if (JOY_NEW(A_BUTTON)) + gBattlescriptCurrInstr = cmd->jumpInstr; + return; + } + + for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++) + { + if (gQueuedStatBoosts[battler].stats & (1 << stat)) { - PlaySE(SE_SELECT); - if (gBattleCommunication[CURSOR_POSITION] == 0) - { - gBattleCommunication[MULTIUSE_STATE]++; - BeginFastPaletteFade(3); - } + if (gQueuedStatBoosts[battler].statChanges[stat] <= -1) + SET_STATCHANGER(stat + 1, abs(gQueuedStatBoosts[battler].statChanges[stat]), TRUE); else - { - gBattleCommunication[MULTIUSE_STATE] = 4; - } - } - else if (JOY_NEW(B_BUTTON)) - { - PlaySE(SE_SELECT); - gBattleCommunication[MULTIUSE_STATE] = 4; - } - break; - case 2: - if (!gPaletteFade.active) - { - struct Pokemon *caughtMon = GetBattlerMon(gBattlerTarget); - GetMonData(caughtMon, MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); - FreeAllWindowBuffers(); - MainCallback callback = CalculatePlayerPartyCount() == PARTY_SIZE ? ReshowBlankBattleScreenAfterMenu : BattleMainCB2; - - DoNamingScreen(NAMING_SCREEN_CAUGHT_MON, gBattleStruct->caughtMonNick, - GetMonData(caughtMon, MON_DATA_SPECIES), - GetMonGender(caughtMon), - GetMonData(caughtMon, MON_DATA_PERSONALITY, NULL), - callback); + SET_STATCHANGER(stat + 1, gQueuedStatBoosts[battler].statChanges[stat], FALSE); - gBattleCommunication[MULTIUSE_STATE]++; - } - break; - case 3: - if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) - { - SetMonData(GetBattlerMon(gBattlerTarget), MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); - gBattleCommunication[MULTIUSE_STATE]++; + gQueuedStatBoosts[battler].stats &= ~(1 << stat); + gBattlerTarget = battler; + gBattlescriptCurrInstr = cmd->nextInstr; + return; } - break; - case 4: - gBattleCommunication[MULTIUSE_STATE] = 0; - gBattlescriptCurrInstr = cmd->nextInstr; - break; } + gBattlescriptCurrInstr = cmd->jumpInstr; } -static void Cmd_subattackerhpbydmg(void) +void BS_RemoveWeather(void) { - CMD_ARGS(); + NATIVE_ARGS(); + RemoveAllWeather(); + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleMons[gBattlerAttacker].hp -= gBattleStruct->moveDamage[gBattlerTarget]; +void BS_ApplyTerastallization(void) +{ + NATIVE_ARGS(); + ApplyBattlerVisualsForTeraAnim(gBattlerAttacker); gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_removeattackerstatus1(void) +void BS_JumpIfSleepClause(void) { - CMD_ARGS(); + NATIVE_ARGS(const u8 *jumpInstr); - gBattleMons[gBattlerAttacker].status1 = 0; - gBattlescriptCurrInstr = cmd->nextInstr; + // Can freely sleep own partner + if (IsDoubleBattle() && IsSleepClauseEnabled() && IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) + { + gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = FALSE; + // Can't sleep if clause is active otherwise + if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -// CMD_ARGS is not needed for these functions as they end the script execution. -static void Cmd_finishaction(void) +void BS_FickleBeamDamageCalculation(void) { - gCurrentActionFuncId = B_ACTION_FINISHED; + NATIVE_ARGS(); + + if (RandomPercentage(RNG_FICKLE_BEAM, 30)) + { + gBattleStruct->fickleBeamBoosted = TRUE; + gBattlescriptCurrInstr = BattleScript_FickleBeamDoubled; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_finishturn(void) +void BS_TryTarShot(void) { - gCurrentActionFuncId = B_ACTION_FINISHED; - gCurrentTurnActionNumber = gBattlersCount; + NATIVE_ARGS(const u8 *failInstr); + if (gDisableStructs[gBattlerTarget].tarShot || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gDisableStructs[gBattlerTarget].tarShot = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void Cmd_trainerslideout(void) +void BS_CanTarShotWork(void) { - CMD_ARGS(u8 position); + NATIVE_ARGS(const u8 *failInstr); + // Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further + if (!gDisableStructs[gBattlerTarget].tarShot + && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->failInstr; +} - u32 battler = GetBattlerForBattleScript(cmd->position); - BtlController_EmitTrainerSlideBack(battler, B_COMM_TO_CONTROLLER); - MarkBattlerForControllerExec(battler); +void BS_JumpIfBlockedBySoundproof(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (IsSoundMove(gCurrentMove) && GetBattlerAbility(battler) == ABILITY_SOUNDPROOF) + { + gLastUsedAbility = ABILITY_SOUNDPROOF; + gBattlescriptCurrInstr = cmd->jumpInstr; + RecordAbilityBattle(battler, gLastUsedAbility); + gBattlerAbility = battler; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_SetMagicCoatTarget(void) +{ + NATIVE_ARGS(); + gBattleStruct->attackerBeforeBounce = gBattleScripting.battler = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = gBattleStruct->attackerBeforeBounce; + HandleMoveTargetRedirection(); gBattlescriptCurrInstr = cmd->nextInstr; } -static const u16 sTelekinesisBanList[] = +void BS_TeatimeInvul(void) { - SPECIES_DIGLETT, - SPECIES_DUGTRIO, - SPECIES_DIGLETT_ALOLA, - SPECIES_DUGTRIO_ALOLA, - SPECIES_SANDYGAST, - SPECIES_PALOSSAND, - SPECIES_GENGAR_MEGA, -}; + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); -bool32 IsTelekinesisBannedSpecies(u16 species) + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} + +void BS_TeatimeTargets(void) { - u32 i; + NATIVE_ARGS(const u8 *failInstr); + u32 count = 0, i; - for (i = 0; i < ARRAY_COUNT(sTelekinesisBanList); i++) + for (i = 0; i < gBattlersCount; i++) { - if (species == sTelekinesisBanList[i]) - return TRUE; + if (IsTeatimeAffected(i)) + count++; } - return FALSE; + if (count == 0) + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_settelekinesis(void) +void BS_TryWindRiderPower(void) { - CMD_ARGS(const u8 *failInstr); + NATIVE_ARGS(u8 battler, const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) - || gFieldStatuses & STATUS_FIELD_GRAVITY - || IsTelekinesisBannedSpecies(gBattleMons[gBattlerTarget].species)) + u32 battler = GetBattlerForBattleScript(cmd->battler); + u16 ability = GetBattlerAbility(battler); + if (IsBattlerAlly(battler, gBattlerAttacker) + && (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER)) { - gBattlescriptCurrInstr = cmd->failInstr; + gLastUsedAbility = ability; + RecordAbilityBattle(battler, gLastUsedAbility); + gBattlerAbility = gBattleScripting.battler = battler; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_TELEKINESIS; - gDisableStructs[gBattlerTarget].telekinesisTimer = gBattleTurnCounter + 3; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } } -static void Cmd_swapstatstages(void) +void BS_ActivateWeatherChangeAbilities(void) { - CMD_ARGS(u8 stat); - - u8 stat = cmd->stat; - s8 atkStatStage = gBattleMons[gBattlerAttacker].statStages[stat]; - s8 defStatStage = gBattleMons[gBattlerTarget].statStages[stat]; - - gBattleMons[gBattlerAttacker].statStages[stat] = defStatStage; - gBattleMons[gBattlerTarget].statStages[stat] = atkStatStage; + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); gBattlescriptCurrInstr = cmd->nextInstr; + AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); } -static u16 *GetBattlerStat(struct BattlePokemon *battler, u32 stat) +void BS_ActivateTerrainChangeAbilities(void) { - switch (stat) - { - case STAT_ATK: return &battler->attack; - case STAT_DEF: return &battler->defense; - case STAT_SPATK: return &battler->spAttack; - case STAT_SPDEF: return &battler->spDefense; - default: return NULL; - } -} + NATIVE_ARGS(u8 battler); -static void Cmd_averagestats(void) -{ - CMD_ARGS(u8 stat); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlescriptCurrInstr = cmd->nextInstr; + AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); +} - u16 *stat1 = GetBattlerStat(&gBattleMons[gBattlerAttacker], cmd->stat); - u16 *stat2 = GetBattlerStat(&gBattleMons[gBattlerTarget], cmd->stat); - u16 avg = (*stat1 + *stat2) / 2; - *stat1 = *stat2 = avg; +void BS_StoreHealingWish(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (gCurrentMove == MOVE_LUNAR_DANCE) + gBattleStruct->battlerState[battler].storedLunarDance = TRUE; + else + gBattleStruct->battlerState[battler].storedHealingWish = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifcaptivateaffected(void) +void BS_TryRevivalBlessing(void) { - CMD_ARGS(const u8 *jumpInstr); + NATIVE_ARGS(const u8 *failInstr); + u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker); - if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) + // Move fails if there are no battlers to revive. + if (index == PARTY_SIZE) { - gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; - gLastUsedAbility = ABILITY_OBLIVIOUS; - RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); + gBattlescriptCurrInstr = cmd->failInstr; + return; } - else if (AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + + // Battler selected! Revive and go to next instruction. + if (gSelectedMonPartyId != PARTY_SIZE) { - gBattlescriptCurrInstr = cmd->jumpInstr; + struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + + u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 1u << gSelectedMonPartyId, sizeof(hp), &hp); + MarkBattlerForControllerExec(gBattlerAttacker); + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES)); + + // If an on-field battler is revived, it needs to be sent out again. + if (IsDoubleBattle() && + gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId) + { + u32 i = BATTLE_PARTNER(gBattlerAttacker); + gAbsentBattlerFlags &= ~(1u << i); + gBattleStruct->monToSwitchIntoId[i] = gSelectedMonPartyId; + gBattleScripting.battler = i; + gBattleCommunication[MULTIUSE_STATE] = TRUE; + } + + gSelectedMonPartyId = PARTY_SIZE; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->nextInstr; + // Open party menu, wait to go to next instruction. + BtlController_EmitChoosePokemon(gBattlerAttacker, B_COMM_TO_CONTROLLER, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, 0, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); + MarkBattlerForControllerExec(gBattlerAttacker); } } -static void Cmd_setnonvolatilestatus(void) +void BS_JumpIfCommanderActive(void) { - CMD_ARGS(u8 trigger); - gBattlescriptCurrInstr = cmd->nextInstr - 1; + NATIVE_ARGS(const u8 *jumpInstr); - switch (cmd->trigger) - { - case TRIGGER_ON_ABILITY: - if (gBattleScripting.moveEffect == MOVE_EFFECT_CONFUSION) - SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); - else - SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); - break; - case TRIGGER_ON_MOVE: - SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); - break; - case TRIGGER_ON_PROTECT: - SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); - break; - } + if (gBattleStruct->commanderActive[gBattlerTarget] != SPECIES_NONE) + gBattlescriptCurrInstr = cmd->jumpInstr; + else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_tryworryseed(void) +static void UpdatePokeFlutePartyStatus(struct Pokemon* party, u8 position) { - CMD_ARGS(const u8 *failInstr); - - if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten - || gBattleMons[gBattlerTarget].ability == ABILITY_INSOMNIA) - { - RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + s32 i; + u8 battler; + u32 monToCheck, status; + u16 species, abilityNum; + monToCheck = 0; + for (i = 0; i < PARTY_SIZE; i++) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM); + status = GetMonData(&party[i], MON_DATA_STATUS); + if (species != SPECIES_NONE + && species != SPECIES_EGG + && status & AILMENT_FNT + && GetAbilityBySpecies(species, abilityNum) != ABILITY_SOUNDPROOF) + monToCheck |= (1 << i); } - else + if (monToCheck) { - if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) - gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - - gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; - gBattlescriptCurrInstr = cmd->nextInstr; + battler = GetBattlerAtPosition(position); + status = 0; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, monToCheck, 4, &status); + MarkBattlerForControllerExec(battler); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; } } -static void Cmd_callnative(void) +void BS_CheckPokeFlute(void) { - CMD_ARGS(void (*func)(void)); - void (*func)(void) = cmd->func; - func(); -} + NATIVE_ARGS(); + gBattleCommunication[MULTISTRING_CHOOSER] = 0; -// Callnative Funcs + s32 i; + for (i = 0; i < gBattlersCount; i++) + { + if (GetBattlerAbility(i) != ABILITY_SOUNDPROOF) + { + gBattleMons[i].status1 &= ~STATUS1_SLEEP; + gBattleMons[i].volatiles.nightmare = FALSE; + } + } -void SaveBattlerTarget(u32 battler) -{ - if (gBattleStruct->savedTargetCount < NELEMS(gBattleStruct->savedBattlerTarget)) - gBattleStruct->savedBattlerTarget[gBattleStruct->savedTargetCount++] = battler; - else - DebugPrintfLevel(MGBA_LOG_WARN, "Attempting to exceed savedBattlerTarget array size!"); -} + UpdatePokeFlutePartyStatus(gPlayerParty, B_POSITION_PLAYER_LEFT); + UpdatePokeFlutePartyStatus(gEnemyParty, B_POSITION_OPPONENT_LEFT); -void SaveBattlerAttacker(u32 battler) -{ - if (gBattleStruct->savedAttackerCount < NELEMS(gBattleStruct->savedBattlerAttacker)) - gBattleStruct->savedBattlerAttacker[gBattleStruct->savedAttackerCount++] = battler; - else - DebugPrintfLevel(MGBA_LOG_WARN, "Attempting to exceed savedBattlerAttacker array size!"); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SaveTarget(void) +void BS_WaitFanfare(void) { NATIVE_ARGS(); - SaveBattlerTarget(gBattlerTarget); + + if (!IsFanfareTaskInactive()) + return; + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_RestoreTarget(void) +void BS_SetBeakBlast(void) { NATIVE_ARGS(); - if (gBattleStruct->savedTargetCount > 0) - { - gBattleStruct->savedTargetCount--; - gBattlerTarget = gBattleStruct->savedBattlerTarget[gBattleStruct->savedTargetCount]; - } - else - { - // #if TESTING - // Test_ExitWithResult(TEST_RESULT_ERROR, "BS_RestoreTarget attempting to restore an empty target!"); - // #else - DebugPrintfLevel(MGBA_LOG_WARN, "BS_RestoreTarget attempting to restore an empty target!"); - // #endif - } + gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SaveAttacker(void) +void BS_RemoveTerrain(void) { NATIVE_ARGS(); - SaveBattlerAttacker(gBattlerAttacker); + RemoveAllTerrains(); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_RestoreAttacker(void) +void BS_TrySpectralThiefSteal(void) { - NATIVE_ARGS(); - if (gBattleStruct->savedAttackerCount > 0) + NATIVE_ARGS(const u8 *jumpInstr); + + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) { - gBattleStruct->savedAttackerCount--; - gBattlerAttacker = gBattleStruct->savedBattlerAttacker[gBattleStruct->savedAttackerCount]; + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + bool32 contrary = GetBattlerAbility(gBattlerAttacker) == ABILITY_CONTRARY; + gBattleStruct->stolenStats[0] = 0; // Stats to steal. + gBattleScripting.animArg1 = 0; + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + { + if (gBattleMons[gBattlerTarget].statStages[stat] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[stat] != MAX_STAT_STAGE) + { + bool32 byTwo = FALSE; + + gBattleStruct->stolenStats[0] |= (1 << (stat)); + // Store by how many stages to raise the stat. + gBattleStruct->stolenStats[stat] = gBattleMons[gBattlerTarget].statStages[stat] - DEFAULT_STAT_STAGE; + + while (gBattleMons[gBattlerAttacker].statStages[stat] + gBattleStruct->stolenStats[stat] > MAX_STAT_STAGE) + gBattleStruct->stolenStats[stat]--; + + gBattleMons[gBattlerTarget].statStages[stat] = DEFAULT_STAT_STAGE; + + if (gBattleStruct->stolenStats[stat] >= 2) + byTwo++; + + if (gBattleScripting.animArg1 == 0) + { + if (byTwo) + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS2 : STAT_ANIM_PLUS2) + stat; + else + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS1 : STAT_ANIM_PLUS1) + stat; + } + else + { + if (byTwo) + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS2 : STAT_ANIM_MULTIPLE_PLUS2); + else + gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS1 : STAT_ANIM_MULTIPLE_PLUS1); + } + } } + + if (gBattleStruct->stolenStats[0] != 0) + gBattlescriptCurrInstr = cmd->jumpInstr; else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_SpectralThiefPrintStats(void) +{ + NATIVE_ARGS(); + + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) { - // #if TESTING - // Test_ExitWithResult(TEST_RESULT_ERROR, "BS_RestoreAttacker attempting to restore an empty attacker!"); - // #else - DebugPrintfLevel(MGBA_LOG_WARN, "BS_RestoreAttacker attempting to restore an empty attacker!"); - // #endif + if (gBattleStruct->stolenStats[0] & (1u << stat)) + { + gBattleStruct->stolenStats[0] &= ~(1u << stat); + SET_STATCHANGER(stat, gBattleStruct->stolenStats[stat], FALSE); + if (ChangeStatBuffs( + gBattlerAttacker, + GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), + stat, + STAT_CHANGE_CERTAIN, + 0, NULL) == STAT_CHANGE_WORKED) + { + BattleScriptCall(BattleScript_StatUp); + return; + } + } } gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_CalcMetalBurstDmg(void) +void BS_SetMoveResultFlags(void) { - NATIVE_ARGS(const u8 *failInstr); - - u8 sideAttacker = GetBattlerSide(gBattlerAttacker); - u8 sideTarget = 0; - - if (gProtectStructs[gBattlerAttacker].physicalDmg - && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId)) - && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) - { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; - - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) - gBattlerTarget = gSideTimers[sideTarget].followmeTarget; - else - gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; - - gBattlescriptCurrInstr = cmd->nextInstr; - } - else if (gProtectStructs[gBattlerAttacker].specialDmg - && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId)) - && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) - { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; - - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) - gBattlerTarget = gSideTimers[sideTarget].followmeTarget; - else - gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + NATIVE_ARGS(u16 value); + gBattleStruct->moveResultFlags[gBattlerTarget] |= cmd->value; + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } +void BS_ClearMoveResultFlags(void) +{ + NATIVE_ARGS(u16 value); + gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(cmd->value); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfCantFling(void) +void BS_JumpIfMoveResultFlags(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + NATIVE_ARGS(u16 value, const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (!CanFling(battler)) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & cmd->value) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfMoreThanHalfHP(void) +void BS_JumpIfCriticalHit(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + NATIVE_ARGS(const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gBattleMons[battler].hp > (gBattleMons[battler].maxHP + 1) / 2) + if (gSpecialStatuses[gBattlerTarget].criticalHit) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_DoStockpileStatChangesWearOff(void) +void BS_SwapStats(void) { - NATIVE_ARGS(u8 battler, const u8 *statChangeInstr); + NATIVE_ARGS(u8 stat); - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gDisableStructs[battler].stockpileDef != 0) - { - SET_STATCHANGER(STAT_DEF, abs(gDisableStructs[battler].stockpileDef), TRUE); - gDisableStructs[battler].stockpileDef = 0; - BattleScriptCall(cmd->statChangeInstr); - } - else if (gDisableStructs[battler].stockpileSpDef) - { - SET_STATCHANGER(STAT_SPDEF, abs(gDisableStructs[battler].stockpileSpDef), TRUE); - gDisableStructs[battler].stockpileSpDef = 0; - BattleScriptCall(cmd->statChangeInstr); - } - else + u32 stat = cmd->stat; + u32 temp; + + switch (stat) { - gBattlescriptCurrInstr = cmd->nextInstr; + case STAT_HP: + SWAP(gBattleMons[gBattlerAttacker].hp, gBattleMons[gBattlerTarget].hp, temp); + break; + case STAT_ATK: + SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerTarget].attack, temp); + break; + case STAT_DEF: + SWAP(gBattleMons[gBattlerAttacker].defense, gBattleMons[gBattlerTarget].defense, temp); + break; + case STAT_SPEED: + SWAP(gBattleMons[gBattlerAttacker].speed, gBattleMons[gBattlerTarget].speed, temp); + break; + case STAT_SPATK: + SWAP(gBattleMons[gBattlerAttacker].spAttack, gBattleMons[gBattlerTarget].spAttack, temp); + break; + case STAT_SPDEF: + SWAP(gBattleMons[gBattlerAttacker].spDefense, gBattleMons[gBattlerTarget].spDefense, temp); + break; } + PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); + gBattlescriptCurrInstr = cmd->nextInstr; } -static bool32 CriticalCapture(u32 odds) +static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr) { - u32 numCaught; - u32 totalDexCount; - - if (B_CRITICAL_CAPTURE == FALSE) - return FALSE; - - if (B_CRITICAL_CAPTURE_LOCAL_DEX == TRUE) - totalDexCount = HOENN_DEX_COUNT; - else - totalDexCount = NATIONAL_DEX_COUNT; - - numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); - - if (numCaught <= (totalDexCount * 30) / 650) - odds = 0; - else if (numCaught <= (totalDexCount * 150) / 650) - odds /= 2; - else if (numCaught <= (totalDexCount * 300) / 650) - ; // odds = (odds * 100) / 100; - else if (numCaught <= (totalDexCount * 450) / 650) - odds = (odds * 150) / 100; - else if (numCaught <= (totalDexCount * 600) / 650) - odds *= 2; + if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))) + { + gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS; + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + gEffectBattler = gBattlerTarget; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + gBattlescriptCurrInstr = nextInstr; + } else - odds = (odds * 250) / 100; - - if (CheckBagHasItem(ITEM_CATCHING_CHARM, 1)) - odds = (odds * (100 + B_CATCHING_CHARM_BOOST)) / 100; - - odds /= 6; - - if ((Random() % 255) < odds) - return TRUE; - - return FALSE; -} - -bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) -{ - if (move != MOVE_NONE && move != MOVE_UNAVAILABLE && move != MOVE_STRUGGLE - && !IsMoveParentalBondBanned(move) - && GetMoveCategory(move) != DAMAGE_CATEGORY_STATUS - && GetMoveStrikeCount(move) < 2 - && GetMoveEffect(move) != EFFECT_SEMI_INVULNERABLE - && GetMoveEffect(move) != EFFECT_TWO_TURNS_ATTACK - && GetMoveEffect(move) != EFFECT_MULTI_HIT) { - if (IsDoubleBattle()) - { - switch (GetBattlerMoveTargetType(battler, move)) - { - // Both foes are alive, spread move strikes once - case MOVE_TARGET_BOTH: - if (CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerTarget) >= 2) - return FALSE; - break; - // Either both foes or one foe and its ally are alive; spread move strikes once - case MOVE_TARGET_FOES_AND_ALLY: - if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker) >= 2) - return FALSE; - break; - default: - break; - } - } - return TRUE; + gBattlescriptCurrInstr = failInstr; } - return FALSE; } -static bool8 IsFinalStrikeEffect(enum BattleMoveEffects moveEffect) +static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr) { - u32 i; - - for (i = 0; i < ARRAY_COUNT(sFinalStrikeOnlyEffects); i++) + if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget))) { - if (moveEffect == sFinalStrikeOnlyEffects[i]) - return TRUE; + gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gEffectBattler = gBattlerTarget; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + gBattlescriptCurrInstr = nextInstr; } - return FALSE; -} - -static bool32 CanAbilityPreventStatLoss(u32 abilityDef) -{ - switch (abilityDef) + else { - case ABILITY_CLEAR_BODY: - case ABILITY_FULL_METAL_BODY: - case ABILITY_WHITE_SMOKE: - return TRUE; + gBattlescriptCurrInstr = failInstr; } - return FALSE; } -bool32 CanBurnHitThaw(u16 move) +static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr) { - u8 i; - - if (B_BURN_HIT_THAW >= GEN_6) + if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)) { - u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move); - for (i = 0; i < numAdditionalEffects; i++) - { - const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - if (additionalEffect->moveEffect == MOVE_EFFECT_BURN) - return TRUE; - } - } - return FALSE; -} + if (B_SLEEP_TURNS >= GEN_5) + gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2); + else + gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3); -void BS_CheckParentalBondCounter(void) -{ - NATIVE_ARGS(u8 counter, const u8 *jumpInstr); - // Some effects should only happen on the first or second strike of Parental Bond, - // so a way to check this in battle scripts is useful - if (gSpecialStatuses[gBattlerAttacker].parentalBondState == cmd->counter && IsBattlerAlive(gBattlerTarget)) - gBattlescriptCurrInstr = cmd->jumpInstr; + TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + gEffectBattler = gBattlerTarget; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + gBattlescriptCurrInstr = nextInstr; + } else - gBattlescriptCurrInstr = cmd->nextInstr; + { + gBattlescriptCurrInstr = failInstr; + } } -void BS_JumpIfCantLoseItem(void) +void BS_TrySetParalysis(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - u8 battler = GetBattlerForBattleScript(cmd->battler); - u16 item = gBattleMons[battler].item; - - if (item == ITEM_NONE || !CanBattlerGetOrLoseItem(battler, item)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(const u8 *failInstr); + TrySetParalysis(cmd->nextInstr, cmd->failInstr); } -void BS_GetBattlerSide(void) +void BS_TrySetPoison(void) { - NATIVE_ARGS(u8 battler); - gBattleCommunication[0] = GetBattlerSide(GetBattlerForBattleScript(cmd->battler)); - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(const u8 *failInstr); + TrySetPoison(cmd->nextInstr, cmd->failInstr); } -void BS_TrySymbiosis(void) +void BS_TrySetPoisonParalyzis(void) { - NATIVE_ARGS(u8 battler); - u32 battler = GetBattlerForBattleScript(cmd->battler); - //called by Bestow, Fling, and Bug Bite, which don't work with Cmd_removeitem. - u32 partner = BATTLE_PARTNER(battler); - if (TryTriggerSymbiosis(battler, partner)) - { - BestowItem(partner, battler); - gLastUsedAbility = gBattleMons[partner].ability; - gBattleScripting.battler = gBattlerAbility = partner; - gEffectBattler = battler; - BattleScriptCall(BattleScript_SymbiosisActivates); - return; - } + NATIVE_ARGS(const u8 *failInstr); - gBattlescriptCurrInstr = cmd->nextInstr; -} + static const u32 sStunShockEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON}; + u32 status = RandomElement(RNG_G_MAX_STUN_SHOCK, sStunShockEffects); -void BS_SetZEffect(void) -{ - SetZEffect(); // Handles battle script jumping internally + if (status == STATUS1_PARALYSIS) + TrySetParalysis(cmd->nextInstr, cmd->failInstr); + else + TrySetPoison(cmd->nextInstr, cmd->failInstr); } -static void TryUpdateRoundTurnOrder(void) +void BS_TrySetEffectSpore(void) { - if (IsDoubleBattle()) - { - u32 i; - u32 j = 0; - u32 k = 0; - u32 currRounder = 0; - u8 roundUsers[3] = {0xFF, 0xFF, 0xFF}; - u8 nonRoundUsers[3] = {0xFF, 0xFF, 0xFF}; - for (i = 0; i < gBattlersCount; i++) - { - if (gBattlerByTurnOrder[i] == gBattlerAttacker) - { - currRounder = i + 1; // Current battler going after attacker - break; - } - } - - // Get battlers after attacker using round - for (i = currRounder; i < gBattlersCount; i++) - { - if (gChosenMoveByBattler[gBattlerByTurnOrder[i]] == MOVE_ROUND) - roundUsers[j++] = gBattlerByTurnOrder[i]; - else - nonRoundUsers[k++] = gBattlerByTurnOrder[i]; - } + NATIVE_ARGS(const u8 *failInstr); - // update turn order for round users - for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) - { - gBattlerByTurnOrder[currRounder] = roundUsers[i]; - gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again - currRounder++; - } + static const u32 sBefuddleEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON, STATUS1_SLEEP}; + u32 status = RandomElement(RNG_G_MAX_BEFUDDLE, sBefuddleEffects); - // Update turn order for non-round users - for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) - { - gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; - currRounder++; - } - } + if (status == STATUS1_PARALYSIS) + TrySetParalysis(cmd->nextInstr, cmd->failInstr); + else if (status == STATUS1_POISON) + TrySetPoison(cmd->nextInstr, cmd->failInstr); + else + TrySetSleep(cmd->nextInstr, cmd->failInstr); } -u8 GetFirstFaintedPartyIndex(u8 battler) +void BS_TrySetConfusion(void) { - u32 i; - u32 start = 0; - u32 end = PARTY_SIZE; - struct Pokemon *party = GetBattlerParty(battler); + NATIVE_ARGS(const u8 *failInstr); - // Check whether partner is separate trainer. - if ((IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - || (!IsOnPlayerSide(battler) && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + if (CanBeConfused(gBattlerTarget)) { - if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_LEFT - || GetBattlerPosition(battler) == B_POSITION_PLAYER_LEFT) - { - end = PARTY_SIZE / 2; - } - else - { - start = PARTY_SIZE / 2; - } + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; + gBattleCommunication[MULTIUSE_STATE] = 1; + gEffectBattler = gBattlerTarget; + gBattlescriptCurrInstr = cmd->nextInstr; } - - // Loop through to find fainted battler. - for (i = start; i < end; ++i) + else { - u32 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); - if (species != SPECIES_NONE - && species != SPECIES_EGG - && GetMonData(&party[i], MON_DATA_HP) == 0) - { - return i; - } + gBattlescriptCurrInstr = cmd->failInstr; } - - // Returns PARTY_SIZE if none found. - return PARTY_SIZE; } -void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler) +void BS_TrySetInfatuation(void) { - enum ItemHoldEffect holdEffect = GetMonHoldEffect(&gPlayerParty[expGetterMonId]); - - if (IsTradedMon(&gPlayerParty[expGetterMonId])) - *expAmount = (*expAmount * 150) / 100; - if (holdEffect == HOLD_EFFECT_LUCKY_EGG) - *expAmount = (*expAmount * 150) / 100; - if (B_UNEVOLVED_EXP_MULTIPLIER >= GEN_6 && IsMonPastEvolutionLevel(&gPlayerParty[expGetterMonId])) - *expAmount = (*expAmount * 4915) / 4096; - if (B_AFFECTION_MECHANICS == TRUE && GetMonAffectionHearts(&gPlayerParty[expGetterMonId]) >= AFFECTION_FOUR_HEARTS) - *expAmount = (*expAmount * 4915) / 4096; - if (CheckBagHasItem(ITEM_EXP_CHARM, 1)) //is also for other exp boosting Powers if/when implemented - *expAmount = (*expAmount * 150) / 100; + NATIVE_ARGS(const u8 *failInstr); - if (B_SCALED_EXP >= GEN_5 && B_SCALED_EXP != GEN_6) + if (!gBattleMons[gBattlerTarget].volatiles.infatuation + && gBattleMons[gBattlerTarget].ability != ABILITY_OBLIVIOUS + && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL) + && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) { - // Note: There is an edge case where if a pokemon receives a large amount of exp, it wouldn't be properly calculated - // because of multiplying by scaling factor(the value would simply be larger than an u32 can hold). Hence u64 is needed. - u64 value = *expAmount; - u8 faintedLevel = gBattleMons[faintedBattler].level; - u8 expGetterLevel = GetMonData(&gPlayerParty[expGetterMonId], MON_DATA_LEVEL); - - value *= sExperienceScalingFactors[(faintedLevel * 2) + 10]; - value /= sExperienceScalingFactors[faintedLevel + expGetterLevel + 10]; - - *expAmount = value + 1; + gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); + gBattleCommunication[MULTIUSE_STATE] = 2; + gEffectBattler = gBattlerTarget; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; } } -void BS_ItemRestoreHP(void) +void BS_TrySetEscapePrevention(void) { - NATIVE_ARGS(const u8 *alreadyMaxHpInstr, const u8 *restoreBattlerInstr); - u16 healAmount; - u32 battler = MAX_BATTLERS_COUNT; - u32 healParam = GetItemEffect(gLastUsedItem)[6]; - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP); - u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP); - gBattleCommunication[MULTIUSE_STATE] = 0; + NATIVE_ARGS(const u8 *failInstr); - if (hp == maxHP) + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) { - gBattlescriptCurrInstr = cmd->alreadyMaxHpInstr; + gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; + gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; + gEffectBattler = gBattlerTarget; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - // Track the number of Revives used in a battle. - if (hp == 0 && IsOnPlayerSide(gBattlerAttacker) && gBattleResults.numRevivesUsed < 255) - gBattleResults.numRevivesUsed++; - - // Check if the recipient is an active battler. - if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - battler = gBattlerAttacker; - else if (IsDoubleBattle() && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) - battler = BATTLE_PARTNER(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->failInstr; + } +} - // Get amount to heal. - switch (healParam) - { - case ITEM6_HEAL_HP_FULL: - healAmount = maxHP; - break; - case ITEM6_HEAL_HP_HALF: - healAmount = maxHP / 2; - break; - case ITEM6_HEAL_HP_QUARTER: - healAmount = maxHP / 4; - break; - default: - healAmount = healParam; - break; - } - if (hp + healAmount > maxHP) - healAmount = maxHP - hp; +void BS_TrySetTorment(void) +{ + NATIVE_ARGS(const u8 *failInstr); - gBattleScripting.battler = battler; - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); + if (!(gBattleMons[gBattlerTarget].volatiles.torment == TRUE) + && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)) + { + gBattleMons[gBattlerTarget].volatiles.torment = TRUE; + gDisableStructs[gBattlerTarget].tormentTimer = gBattleTurnCounter + 3; // 3 turns excluding current turn + gEffectBattler = gBattlerTarget; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} - // Heal is applied as move damage if battler is active. - if (battler != MAX_BATTLERS_COUNT && hp != 0) - { - gBattleStruct->moveDamage[battler] = -healAmount; - gBattlescriptCurrInstr = cmd->restoreBattlerInstr; - } - else - { - hp += healAmount; - SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp); +// Heals one-sixth of the target's HP, including for Dynamaxed targets. +void BS_HealOneSixth(void) +{ + NATIVE_ARGS(const u8* failInstr); + gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP / 6; + if (gBattleStruct->moveDamage[gBattlerTarget] == 0) + gBattleStruct->moveDamage[gBattlerTarget] = 1; + gBattleStruct->moveDamage[gBattlerTarget] *= -1; - // Revived battlers on the field need to be brought back. - if (IsDoubleBattle() && battler != MAX_BATTLERS_COUNT) - { - gAbsentBattlerFlags &= ~(1u << battler); - gBattleMons[battler].hp = hp; - gBattleCommunication[MULTIUSE_STATE] = TRUE; - } - gBattlescriptCurrInstr = cmd->nextInstr; - } - } + if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) + gBattlescriptCurrInstr = cmd->failInstr; // fail + else + gBattlescriptCurrInstr = cmd->nextInstr; // can heal } -void BS_ItemCureStatus(void) +// Recycles the target's item if it is specifically holding a berry. +void BS_TryRecycleBerry(void) { - NATIVE_ARGS(const u8 *noStatusInstr); - u32 battler = gBattlerAttacker; - bool32 statusChanged = FALSE; - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); + NATIVE_ARGS(const u8 *failInstr); + u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; + if (gBattleMons[gBattlerTarget].item == ITEM_NONE + && gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item + && GetItemPocket(*usedHeldItem) == POCKET_BERRIES) + { + gLastUsedItem = *usedHeldItem; + *usedHeldItem = ITEM_NONE; + gBattleMons[gBattlerTarget].item = gLastUsedItem; - // Heal volatile conditions if battler is active. - if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - statusChanged = ItemHealMonVolatile(battler, gLastUsedItem); - else if (IsDoubleBattle() - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) - statusChanged = ItemHealMonVolatile(BATTLE_PARTNER(gBattlerAttacker), gLastUsedItem); + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); + MarkBattlerForControllerExec(gBattlerTarget); - // Heal Status1 conditions. - if (!HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler)) + gBattlescriptCurrInstr = cmd->nextInstr; + } + else { - statusChanged = TRUE; - if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) - gBattleMons[battler].volatiles.nightmare = FALSE; - if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) - gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + gBattlescriptCurrInstr = cmd->failInstr; } +} - if (statusChanged) +// Sets up sharp steel on the target's side. +void BS_SetSteelsurge(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u8 targetSide = GetBattlerSide(gBattlerTarget); + if (IsHazardOnSide(targetSide, HAZARDS_STEELSURGE)) { - gBattleScripting.battler = battler; - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES)); - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattlescriptCurrInstr = cmd->noStatusInstr; + PushHazardTypeToQueue(targetSide, HAZARDS_STEELSURGE); + gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_ItemIncreaseStat(void) +void BS_JumpIfIntimidateAbilityPrevented(void) { NATIVE_ARGS(); - u16 statId = GetItemEffect(gLastUsedItem)[1]; - u16 stages = GetItemHoldEffectParam(gLastUsedItem); - SET_STATCHANGER(statId, stages, FALSE); - gBattlescriptCurrInstr = cmd->nextInstr; -} -void BS_ItemRestorePP(void) -{ - NATIVE_ARGS(); - const u8 *effect = GetItemEffect(gLastUsedItem); - u32 i, pp, maxPP, moveId, loopEnd; - u32 battler = MAX_BATTLERS_COUNT; - struct Pokemon *mon = (IsOnPlayerSide(gBattlerAttacker)) ? &gPlayerParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]] : &gEnemyParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]]; + u32 hasAbility = FALSE; + u32 ability = GetBattlerAbility(gBattlerTarget); - // Check whether to apply to all moves. - if (effect[4] & ITEM4_HEAL_PP_ONE) + switch (ability) { - i = gBattleStruct->itemMoveIndex[gBattlerAttacker]; - loopEnd = i + 1; + case ABILITY_INNER_FOCUS: + case ABILITY_SCRAPPY: + case ABILITY_OWN_TEMPO: + case ABILITY_OBLIVIOUS: + if (B_UPDATED_INTIMIDATE >= GEN_8) + { + hasAbility = TRUE; + gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } + break; + case ABILITY_GUARD_DOG: + hasAbility = TRUE; + gBattlescriptCurrInstr = BattleScript_IntimidateInReverse; + break; + default: + gBattlescriptCurrInstr = cmd->nextInstr; + break; } - else + + if (hasAbility) { - i = 0; - loopEnd = MAX_MON_MOVES; + gLastUsedAbility = ability; + gBattlerAbility = gBattlerTarget; + RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } +} - // Check if the recipient is an active battler. - if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker]) - battler = gBattlerAttacker; - else if (IsDoubleBattle() - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)]) - battler = BATTLE_PARTNER(gBattlerAttacker); +void BS_JumpIfCanGigantamax(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); - // Heal PP! - for (; i < loopEnd; i++) - { - pp = GetMonData(mon, MON_DATA_PP1 + i, NULL); - moveId = GetMonData(mon, MON_DATA_MOVE1 + i, NULL); - maxPP = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), i); - if (pp != maxPP) - { - pp += effect[6]; - if (pp > maxPP) - pp = maxPP; - SetMonData(mon, MON_DATA_PP1 + i, &pp); + if (GetMonData(GetBattlerMon(battler), MON_DATA_GIGANTAMAX_FACTOR) + && GetGMaxTargetSpecies(gBattleMons[battler].species) != SPECIES_NONE) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} - // Update battler PP if needed. - if (battler != MAX_BATTLERS_COUNT - && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[battler] - && MOVE_IS_PERMANENT(battler, i)) - { - gBattleMons[battler].pp[i] = pp; - } - } - } - gBattleScripting.battler = battler; - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES)); - gBattlescriptCurrInstr = cmd->nextInstr; +void BS_JumpIfLastUsedItemHoldEffect(void) +{ + NATIVE_ARGS(u8 holdEffect, u16 secondaryId, const u8 *jumpInstr); + if (GetItemHoldEffect(gLastUsedItem) == cmd->holdEffect + && (cmd->secondaryId == 0 || GetItemSecondaryId(gLastUsedItem) == cmd->secondaryId)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryRevertWeatherForm(void) +void BS_JumpIfNoWhiteOut(void) { - NATIVE_ARGS(); - if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_BATTLE_WEATHER)) + NATIVE_ARGS(const u8 *jumpInstr); + + if (FlagGet(B_FLAG_NO_WHITEOUT)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryBoosterEnergy(void) +{ + NATIVE_ARGS(u8 onFieldStatus); + + for (u32 orderNum = 0; orderNum < gBattlersCount; orderNum++) { - gBattleScripting.battler = gBattlerTarget; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_TargetFormChangeWithStringNoPopup; - return; + u32 battlerByTurnOrder = gBattlerByTurnOrder[orderNum]; + if (GetBattlerHoldEffect(battlerByTurnOrder, TRUE) != HOLD_EFFECT_BOOSTER_ENERGY) + continue; + + u32 ability = GetBattlerAbility(battlerByTurnOrder); + if (!(ability == ABILITY_PROTOSYNTHESIS && cmd->onFieldStatus != ON_TERRAIN) + && !(ability == ABILITY_QUARK_DRIVE && cmd->onFieldStatus != ON_WEATHER)) + continue; + + if (TryBoosterEnergy(battlerByTurnOrder, ability, ITEMEFFECT_NONE)) + return; } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_HandleMegaEvolution(void) +void BS_JumpIfAbilityCantBeSuppressed(void) { - NATIVE_ARGS(u8 battler, u8 caseId); + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); - u8 battler = GetBattlerForBattleScript(cmd->battler); - HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_MEGA_EVOLUTION); - gBattlescriptCurrInstr = cmd->nextInstr; + if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_HandlePrimalReversion(void) +void BS_TryActivateAbilityShield(void) { - NATIVE_ARGS(u8 battler, u8 caseId); + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); - u8 battler = GetBattlerForBattleScript(cmd->battler); - HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_PRIMAL_REVERSION); gBattlescriptCurrInstr = cmd->nextInstr; + + if (GetBattlerAbilityNoAbilityShield(battler) != GetBattlerAbility(battler)) + { + gLastUsedItem = gBattleMons[battler].item; + RecordItemEffectBattle(battler, GetItemHoldEffect(gLastUsedItem)); + BattleScriptCall(BattleScript_AbilityShieldProtects); + } } -void BS_HandleUltraBurst(void) +void BS_TrySynchronoise(void) { - NATIVE_ARGS(u8 battler, u8 caseId); + NATIVE_ARGS(const u8 *jumpInstr); + bool32 atleastOneSharedType = FALSE; - u8 battler = GetBattlerForBattleScript(cmd->battler); - HandleScriptMegaPrimalBurst(cmd->caseId, battler, HANDLE_TYPE_ULTRA_BURST); - gBattlescriptCurrInstr = cmd->nextInstr; + for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) + { + if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SYNCHRONOISE_AFFECTED + || gBattlerAttacker == battlerDef + || !IsBattlerAlive(battlerDef)) + continue; + + if (DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + atleastOneSharedType = TRUE; + continue; + } + + if (!DoBattlersShareType(gBattlerAttacker, battlerDef)) + { + gBattleScripting.battler = battlerDef; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_NO_EFFECT | MOVE_RESULT_SYNCHRONOISE_AFFECTED; + BattleScriptCall(BattleScript_ItDoesntAffectFoe); + return; + } + } + + if (atleastOneSharedType) + gBattlescriptCurrInstr = cmd->nextInstr; + else + gBattlescriptCurrInstr = cmd->jumpInstr; +} + +void BS_JumpIfRoarFails(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + + if (WILD_DOUBLE_BATTLE + && IsOnPlayerSide(gBattlerAttacker) + && !IsOnPlayerSide(gBattlerTarget) + && IS_WHOLE_SIDE_ALIVE(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else if (WILD_DOUBLE_BATTLE + && !IsOnPlayerSide(gBattlerAttacker) + && !IsOnPlayerSide(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else if (FlagGet(B_FLAG_NO_RUNNING)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfShellTrap(void) +void BS_JumpIfAbsent(void) { NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - if (gProtectStructs[battler].shellTrap) + if (!IsBattlerAlive(GetBattlerForBattleScript(cmd->battler))) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfElectricAbilityAffected(void) +void BS_JumpIfHoldEffect(void) { - NATIVE_ARGS(u8 battler, u16 ability, const u8 *jumpInstr); + NATIVE_ARGS(u8 battler, u8 holdEffect, const u8 *jumpInstr, u8 equal); u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (IsElectricAbilityAffected(battler, cmd->ability)) + if ((GetBattlerHoldEffect(battler, TRUE) == cmd->holdEffect) == cmd->equal) + { + if (cmd->equal) + gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM gBattlescriptCurrInstr = cmd->jumpInstr; + } else + { + if (!cmd->equal) + gLastUsedItem = gBattleMons[battler].item; // For B_LAST_USED_ITEM gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_ApplySaltCure(void) +void BS_JumpIfNoAlly(void) { - NATIVE_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses4[battler] |= STATUS4_SALT_CURE; - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 partner = BATTLE_PARTNER(GetBattlerForBattleScript(cmd->battler)); + if (!IsBattlerAlive(partner)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SetTerrain(void) +void BS_InfatuateWithBattler(void) { - NATIVE_ARGS(const u8 *jumpInstr); - u32 statusFlag = 0; - - switch (GetMoveEffect(gCurrentMove)) - { - case EFFECT_MISTY_TERRAIN: - statusFlag = STATUS_FIELD_MISTY_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; - break; - case EFFECT_GRASSY_TERRAIN: - statusFlag = STATUS_FIELD_GRASSY_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY; - break; - case EFFECT_ELECTRIC_TERRAIN: - statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; - break; - case EFFECT_PSYCHIC_TERRAIN: - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - break; - case EFFECT_HIT_SET_TERRAIN: - statusFlag = GetMoveTerrainFlag(gCurrentMove); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - break; - default: - break; - } - enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - - gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; - gFieldStatuses |= statusFlag; - gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; + NATIVE_ARGS(u8 battler, u8 infatuateWith); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleScripting.battler = battler; + gBattleMons[battler].volatiles.infatuation = INFATUATED_WITH(GetBattlerForBattleScript(cmd->infatuateWith)); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfTerrainAffected(void) +void BS_SetLastUsedItem(void) { - NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (IsBattlerTerrainAffected(battler, cmd->flags)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(u8 battler); + gLastUsedItem = gBattleMons[GetBattlerForBattleScript(cmd->battler)].item; + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryReflectType(void) +void BS_TrySetFairyLock(void) { NATIVE_ARGS(const u8 *failInstr); - u16 targetBaseSpecies = GET_BASE_SPECIES_ID(gBattleMons[gBattlerTarget].species); - u32 targetTypes[3]; - GetBattlerTypes(gBattlerTarget, FALSE, targetTypes); - - if (targetBaseSpecies == SPECIES_ARCEUS || targetBaseSpecies == SPECIES_SILVALLY) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (IS_BATTLER_TYPELESS(gBattlerTarget)) + if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (targetTypes[0] == TYPE_MYSTERY && targetTypes[1] == TYPE_MYSTERY && targetTypes[2] != TYPE_MYSTERY) - { - gBattleMons[gBattlerAttacker].types[0] = TYPE_NORMAL; - gBattleMons[gBattlerAttacker].types[1] = TYPE_NORMAL; - gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else if (targetTypes[0] == TYPE_MYSTERY && targetTypes[1] != TYPE_MYSTERY) - { - gBattleMons[gBattlerAttacker].types[0] = targetTypes[1]; - gBattleMons[gBattlerAttacker].types[1] = targetTypes[1]; - gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else if (targetTypes[0] != TYPE_MYSTERY && targetTypes[1] == TYPE_MYSTERY) - { - gBattleMons[gBattlerAttacker].types[0] = targetTypes[0]; - gBattleMons[gBattlerAttacker].types[1] = targetTypes[0]; - gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; - gBattlescriptCurrInstr = cmd->nextInstr; - } else { - gBattleMons[gBattlerAttacker].types[0] = targetTypes[0]; - gBattleMons[gBattlerAttacker].types[1] = targetTypes[1]; - gBattleMons[gBattlerAttacker].types[2] = targetTypes[2]; + gFieldStatuses |= STATUS_FIELD_FAIRY_LOCK; + gFieldTimers.fairyLockTimer = gBattleTurnCounter + 2; gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_TrySetOctolock(void) +void BS_GetStatValue(void) { - NATIVE_ARGS(u8 battler, const u8 *failInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); + NATIVE_ARGS(u8 stat); + u32 stat = cmd->stat; + gBattleStruct->moveDamage[gBattlerAttacker] = *(u16 *)(&gBattleMons[gBattlerTarget].attack) + (stat - 1); + gBattleStruct->moveDamage[gBattlerAttacker] *= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][0]; + gBattleStruct->moveDamage[gBattlerAttacker] /= gStatStageRatios[gBattleMons[gBattlerTarget].statStages[stat]][1]; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (gDisableStructs[battler].octolock) - { - gBattlescriptCurrInstr = cmd->failInstr; - } +void BS_JumpIfFullHp(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + if (IsBattlerAtMaxHp(GetBattlerForBattleScript(cmd->battler))) + gBattlescriptCurrInstr = cmd->jumpInstr; else - { - gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].volatiles.escapePrevention = TRUE; - gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; - } } -void BS_SetGlaiveRush(void) +void BS_TryFriskMessage(void) { NATIVE_ARGS(); - gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH; - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_SetPledge(void) -{ - NATIVE_ARGS(const u8 *jumpInstr); - - u32 partner = BATTLE_PARTNER(gBattlerAttacker); - u32 partnerMove = gBattleMons[partner].moves[gBattleStruct->chosenMovePositions[partner]]; - u32 i = 0; - u32 k = 0; - - if (gBattleStruct->pledgeMove && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)) - { - PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker); - gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; - - if ((gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_WATER_PLEDGE) - || (gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE)) - { - gCurrentMove = MOVE_GRASS_PLEDGE; - gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Grass; - } - else if ((gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_GRASS_PLEDGE) - || (gCurrentMove == MOVE_GRASS_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE)) - { - gCurrentMove = MOVE_FIRE_PLEDGE; - gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Fire; - } - else if ((gCurrentMove == MOVE_WATER_PLEDGE && partnerMove == MOVE_FIRE_PLEDGE) - || (gCurrentMove == MOVE_FIRE_PLEDGE && partnerMove == MOVE_WATER_PLEDGE)) - { - gCurrentMove = MOVE_WATER_PLEDGE; - gBattlescriptCurrInstr = BattleScript_EffectCombinedPledge_Water; - } - - gBattleCommunication[MSG_DISPLAY] = 0; - } - else if ((gChosenActionByBattler[partner] == B_ACTION_USE_MOVE) - && IsDoubleBattle() - && IsBattlerAlive(partner) - && GetBattlerTurnOrderNum(gBattlerAttacker) < GetBattlerTurnOrderNum(partner) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && gCurrentMove != partnerMove - && GetMoveEffect(partnerMove) == EFFECT_PLEDGE) + while (gBattleStruct->friskedBattler < gBattlersCount) { - u32 currPledgeUser = 0; - u32 newTurnOrder[] = {0xFF, 0xFF}; - - for (i = 0; i < gBattlersCount; i++) + gBattlerTarget = gBattleStruct->friskedBattler++; + if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattleMons[gBattlerTarget].item != ITEM_NONE) { - if (gBattlerByTurnOrder[i] == gBattlerAttacker) + gLastUsedItem = gBattleMons[gBattlerTarget].item; + RecordItemEffectBattle(gBattlerTarget, GetBattlerHoldEffect(gBattlerTarget, FALSE)); + // If Frisk identifies two mons' items, show the pop-up only once. + if (gBattleStruct->friskedAbility) { - currPledgeUser = i + 1; // Current battler going after attacker - break; + BattleScriptCall(BattleScript_FriskMsg); } - } - for (i = currPledgeUser; i < gBattlersCount; i++) - { - if (gBattlerByTurnOrder[i] != partner) + else { - newTurnOrder[k] = gBattlerByTurnOrder[i]; - k++; + gBattleStruct->friskedAbility = TRUE; + BattleScriptCall(BattleScript_FriskMsgWithPopup); } + return; } + } + gBattleStruct->friskedBattler = 0; + gBattleStruct->friskedAbility = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattlerByTurnOrder[currPledgeUser] = partner; - currPledgeUser++; +void BS_SetTracedAbility(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = gBattleStruct->tracedAbility[battler]; + gBattlescriptCurrInstr = cmd->nextInstr; +} - for (i = 0; newTurnOrder[i] != 0xFF && i < 2; i++) - { - gBattlerByTurnOrder[currPledgeUser] = newTurnOrder[i]; - currPledgeUser++; - } +void BS_TryIllusionOff(void) +{ + NATIVE_ARGS(u8 battler); + if (TryClearIllusion(GetBattlerForBattleScript(cmd->battler), ABILITYEFFECT_MOVE_END)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleStruct->pledgeMove = TRUE; - gBattleScripting.battler = partner; +void BS_SetSpriteIgnore0Hp(void) +{ + NATIVE_ARGS(bool8 ignore0HP); + gBattleStruct->spriteIgnore0Hp = cmd->ignore0HP; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_UpdateNick(void) +{ + NATIVE_ARGS(); + u32 battler = gBattleScripting.battler; + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], GetBattlerMon(battler), HEALTHBOX_NICK); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfNotBerry(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + if (GetItemPocket(gBattleMons[GetBattlerForBattleScript(cmd->battler)].item) == POCKET_BERRIES) gBattlescriptCurrInstr = cmd->nextInstr; - } else - { - gBattleStruct->pledgeMove = FALSE; gBattlescriptCurrInstr = cmd->jumpInstr; - } } -void BS_SetPledgeStatus(void) +void BS_GravityOnAirborneMons(void) { - NATIVE_ARGS(u8 battler, u32 sideStatus); + NATIVE_ARGS(); + // Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop. + if (gStatuses3[gBattlerTarget] & STATUS3_ON_AIR && !(gStatuses3[gBattlerTarget] & STATUS3_SKY_DROPPED)) + CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_GRAVITY_ON_AIRBORNE); - u32 battler = GetBattlerForBattleScript(cmd->battler); - u32 side = GetBattlerSide(battler); + gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleStruct->pledgeMove = FALSE; - if (!(gSideStatuses[side] & cmd->sideStatus)) +void BS_TryAcupressure(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 bits = 0; + for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) { - gSideStatuses[side] |= cmd->sideStatus; - - switch (cmd->sideStatus) + if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + bits |= 1u << stat; + } + if (bits) + { + u32 statId; + do { - case SIDE_STATUS_RAINBOW: - gSideTimers[side].rainbowTimer = gBattleTurnCounter + 4; - break; - case SIDE_STATUS_SEA_OF_FIRE: - gSideTimers[side].seaOfFireTimer = gBattleTurnCounter + 4; - break; - case SIDE_STATUS_SWAMP: - gSideTimers[side].swampTimer = gBattleTurnCounter + 4; - } + statId = (Random() % (NUM_BATTLE_STATS - 1)) + 1; + } while (!(bits & (1u << statId))); + SET_STATCHANGER(statId, 2, FALSE); gBattlescriptCurrInstr = cmd->nextInstr; } else - gBattlescriptCurrInstr = BattleScript_MoveEnd; + { + gBattlescriptCurrInstr = cmd->failInstr; + } } -void BS_TryTrainerSlideZMoveMsg(void) +void BS_CancelMultiTurnMoves(void) { NATIVE_ARGS(); - s32 shouldSlide; - - if ((shouldSlide = ShouldDoTrainerSlide(gBattlerAttacker, TRAINER_SLIDE_Z_MOVE))) - { - gBattleScripting.battler = gBattlerAttacker; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - } + const u8 *result = CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_CANCEL_MULTI_TURN_MOVES); + if (result) + gBattlescriptCurrInstr = result; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryTrainerSlideMegaEvolutionMsg(void) +void BS_IsRunningImpossible(void) { NATIVE_ARGS(); - s32 shouldSlide; - - if ((shouldSlide = ShouldDoTrainerSlide(gBattlerAttacker, TRAINER_SLIDE_MEGA_EVOLUTION))) - { - gBattleScripting.battler = gBattlerAttacker; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - } - else - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleCommunication[0] = IsRunningFromBattleImpossible(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryTrainerSlideDynamaxMsg(void) +void BS_GetMoveTarget(void) { NATIVE_ARGS(); - s32 shouldSlide; - - if ((shouldSlide = ShouldDoTrainerSlide(gBattleScripting.battler, TRAINER_SLIDE_DYNAMAX))) - { - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = (shouldSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); - } - else - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlerTarget = GetBattleMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryHealPulse(void) +void BS_GetBattlerFainted(void) { - NATIVE_ARGS(const u8 *failInstr); - - if (IsBattlerAtMaxHp(gBattlerTarget)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + NATIVE_ARGS(u8 battler); + if (gHitMarker & HITMARKER_FAINTED(GetBattlerForBattleScript(cmd->battler))) + gBattleCommunication[0] = TRUE; else - { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_MEGA_LAUNCHER && IsPulseMove(gCurrentMove)) - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 75 / 100); - else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && GetMoveEffectArg_MoveProperty(gCurrentMove) == MOVE_EFFECT_FLORAL_HEALING) - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) * 2 / 3); - else - gBattleStruct->moveDamage[gBattlerTarget] = -(GetNonDynamaxMaxHP(gBattlerTarget) / 2); - - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = -1; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gBattleCommunication[0] = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryCopycat(void) +void BS_ResetSwitchInAbilityBits(void) { - NATIVE_ARGS(const u8 *failInstr); + NATIVE_ARGS(); + gSpecialStatuses[gBattlerAttacker].switchInAbilityDone = FALSE; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (gLastUsedMove == MOVE_NONE || gLastUsedMove == MOVE_UNAVAILABLE || IsMoveCopycatBanned(gLastUsedMove) || IsZMove(gLastUsedMove)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else +void BS_UpdateChoiceMoveOnLvlUp(void) +{ + NATIVE_ARGS(); + if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId || gBattlerPartyIndexes[2] == gBattleStruct->expGetterMonId) { - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(gLastUsedMove)) - { - gBattleStruct->zmove.baseMoves[gBattlerAttacker] = gLastUsedMove; - gCalledMove = GetTypeBasedZMove(gLastUsedMove); - } - else if (IsMaxMove(gLastUsedMove)) - { - gCalledMove = gBattleStruct->dynamax.lastUsedBaseMove; - } + u32 battler; + if (gBattlerPartyIndexes[0] == gBattleStruct->expGetterMonId) + battler = 0; else + battler = 2; + + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { - gCalledMove = gLastUsedMove; + if (gBattleMons[battler].moves[moveIndex] == gBattleStruct->choicedMove[battler]) + break; } - - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gBattlescriptCurrInstr = cmd->nextInstr; + if (moveIndex == MAX_MON_MOVES) + gBattleStruct->choicedMove[battler] = MOVE_NONE; } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryDefog(void) +void BS_ResetPlayerFainted(void) { - NATIVE_ARGS(u8 clear, const u8 *failInstr); - - if (cmd->clear) + NATIVE_ARGS(); + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE)) + && gBattleTypeFlags & BATTLE_TYPE_TRAINER + && IsBattlerAlive(B_POSITION_PLAYER_LEFT) + && IsBattlerAlive(B_POSITION_OPPONENT_LEFT)) { - if (TryDefogClear(gEffectBattler, TRUE)) - return; - else - gBattlescriptCurrInstr = cmd->nextInstr; + gHitMarker &= ~HITMARKER_PLAYER_FAINTED; } - else + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_PalaceFlavorText(void) +{ + NATIVE_ARGS(); + // Try and print end-of-turn Battle Palace flavor text (e.g. "A glint appears in mon's eyes") + u32 battler; + gBattleCommunication[0] = FALSE; // whether or not msg should be printed + gBattleScripting.battler = battler = gBattleCommunication[1]; + if (!(gBattleStruct->palaceFlags & (1u << battler)) + && gBattleMons[battler].maxHP / 2 >= gBattleMons[battler].hp + && IsBattlerAlive(battler) + && !(gBattleMons[battler].status1 & STATUS1_SLEEP)) { - if (TryDefogClear(gBattlerAttacker, FALSE)) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->failInstr; + gBattleStruct->palaceFlags |= 1u << battler; + gBattleCommunication[0] = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = gNaturesInfo[GetNatureFromPersonality(gBattleMons[battler].personality)].battlePalaceFlavorText; } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryUpperHand(void) +void BS_ArenaJudgmentWindow(void) { - NATIVE_ARGS(const u8 *failInstr); + NATIVE_ARGS(); + u32 judgmentWindow = BattleArena_ShowJudgmentWindow(&gBattleCommunication[0]); - u32 abilityDef = GetBattlerAbility(gBattlerTarget); - u32 prio = GetChosenMovePriority(gBattlerTarget, abilityDef); + // BattleArena_ShowJudgmentWindow's last state was an intermediate step. + // Return without advancing the current instruction so that it will be called again. + if (judgmentWindow == ARENA_RESULT_RUNNING) + return; - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) - || gChosenMoveByBattler[gBattlerTarget] == MOVE_NONE - || IsBattleMoveStatus(gChosenMoveByBattler[gBattlerTarget]) - || prio < 1 - || prio > 3) // Fails if priority is less than 1 or greater than 3, if target already moved, or if using a status - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleCommunication[1] = judgmentWindow; + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryTriggerStatusForm(void) +static void SetArenMonLostValues(u32 battler) +{ + gBattleMons[battler].hp = 0; + gHitMarker |= HITMARKER_FAINTED(battler); + gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[battler]; + gDisableStructs[battler].truantSwitchInHack = TRUE; +} + +#define playerMon 0 +#define opponentMon 1 +void BS_ArenaOpponentMonLost(void) { NATIVE_ARGS(); - if (TryBattleFormChange(gBattlerTarget, FORM_CHANGE_STATUS)) - { - gBattleScripting.battler = gBattlerTarget; - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_TargetFormChangeWithStringNoPopup; - return; - } + SetArenMonLostValues(opponentMon); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_AllySwitchSwapBattler(void) +void BS_ArenaPlayerMonLost(void) { NATIVE_ARGS(); + SetArenMonLostValues(playerMon); + gBattlescriptCurrInstr = cmd->nextInstr; +} - gBattleScripting.battler = gBattlerAttacker; - gBattlerAttacker ^= BIT_FLANK; - gProtectStructs[gBattlerAttacker].usedAllySwitch = TRUE; +void BS_ArenaBothMonsLost(void) +{ + NATIVE_ARGS(); + SetArenMonLostValues(playerMon); + SetArenMonLostValues(opponentMon); gBattlescriptCurrInstr = cmd->nextInstr; } +#undef playerMon +#undef opponentMon -void BS_TryAllySwitch(void) +void BS_ForfeitYesNoBox(void) { - NATIVE_ARGS(const u8 *failInstr); + NATIVE_ARGS(); + BtlController_EmitYesNoBox(gBattlerAttacker, B_COMM_TO_CONTROLLER); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (!IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) - || (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - || (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9) - { - TryResetProtectUseCounter(gBattlerAttacker); - if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random()) - { - gDisableStructs[gBattlerAttacker].protectUses = 0; - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - gDisableStructs[gBattlerAttacker].protectUses++; - gBattlescriptCurrInstr = cmd->nextInstr; - } - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; - } +void BS_DrawArenaRefTextBox(void) +{ + NATIVE_ARGS(); + DrawArenaRefereeTextBox(); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_RunStatChangeItems(void) +void BS_EraseArenaRefTextBox(void) { - NATIVE_ARGS(u8 battler); + NATIVE_ARGS(); + EraseArenaRefereeTextBox(); + gBattlescriptCurrInstr = cmd->nextInstr; +} - // Change instruction before calling ItemBattleEffects. +void BS_ArenaJudgmentString(void) +{ + CMD_ARGS(u8 id); + BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[cmd->id]); + BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGMENT_TEXT); gBattlescriptCurrInstr = cmd->nextInstr; - ItemBattleEffects(ITEMEFFECT_STATS_CHANGED, GetBattlerForBattleScript(cmd->battler)); } -static void TryUpdateEvolutionTracker(u32 evolutionCondition, u32 upAmount, u16 usedMove) +// Argument passed but no use +void BS_ArenaWaitMessage(void) { - u32 i, j; + NATIVE_ARGS(); + if (IsTextPrinterActive(ARENA_WIN_JUDGMENT_TEXT)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (IsOnPlayerSide(gBattlerAttacker) - && !(gBattleTypeFlags & (BATTLE_TYPE_LINK - | BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_RECORDED_LINK - | BATTLE_TYPE_TRAINER_HILL - | BATTLE_TYPE_FRONTIER))) +void BS_WaitCry(void) +{ + NATIVE_ARGS(); + if (!IsCryFinished()) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +#define opponentFirstBattler 1 +#define opponentSecondBattler 3 +void BS_ReturnOpponentMon1ToBall(void) +{ + NATIVE_ARGS(); + if (IsBattlerAlive(opponentFirstBattler)) { - const struct Evolution *evolutions = GetSpeciesEvolutions(gBattleMons[gBattlerAttacker].species); - if (evolutions == NULL) - return; + BtlController_EmitReturnMonToBall(opponentFirstBattler, B_COMM_TO_CONTROLLER, FALSE); + MarkBattlerForControllerExec(opponentFirstBattler); + } + gBattlescriptCurrInstr = cmd->nextInstr; +} - for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) +void BS_ReturnOpponentMon2ToBall(void) +{ + NATIVE_ARGS(); + if (gBattlersCount > opponentSecondBattler) + { + if (IsBattlerAlive(opponentSecondBattler)) { - if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) - continue; - if (evolutions[i].params == NULL) - continue; - - for (j = 0; evolutions[i].params[j].condition != CONDITIONS_END; j++) - { - if (evolutions[i].params[j].condition == evolutionCondition) - { - struct Pokemon *monAtk = GetBattlerMon(gBattlerAttacker); - struct Pokemon *monDef = GetBattlerMon(gBattlerTarget); - // We only have 10 bits to use - u16 val = min(1023, GetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER) + upAmount); - // Reset progress if you faint for the recoil method. - switch (evolutionCondition) - { - case IF_USED_MOVE_X_TIMES: - if (evolutions[i].params[j].arg1 == usedMove) - SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); - break; - case IF_RECOIL_DAMAGE_GE: - if (gBattleMons[gBattlerAttacker].hp == 0) - val = 0; - SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); - break; - case IF_DEFEAT_X_WITH_ITEMS: - if (GetMonData(monDef, MON_DATA_SPECIES) == evolutions[i].params[j].arg1 - && GetMonData(monDef, MON_DATA_HELD_ITEM) == evolutions[i].params[j].arg2) - SetMonData(monAtk, MON_DATA_EVOLUTION_TRACKER, &val); - break; - } - return; - } - } + BtlController_EmitReturnMonToBall(opponentSecondBattler, B_COMM_TO_CONTROLLER, FALSE); + MarkBattlerForControllerExec(opponentSecondBattler); } } + gBattlescriptCurrInstr = cmd->nextInstr; +} +#undef opponentFirstBattler +#undef opponentSecondBattler + +void BS_VolumeDown(void) +{ + NATIVE_ARGS(); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x55); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_VolumeUp(void) +{ + NATIVE_ARGS(); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryUpdateRecoilTracker(void) +void BS_SetAlreadyStatusedMoveAttempt(void) { NATIVE_ARGS(); - TryUpdateEvolutionTracker(IF_RECOIL_DAMAGE_GE, gBattleStruct->moveDamage[gBattlerAttacker], MOVE_NONE); + gBattleStruct->battlerState[gBattlerAttacker].alreadyStatusedMoveAttempt = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryUpdateLeadersCrestTracker(void) +void BS_PalaceTryEscapeStatus(void) { NATIVE_ARGS(); - TryUpdateEvolutionTracker(IF_DEFEAT_X_WITH_ITEMS, 1, MOVE_NONE); + if (BattlePalace_TryEscapeStatus(gBattlerAttacker)) + return; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryTidyUp(void) +void BS_SetTeleportOutcome(void) { - NATIVE_ARGS(u8 clear, const u8 *jumpInstr); + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); - if (cmd->clear) + // Don't end the battle if one of the wild mons teleported from the wild double battle + // and its partner is still alive. + if (!IsOnPlayerSide(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))) { - if (TryTidyUpClear(gEffectBattler, TRUE)) - return; - else - gBattlescriptCurrInstr = cmd->nextInstr; + gAbsentBattlerFlags |= 1u << battler; + gHitMarker |= HITMARKER_FAINTED(battler); + gBattleMons[battler].hp = 0; + SetMonData(GetBattlerMon(battler), MON_DATA_HP, &gBattleMons[battler].hp); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[battler]); + FaintClearSetData(battler); + } + else if (IsOnPlayerSide(battler)) + { + gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED; } else { - if (TryTidyUpClear(gBattlerAttacker, FALSE)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleOutcome = B_OUTCOME_MON_TELEPORTED; } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryGulpMissile(void) +void BS_PlayTrainerDefeatedMusic(void) { NATIVE_ARGS(); + BtlController_EmitPlayFanfareOrBGM(gBattlerAttacker, B_COMM_TO_CONTROLLER, MUS_VICTORY_TRAINER, TRUE); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) - && (gCurrentMove == MOVE_DIVE) - && GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE - && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) - gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; - else - gBattlescriptCurrInstr = cmd->nextInstr; +void BS_StatTextBuffer(void) +{ + NATIVE_ARGS(); + PREPARE_STAT_BUFFER(gBattleTextBuff1, gBattleCommunication[0]); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryActivateGulpMissile(void) +void BS_SwitchinAbilities(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlescriptCurrInstr = cmd->nextInstr; + AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); +} + +void BS_InstantHpDrop(void) +{ + NATIVE_ARGS(); + BtlController_EmitHealthBarUpdate(gBattlerAttacker, B_COMM_TO_CONTROLLER, INSTANT_HP_BAR_DROP); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_ClearStatus(void) { NATIVE_ARGS(); + gBattleMons[gBattlerAttacker].status1 = 0; + BtlController_EmitSetMonData( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + sizeof(gBattleMons[gBattlerAttacker].status1), + &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (!gProtectStructs[gBattlerAttacker].confusionSelfDmg - && IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget) - && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT - && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) +// NEW BATCH + +void BS_RestoreMovePp(void) +{ + NATIVE_ARGS(); + u32 moveIndex; + u32 data[MAX_MON_MOVES + 1]; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - } + gBattleMons[gBattlerAttacker].pp[moveIndex] = CalculatePPWithBonus(gBattleMons[gBattlerAttacker].moves[moveIndex], gBattleMons[gBattlerAttacker].ppBonuses, moveIndex); + data[moveIndex] = gBattleMons[gBattlerAttacker].pp[moveIndex]; + } + data[moveIndex] = gBattleMons[gBattlerAttacker].ppBonuses; + BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_PP_DATA_BATTLE, 0, 5, data); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - switch(gBattleMons[gBattlerTarget].species) +void BS_TryActivateReceiver(void) +{ + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattlerAbility = BATTLE_PARTNER(battler); + u32 partnerAbility = GetBattlerAbility(gBattlerAbility); + if (IsBattlerAlive(gBattlerAbility) + && (partnerAbility == ABILITY_RECEIVER || partnerAbility == ABILITY_POWER_OF_ALCHEMY) + && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD + && !gAbilitiesInfo[gBattleMons[battler].ability].cantBeCopied) + { + gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_ReceiverActivates; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_TryActivateSoulheart(void) +{ + NATIVE_ARGS(); + while (gBattleStruct->soulheartBattlerId < gBattlersCount) + { + gBattleScripting.battler = gBattleStruct->soulheartBattlerId++; + if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART + && IsBattlerAlive(gBattleScripting.battler) + && !NoAliveMonsForEitherParty() + && CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { - case SPECIES_CRAMORANT_GORGING: - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); - BattleScriptCall(BattleScript_GulpMissileGorging); - return; - case SPECIES_CRAMORANT_GULPING: - TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); - BattleScriptCall(BattleScript_GulpMissileGulping); - return; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); + BattleScriptCall(BattleScript_ScriptingAbilityStatRaise); + return; } } + gBattleStruct->soulheartBattlerId = 0; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryQuash(void) +void BS_PlayMoveAnimation(void) { - NATIVE_ARGS(const u8 *failInstr); - u32 i, j; + NATIVE_ARGS(u16 move); + BtlController_EmitMoveAnimation( + gBattlerAttacker, + B_COMM_TO_CONTROLLER, + cmd->move, + gBattleScripting.animTurn, + 0, + 0, + gBattleMons[gBattlerAttacker].friendship, + &gDisableStructs[gBattlerAttacker], + gMultiHitCounter); + MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->nextInstr; +} - // It's true if foe is faster, has a bigger priority, or switches - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) +void BS_SetLuckyChant(void) +{ + NATIVE_ARGS(const u8 *failInstr); + u32 side = GetBattlerSide(gBattlerAttacker); + if (!(gSideStatuses[side] & SIDE_STATUS_LUCKY_CHANT)) + { + gSideStatuses[side] |= SIDE_STATUS_LUCKY_CHANT; + gSideTimers[side].luckyChantTimer = gBattleTurnCounter + 5; + gBattlescriptCurrInstr = cmd->nextInstr; + } + else { gBattlescriptCurrInstr = cmd->failInstr; - return; } +} - // If the above condition is not true, it means we are faster than the foe, so we can set the quash bit - gProtectStructs[gBattlerTarget].quash = TRUE; +void BS_SuckerPunchCheck(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gProtectStructs[gBattlerTarget].protected == PROTECT_OBSTRUCT) + gBattlescriptCurrInstr = cmd->failInstr; + else if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) + gBattlescriptCurrInstr = cmd->failInstr; + else if (IsBattleMoveStatus(gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]) && !gProtectStructs[gBattlerTarget].noValidMoves) + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} - // this implementation assumes turn order is correct when using Quash - i = GetBattlerTurnOrderNum(gBattlerTarget); - for (j = i + 1; j < gBattlersCount; j++) +void BS_SetSimpleBeam(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten + || gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE) { - // Gen 7- config makes target go last so that the order of quash targets is kept for the correct turn order - // Gen 8+ config alters Turn Order of the target according to speed, dynamic speed should handle the rest - if (B_QUASH_TURN_ORDER < GEN_8 || GetWhichBattlerFaster(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], FALSE) == -1) - SwapTurnOrder(i, j); - else - break; - i++; + RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); + gBattlescriptCurrInstr = cmd->failInstr; + } + else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; + gBattlescriptCurrInstr = cmd->nextInstr; } - gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_CopyFoesStatIncrease(void) +void BS_TryEntrainment(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - u32 stat = 0; - u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (gQueuedStatBoosts[battler].stats == 0) + NATIVE_ARGS(const u8 *failInstr); + if (gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeCopied + || gAbilitiesInfo[gBattleMons[gBattlerTarget].ability].cantBeOverwritten) { - for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++) - { - if (gQueuedStatBoosts[battler].statChanges[stat] != 0) - gQueuedStatBoosts[battler].stats |= (1 << stat); - } - gBattlescriptCurrInstr = cmd->jumpInstr; - return; + RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); + gBattlescriptCurrInstr = cmd->failInstr; } - - for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++) + else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) { - if (gQueuedStatBoosts[battler].stats & (1 << stat)) + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + if (gBattleMons[gBattlerTarget].ability == gBattleMons[gBattlerAttacker].ability + || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) { - if (gQueuedStatBoosts[battler].statChanges[stat] <= -1) - SET_STATCHANGER(stat + 1, abs(gQueuedStatBoosts[battler].statChanges[stat]), TRUE); - else - SET_STATCHANGER(stat + 1, gQueuedStatBoosts[battler].statChanges[stat], FALSE); - - gQueuedStatBoosts[battler].stats &= ~(1 << stat); - gBattlerTarget = battler; + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; gBattlescriptCurrInstr = cmd->nextInstr; - return; } } - gBattlescriptCurrInstr = cmd->jumpInstr; } -void BS_RemoveWeather(void) +void BS_SetLastUsedAbility(void) { NATIVE_ARGS(); - RemoveAllWeather(); + gLastUsedAbility = gBattleMons[gBattlerTarget].ability; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ApplyTerastallization(void) +void BS_InvertStatStages(void) { NATIVE_ARGS(); - ApplyBattlerVisualsForTeraAnim(gBattlerAttacker); + for (u32 i = 0; i < NUM_BATTLE_STATS; i++) + { + if (gBattleMons[gBattlerTarget].statStages[i] < DEFAULT_STAT_STAGE) // Negative becomes positive. + gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE + (DEFAULT_STAT_STAGE - gBattleMons[gBattlerTarget].statStages[i]); + else if (gBattleMons[gBattlerTarget].statStages[i] > DEFAULT_STAT_STAGE) // Positive becomes negative. + gBattleMons[gBattlerTarget].statStages[i] = DEFAULT_STAT_STAGE - (gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE); + } gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfSleepClause(void) +void BS_TryMeFirst(void) { - NATIVE_ARGS(const u8 *jumpInstr); - - // Can freely sleep own partner - if (IsDoubleBattle() && IsSleepClauseEnabled() && IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) + NATIVE_ARGS(const u8 *failInstr); + u16 move = gBattleMons[gBattlerTarget].moves[gBattleStruct->chosenMovePositions[gBattlerTarget]]; + if (IsBattleMoveStatus(move) || IsMoveMeFirstBanned(move) + || GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) { - gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gBattlescriptCurrInstr = cmd->failInstr; } - gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = FALSE; - // Can't sleep if clause is active otherwise - if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) - gBattlescriptCurrInstr = cmd->jumpInstr; else + { + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !IsBattleMoveStatus(move)) + { + gBattleStruct->zmove.baseMoves[gBattlerAttacker] = move; + gCalledMove = GetTypeBasedZMove(move); + } + else + { + gCalledMove = move; + } + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_FickleBeamDamageCalculation(void) +void BS_TryElectrify(void) { - NATIVE_ARGS(); - - if (RandomPercentage(RNG_FICKLE_BEAM, 30)) + NATIVE_ARGS(const u8 *failInstr); + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) { - gBattleStruct->fickleBeamBoosted = TRUE; - gBattlescriptCurrInstr = BattleScript_FickleBeamDoubled; + gBattlescriptCurrInstr = cmd->failInstr; } else { + gStatuses4[gBattlerTarget] |= STATUS4_ELECTRIFIED; gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_TryTarShot(void) +void BS_TrySoak(void) { NATIVE_ARGS(const u8 *failInstr); - if (gDisableStructs[gBattlerTarget].tarShot || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + u32 types[3]; + GetBattlerTypes(gBattlerTarget, FALSE, types); + u32 typeToSet = GetMoveArgType(gCurrentMove); + if ((types[0] == typeToSet && types[1] == typeToSet) + || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gDisableStructs[gBattlerTarget].tarShot = TRUE; + SET_BATTLER_TYPE(gBattlerTarget, typeToSet); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, typeToSet); + gBattlescriptCurrInstr = cmd->nextInstr; + } +} + +void BS_HandleFormChange(void) +{ + NATIVE_ARGS(u8 battler, u8 case_); + u32 battler = GetBattlerForBattleScript(cmd->battler); + struct Pokemon *mon = GetBattlerMon(battler); + + if (cmd->case_ == 0) // Change species. + { + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_SPECIES_BATTLE, 1u << gBattlerPartyIndexes[battler], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); + MarkBattlerForControllerExec(battler); + } + else if (cmd->case_ == 1) // Change stats. + { + RecalcBattlerStats(battler, mon, FALSE); + } + else // Update healthbox. + { + UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_TryLastResort(void) +{ + NATIVE_ARGS(const u8 *failInstr); + if (CanUseLastResort(gBattlerAttacker)) gBattlescriptCurrInstr = cmd->nextInstr; - } + else + gBattlescriptCurrInstr = cmd->failInstr; } -void BS_CanTarShotWork(void) +void BS_TryAutotomize(void) { NATIVE_ARGS(const u8 *failInstr); - // Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further - if (!gDisableStructs[gBattlerTarget].tarShot - && CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) + if (GetBattlerWeight(gBattlerAttacker) > 1) + { + gDisableStructs[gBattlerAttacker].autotomizeCount++; gBattlescriptCurrInstr = cmd->nextInstr; + } else + { gBattlescriptCurrInstr = cmd->failInstr; + } } -void BS_JumpIfBlockedBySoundproof(void) +void BS_TryInstruct(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (IsSoundMove(gCurrentMove) && GetBattlerAbility(battler) == ABILITY_SOUNDPROOF) + NATIVE_ARGS(const u8 *failInstr); + u16 move = gLastPrintedMoves[gBattlerTarget]; + if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasAdditionalEffectSelf(move, MOVE_EFFECT_RECHARGE) + || IsMoveInstructBanned(move) + || gBattleMoveEffects[GetMoveEffect(move)].twoTurnEffect + || (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) + || IsZMove(move) + || IsMaxMove(move)) { - gLastUsedAbility = ABILITY_SOUNDPROOF; - gBattlescriptCurrInstr = cmd->jumpInstr; - RecordAbilityBattle(battler, gLastUsedAbility); - gBattlerAbility = battler; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattlescriptCurrInstr = cmd->nextInstr; + gSpecialStatuses[gBattlerTarget].instructedChosenTarget = gBattleStruct->moveTarget[gBattlerTarget] | 0x4; + gCalledMove = move; + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (gBattleMons[gBattlerTarget].moves[moveIndex] == gCalledMove) + { + gCurrMovePos = moveIndex; + moveIndex = 4; + break; + } + } + if (moveIndex != 4 || gBattleMons[gBattlerTarget].pp[gCurrMovePos] == 0) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gEffectBattler = gBattleStruct->lastMoveTarget[gBattlerTarget]; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); + gBattlescriptCurrInstr = cmd->nextInstr; + } } } -void BS_SetMagicCoatTarget(void) +void BS_ShowAbilityPopup(void) { NATIVE_ARGS(); - gBattleStruct->attackerBeforeBounce = gBattleScripting.battler = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = gBattleStruct->attackerBeforeBounce; - HandleMoveTargetRedirection(); - + CreateAbilityPopUp(gBattlerAbility, gBattleMons[gBattlerAbility].ability, (IsDoubleBattle()) != 0); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TeatimeInvul(void) +void BS_UpdateAbilityPopup(void) { - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + NATIVE_ARGS(); + UpdateAbilityPopup(gBattlerAbility); + gBattlescriptCurrInstr = cmd->nextInstr; +} - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))) +void BS_JumpIfTargetAlly(void) +{ + NATIVE_ARGS(const u8 *jumpInstr); + if (!IsBattlerAlly(gBattlerAttacker, gBattlerTarget)) gBattlescriptCurrInstr = cmd->nextInstr; else gBattlescriptCurrInstr = cmd->jumpInstr; } -void BS_TeatimeTargets(void) +void BS_TryPsychoShift(void) { - NATIVE_ARGS(const u8 *failInstr); - u32 count = 0, i; - - for (i = 0; i < gBattlersCount; i++) + NATIVE_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr); + u32 targetAbility = GetBattlerAbility(gBattlerTarget); + // Psycho shift works + if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) { - if (IsTeatimeAffected(i)) - count++; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; } - if (count == 0) - gBattlescriptCurrInstr = cmd->failInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_TryWindRiderPower(void) -{ - NATIVE_ARGS(u8 battler, const u8 *failInstr); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - u16 ability = GetBattlerAbility(battler); - if (IsBattlerAlly(battler, gBattlerAttacker) - && (ability == ABILITY_WIND_RIDER || ability == ABILITY_WIND_POWER)) + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_TOXIC_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), targetAbility)) { - gLastUsedAbility = ability; - RecordAbilityBattle(battler, gLastUsedAbility); - gBattlerAbility = gBattleScripting.battler = battler; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_BURN) && CanBeBurned(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerAttacker, gBattlerTarget, targetAbility, BLOCKED_BY_SLEEP_CLAUSE)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 4; + } + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerAttacker, gBattlerTarget, targetAbility)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + } + else if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) + { + gBattlescriptCurrInstr = cmd->sleepClauseFailInstr; + return; } else { gBattlescriptCurrInstr = cmd->failInstr; + return; } + gBattleMons[gBattlerTarget].status1 = gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY; + BtlController_EmitSetMonData( + gBattlerTarget, + B_COMM_TO_CONTROLLER, + REQUEST_STATUS_BATTLE, + 0, + sizeof(gBattleMons[gBattlerTarget].status1), + &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ActivateWeatherChangeAbilities(void) +void BS_CureStatus(void) { NATIVE_ARGS(u8 battler); - u32 battler = GetBattlerForBattleScript(cmd->battler); - gBattlescriptCurrInstr = cmd->nextInstr; - AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); -} -void BS_ActivateTerrainChangeAbilities(void) -{ - NATIVE_ARGS(u8 battler); + if (gBattleMons[battler].status1 & STATUS1_SLEEP) + TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); - u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleMons[battler].status1 = 0; + BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1); + MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; - AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); } -void BS_StoreHealingWish(void) +void BS_PowerTrick(void) { - NATIVE_ARGS(u8 battler); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gCurrentMove == MOVE_LUNAR_DANCE) - gBattleStruct->battlerState[battler].storedLunarDance = TRUE; - else - gBattleStruct->battlerState[battler].storedHealingWish = TRUE; + NATIVE_ARGS(); + u32 temp; + gStatuses3[gBattlerAttacker] ^= STATUS3_POWER_TRICK; + SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerAttacker].defense, temp); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryRevivalBlessing(void) +void BS_TryAfterYou(void) { NATIVE_ARGS(const u8 *failInstr); - u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker); - - // Move fails if there are no battlers to revive. - if (index == PARTY_SIZE) + if (ChangeOrderTargetAfterAttacker()) { - gBattlescriptCurrInstr = cmd->failInstr; - return; - } - - // Battler selected! Revive and go to next instruction. - if (gSelectedMonPartyId != PARTY_SIZE) - { - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - - u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2; - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 1u << gSelectedMonPartyId, sizeof(hp), &hp); - MarkBattlerForControllerExec(gBattlerAttacker); - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES)); - - // If an on-field battler is revived, it needs to be sent out again. - if (IsDoubleBattle() && - gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId) - { - u32 i = BATTLE_PARTNER(gBattlerAttacker); - gAbsentBattlerFlags &= ~(1u << i); - gBattleStruct->monToSwitchIntoId[i] = gSelectedMonPartyId; - gBattleScripting.battler = i; - gBattleCommunication[MULTIUSE_STATE] = TRUE; - } - - gSelectedMonPartyId = PARTY_SIZE; + gSpecialStatuses[gBattlerTarget].afterYou = 1; gBattlescriptCurrInstr = cmd->nextInstr; } else { - // Open party menu, wait to go to next instruction. - BtlController_EmitChoosePokemon(gBattlerAttacker, B_COMM_TO_CONTROLLER, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, 0, gBattleStruct->battlerPartyOrders[gBattlerAttacker]); - MarkBattlerForControllerExec(gBattlerAttacker); + gBattlescriptCurrInstr = cmd->failInstr; } } -void BS_JumpIfCommanderActive(void) +void BS_TryBestow(void) { - NATIVE_ARGS(const u8 *jumpInstr); - - if (gBattleStruct->commanderActive[gBattlerTarget] != SPECIES_NONE) - gBattlescriptCurrInstr = cmd->jumpInstr; - else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER) - gBattlescriptCurrInstr = cmd->jumpInstr; + NATIVE_ARGS(const u8 *failInstr); + if (gBattleMons[gBattlerAttacker].item == ITEM_NONE + || gBattleMons[gBattlerTarget].item != ITEM_NONE + || !CanBattlerGetOrLoseItem(gBattlerAttacker, gBattleMons[gBattlerAttacker].item) + || !CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerAttacker].item) + || gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) + { + gBattlescriptCurrInstr = cmd->failInstr; + } else + { + BestowItem(gBattlerAttacker, gBattlerTarget); gBattlescriptCurrInstr = cmd->nextInstr; + } } -static void UpdatePokeFlutePartyStatus(struct Pokemon* party, u8 position) +void BS_HandleTrainerSlideMsg(void) { - s32 i; - u8 battler; - u32 monToCheck, status; - u16 species, abilityNum; - monToCheck = 0; - for (i = 0; i < PARTY_SIZE; i++) + NATIVE_ARGS(u8 battler, u8 case_); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (cmd->case_ == PRINT_SLIDE_MESSAGE) { - species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); - abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM); - status = GetMonData(&party[i], MON_DATA_STATUS); - if (species != SPECIES_NONE - && species != SPECIES_EGG - && status & AILMENT_FNT - && GetAbilityBySpecies(species, abilityNum) != ABILITY_SOUNDPROOF) - monToCheck |= (1 << i); + BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, STRINGID_TRAINERSLIDE); + MarkBattlerForControllerExec(battler); } - if (monToCheck) + else if (cmd->case_ == RESTORE_BATTLER_SLIDE_CONTROL) { - battler = GetBattlerAtPosition(position); - status = 0; - BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, monToCheck, 4, &status); - MarkBattlerForControllerExec(battler); - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + if (IsBattlerAlive(battler)) + { + SetBattlerShadowSpriteCallback(battler, gBattleMons[battler].species); + BattleLoadMonSpriteGfx(GetBattlerMon(battler), battler); + } + u32 partner = BATTLE_PARTNER(battler); + if (IsBattlerAlive(partner)) + { + SetBattlerShadowSpriteCallback(partner, gBattleMons[partner].species); + BattleLoadMonSpriteGfx(GetBattlerMon(partner), partner); + } } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_CheckPokeFlute(void) +void BS_TryTrainerSlideMsgFirstOff(void) { - NATIVE_ARGS(); - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - - s32 i; - for (i = 0; i < gBattlersCount; i++) + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 shouldDoTrainerSlide = 0; + if ((shouldDoTrainerSlide = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN))) { - if (GetBattlerAbility(i) != ABILITY_SOUNDPROOF) - { - gBattleMons[i].status1 &= ~STATUS1_SLEEP; - gBattleMons[i].volatiles.nightmare = FALSE; - } + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldDoTrainerSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } +} - UpdatePokeFlutePartyStatus(gPlayerParty, B_POSITION_PLAYER_LEFT); - UpdatePokeFlutePartyStatus(gEnemyParty, B_POSITION_OPPONENT_LEFT); - - gBattlescriptCurrInstr = cmd->nextInstr; +void BS_TryTrainerSlideMsgLastOn(void) +{ + NATIVE_ARGS(u8 battler); + u32 shouldDoTrainerSlide = 0; + u32 battler = GetBattlerForBattleScript(cmd->battler); + if ((shouldDoTrainerSlide = ShouldDoTrainerSlide(battler, TRAINER_SLIDE_LAST_SWITCHIN))) + { + gBattleScripting.battler = battler; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = (shouldDoTrainerSlide == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet); + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_WaitFanfare(void) +// Potential bug with failing message and missed result on wrong battler +void BS_SetAuroraVeil(void) { NATIVE_ARGS(); + u32 side = GetBattlerSide(gBattlerAttacker); + if (gSideStatuses[side] & SIDE_STATUS_AURORA_VEIL + || !(HasWeatherEffect() && gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + { + gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } + else + { + gSideStatuses[side] |= SIDE_STATUS_AURORA_VEIL; + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY) + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8; + else + gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; - if (!IsFanfareTaskInactive()) - return; - + if (IsDoubleBattle() && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker) == 2) + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 5; + } gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SetBeakBlast(void) +void BS_TryThirdType(void) { - NATIVE_ARGS(); - gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(const u8 *failInstr); + u32 type = GetMoveArgType(gCurrentMove); + if (IS_BATTLER_OF_TYPE(gBattlerTarget, type) || GetActiveGimmick(gBattlerTarget) == GIMMICK_TERA) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerTarget].types[2] = type; + PREPARE_TYPE_BUFFER(gBattleTextBuff1, type); + gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_RemoveTerrain(void) +void BS_DestroyAbilityPopup(void) { NATIVE_ARGS(); - RemoveAllTerrains(); + for (u32 battler = 0; battler < gBattlersCount; battler++) + DestroyAbilityPopUp(battler); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TrySpectralThiefSteal(void) +void BS_GetTotemBoost(void) { NATIVE_ARGS(const u8 *jumpInstr); - - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) + u32 battler = gBattlerAttacker; + if (gQueuedStatBoosts[battler].stats == 0) { - gBattlescriptCurrInstr = cmd->nextInstr; - return; + gBattlescriptCurrInstr = cmd->nextInstr; // stats done, exit } - - bool32 contrary = GetBattlerAbility(gBattlerAttacker) == ABILITY_CONTRARY; - gBattleStruct->stolenStats[0] = 0; // Stats to steal. - gBattleScripting.animArg1 = 0; - for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) + else { - if (gBattleMons[gBattlerTarget].statStages[stat] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[stat] != MAX_STAT_STAGE) + for (u32 i = 0; i < (NUM_BATTLE_STATS - 1); i++) { - bool32 byTwo = FALSE; - - gBattleStruct->stolenStats[0] |= (1 << (stat)); - // Store by how many stages to raise the stat. - gBattleStruct->stolenStats[stat] = gBattleMons[gBattlerTarget].statStages[stat] - DEFAULT_STAT_STAGE; - - while (gBattleMons[gBattlerAttacker].statStages[stat] + gBattleStruct->stolenStats[stat] > MAX_STAT_STAGE) - gBattleStruct->stolenStats[stat]--; - - gBattleMons[gBattlerTarget].statStages[stat] = DEFAULT_STAT_STAGE; - - if (gBattleStruct->stolenStats[stat] >= 2) - byTwo++; - - if (gBattleScripting.animArg1 == 0) + if (gQueuedStatBoosts[battler].stats & (1 << i)) { - if (byTwo) - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS2 : STAT_ANIM_PLUS2) + stat; + if (gQueuedStatBoosts[battler].statChanges[i] <= -1) + SET_STATCHANGER(i + 1, abs(gQueuedStatBoosts[battler].statChanges[i]), TRUE); else - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MINUS1 : STAT_ANIM_PLUS1) + stat; - } - else - { - if (byTwo) - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS2 : STAT_ANIM_MULTIPLE_PLUS2); + SET_STATCHANGER(i + 1, gQueuedStatBoosts[battler].statChanges[i], FALSE); + + gQueuedStatBoosts[battler].stats &= ~(1 << i); + gBattleScripting.battler = battler; + gBattlerTarget = battler; + if (gQueuedStatBoosts[battler].stats & 0x80) + { + gQueuedStatBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag + gBattlescriptCurrInstr = BattleScript_TotemFlaredToLife; + } else - gBattleScripting.animArg1 = (contrary ? STAT_ANIM_MULTIPLE_MINUS1 : STAT_ANIM_MULTIPLE_PLUS1); + { + gBattlescriptCurrInstr = cmd->jumpInstr; // do boost + } + return; } } + gBattlescriptCurrInstr = cmd->nextInstr; // exit if loop failed (failsafe) } - - if (gBattleStruct->stolenStats[0] != 0) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SpectralThiefPrintStats(void) +void BS_ActivateItemEffects(void) { NATIVE_ARGS(); + if (ItemBattleEffects(ITEMEFFECT_NORMAL, gBattlerTarget)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} - for (u32 stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++) +void BS_TryRoomService(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(battler)) { - if (gBattleStruct->stolenStats[0] & (1u << stat)) + BattleScriptCall(BattleScript_ConsumableStatRaiseRet); + } + else + { + gBattlescriptCurrInstr = cmd->failInstr; + } +} + +void BS_TryTerrainSeed(void) +{ + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SEEDS) + { + enum ItemEffect effect = ITEM_NO_EFFECT; + u16 item = gBattleMons[battler].item; + switch (GetBattlerHoldEffectParam(battler)) { - gBattleStruct->stolenStats[0] &= ~(1u << stat); - SET_STATCHANGER(stat, gBattleStruct->stolenStats[stat], FALSE); - if (ChangeStatBuffs( - gBattlerAttacker, - GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), - stat, - STAT_CHANGE_CERTAIN, - 0, NULL) == STAT_CHANGE_WORKED) - { - BattleScriptCall(BattleScript_StatUp); - return; - } + case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_MISTY_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); + break; + case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: + effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, ITEMEFFECT_NONE); + break; } + + if (effect != ITEM_NO_EFFECT) + return; } - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } -void BS_SetMoveResultFlags(void) +void BS_MakeInvisible(void) { - NATIVE_ARGS(u16 value); - gBattleStruct->moveResultFlags[gBattlerTarget] |= cmd->value; + NATIVE_ARGS(u8 battler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gBattleControllerExecFlags) + return; + + BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); + MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ClearMoveResultFlags(void) +void BS_JumpIfTeamHealthy(void) { - NATIVE_ARGS(u16 value); - gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(cmd->value); - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(const u8 *jumpInstr); + u32 battler = gBattlerAttacker; + if ((IsDoubleBattle()) && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + u8 partner = BATTLE_PARTNER(battler); + if ((gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) + && (gBattleMons[partner].hp == gBattleMons[partner].maxHP && !(gBattleMons[partner].status1 & STATUS1_ANY))) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + } + else // single battle + { + if (gBattleMons[battler].hp == gBattleMons[battler].maxHP && !(gBattleMons[battler].status1 & STATUS1_ANY)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_JumpIfMoveResultFlags(void) +void BS_TryHealQuarterHealth(void) { - NATIVE_ARGS(u16 value, const u8 *jumpInstr); + NATIVE_ARGS(u8 battler, const u8 *failInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; + if (gBattleStruct->moveDamage[battler] == 0) + gBattleStruct->moveDamage[battler] = 1; + gBattleStruct->moveDamage[battler] *= -1; - if (gBattleStruct->moveResultFlags[gBattlerTarget] & cmd->value) - gBattlescriptCurrInstr = cmd->jumpInstr; + if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) + gBattlescriptCurrInstr = cmd->failInstr; // fail else - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->nextInstr; // can heal } -void BS_JumpIfCriticalHit(void) +void BS_JumpIfUnder200(void) { NATIVE_ARGS(const u8 *jumpInstr); - - if (gSpecialStatuses[gBattlerTarget].criticalHit) + // If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail. + if (GetBattlerWeight(gBattlerTarget) < 2000) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_SwapStats(void) +void BS_SetSkyDrop(void) { - NATIVE_ARGS(u8 stat); - - u32 stat = cmd->stat; - u32 temp; + NATIVE_ARGS(); + gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + /* skyDropTargets holds the information of who is in a particular instance of Sky Drop. + This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if + the target of a Sky Drop faints while in the air.*/ + gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget; + gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker; + + // End any multiturn effects caused by the target except VOLATILE_LOCK_CONFUSE + gBattleMons[gBattlerTarget].volatiles.multipleTurns = 0; + gBattleMons[gBattlerTarget].volatiles.uproarTurns = 0; + gBattleMons[gBattlerTarget].volatiles.bideTurns = 0; + gDisableStructs[gBattlerTarget].rolloutTimer = 0; + gDisableStructs[gBattlerTarget].furyCutterCounter = 0; + + // End any Follow Me/Rage Powder effects caused by the target + if (gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer != 0 && gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget == gBattlerTarget) + gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 0; - switch (stat) - { - case STAT_HP: - SWAP(gBattleMons[gBattlerAttacker].hp, gBattleMons[gBattlerTarget].hp, temp); - break; - case STAT_ATK: - SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerTarget].attack, temp); - break; - case STAT_DEF: - SWAP(gBattleMons[gBattlerAttacker].defense, gBattleMons[gBattlerTarget].defense, temp); - break; - case STAT_SPEED: - SWAP(gBattleMons[gBattlerAttacker].speed, gBattleMons[gBattlerTarget].speed, temp); - break; - case STAT_SPATK: - SWAP(gBattleMons[gBattlerAttacker].spAttack, gBattleMons[gBattlerTarget].spAttack, temp); - break; - case STAT_SPDEF: - SWAP(gBattleMons[gBattlerAttacker].spDefense, gBattleMons[gBattlerTarget].spDefense, temp); - break; - } - PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); gBattlescriptCurrInstr = cmd->nextInstr; } -static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr) +void BS_ClearSkyDrop(void) { - if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))) + NATIVE_ARGS(const u8 *failInstr); + // Check to see if the initial target of this Sky Drop fainted before the 2nd turn of Sky Drop. + // If so, make the move fail. If not, clear all of the statuses and continue the move. + if (gBattleStruct->skyDropTargets[gBattlerAttacker] == SKY_DROP_NO_TARGET) { - gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS; - gBattleCommunication[MULTISTRING_CHOOSER] = 3; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattlescriptCurrInstr = failInstr; + gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET; + gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET; + gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattlescriptCurrInstr = cmd->nextInstr; } -} -static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr) -{ - if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget))) - { - gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; - } - else - { - gBattlescriptCurrInstr = failInstr; - } + // Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted. + if (gBattleMons[gBattlerTarget].volatiles.lockConfusionTurns) + gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION; } -static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr) +void BS_SkyDropYawn(void) { - if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)) + NATIVE_ARGS(); + if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED)) { - if (B_SLEEP_TURNS >= GEN_5) - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2); - else - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3); + // Set the target of Sky Drop as gEffectBattler + gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler]; - TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); - gBattleCommunication[MULTISTRING_CHOOSER] = 4; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + // Clear skyDropTargets data + gBattleStruct->skyDropTargets[gBattleStruct->skyDropTargets[gEffectBattler]] = SKY_DROP_NO_TARGET; + gBattleStruct->skyDropTargets[gEffectBattler] = SKY_DROP_NO_TARGET; + + // If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation + if (gBattleMons[gEffectBattler].volatiles.lockConfusionTurns && CanBeConfused(gEffectBattler)) + { + gBattleMons[gEffectBattler].volatiles.lockConfusionTurns = 0; + gBattlerAttacker = gEffectBattler; + gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; + gBattlescriptCurrInstr = BattleScript_ThrashConfuses; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } } else { - gBattlescriptCurrInstr = failInstr; + gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_TrySetParalysis(void) +void BS_JumpIfPranksterBlocked(void) { - NATIVE_ARGS(const u8 *failInstr); - TrySetParalysis(cmd->nextInstr, cmd->failInstr); + NATIVE_ARGS(const u8 *jumpInstr); + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget, TRUE)) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TrySetPoison(void) +void BS_TryToClearPrimalWeather(void) { - NATIVE_ARGS(const u8 *failInstr); - TrySetPoison(cmd->nextInstr, cmd->failInstr); + NATIVE_ARGS(); + bool32 shouldNotClear = FALSE; + + for (u32 i = 0; i < gBattlersCount; i++) + { + u32 ability = GetBattlerAbility(i); + if (((ability == ABILITY_DESOLATE_LAND && gBattleWeather & B_WEATHER_SUN_PRIMAL) + || (ability == ABILITY_PRIMORDIAL_SEA && gBattleWeather & B_WEATHER_RAIN_PRIMAL) + || (ability == ABILITY_DELTA_STREAM && gBattleWeather & B_WEATHER_STRONG_WINDS)) + && IsBattlerAlive(i)) + shouldNotClear = TRUE; + } + if (gBattleWeather & B_WEATHER_SUN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_SUN_PRIMAL; + PrepareStringBattle(STRINGID_EXTREMESUNLIGHTFADED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_RAIN_PRIMAL && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_RAIN_PRIMAL; + PrepareStringBattle(STRINGID_HEAVYRAINLIFTED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleWeather & B_WEATHER_STRONG_WINDS && !shouldNotClear) + { + gBattleWeather &= ~B_WEATHER_STRONG_WINDS; + PrepareStringBattle(STRINGID_STRONGWINDSDISSIPATED, gBattlerAttacker); + gBattleCommunication[MSG_DISPLAY] = 1; + } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TrySetPoisonParalyzis(void) +void BS_TryEndNeutralizingGas(void) { - NATIVE_ARGS(const u8 *failInstr); - - static const u32 sStunShockEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON}; - u32 status = RandomElement(RNG_G_MAX_STUN_SHOCK, sStunShockEffects); - - if (status == STATUS1_PARALYSIS) - TrySetParalysis(cmd->nextInstr, cmd->failInstr); + NATIVE_ARGS(); + if (gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved) + { + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = FALSE; + BattleScriptPush(cmd->nextInstr); + gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits; + } else - TrySetPoison(cmd->nextInstr, cmd->failInstr); + { + gBattlescriptCurrInstr = cmd->nextInstr; + } } -void BS_TrySetEffectSpore(void) +void BS_GetRototillerTargets(void) { NATIVE_ARGS(const u8 *failInstr); + u32 count = 0; + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + gSpecialStatuses[battler].rototillerAffected = FALSE; + if (IsRototillerAffected(battler)) + { + gSpecialStatuses[battler].rototillerAffected = TRUE; + count++; + } + } - static const u32 sBefuddleEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON, STATUS1_SLEEP}; - u32 status = RandomElement(RNG_G_MAX_BEFUDDLE, sBefuddleEffects); - - if (status == STATUS1_PARALYSIS) - TrySetParalysis(cmd->nextInstr, cmd->failInstr); - else if (status == STATUS1_POISON) - TrySetPoison(cmd->nextInstr, cmd->failInstr); + if (count == 0) + gBattlescriptCurrInstr = cmd->failInstr; // Rototiller fails else - TrySetSleep(cmd->nextInstr, cmd->failInstr); + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TrySetConfusion(void) +void BS_JumpIfNotRototillerAffected(void) { - NATIVE_ARGS(const u8 *failInstr); - - if (CanBeConfused(gBattlerTarget)) + NATIVE_ARGS(const u8 *jumpInstr); + if (gSpecialStatuses[gBattlerTarget].rototillerAffected) { - gBattleMons[gBattlerTarget].volatiles.confusionTurns = ((Random()) % 4) + 2; - gBattleCommunication[MULTIUSE_STATE] = 1; - gEffectBattler = gBattlerTarget; + gSpecialStatuses[gBattlerTarget].rototillerAffected = FALSE; gBattlescriptCurrInstr = cmd->nextInstr; } else { - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = cmd->jumpInstr; // Unaffected by rototiller - print STRINGID_NOEFFECTONTARGET } } -void BS_TrySetInfatuation(void) +void BS_ConsumeBerry(void) { - NATIVE_ARGS(const u8 *failInstr); - - if (!gBattleMons[gBattlerTarget].volatiles.infatuation - && gBattleMons[gBattlerTarget].ability != ABILITY_OBLIVIOUS - && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL) - && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + NATIVE_ARGS(u8 battler, bool8 fromBattler); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (gBattleScripting.overrideBerryRequirements == 2) { - gBattleMons[gBattlerTarget].volatiles.infatuation = INFATUATED_WITH(gBattlerAttacker); - gBattleCommunication[MULTIUSE_STATE] = 2; - gEffectBattler = gBattlerTarget; gBattlescriptCurrInstr = cmd->nextInstr; + return; } + + if (cmd->fromBattler) + gLastUsedItem = gBattleMons[battler].item; + + gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; + gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID + if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) + return; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_JumpIfWeatherAffected(void) +{ + NATIVE_ARGS(u16 flags, const u8 *jumpInstr); + u32 weather = cmd->flags; + if (IsBattlerWeatherAffected(gBattlerAttacker, weather)) + gBattlescriptCurrInstr = cmd->jumpInstr; else - { - gBattlescriptCurrInstr = cmd->failInstr; - } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TrySetEscapePrevention(void) +void BS_JumpIfSpecies(void) { - NATIVE_ARGS(const u8 *failInstr); + NATIVE_ARGS(u16 species, const u8 *jumpInstr); + if (gBattleMons[gBattlerAttacker].species == cmd->species) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} - if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) +void BS_JumpIfLeafGuardProtected(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + if (IsLeafGuardProtected(battler, GetBattlerAbility(battler))) { - gBattleMons[gBattlerTarget].volatiles.escapePrevention = TRUE; - gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; - gEffectBattler = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlerAbility = battler; + gBattlescriptCurrInstr = cmd->jumpInstr; } else { - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_TrySetTorment(void) +void BS_SetAttackerToStickyWebUser(void) +{ + NATIVE_ARGS(); + // For Mirror Armor: "If the Pokémon with this Ability is affected by Sticky Web, the effect is reflected back to the Pokémon which set it up. + // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." + gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition + SET_STATCHANGER(STAT_SPEED, 1, TRUE); + if (gSideTimers[GetBattlerSide(gBattlerTarget)].stickyWebBattlerId != 0xFF) + gBattlerAttacker = gSideTimers[GetBattlerSide(gBattlerTarget)].stickyWebBattlerId; + gBattlescriptCurrInstr = cmd->nextInstr; +} + +void BS_CutOneThirdHpAndRaiseStats(void) { NATIVE_ARGS(const u8 *failInstr); - if (!(gBattleMons[gBattlerTarget].volatiles.torment == TRUE) - && !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)) + bool8 atLeastOneStatBoosted = FALSE; + u16 hpFraction = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 3); + + for (u32 stat = 1; stat < NUM_STATS; stat++) { - gBattleMons[gBattlerTarget].volatiles.torment = TRUE; - gDisableStructs[gBattlerTarget].tormentTimer = gBattleTurnCounter + 3; // 3 turns excluding current turn - gEffectBattler = gBattlerTarget; + if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + atLeastOneStatBoosted = TRUE; + break; + } + } + if (atLeastOneStatBoosted && gBattleMons[gBattlerAttacker].hp > hpFraction) + { + gBattleStruct->moveDamage[gBattlerAttacker] = hpFraction; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -18144,210 +18274,119 @@ void BS_TrySetTorment(void) } } -// Heals one-sixth of the target's HP, including for Dynamaxed targets. -void BS_HealOneSixth(void) -{ - NATIVE_ARGS(const u8* failInstr); - gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP / 6; - if (gBattleStruct->moveDamage[gBattlerTarget] == 0) - gBattleStruct->moveDamage[gBattlerTarget] = 1; - gBattleStruct->moveDamage[gBattlerTarget] *= -1; - - if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - gBattlescriptCurrInstr = cmd->failInstr; // fail - else - gBattlescriptCurrInstr = cmd->nextInstr; // can heal -} - -// Recycles the target's item if it is specifically holding a berry. -void BS_TryRecycleBerry(void) +void BS_CheckPoltergeist(void) { NATIVE_ARGS(const u8 *failInstr); - u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)]; if (gBattleMons[gBattlerTarget].item == ITEM_NONE - && gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item - && GetItemPocket(*usedHeldItem) == POCKET_BERRIES) + || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM + || GetBattlerAbility(gBattlerTarget) == ABILITY_KLUTZ) { - gLastUsedItem = *usedHeldItem; - *usedHeldItem = ITEM_NONE; - gBattleMons[gBattlerTarget].item = gLastUsedItem; - - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item); - MarkBattlerForControllerExec(gBattlerTarget); - - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } else { - gBattlescriptCurrInstr = cmd->failInstr; + PREPARE_ITEM_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].item); + gLastUsedItem = gBattleMons[gBattlerTarget].item; + gBattlescriptCurrInstr = cmd->nextInstr; } } -// Sets up sharp steel on the target's side. -void BS_SetSteelsurge(void) +void BS_TryNoRetreat(void) { NATIVE_ARGS(const u8 *failInstr); - u8 targetSide = GetBattlerSide(gBattlerTarget); - if (IsHazardOnSide(targetSide, HAZARDS_STEELSURGE)) + if (gDisableStructs[gBattlerTarget].noRetreat) { gBattlescriptCurrInstr = cmd->failInstr; } else { - PushHazardTypeToQueue(targetSide, HAZARDS_STEELSURGE); + if (!gBattleMons[gBattlerTarget].volatiles.escapePrevention) + gDisableStructs[gBattlerTarget].noRetreat = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } -void BS_JumpIfIntimidateAbilityPrevented(void) +void BS_CureCertainStatuses(void) { NATIVE_ARGS(); - - u32 hasAbility = FALSE; - u32 ability = GetBattlerAbility(gBattlerTarget); - - switch (ability) + // Check infatuation + if (gBattleMons[gBattlerTarget].volatiles.infatuation) { - case ABILITY_INNER_FOCUS: - case ABILITY_SCRAPPY: - case ABILITY_OWN_TEMPO: - case ABILITY_OBLIVIOUS: - if (B_UPDATED_INTIMIDATE >= GEN_8) - { - hasAbility = TRUE; - gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; - } - else - { - gBattlescriptCurrInstr = cmd->nextInstr; - } - break; - case ABILITY_GUARD_DOG: - hasAbility = TRUE; - gBattlescriptCurrInstr = BattleScript_IntimidateInReverse; - break; - default: - gBattlescriptCurrInstr = cmd->nextInstr; - break; + gBattleMons[gBattlerTarget].volatiles.infatuation = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION + StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); } - - if (hasAbility) + // Check taunt + if (gDisableStructs[gBattlerTarget].tauntTimer != 0) { - gLastUsedAbility = ability; - gBattlerAbility = gBattlerTarget; - RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + gDisableStructs[gBattlerTarget].tauntTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); } + // Check encore + if (gDisableStructs[gBattlerTarget].encoreTimer != 0) + { + gDisableStructs[gBattlerTarget].encoredMove = 0; + gDisableStructs[gBattlerTarget].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED + } + // Check torment + if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE) + { + gBattleMons[gBattlerTarget].volatiles.torment = FALSE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; + } + // Check heal block + if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + { + gStatuses3[gBattlerTarget] &= ~(STATUS3_HEAL_BLOCK); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; + } + // Check disable + if (gDisableStructs[gBattlerTarget].disableTimer != 0) + { + gDisableStructs[gBattlerTarget].disableTimer = 0; + gDisableStructs[gBattlerTarget].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; + } + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfCanGigantamax(void) -{ - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (GetMonData(GetBattlerMon(battler), MON_DATA_GIGANTAMAX_FACTOR) - && GetGMaxTargetSpecies(gBattleMons[battler].species) != SPECIES_NONE) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_JumpIfLastUsedItemHoldEffect(void) +void BS_TryResetNegativeStatStages(void) { - NATIVE_ARGS(u8 holdEffect, u16 secondaryId, const u8 *jumpInstr); - if (GetItemHoldEffect(gLastUsedItem) == cmd->holdEffect - && (cmd->secondaryId == 0 || GetItemSecondaryId(gLastUsedItem) == cmd->secondaryId)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; + NATIVE_ARGS(); + for (u32 stat = 0; stat < NUM_BATTLE_STATS; stat++) + if (gBattleMons[gBattlerTarget].statStages[stat] < DEFAULT_STAT_STAGE) + gBattleMons[gBattlerTarget].statStages[stat] = DEFAULT_STAT_STAGE; + gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfNoWhiteOut(void) +void BS_JumpIfLastUsedItemBerry(void) { NATIVE_ARGS(const u8 *jumpInstr); - - if (FlagGet(B_FLAG_NO_WHITEOUT)) + if (GetItemPocket(gLastUsedItem) == POCKET_BERRIES) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_TryBoosterEnergy(void) +void BS_SaveBattlerItem(void) { - NATIVE_ARGS(u8 onFieldStatus); - - for (u32 orderNum = 0; orderNum < gBattlersCount; orderNum++) - { - u32 battlerByTurnOrder = gBattlerByTurnOrder[orderNum]; - if (GetBattlerHoldEffect(battlerByTurnOrder, TRUE) != HOLD_EFFECT_BOOSTER_ENERGY) - continue; - - u32 ability = GetBattlerAbility(battlerByTurnOrder); - if (!(ability == ABILITY_PROTOSYNTHESIS && cmd->onFieldStatus != ON_TERRAIN) - && !(ability == ABILITY_QUARK_DRIVE && cmd->onFieldStatus != ON_WEATHER)) - continue; - - if (TryBoosterEnergy(battlerByTurnOrder, ability, ITEMEFFECT_NONE)) - return; - } - + NATIVE_ARGS(); + gBattleHistory->heldItems[gBattlerTarget] = gBattleMons[gBattlerTarget].item; gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfAbilityCantBeSuppressed(void) -{ - NATIVE_ARGS(u8 battler, const u8 *jumpInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); - - if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_TryActivateAbilityShield(void) +void BS_RestoreBattlerItem(void) { - NATIVE_ARGS(u8 battler); - u32 battler = GetBattlerForBattleScript(cmd->battler); - + NATIVE_ARGS(); + gBattleMons[gBattlerTarget].item = gBattleHistory->heldItems[gBattlerTarget]; gBattlescriptCurrInstr = cmd->nextInstr; - - if (GetBattlerAbilityNoAbilityShield(battler) != GetBattlerAbility(battler)) - { - gLastUsedItem = gBattleMons[battler].item; - RecordItemEffectBattle(battler, GetItemHoldEffect(gLastUsedItem)); - BattleScriptCall(BattleScript_AbilityShieldProtects); - } } -void BS_TrySynchronoise(void) +void BS_BattlerItemToLastUsedItem(void) { - NATIVE_ARGS(const u8 *jumpInstr); - bool32 atleastOneSharedType = FALSE; - - for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) - { - if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_SYNCHRONOISE_AFFECTED - || gBattlerAttacker == battlerDef - || !IsBattlerAlive(battlerDef)) - continue; - - if (DoBattlersShareType(gBattlerAttacker, battlerDef)) - { - atleastOneSharedType = TRUE; - continue; - } - - if (!DoBattlersShareType(gBattlerAttacker, battlerDef)) - { - gBattleScripting.battler = battlerDef; - gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_NO_EFFECT | MOVE_RESULT_SYNCHRONOISE_AFFECTED; - BattleScriptCall(BattleScript_ItDoesntAffectFoe); - return; - } - } - - if (atleastOneSharedType) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; + NATIVE_ARGS(); + gBattleMons[gBattlerTarget].item = gLastUsedItem; + gBattlescriptCurrInstr = cmd->nextInstr; } From 731948a769745dc092a168c3f793ace0cec92df4 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Fri, 18 Jul 2025 20:43:02 +0100 Subject: [PATCH 115/283] preproc: Support __attribute__ in enums (#7344) --- tools/preproc/asm_file.cpp | 49 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 66667935a1..60296fa943 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -517,8 +517,53 @@ bool AsmFile::ParseEnum() long fallbackPosition = m_pos; std::string headerFilename = ""; - long currentHeaderLine = SkipWhitespaceAndEol(); - std::string enumName = ReadIdentifier(); + long currentHeaderLine = 0; + std::string enumName; + while (true) + { + currentHeaderLine += SkipWhitespaceAndEol(); + std::string identifier = ReadIdentifier(); + if (identifier == "__attribute__") + { + if (m_pos + 1 >= m_size + || m_buffer[m_pos] != '(' + || m_buffer[m_pos + 1] != '(') + { + m_pos = fallbackPosition - 4; + return false; + } + + m_pos += 2; + int parens = 2; + while (true) + { + char c = m_buffer[m_pos++]; + if (c == '\n') + currentHeaderLine++; + + if (c == '(') + { + parens++; + } + else if (c == ')') + { + parens--; + if (parens == 0) + break; + } + else if (parens < 2 || m_pos == m_size) + { + m_pos = fallbackPosition - 4; + return false; + } + } + } + else + { + enumName = identifier; + break; + } + } currentHeaderLine += SkipWhitespaceAndEol(); std::string enumBase = "0"; long enumCounter = 0; From c61c2bbbc1b59a26f5a0b75f3b25336d99d5f35a Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 19 Jul 2025 03:56:56 -0400 Subject: [PATCH 116/283] Fix AI unusable move scoring freeze (#7369) --- src/battle_ai_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 96265621b2..5c0c0b0590 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -290,7 +290,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) { if (moveLimitations & (1u << moveIndex)) SET_SCORE(battler, moveIndex, 0); - if (defaultScoreMoves & 1) + else if (defaultScoreMoves & 1) SET_SCORE(battler, moveIndex, AI_SCORE_DEFAULT); else SET_SCORE(battler, moveIndex, 0); From e502c078e83b3816ae92a4fca604740816751766 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 19 Jul 2025 04:22:24 -0400 Subject: [PATCH 117/283] Switch AI can see weather abilities of switchin candidates during damage calcs (#7373) --- include/battle_ai_util.h | 1 + src/battle_ai_util.c | 29 ++++++++++++++++++++++++++++- test/battle/ai/ai_switching.c | 19 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index d4a66f2028..473a8758a5 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -102,6 +102,7 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId); enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId); bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move); u32 AI_GetWeather(void); +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon); enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, enum DamageCalcContext calcContext); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ff81162d52..b480ac6118 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1638,6 +1638,33 @@ u32 AI_GetWeather(void) return gBattleWeather; } +u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon) +{ + u32 ability = battleMon.ability; + // Forced weather behaviour + if (!AI_WeatherHasEffect()) + return B_WEATHER_NONE; + if (ability == ABILITY_CLOUD_NINE || ability == ABILITY_AIR_LOCK) + return B_WEATHER_NONE; + if (gBattleWeather & B_WEATHER_PRIMAL_ANY) + return gBattleWeather; + + // Switchin will introduce new weather + switch(ability) + { + case ABILITY_DRIZZLE: + return B_WEATHER_RAIN_NORMAL; + case ABILITY_DROUGHT: + return B_WEATHER_SUN_NORMAL; + case ABILITY_SAND_STREAM: + return B_WEATHER_SANDSTORM; + case ABILITY_SNOW_WARNING: + return B_SNOW_WARNING >= GEN_9 ? B_WEATHER_SNOW : B_WEATHER_HAIL; + default: + return gBattleWeather; + } +} + enum WeatherState IsWeatherActive(u32 flags) { enum WeatherState state = WEATHER_INACTIVE; @@ -4057,7 +4084,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl gAiThinkingStruct->saved[battlerAtk].saved = FALSE; } - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetWeather()); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, NO_GIMMICK, NO_GIMMICK, AI_GetSwitchinWeather(switchinCandidate)); // restores original gBattleMon struct FreeRestoreBattleMons(savedBattleMons); diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 0aae647030..2eb6834c6c 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1267,3 +1267,22 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as los TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_SMART_MON_CHOICES: AI sees its own weather setting ability when considering switchin candidates") +{ + u32 ability = ABILITY_NONE; + PARAMETRIZE { ability = ABILITY_WATER_ABSORB; } + PARAMETRIZE { ability = ABILITY_DRIZZLE; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZIGZAGOON) { Speed(2); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(1); Level(1); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_POLITOED) { Speed(5); Ability(ability); Moves(MOVE_BUBBLE_BEAM); } + OPPONENT(SPECIES_CONKELDURR) { Speed(1); Ability(ABILITY_GUTS); Moves(MOVE_SUPERPOWER); } + } WHEN { + if (ability == ABILITY_DRIZZLE) + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 1); } + else + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 2); } + } +} From 2f6e1ea6d3c45366a31f1bc40a2de4c0f568a861 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 19 Jul 2025 10:28:25 +0200 Subject: [PATCH 118/283] Enum conversion for `enum MoveEffects` and `enum BattleMoveEffects` (#7366) --- Makefile | 2 +- include/battle_ai_util.h | 4 +- include/constants/battle.h | 2 +- include/constants/battle_move_effects.h | 2 +- include/move.h | 4 +- src/battle_ai_main.c | 253 ++++++++++++------------ src/battle_ai_util.c | 30 ++- src/battle_tv.c | 2 + 8 files changed, 161 insertions(+), 138 deletions(-) diff --git a/Makefile b/Makefile index dd1c0f2c92..759512ea63 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ ARMCC := $(PREFIX)gcc PATH_ARMCC := PATH="$(PATH)" $(ARMCC) CC1 := $(shell $(PATH_ARMCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init -Wnonnull +override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init -Wnonnull -Wenum-conversion ifneq ($(LTO),0) ifneq ($(TEST),1) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 473a8758a5..6450dfe907 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -189,8 +189,8 @@ bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move); bool32 HasThawingMove(u32 battler); bool32 IsStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsStatLoweringEffect(enum BattleMoveEffects effect); -bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect); -bool32 IsSelfStatRaisingEffect(enum BattleMoveEffects effect); +bool32 IsSelfStatLoweringEffect(enum MoveEffects effect); +bool32 IsSelfStatRaisingEffect(enum MoveEffects effect); bool32 IsSwitchOutEffect(enum BattleMoveEffects effect); bool32 IsChaseEffect(enum BattleMoveEffects effect); bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect); diff --git a/include/constants/battle.h b/include/constants/battle.h index 28b39117ff..c659cdf7e8 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -389,7 +389,7 @@ enum BattleWeather #define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) -enum MoveEffects +enum __attribute__((packed)) MoveEffects { MOVE_EFFECT_NONE, MOVE_EFFECT_SLEEP, diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index bb37a33933..3e5559748f 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -1,7 +1,7 @@ #ifndef GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H #define GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H -enum BattleMoveEffects +enum __attribute__((packed)) BattleMoveEffects { EFFECT_PLACEHOLDER, EFFECT_HIT, diff --git a/include/move.h b/include/move.h index 9e37b75ab2..fa89ec3cf3 100644 --- a/include/move.h +++ b/include/move.h @@ -30,7 +30,7 @@ enum SheerForceBoost struct AdditionalEffect { - u16 moveEffect; + enum MoveEffects moveEffect; u8 self:1; u8 onlyIfTargetRaisedStats:1; u8 onChargeTurnOnly:1; @@ -67,7 +67,7 @@ struct MoveInfo { const u8 *name; const u8 *description; - u16 effect; + enum BattleMoveEffects effect; u16 type:5; // Up to 32 enum DamageCategory category:2; u16 power:9; // up to 511 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 5586934eea..1198768b73 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5164,6 +5164,8 @@ case EFFECT_GUARD_SPLIT: case MOVE_EFFECT_EVS_PLUS_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_EVASION)); break; + default: + break; } } else @@ -5207,6 +5209,8 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); ADJUST_SCORE(IncreaseStatUpScoreContrary(battlerAtk, battlerDef, STAT_CHANGE_SPDEF)); break; + default: + break; } } } @@ -5214,133 +5218,134 @@ case EFFECT_GUARD_SPLIT: { switch (additionalEffect->moveEffect) { - case MOVE_EFFECT_FLINCH: - score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move); - break; - case MOVE_EFFECT_SPD_MINUS_1: - case MOVE_EFFECT_SPD_MINUS_2: - ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_SPEED)); - break; - case MOVE_EFFECT_ATK_MINUS_1: - case MOVE_EFFECT_DEF_MINUS_1: - case MOVE_EFFECT_SP_ATK_MINUS_1: - case MOVE_EFFECT_SP_DEF_MINUS_1: - case MOVE_EFFECT_ACC_MINUS_1: - case MOVE_EFFECT_EVS_MINUS_1: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_ATK_MINUS_2: - case MOVE_EFFECT_DEF_MINUS_2: - case MOVE_EFFECT_SP_ATK_MINUS_2: - case MOVE_EFFECT_SP_DEF_MINUS_2: - case MOVE_EFFECT_ACC_MINUS_2: - case MOVE_EFFECT_EVS_MINUS_2: - if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) - ADJUST_SCORE(DECENT_EFFECT); - break; - case MOVE_EFFECT_POISON: - IncreasePoisonScore(battlerAtk, battlerDef, move, &score); - break; - case MOVE_EFFECT_CLEAR_SMOG: - score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); - break; - case MOVE_EFFECT_BUG_BITE: // And pluck - if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) - break; - else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES) - ADJUST_SCORE(DECENT_EFFECT); + case MOVE_EFFECT_FLINCH: + score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move); + break; + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_SPEED)); + break; + case MOVE_EFFECT_ATK_MINUS_1: + case MOVE_EFFECT_DEF_MINUS_1: + case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_1: + if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_ATK_MINUS_2: + case MOVE_EFFECT_DEF_MINUS_2: + case MOVE_EFFECT_SP_ATK_MINUS_2: + case MOVE_EFFECT_SP_DEF_MINUS_2: + case MOVE_EFFECT_ACC_MINUS_2: + case MOVE_EFFECT_EVS_MINUS_2: + if (aiData->abilities[battlerDef] != ABILITY_CONTRARY) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_POISON: + IncreasePoisonScore(battlerAtk, battlerDef, move, &score); + break; + case MOVE_EFFECT_CLEAR_SMOG: + score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); + break; + case MOVE_EFFECT_BUG_BITE: // And pluck + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; - case MOVE_EFFECT_INCINERATE: - if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) - break; - else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) - ADJUST_SCORE(DECENT_EFFECT); + else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_INCINERATE: + if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) break; - case MOVE_EFFECT_STEAL_ITEM: + else if (GetItemPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS) + ADJUST_SCORE(DECENT_EFFECT); + break; + case MOVE_EFFECT_STEAL_ITEM: + { + bool32 canSteal = FALSE; + + if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) + canSteal = TRUE; + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) + canSteal = TRUE; + + if (canSteal && aiData->items[battlerAtk] == ITEM_NONE + && aiData->items[battlerDef] != ITEM_NONE + && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) + && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) + && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) + && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) { - bool32 canSteal = FALSE; - - if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) - canSteal = TRUE; - if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || IsOnPlayerSide(battlerAtk)) - canSteal = TRUE; - - if (canSteal && aiData->items[battlerAtk] == ITEM_NONE - && aiData->items[battlerDef] != ITEM_NONE - && CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef]) - && CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef]) - && !HasMoveWithEffect(battlerAtk, EFFECT_ACROBATICS) - && aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD) + switch (aiData->holdEffects[battlerDef]) { - switch (aiData->holdEffects[battlerDef]) - { - case HOLD_EFFECT_NONE: - break; - case HOLD_EFFECT_CHOICE_BAND: - case HOLD_EFFECT_CHOICE_SCARF: - case HOLD_EFFECT_CHOICE_SPECS: + case HOLD_EFFECT_NONE: + break; + case HOLD_EFFECT_CHOICE_BAND: + case HOLD_EFFECT_CHOICE_SCARF: + case HOLD_EFFECT_CHOICE_SPECS: + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_TOXIC_ORB: + if (ShouldPoison(battlerAtk, battlerAtk)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_FLAME_ORB: + if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_BLACK_SLUDGE: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case HOLD_EFFECT_IRON_BALL: + if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_TOXIC_ORB: - if (ShouldPoison(battlerAtk, battlerAtk)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_FLAME_ORB: - if (ShouldBurn(battlerAtk, battlerAtk, aiData->abilities[battlerAtk])) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_BLACK_SLUDGE: - if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_IRON_BALL: - if (HasMoveWithEffect(battlerAtk, EFFECT_FLING)) - ADJUST_SCORE(DECENT_EFFECT); - break; - case HOLD_EFFECT_LAGGING_TAIL: - case HOLD_EFFECT_STICKY_BARB: - break; - default: - ADJUST_SCORE(WEAK_EFFECT); - break; - } + break; + case HOLD_EFFECT_LAGGING_TAIL: + case HOLD_EFFECT_STICKY_BARB: + break; + default: + ADJUST_SCORE(WEAK_EFFECT); + break; } - break; } break; - case MOVE_EFFECT_STEALTH_ROCK: - case MOVE_EFFECT_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); - { - if (gDisableStructs[battlerAtk].isFirstTurn) - ADJUST_SCORE(BEST_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; - case MOVE_EFFECT_FEINT: - if (GetMoveEffect(predictedMove) == EFFECT_PROTECT) - ADJUST_SCORE(GOOD_EFFECT); - break; - case MOVE_EFFECT_THROAT_CHOP: - if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) - { - if (AI_IsFaster(battlerAtk, battlerDef, move)) - ADJUST_SCORE(GOOD_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; - case MOVE_EFFECT_WRAP: - if (!HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move)) + } + break; + case MOVE_EFFECT_STEALTH_ROCK: + case MOVE_EFFECT_SPIKES: + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); + { + if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); - break; - case MOVE_EFFECT_SALT_CURE: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + else ADJUST_SCORE(DECENT_EFFECT); - break; - + } + break; + case MOVE_EFFECT_FEINT: + if (GetMoveEffect(predictedMove) == EFFECT_PROTECT) + ADJUST_SCORE(GOOD_EFFECT); + break; + case MOVE_EFFECT_THROAT_CHOP: + if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) + { + if (AI_IsFaster(battlerAtk, battlerDef, move)) + ADJUST_SCORE(GOOD_EFFECT); + else + ADJUST_SCORE(DECENT_EFFECT); + } + break; + case MOVE_EFFECT_WRAP: + if (!HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) && ShouldTrap(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + break; + case MOVE_EFFECT_SALT_CURE: + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_WATER) || IS_BATTLER_OF_TYPE(battlerDef, TYPE_STEEL)) + ADJUST_SCORE(DECENT_EFFECT); + break; + default: + break; } } } @@ -6092,12 +6097,14 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { switch (GetMoveAdditionalEffectById(move, i)->moveEffect) { - case MOVE_EFFECT_WRAP: - ADJUST_SCORE(AWFUL_EFFECT); - break; - case MOVE_EFFECT_FEINT: - ADJUST_SCORE(WORST_EFFECT); - break; + case MOVE_EFFECT_WRAP: + ADJUST_SCORE(AWFUL_EFFECT); + break; + case MOVE_EFFECT_FEINT: + ADJUST_SCORE(WORST_EFFECT); + break; + default: + break; } } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b480ac6118..5d0f34b4fd 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1021,6 +1021,8 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 return TRUE; } break; + default: + break; } } else // consider move effects that hinder the target @@ -1072,6 +1074,8 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 if (CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1) return TRUE; break; + default: + break; } } } @@ -1148,6 +1152,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s || (noOfHitsToKo != 1 && !(abilityDef == ABILITY_CONTRARY && !DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)))) return TRUE; break; + default: + break; } } break; @@ -1740,6 +1746,8 @@ bool32 IsHazardMove(u32 move) { case MOVE_EFFECT_STEELSURGE: return TRUE; + default: + break; } } return FALSE; @@ -1768,6 +1776,8 @@ bool32 IsHazardClearingMove(u32 move) { case MOVE_EFFECT_DEFOG: return TRUE; + default: + break; } } @@ -2744,7 +2754,7 @@ bool32 IsStatLoweringEffect(enum BattleMoveEffects effect) } } -bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect) +bool32 IsSelfStatLoweringEffect(enum MoveEffects effect) { // Self stat lowering moves like Overheart, Superpower etc. switch (effect) @@ -2772,7 +2782,7 @@ bool32 IsSelfStatLoweringEffect(enum BattleMoveEffects effect) } } -bool32 IsSelfStatRaisingEffect(enum BattleMoveEffects effect) +bool32 IsSelfStatRaisingEffect(enum MoveEffects effect) { // Self stat lowering moves like Power Up Punch or Charge Beam switch (effect) @@ -2872,6 +2882,8 @@ static inline bool32 IsMoveSleepClauseTrigger(u32 move) case MOVE_EFFECT_EFFECT_SPORE_SIDE: case MOVE_EFFECT_YAWN_FOE: return TRUE; + default: + break; } } return FALSE; @@ -4318,12 +4330,14 @@ bool32 HasMoveThatChangesKOThreshold(u32 battlerId, u32 noOfHitsToFaint, u32 aiI switch (gMovesInfo[moves[i]].additionalEffects[i].moveEffect) { - case MOVE_EFFECT_SPD_MINUS_1: - case MOVE_EFFECT_SPD_MINUS_2: - { - if(aiIsFaster) - return TRUE; - } + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + { + if(aiIsFaster) + return TRUE; + } + default: + break; } } } diff --git a/src/battle_tv.c b/src/battle_tv.c index 4215d3ead3..433390caa4 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -867,6 +867,8 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3) if (additionalEffect->self == TRUE && (additionalEffect->chance == 100 || additionalEffect->chance == 0)) baseFromEffect += 2; break; + default: + break; } } From 1b996fbb8e13e3ddcb688755277acef2f50a50a6 Mon Sep 17 00:00:00 2001 From: surskitty Date: Sat, 19 Jul 2025 19:20:07 -0400 Subject: [PATCH 119/283] AI refactor for weather-setting, terrain-setting, Trick Room behaviors; doubles-focused (#7319) --- include/battle_ai_field_statuses.h | 18 ++ include/battle_ai_util.h | 13 +- include/config/ai.h | 11 +- include/constants/battle.h | 3 + include/random.h | 2 + src/battle_ai_field_statuses.c | 454 +++++++++++++++++++++++++++++ src/battle_ai_main.c | 208 +++++++------ src/battle_ai_util.c | 107 +------ test/battle/ai/ai_doubles.c | 66 ++++- 9 files changed, 683 insertions(+), 199 deletions(-) create mode 100644 include/battle_ai_field_statuses.h create mode 100644 src/battle_ai_field_statuses.c diff --git a/include/battle_ai_field_statuses.h b/include/battle_ai_field_statuses.h new file mode 100644 index 0000000000..64608f6370 --- /dev/null +++ b/include/battle_ai_field_statuses.h @@ -0,0 +1,18 @@ +#ifndef GUARD_BATTLE_AI_FIELD_STATUSES_H +#define GUARD_BATTLE_AI_FIELD_STATUSES_H + +#include "battle_ai_main.h" +#include "battle_ai_util.h" + +enum FieldEffectOutcome +{ + FIELD_EFFECT_POSITIVE, + FIELD_EFFECT_NEUTRAL, + FIELD_EFFECT_NEGATIVE, + FIELD_EFFECT_BLOCKED, +}; + +bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredResult); +bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome desiredResult); + +#endif //GUARD_BATTLE_AI_FIELD_STATUSES_H diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 6450dfe907..4dfea63dfe 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -2,6 +2,7 @@ #define GUARD_BATTLE_AI_UTIL_H #include "battle_ai_main.h" +#include "battle_ai_field_statuses.h" #define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) @@ -159,9 +160,12 @@ bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category); bool32 HasMoveWithType(u32 battler, u32 type); bool32 HasMoveWithEffect(u32 battlerId, enum BattleMoveEffects moveEffect); bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect); +bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect); bool32 HasNonVolatileMoveEffect(u32 battlerId, u32 effect); bool32 IsPowerBasedOnStatus(u32 battlerId, enum BattleMoveEffects effect, u32 argument); bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect); +bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect); +bool32 HasBattlerSideUsedMoveWithAdditionalEffect(u32 battler, u32 moveEffect); bool32 HasMoveWithCriticalHitChance(u32 battlerId); bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, enum BattleMoveEffects exception); bool32 HasMoveThatLowersOwnStats(u32 battlerId); @@ -175,11 +179,10 @@ bool32 IsHazardMove(u32 move); bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move); bool32 IsBattlerDamagedByStatus(u32 battler); s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove); -bool32 ShouldSetSandstorm(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetHail(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetRain(u32 battlerAtk, u32 ability, enum ItemHoldEffect holdEffect); -bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect); +bool32 ShouldSetWeather(u32 battler, u32 weather); +bool32 ShouldClearWeather(u32 battler, u32 weather); +bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus); +bool32 ShouldClearFieldStatus(u32 battler, u32 fieldStatus); bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef); bool32 IsHealingMove(u32 move); bool32 HasHealingEffect(u32 battler); diff --git a/include/config/ai.h b/include/config/ai.h index ec359c646d..99283ee90a 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -89,10 +89,13 @@ // AI_FLAG_SMART_SWITCHING settings #define SMART_SWITCHING_OMNISCIENT FALSE // AI will use omniscience for switching calcs, regardless of omniscience setting otherwise -// AI's acceptable number of hits to KO the partner via friendly fire in a double battle. -#define FRIENDLY_FIRE_RISKY_THRESHOLD 2 -#define FRIENDLY_FIRE_NORMAL_THRESHOLD 3 -#define FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD 4 +// Configurations specifically for AI_FLAG_DOUBLE_BATTLE. +#define FRIENDLY_FIRE_RISKY_THRESHOLD 2 // AI_FLAG_RISKY acceptable number of hits to KO the partner via friendly fire +#define FRIENDLY_FIRE_NORMAL_THRESHOLD 3 // typical acceptable number of hits to KO the partner via friendly fire +#define FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD 4 // AI_FLAG_CONSERVATIVE acceptable number of hits to KO the partner via friendly fire +// Counterplay on the assumption of opponents Protecting. +#define DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE 35 // both pokemon use Trick Room on turn Trick Room expires in the hopes both opponents used Protect to stall, getting a free refresh on the timer +#define TAILWIND_IN_TRICK_ROOM_CHANCE 35 // use Tailwind on turn Trick Room expires in the hopes both opponents used Protect to stall // AI's desired stat changes for Guard Split and Power Split, treated as % #define GUARD_SPLIT_ALLY_PERCENTAGE 200 diff --git a/include/constants/battle.h b/include/constants/battle.h index c659cdf7e8..1abace348a 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -387,6 +387,9 @@ enum BattleWeather #define B_WEATHER_STRONG_WINDS (1 << BATTLE_WEATHER_STRONG_WINDS) #define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) +#define B_WEATHER_DAMAGING_ANY (B_WEATHER_HAIL | B_WEATHER_SANDSTORM) +#define B_WEATHER_ICY_ANY (B_WEATHER_HAIL | B_WEATHER_SNOW) +#define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) enum __attribute__((packed)) MoveEffects diff --git a/include/random.h b/include/random.h index 65e48e1b86..f00ace1f8c 100644 --- a/include/random.h +++ b/include/random.h @@ -209,6 +209,8 @@ enum RandomTag RNG_AI_ASSUME_STATUS_MEDIUM_ODDS, RNG_AI_ASSUME_STATUS_LOW_ODDS, RNG_AI_ASSUME_ALL_STATUS, + RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, + RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, }; #define RandomWeighted(tag, ...) \ diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c new file mode 100644 index 0000000000..fc5ea0ccf6 --- /dev/null +++ b/src/battle_ai_field_statuses.c @@ -0,0 +1,454 @@ +#include "global.h" +#include "battle_z_move.h" +#include "malloc.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_ai_field_statuses.h" +#include "battle_ai_util.h" +#include "battle_ai_main.h" +#include "battle_ai_switch_items.h" +#include "battle_factory.h" +#include "battle_setup.h" +#include "event_data.h" +#include "data.h" +#include "item.h" +#include "move.h" +#include "pokemon.h" +#include "random.h" +#include "recorded_battle.h" +#include "util.h" +#include "constants/abilities.h" +#include "constants/battle_ai.h" +#include "constants/battle_move_effects.h" +#include "constants/hold_effects.h" +#include "constants/moves.h" +#include "constants/items.h" + +static bool32 DoesAbilityBenefitFromWeather(u32 ability, u32 weather); +static bool32 DoesAbilityBenefitFromFieldStatus(u32 ability, u32 fieldStatus); +// A move is light sensitive if it is boosted by Sunny Day and weakened by low light weathers. +static bool32 IsLightSensitiveMove(u32 move); +static bool32 HasLightSensitiveMove(u32 battler); +// The following functions all feed into WeatherChecker, which is then called by ShouldSetWeather and ShouldClearWeather. +// BenefitsFrom functions all return FIELD_EFFECT_POSITIVE if the weather or field effect is good to have in place from the perspective of the battler, FIELD_EFFECT_NEUTRAL if it is neither good nor bad, and FIELD_EFFECT_NEGATIVE if it is bad. +// The purpose of WeatherChecker and FieldStatusChecker is to cleanly homogenize the logic that's the same with all of them, and to more easily apply single battle logic to double battles. +// ShouldSetWeather and ShouldClearWeather are looking for a positive or negative result respectively, and check the entire side. +// If one pokemon has a positive result and the other has a negative result, it defaults to the opinion of the battler that may change the weather or field status. +static enum FieldEffectOutcome BenefitsFromSun(u32 battler); +static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler); +static enum FieldEffectOutcome BenefitsFromHailOrSnow(u32 battler, u32 weather); +static enum FieldEffectOutcome BenefitsFromRain(u32 battler); +// The following functions all feed into FieldStatusChecker, which is then called by ShouldSetFieldStatus and ShouldClearFieldStatus. +// They work approximately the same as the weather functions. +static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler); +static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler); + +bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredResult) +{ + if (IsWeatherActive(B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) + return (FIELD_EFFECT_BLOCKED == desiredResult); + + enum FieldEffectOutcome result = FIELD_EFFECT_NEUTRAL; + enum FieldEffectOutcome firstResult = FIELD_EFFECT_NEUTRAL; + + u32 i; + u32 battlersOnSide = 1; + + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + battlersOnSide = 2; + + for (i = 0; i < battlersOnSide; i++) + { + if (weather & B_WEATHER_RAIN) + result = BenefitsFromRain(battler); + else if (weather & B_WEATHER_SUN) + result = BenefitsFromSun(battler); + else if (weather & B_WEATHER_SANDSTORM) + result = BenefitsFromSandstorm(battler); + else if (weather & B_WEATHER_ICY_ANY) + result = BenefitsFromHailOrSnow(battler, weather); + + battler = BATTLE_PARTNER(battler); + + if (result != FIELD_EFFECT_NEUTRAL) + { + if (weather & B_WEATHER_DAMAGING_ANY && i == 0 && battlersOnSide == 2) + firstResult = result; + } + } + if (firstResult != FIELD_EFFECT_NEUTRAL) + return (firstResult == result) && (result == desiredResult); + return (result == desiredResult); +} + +bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome desiredResult) +{ + enum FieldEffectOutcome result = FIELD_EFFECT_NEUTRAL; + enum FieldEffectOutcome firstResult = FIELD_EFFECT_NEUTRAL; + u32 i; + + u32 battlersOnSide = 1; + + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + battlersOnSide = 2; + + for (i = 0; i < battlersOnSide; i++) + { + // terrains + if (fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN) + result = BenefitsFromElectricTerrain(battler); + if (fieldStatus & STATUS_FIELD_GRASSY_TERRAIN) + result = BenefitsFromGrassyTerrain(battler); + if (fieldStatus & STATUS_FIELD_MISTY_TERRAIN) + result = BenefitsFromMistyTerrain(battler); + if (fieldStatus & STATUS_FIELD_PSYCHIC_TERRAIN) + result = BenefitsFromPsychicTerrain(battler); + + // other field statuses + if (fieldStatus & STATUS_FIELD_TRICK_ROOM) + result = BenefitsFromTrickRoom(battler); + + battler = BATTLE_PARTNER(battler); + + if (result != FIELD_EFFECT_NEUTRAL) + { + // Trick room wants both pokemon to agree, not just one + if (fieldStatus & STATUS_FIELD_TRICK_ROOM && i == 0 && battlersOnSide == 2) + firstResult = result; + } + } + if (firstResult != FIELD_EFFECT_NEUTRAL) + return (firstResult == result) && (result == desiredResult); + return (result == desiredResult); +} + +static bool32 DoesAbilityBenefitFromWeather(u32 ability, u32 weather) +{ + switch (ability) + { + case ABILITY_FORECAST: + return (weather & (B_WEATHER_RAIN | B_WEATHER_SUN | B_WEATHER_ICY_ANY)); + case ABILITY_MAGIC_GUARD: + case ABILITY_OVERCOAT: + return (weather & B_WEATHER_DAMAGING_ANY); + case ABILITY_SAND_FORCE: + case ABILITY_SAND_RUSH: + case ABILITY_SAND_VEIL: + return (weather & B_WEATHER_SANDSTORM); + case ABILITY_ICE_BODY: + case ABILITY_ICE_FACE: + case ABILITY_SNOW_CLOAK: + return (weather & B_WEATHER_ICY_ANY); + case ABILITY_SLUSH_RUSH: + return (weather & B_WEATHER_SNOW); + case ABILITY_DRY_SKIN: + case ABILITY_HYDRATION: + case ABILITY_RAIN_DISH: + case ABILITY_SWIFT_SWIM: + return (weather & B_WEATHER_RAIN); + case ABILITY_CHLOROPHYLL: + case ABILITY_FLOWER_GIFT: + case ABILITY_HARVEST: + case ABILITY_LEAF_GUARD: + case ABILITY_ORICHALCUM_PULSE: + case ABILITY_PROTOSYNTHESIS: + case ABILITY_SOLAR_POWER: + return (weather & B_WEATHER_SUN); + default: + break; + } + return FALSE; +} + +static bool32 DoesAbilityBenefitFromFieldStatus(u32 ability, u32 fieldStatus) +{ + switch (ability) + { + case ABILITY_MIMICRY: + return (fieldStatus & STATUS_FIELD_TERRAIN_ANY); + case ABILITY_HADRON_ENGINE: + case ABILITY_QUARK_DRIVE: + case ABILITY_SURGE_SURFER: + return (fieldStatus & STATUS_FIELD_ELECTRIC_TERRAIN); + case ABILITY_GRASS_PELT: + return (fieldStatus & STATUS_FIELD_GRASSY_TERRAIN); + // no abilities inherently benefit from Misty or Psychic Terrains + // return (fieldStatus & STATUS_FIELD_MISTY_TERRAIN); + // return (fieldStatus & STATUS_FIELD_PSYCHIC_TERRAIN); + default: + break; + } + return FALSE; +} + +static bool32 IsLightSensitiveMove(u32 move) +{ + switch (GetMoveEffect(move)) + { + case EFFECT_SOLAR_BEAM: + case EFFECT_MORNING_SUN: + case EFFECT_SYNTHESIS: + case EFFECT_MOONLIGHT: + case EFFECT_GROWTH: + return TRUE; + default: + return FALSE; + } +} + +static bool32 HasLightSensitiveMove(u32 battler) +{ + s32 i; + u16 *moves = GetMovesArray(battler); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && IsLightSensitiveMove(moves[i])) + return TRUE; + } + + return FALSE; +} + +// Sun +// Utility Umbrella does NOT block Ancient Pokemon from their stat boosts. +static enum FieldEffectOutcome BenefitsFromSun(u32 battler) +{ + u32 ability = gAiLogicData->abilities[battler]; + + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) + { + if (ability == ABILITY_ORICHALCUM_PULSE || ability == ABILITY_PROTOSYNTHESIS) + return FIELD_EFFECT_POSITIVE; + else + return FIELD_EFFECT_NEUTRAL; + } + + if (DoesAbilityBenefitFromWeather(ability, B_WEATHER_SUN) + || HasLightSensitiveMove(battler) + || HasDamagingMoveOfType(battler, TYPE_FIRE) + || HasBattlerSideMoveWithEffect(battler, EFFECT_HYDRO_STEAM)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithFlag(battler, MoveHas50AccuracyInSun) || HasDamagingMoveOfType(battler, TYPE_WATER) || gAiLogicData->abilities[battler] == ABILITY_DRY_SKIN) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +// Sandstorm +static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler) +{ + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_SANDSTORM) + || IS_BATTLER_OF_TYPE(battler, TYPE_ROCK) + || HasBattlerSideMoveWithEffect(battler, EFFECT_SHORE_UP)) + return FIELD_EFFECT_POSITIVE; + + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + { + if (!(IS_BATTLER_ANY_TYPE(FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + || gAiLogicData->holdEffects[FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES + || DoesAbilityBenefitFromWeather(gAiLogicData->abilities[FOE(battler)], B_WEATHER_SANDSTORM)) + return FIELD_EFFECT_POSITIVE; + else + return FIELD_EFFECT_NEUTRAL; + } + + return FIELD_EFFECT_NEGATIVE; +} + +// Hail or Snow +static enum FieldEffectOutcome BenefitsFromHailOrSnow(u32 battler, u32 weather) +{ + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], weather) + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) + || HasBattlerSideMoveWithEffect(battler, EFFECT_AURORA_VEIL)) + return FIELD_EFFECT_POSITIVE; + + if ((weather & B_WEATHER_DAMAGING_ANY) && gAiLogicData->holdEffects[battler] != HOLD_EFFECT_SAFETY_GOGGLES) + return FIELD_EFFECT_NEGATIVE; + + if (HasLightSensitiveMove(battler)) + return FIELD_EFFECT_NEGATIVE; + + if (HasMoveWithFlag(FOE(battler), MoveAlwaysHitsInHailSnow)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +// Rain +static enum FieldEffectOutcome BenefitsFromRain(u32 battler) +{ + if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) + return FIELD_EFFECT_NEUTRAL; + + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_RAIN) + || HasMoveWithFlag(battler, MoveAlwaysHitsInRain) + || HasDamagingMoveOfType(battler, TYPE_WATER)) + return FIELD_EFFECT_POSITIVE; + + if (HasLightSensitiveMove(battler) || HasDamagingMoveOfType(battler, TYPE_FIRE)) + return FIELD_EFFECT_NEGATIVE; + + if (HasMoveWithFlag(FOE(battler), MoveAlwaysHitsInRain)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is electric terrain bad? +static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_ELECTRIC_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithEffect(battler, EFFECT_RISING_VOLTAGE)) + return FIELD_EFFECT_POSITIVE; + + if (HasMoveWithEffect(FOE(battler), EFFECT_REST) && IsBattlerGrounded(FOE(battler))) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = IsBattlerGrounded(battler); + if (grounded && HasBattlerSideUsedMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) + return FIELD_EFFECT_POSITIVE; + + if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) + || (gStatuses3[battler] & STATUS3_YAWN) + || HasDamagingMoveOfType(battler, TYPE_ELECTRIC))) + return FIELD_EFFECT_POSITIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is grassy terrain bad? +static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_GRASSY_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) + return FIELD_EFFECT_POSITIVE; + if (HasBattlerSideUsedMoveWithAdditionalEffect(battler, MOVE_EFFECT_FLORAL_HEALING)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = IsBattlerGrounded(battler); + + // Weaken spamming Earthquake, Magnitude, and Bulldoze. + if (grounded && (HasBattlerSideUsedMoveWithEffect(FOE(battler), EFFECT_EARTHQUAKE) + || HasBattlerSideUsedMoveWithEffect(FOE(battler), EFFECT_MAGNITUDE))) + return FIELD_EFFECT_POSITIVE; + + if (grounded && HasDamagingMoveOfType(battler, TYPE_GRASS)) + return FIELD_EFFECT_POSITIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is misty terrain bad? +static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_MISTY_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(battler, EFFECT_MISTY_EXPLOSION)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = IsBattlerGrounded(battler); + bool32 allyGrounded = FALSE; + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); + + if (HasMoveWithEffect(FOE(battler), EFFECT_REST) && IsBattlerGrounded(FOE(battler))) + return FIELD_EFFECT_POSITIVE; + + // harass dragons + if ((grounded || allyGrounded) + && (HasDamagingMoveOfType(FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(BATTLE_PARTNER(FOE(battler)), TYPE_DRAGON))) + return FIELD_EFFECT_POSITIVE; + + if ((grounded || allyGrounded) && HasBattlerSideUsedMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) + return FIELD_EFFECT_POSITIVE; + + if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) + || (gStatuses3[battler] & STATUS3_YAWN))) + return FIELD_EFFECT_POSITIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +//TODO: when is Psychic Terrain negative? +static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) +{ + if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_PSYCHIC_TERRAIN)) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) + return FIELD_EFFECT_POSITIVE; + + bool32 grounded = IsBattlerGrounded(battler); + bool32 allyGrounded = FALSE; + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); + + // don't bother if we're not grounded + if (grounded || allyGrounded) + { + // harass priority + if (HasBattlerSideAbility(FOE(battler), ABILITY_GALE_WINGS, gAiLogicData) + || HasBattlerSideAbility(FOE(battler), ABILITY_TRIAGE, gAiLogicData) + || HasBattlerSideAbility(FOE(battler), ABILITY_PRANKSTER, gAiLogicData)) + return FIELD_EFFECT_POSITIVE; + } + + if (grounded && (HasDamagingMoveOfType(battler, TYPE_PSYCHIC))) + return FIELD_EFFECT_POSITIVE; + + if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) + || HasBattlerSideAbility(battler, ABILITY_TRIAGE, gAiLogicData) + || HasBattlerSideAbility(battler, ABILITY_PRANKSTER, gAiLogicData)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; +} + +static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) +{ + // If we're in singles, we literally only care about speed. + if (!IsDoubleBattle()) + { + if (GetBattlerSideSpeedAverage(battler) < GetBattlerSideSpeedAverage(FOE(battler))) + return FIELD_EFFECT_POSITIVE; + // If we tie, we shouldn't change trick room state. + else if (GetBattlerSideSpeedAverage(battler) == GetBattlerSideSpeedAverage(FOE(battler))) + return FIELD_EFFECT_NEUTRAL; + else + return FIELD_EFFECT_NEGATIVE; + } + + // First checking if we have enough priority for one pokemon to disregard Trick Room entirely. + if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)) + { + u16* aiMoves = GetMovesArray(battler); + for (int i = 0; i < MAX_MON_MOVES; i++) + { + u16 move = aiMoves[i]; + if (GetBattleMovePriority(battler, gAiLogicData->abilities[battler], move) > 0 && !(GetMovePriority(move) > 0 && IsBattleMoveStatus(move))) + { + return FIELD_EFFECT_POSITIVE; + } + } + } + + // If we are faster or tie, we don't want trick room. + if ((gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[FOE(battler)]) || (gAiLogicData->speedStats[battler] >= gAiLogicData->speedStats[BATTLE_PARTNER(FOE(battler))])) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_POSITIVE; +} + + diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 1198768b73..f9f5cc46a9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1698,7 +1698,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_AURORA_VEIL: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_AURORA_VEIL || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) - || !(weather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + || !(weather & (B_WEATHER_ICY_ANY))) ADJUST_SCORE(-10); break; case EFFECT_SHEER_COLD: @@ -1912,18 +1912,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; case EFFECT_HAIL: - if (weather & (B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) - ADJUST_SCORE(-8); - else if (weather & B_WEATHER_SNOW) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow - break; case EFFECT_SNOWSCAPE: - if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) + if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) ADJUST_SCORE(-8); - else if (weather & B_WEATHER_HAIL) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow break; case EFFECT_ATTRACT: if (!AI_CanBeInfatuated(battlerAtk, battlerDef, aiData->abilities[battlerDef])) @@ -1957,10 +1949,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CHILLY_RECEPTION: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (weather & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) + else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) ADJUST_SCORE(-8); - else if (weather & B_WEATHER_HAIL) - ADJUST_SCORE(-2); // mainly to prevent looping between hail and snow break; case EFFECT_BELLY_DRUM: case EFFECT_FILLET_AWAY: @@ -2143,12 +2133,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MORNING_SUN: case EFFECT_SYNTHESIS: case EFFECT_MOONLIGHT: - if ((AI_GetWeather() & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_FOG))) - ADJUST_SCORE(-3); - else if (AI_BattlerAtMaxHp(battlerAtk)) + if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 90) ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better + else if ((AI_GetWeather() & (B_WEATHER_LOW_LIGHT))) + ADJUST_SCORE(-3); break; case EFFECT_PURIFY: if (!(gBattleMons[battlerDef].status1 & STATUS1_ANY)) @@ -2535,6 +2525,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) ADJUST_SCORE(-10); break; + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + ADJUST_SCORE(-10); + break; case EFFECT_PLEDGE: if (isDoubleBattle && gBattleMons[BATTLE_PARTNER(battlerAtk)].hp > 0) { @@ -2551,20 +2545,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TRICK_ROOM: if (PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TRICK_ROOM)) { - ADJUST_SCORE(-10); + // This only happens if the ally already rolled on double trick room on final turn. + // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. + if (gFieldTimers.trickRoomTimer == gBattleTurnCounter) + ADJUST_SCORE(PERFECT_EFFECT); + else + ADJUST_SCORE(-10); } else if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS)) { - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM) // Trick Room Up - { - if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) // Attacker side slower than target side - ADJUST_SCORE(-10); // Keep the Trick Room up - } - else - { - if (GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) // Attacker side faster than target side - ADJUST_SCORE(-10); // Keep the Trick Room down - } + // Don't set a trick room you don't benefit from. + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(-10); + // Don't unset a trick room that doesn't harm you unless it's about to expire. + else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != gBattleTurnCounter && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + ADJUST_SCORE(-10); } break; case EFFECT_MAGIC_ROOM: @@ -2759,7 +2754,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TAILWIND: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND) - || gFieldStatuses & STATUS_FIELD_TRICK_ROOM) + || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter)) ADJUST_SCORE(-10); break; case EFFECT_LUCKY_CHANT: @@ -2900,7 +2895,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Don't use user-target moves ie. Swords Dance, with exceptions if ((moveTarget & MOVE_TARGET_USER) && moveEffect != EFFECT_DESTINY_BOND && moveEffect != EFFECT_WISH && moveEffect != EFFECT_HEALING_WISH - && !(moveEffect == EFFECT_AURORA_VEIL && (AI_GetWeather() & (B_WEATHER_SNOW | B_WEATHER_HAIL)))) + && !(moveEffect == EFFECT_AURORA_VEIL && (AI_GetWeather() & B_WEATHER_ICY_ANY))) ADJUST_SCORE(-30); // Don't use a status move if the mon is the last one in the party, has no good switchin, or is trapped else if (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_STATUS @@ -3000,11 +2995,11 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: - if (effect == EFFECT_TRICK_ROOM) + if (effect == EFFECT_TRICK_ROOM && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TRICK_ROOM: - if (effect == EFFECT_AFTER_YOU) + if (effect == EFFECT_AFTER_YOU && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); break; default: @@ -3039,7 +3034,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAGNET_RISE: if (IsBattlerGrounded(battlerAtk) - && (HasMove(battlerAtkPartner, MOVE_EARTHQUAKE) || HasMove(battlerAtkPartner, MOVE_MAGNITUDE)) + && (HasMoveWithEffect(battlerAtkPartner, EFFECT_EARTHQUAKE) || HasMoveWithEffect(battlerAtkPartner, EFFECT_MAGNITUDE)) && (AI_GetMoveEffectiveness(MOVE_EARTHQUAKE, battlerAtk, battlerAtkPartner) != UQ_4_12(0.0))) // Doesn't resist ground move { RETURN_SCORE_PLUS(DECENT_EFFECT); // partner has earthquake or magnitude -> good idea to use magnet rise @@ -3063,38 +3058,20 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // consider global move effects switch (effect) { - case EFFECT_SANDSTORM: - if (ShouldSetSandstorm(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from sandstorm - } - break; - case EFFECT_RAIN_DANCE: - if (ShouldSetRain(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from rain - } - break; - case EFFECT_SUNNY_DAY: - if (ShouldSetSun(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(WEAK_EFFECT); // our partner benefits from sun - } - break; - case EFFECT_HAIL: - if (IsBattlerAlive(battlerAtkPartner) - && ShouldSetHail(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); // our partner benefits from hail - } + // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. + // This unsets Trick Room and resets it with a full timer. + case EFFECT_TRICK_ROOM: + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) + && HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM) + && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) + ADJUST_SCORE(PERFECT_EFFECT); break; - case EFFECT_SNOWSCAPE: - case EFFECT_CHILLY_RECEPTION: - if (IsBattlerAlive(battlerAtkPartner) - && ShouldSetSnow(battlerAtkPartner, atkPartnerAbility, atkPartnerHoldEffect)) - { - RETURN_SCORE_PLUS(DECENT_EFFECT); // our partner benefits from snow - } + case EFFECT_TAILWIND: + // Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind. + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + && RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE)) + ADJUST_SCORE(BEST_EFFECT); break; default: break; @@ -4355,9 +4332,12 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SANDSTORM: - if (ShouldSetSandstorm(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SANDSTORM)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_SMOOTH_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4367,12 +4347,14 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_HAIL: - if (ShouldSetHail(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_HAIL)) { + ADJUST_SCORE(DECENT_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) ADJUST_SCORE(GOOD_EFFECT); - - ADJUST_SCORE(DECENT_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ICY_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4382,12 +4364,14 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_SNOWSCAPE: - if (ShouldSetSnow(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SNOW)) { + ADJUST_SCORE(DECENT_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_AURORA_VEIL) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) ADJUST_SCORE(GOOD_EFFECT); - - ADJUST_SCORE(DECENT_EFFECT); + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ICY_ROCK) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) @@ -4397,27 +4381,33 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } break; case EFFECT_RAIN_DANCE: - if (ShouldSetRain(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_RAIN)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_DAMP_ROCK) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) - || HasMoveWithEffect(battlerDef, EFFECT_SYNTHESIS) - || HasMoveWithEffect(battlerDef, EFFECT_SOLAR_BEAM) - || HasMoveWithEffect(battlerDef, EFFECT_MOONLIGHT)) + if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_MORNING_SUN) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_SYNTHESIS) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_SOLAR_BEAM) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_MOONLIGHT)) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithType(battlerDef, TYPE_FIRE) || HasMoveWithType(BATTLE_PARTNER(battlerDef), TYPE_FIRE)) + if (HasDamagingMoveOfType(battlerDef, TYPE_FIRE) || HasDamagingMoveOfType(BATTLE_PARTNER(battlerDef), TYPE_FIRE)) ADJUST_SCORE(WEAK_EFFECT); } break; case EFFECT_SUNNY_DAY: - if (ShouldSetSun(battlerAtk, aiData->abilities[battlerAtk], aiData->holdEffects[battlerAtk])) + if (ShouldSetWeather(battlerAtk, B_WEATHER_SUN)) { ADJUST_SCORE(DECENT_EFFECT); + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL)) + ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_HEAT_ROCK) ADJUST_SCORE(WEAK_EFFECT); - if (HasMoveWithType(battlerDef, TYPE_WATER) || HasMoveWithType(BATTLE_PARTNER(battlerDef), TYPE_WATER)) + if (HasDamagingMoveOfType(battlerDef, TYPE_WATER) || HasDamagingMoveOfType(BATTLE_PARTNER(battlerDef), TYPE_WATER)) ADJUST_SCORE(WEAK_EFFECT); if (HasMoveWithFlag(battlerDef, MoveHas50AccuracyInSun) || HasMoveWithFlag(BATTLE_PARTNER(battlerDef), MoveHas50AccuracyInSun)) ADJUST_SCORE(WEAK_EFFECT); @@ -4883,14 +4873,58 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(WORST_EFFECT); } case EFFECT_ELECTRIC_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) + ADJUST_SCORE(BEST_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; case EFFECT_MISTY_TERRAIN: - if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) - ADJUST_SCORE(BEST_EFFECT); + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) + ADJUST_SCORE(BEST_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; case EFFECT_GRASSY_TERRAIN: + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN)) + { + ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; case EFFECT_PSYCHIC_TERRAIN: - ADJUST_SCORE(GOOD_EFFECT); - if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER) + if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) + { ADJUST_SCORE(GOOD_EFFECT); + if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) + ADJUST_SCORE(WEAK_EFFECT); + } + break; + case EFFECT_STEEL_ROLLER: + { + u32 terrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + if (ShouldClearFieldStatus(battlerAtk, terrain)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldSetFieldStatus(battlerDef, terrain)) + ADJUST_SCORE(DECENT_EFFECT); + } + break; + case EFFECT_ICE_SPINNER: + { + u32 terrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY; + if (ShouldClearFieldStatus(battlerAtk, terrain)) + ADJUST_SCORE(GOOD_EFFECT); + if (ShouldSetFieldStatus(battlerDef, terrain)) + ADJUST_SCORE(DECENT_EFFECT); + } break; case EFFECT_PLEDGE: if (isDoubleBattle && HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_PLEDGE)) @@ -4899,9 +4933,10 @@ case EFFECT_GUARD_SPLIT: case EFFECT_TRICK_ROOM: if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_POWERFUL_STATUS)) { - if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) + if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); - else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && GetBattlerSideSpeedAverage(battlerAtk) >= GetBattlerSideSpeedAverage(battlerDef)) + // Don't unset it on last turn. + else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); } break; @@ -5929,11 +5964,8 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_HAIL: - if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) - ADJUST_SCORE(POWERFUL_STATUS_MOVE); - break; case EFFECT_SNOWSCAPE: - if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) + if (IsWeatherActive(B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; default: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 5d0f34b4fd..ce13267ed6 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3,6 +3,7 @@ #include "malloc.h" #include "battle.h" #include "battle_anim.h" +#include "battle_ai_field_statuses.h" #include "battle_ai_util.h" #include "battle_ai_main.h" #include "battle_ai_switch_items.h" @@ -1887,7 +1888,7 @@ bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move) if ((weather & B_WEATHER_RAIN) && MoveAlwaysHitsInRain(move)) return TRUE; - if ((weather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && MoveAlwaysHitsInHailSnow(move)) + if ((weather & B_WEATHER_ICY_ANY) && MoveAlwaysHitsInHailSnow(move)) return TRUE; if (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && MoveIncreasesPowerToMinimizedTargets(move)) return TRUE; @@ -1929,110 +1930,24 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil return FALSE; } -bool32 ShouldSetSandstorm(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 ShouldSetWeather(u32 battler, u32 weather) { - if (IsWeatherActive(B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (ability == ABILITY_SAND_VEIL - || ability == ABILITY_SAND_RUSH - || ability == ABILITY_SAND_FORCE - || ability == ABILITY_OVERCOAT - || ability == ABILITY_MAGIC_GUARD - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) - || HasMoveWithEffect(battler, EFFECT_SHORE_UP) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + return WeatherChecker(battler, weather, FIELD_EFFECT_POSITIVE); } -bool32 ShouldSetHail(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +bool32 ShouldClearWeather(u32 battler, u32 weather) { - if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || ability == ABILITY_MAGIC_GUARD - || ability == ABILITY_OVERCOAT - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) - || HasMoveWithEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + return WeatherChecker(battler, weather, FIELD_EFFECT_NEGATIVE); } -bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect) +bool32 ShouldSetFieldStatus(u32 battler, u32 fieldStatus) { - if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA - && (atkAbility == ABILITY_SWIFT_SWIM - || atkAbility == ABILITY_FORECAST - || atkAbility == ABILITY_HYDRATION - || atkAbility == ABILITY_RAIN_DISH - || atkAbility == ABILITY_DRY_SKIN - || HasMoveWithFlag(battlerAtk, MoveAlwaysHitsInRain) - || HasMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL) - || HasMoveWithType(battlerAtk, TYPE_WATER))) - { - return TRUE; - } - return FALSE; + return FieldStatusChecker(battler, fieldStatus, FIELD_EFFECT_POSITIVE); } -bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, enum ItemHoldEffect holdEffect) +bool32 ShouldClearFieldStatus(u32 battler, u32 fieldStatus) { - if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA - && (atkAbility == ABILITY_CHLOROPHYLL - || atkAbility == ABILITY_FLOWER_GIFT - || atkAbility == ABILITY_FORECAST - || atkAbility == ABILITY_LEAF_GUARD - || atkAbility == ABILITY_SOLAR_POWER - || atkAbility == ABILITY_HARVEST - || HasMoveWithEffect(battlerAtk, EFFECT_SOLAR_BEAM) - || HasMoveWithEffect(battlerAtk, EFFECT_MORNING_SUN) - || HasMoveWithEffect(battlerAtk, EFFECT_SYNTHESIS) - || HasMoveWithEffect(battlerAtk, EFFECT_MOONLIGHT) - || HasMoveWithEffect(battlerAtk, EFFECT_WEATHER_BALL) - || HasMoveWithEffect(battlerAtk, EFFECT_GROWTH) - || HasMoveWithType(battlerAtk, TYPE_FIRE))) - { - return TRUE; - } - return FALSE; -} - -bool32 ShouldSetSnow(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) -{ - if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE) - return FALSE; - - if (ability == ABILITY_SNOW_CLOAK - || ability == ABILITY_ICE_BODY - || ability == ABILITY_FORECAST - || ability == ABILITY_SLUSH_RUSH - || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - || HasMoveWithFlag(battler, MoveAlwaysHitsInHailSnow) - || HasMoveWithEffect(battler, EFFECT_AURORA_VEIL) - || HasMoveWithEffect(battler, EFFECT_WEATHER_BALL)) - { - return TRUE; - } - return FALSE; + return FieldStatusChecker(battler, fieldStatus, FIELD_EFFECT_NEGATIVE); } bool32 IsBattlerDamagedByStatus(u32 battler) @@ -3816,7 +3731,7 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo { case EFFECT_AURORA_VEIL: // Use only in Hail and only if AI doesn't already have Reflect, Light Screen or Aurora Veil itself active. - if ((AI_GetWeather() & (B_WEATHER_HAIL | B_WEATHER_SNOW)) + if ((AI_GetWeather() & (B_WEATHER_ICY_ANY)) && !(gSideStatuses[atkSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 33c3eca074..e4ab8610ab 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -431,7 +431,7 @@ AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons tha // Sandstorm is omitted on purpose. // Tornadus is currently not willing to set up Sandstorm for its ally, but the actual purpose of this test is to demonstrate that Tornadus or Whimsicott will perform standard VGC openers. // Rain Dance, Sunny Day, and Snowscape are the actually important ones; setting up a good Sandstorm test + functionality is less important and will be done in later PRs. -AI_DOUBLE_BATTLE_TEST("AI will set up weather for its ally") +AI_DOUBLE_BATTLE_TEST("AI sets up weather for its ally") { u32 goodWeather, badWeather, weatherTrigger; u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; @@ -440,7 +440,7 @@ AI_DOUBLE_BATTLE_TEST("AI will set up weather for its ally") PARAMETRIZE { goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; } PARAMETRIZE { goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } PARAMETRIZE { goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } -// PARAMETRIZE { goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } + PARAMETRIZE { goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; } PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; @@ -449,20 +449,49 @@ AI_DOUBLE_BATTLE_TEST("AI will set up weather for its ally") goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; } -// PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; -// goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; } GIVEN { AI_FLAGS(aiFlags); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_TORNADUS) { Ability(ABILITY_PRANKSTER); Moves(goodWeather, badWeather, MOVE_RETURN, MOVE_TAUNT); } + OPPONENT(SPECIES_TORNADUS) { Item(ITEM_SAFETY_GOGGLES); Ability(ABILITY_PRANKSTER); Moves(goodWeather, badWeather, MOVE_RETURN, MOVE_TAUNT); } OPPONENT(SPECIES_WOBBUFFET) { Moves(weatherTrigger, MOVE_EARTH_POWER); } } WHEN { TURN { EXPECT_MOVE(opponentLeft, goodWeather); } } } +AI_DOUBLE_BATTLE_TEST("AI sets up terrain for its ally") +{ + u32 goodTerrain, badTerrain, terrainTrigger; + u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; + + PARAMETRIZE { goodTerrain = MOVE_ELECTRIC_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_RISING_VOLTAGE; } + PARAMETRIZE { goodTerrain = MOVE_GRASSY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_GRASSY_GLIDE; } + PARAMETRIZE { goodTerrain = MOVE_MISTY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_MISTY_EXPLOSION; } + PARAMETRIZE { goodTerrain = MOVE_PSYCHIC_TERRAIN; badTerrain = MOVE_ELECTRIC_TERRAIN; terrainTrigger = MOVE_EXPANDING_FORCE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodTerrain = MOVE_ELECTRIC_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_RISING_VOLTAGE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodTerrain = MOVE_GRASSY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_GRASSY_GLIDE; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodTerrain = MOVE_MISTY_TERRAIN; badTerrain = MOVE_PSYCHIC_TERRAIN; terrainTrigger = MOVE_MISTY_EXPLOSION; } + PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; + goodTerrain = MOVE_PSYCHIC_TERRAIN; badTerrain = MOVE_ELECTRIC_TERRAIN; terrainTrigger = MOVE_EXPANDING_FORCE; } + + GIVEN { + AI_FLAGS(aiFlags); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(goodTerrain, badTerrain, MOVE_RETURN, MOVE_TAUNT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(terrainTrigger, MOVE_EARTH_POWER); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, goodTerrain); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") { u32 move; @@ -476,7 +505,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); PLAYER(SPECIES_WOBBUFFET) { Speed(4); } PLAYER(SPECIES_WOBBUFFET) { Speed(4); } - OPPONENT(SPECIES_INDEEDEE_M) { Speed(5); Moves(MOVE_AFTER_YOU, MOVE_PSYCHIC); } + OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_TRIAGE); Speed(5); Moves(MOVE_AFTER_YOU, MOVE_DRAINING_KISS); } OPPONENT(SPECIES_CLEFAIRY) { Speed(3); Moves(move, MOVE_PSYCHIC); } } WHEN { if (move == MOVE_TRICK_ROOM) @@ -486,7 +515,32 @@ AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room") } } +AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently") +{ + u32 move, ability, speed; + PARAMETRIZE { move = MOVE_DRAINING_KISS; ability = ABILITY_SYNCHRONIZE; speed = 4; } + PARAMETRIZE { move = MOVE_DAZZLING_GLEAM; ability = ABILITY_SYNCHRONIZE; speed = 4; } + PARAMETRIZE { move = MOVE_DRAINING_KISS; ability = ABILITY_PSYCHIC_SURGE; speed = 4; } + PARAMETRIZE { move = MOVE_DRAINING_KISS; ability = ABILITY_SYNCHRONIZE; speed = 2; } + PARAMETRIZE { move = MOVE_DAZZLING_GLEAM; ability = ABILITY_SYNCHRONIZE; speed = 2; } + PARAMETRIZE { move = MOVE_DRAINING_KISS; ability = ABILITY_PSYCHIC_SURGE; speed = 2; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); + ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(speed); } + OPPONENT(SPECIES_COMFEY) { Ability(ABILITY_TRIAGE); Speed(5); Moves(move); } + OPPONENT(SPECIES_INDEEDEE) { Ability(ability); Speed(3); Moves(MOVE_TRICK_ROOM, MOVE_PSYCHIC); } + } WHEN { + if (move == MOVE_DRAINING_KISS && ability != ABILITY_PSYCHIC_SURGE && speed > 3) + TURN { EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + else + TURN { NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + } +} AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats") { From c6f539c8be1f6f671e8ce356e7731b699e7263c1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 20 Jul 2025 01:21:10 +0200 Subject: [PATCH 120/283] Adds Missing break in ABILITY_TERAFORM_ZERO (#7377) --- src/battle_util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_util.c b/src/battle_util.c index f3972791f8..b5e68f9cbd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3871,6 +3871,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero); effect++; } + break; case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; From cb66393df7835f7638cdb9d7c0cff7d8339bca76 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 20 Jul 2025 05:34:51 -0400 Subject: [PATCH 121/283] Add missing break (#7356) --- src/battle_ai_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 813ea65d2b..a73de7f94e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3890,6 +3890,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_BIG_ROOT) ADJUST_SCORE(WEAK_EFFECT); } + break; case EFFECT_EXPLOSION: case EFFECT_MISTY_EXPLOSION: case EFFECT_MEMENTO: From a92f432dafacfd5b309cd0f992a3ff8d85506eab Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sun, 20 Jul 2025 06:53:14 -0400 Subject: [PATCH 122/283] Improve AI type matchup calcs (#7364) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_switch_items.c | 60 ++++++++++++++++------------------- test/battle/ai/ai_switching.c | 13 ++++++++ 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 06c41c6d77..84cba174b2 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -31,6 +31,7 @@ static bool32 AI_OpponentCanFaintAiWithMod(u32 battler, u32 healAmount); static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon); static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent); static u32 GetHPHealAmount(u8 itemEffectParam, struct Pokemon *mon); +static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struct BattlePokemon battleMon); static void InitializeSwitchinCandidate(struct Pokemon *mon) { @@ -176,11 +177,11 @@ static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) static bool32 ShouldSwitchIfHasBadOdds(u32 battler) { //Variable initialization - u8 opposingPosition, atkType1, atkType2, defType1, defType2; + u8 opposingPosition; s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0; u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE; - u16 typeEffectiveness = UQ_4_12(1.0); //baseline typing damage + u32 typeMatchup; enum BattleMoveEffects aiMoveEffect; u32 hitsToKoPlayer = 0, hitsToKoAI = 0; @@ -196,12 +197,6 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) opposingBattler = GetBattlerAtPosition(opposingPosition); u16 *playerMoves = GetMovesArray(opposingBattler); - // Gets types of player (opposingBattler) and computer (battler) - atkType1 = gBattleMons[opposingBattler].types[0]; - atkType2 = gBattleMons[opposingBattler].types[1]; - defType1 = gBattleMons[battler].types[0]; - defType2 = gBattleMons[battler].types[1]; - for (i = 0; i < MAX_MON_MOVES; i++) { aiMove = gBattleMons[battler].moves[i]; @@ -245,15 +240,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(maxDamageDealt, opposingBattler); // Calculate type advantage - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); - if (defType2 != defType1) - { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); - } + typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gBattleMons[battler]); // Get max damage mon could take for (i = 0; i < MAX_MON_MOVES; i++) @@ -303,7 +290,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) } // General bad type matchups have more wiggle room - if (typeEffectiveness >= UQ_4_12(2.0)) // If the player has at least a 2x type advantage + if (typeMatchup > UQ_4_12(2.0)) // If the player has favourable offensive matchup (2.0 is neutral, this must be worse) { if (!hasSuperEffectiveMove // If the AI doesn't have a super effective move && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator @@ -1902,25 +1889,34 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) return hitsToKO; } -static u16 GetSwitchinTypeMatchup(u32 opposingBattler, struct BattlePokemon battleMon) +static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struct BattlePokemon battleMon) { - // Check type matchup - u16 typeEffectiveness = UQ_4_12(1.0); - u8 atkType1 = GetSpeciesType(gBattleMons[opposingBattler].species, 0), atkType2 = GetSpeciesType(gBattleMons[opposingBattler].species, 1), + u32 typeEffectiveness1 = UQ_4_12(1.0), typeEffectiveness2 = UQ_4_12(1.0); + u8 atkType1 = opposingBattleMon.types[0], atkType2 = opposingBattleMon.types[1], defType1 = battleMon.types[0], defType2 = battleMon.types[1]; - // Multiply type effectiveness by a factor depending on type matchup - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); + // Add each independent defensive type matchup together + typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType1))); if (defType2 != defType1) + typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType2))); + if (typeEffectiveness1 == 0) // Immunity + typeEffectiveness1 = UQ_4_12(0.1); + + if (atkType2 != atkType1) + { + typeEffectiveness2 = uq4_12_multiply(typeEffectiveness2, (GetTypeModifier(atkType2, defType1))); + if (defType2 != defType1) + typeEffectiveness2 = uq4_12_multiply(typeEffectiveness2, (GetTypeModifier(atkType2, defType2))); + if (typeEffectiveness2 == 0) // Immunity + typeEffectiveness2 = UQ_4_12(0.1); + } + else { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); + typeEffectiveness2 = typeEffectiveness1; } - return typeEffectiveness; + + return typeEffectiveness1 + typeEffectiveness2; } static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId, int lastId, int currentMonId) @@ -2049,7 +2045,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0; u32 aiMove, hitsToKOAI, maxHitsToKO = 0; - u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup; + u32 bestResist = UQ_4_12(2.0), bestResistEffective = UQ_4_12(2.0), typeMatchup; // 2.0 is the default "Neutral" matchup from GetBattleMonTypeMatchup bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1; // Iterate through mons @@ -2082,7 +2078,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, // Get max number of hits for player to KO AI mon and type matchup for defensive switching hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon), battler); - typeMatchup = GetSwitchinTypeMatchup(opposingBattler, gAiLogicData->switchinCandidate.battleMon); + typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); // Check through current mon's moves for (j = 0; j < MAX_MON_MOVES; j++) diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 2eb6834c6c..4d1fa5d746 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1286,3 +1286,16 @@ AI_SINGLE_BATTLE_TEST("AI_SMART_MON_CHOICES: AI sees its own weather setting abi TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will properly consider immunities when determining switchin type matchup") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_POLIWRATH) { Moves(MOVE_WATER_GUN, MOVE_KARATE_CHOP); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(1); Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_CERULEDGE) { Moves(MOVE_SPARK); } + OPPONENT(SPECIES_WHIMSICOTT) { Moves(MOVE_MEGA_DRAIN); } + } WHEN { + TURN { MOVE(player, MOVE_KARATE_CHOP); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 2); } + } +} From 14a7fc58adc2b0e760704367bbbfaebce97a7052 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Sun, 20 Jul 2025 20:00:55 +0100 Subject: [PATCH 123/283] Multibattle Partner AI Flags and 2vs1 battler3 AI Flags fix (#7378) --- include/data.h | 14 ++++++++++++-- src/battle_ai_main.c | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/data.h b/include/data.h index ffa1a4cba0..4663bae33c 100644 --- a/include/data.h +++ b/include/data.h @@ -198,9 +198,16 @@ extern const struct FollowerMsgInfo gFollowerCuriousMessages[]; extern const struct FollowerMsgInfo gFollowerMusicMessages[]; extern const struct FollowerMsgInfo gFollowerPoisonedMessages[]; +static inline bool8 IsPartnerTrainerId(u16 trainerId) +{ + if (trainerId >= TRAINER_PARTNER(PARTNER_NONE) && trainerId < TRAINER_PARTNER(PARTNER_COUNT)) + return TRUE; + return FALSE; +} + static inline u16 SanitizeTrainerId(u16 trainerId) { - if (trainerId >= TRAINERS_COUNT) + if (trainerId >= TRAINERS_COUNT && !IsPartnerTrainerId(trainerId)) return TRAINER_NONE; return trainerId; } @@ -212,7 +219,10 @@ static inline const struct Trainer *GetTrainerStructFromId(u16 trainerId) sanitizedTrainerId = SanitizeTrainerId(trainerId); enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); - return &gTrainers[difficulty][sanitizedTrainerId]; + if (IsPartnerTrainerId(trainerId)) + return &gBattlePartners[difficulty][sanitizedTrainerId - TRAINER_PARTNER(PARTNER_NONE)]; + else + return &gTrainers[difficulty][sanitizedTrainerId]; } static inline const enum TrainerClassID GetTrainerClassFromId(u16 trainerId) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a73de7f94e..b6ddd0dc91 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -251,7 +251,7 @@ void BattleAI_SetupFlags(void) else { gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA); - if (TRAINER_BATTLE_PARAM.opponentB != 0) + if (TRAINER_BATTLE_PARAM.opponentB != 0 && TRAINER_BATTLE_PARAM.opponentB != 0xFFFF) gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); else gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT]; @@ -259,7 +259,7 @@ void BattleAI_SetupFlags(void) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId); } else if (IsDoubleBattle() && IsAiVsAiBattle()) { From e63e89e2704abf7b8515c20b0c8ada769b60ae6a Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Mon, 21 Jul 2025 19:33:44 +0200 Subject: [PATCH 124/283] Fix potential stack memory leak in gbagfx due to out of bounds read (#2162) * fix(tools): gbagfx potential oob read --------- Co-authored-by: sbird --- tools/gbagfx/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c index 98a1a1edf9..497a869e14 100644 --- a/tools/gbagfx/main.c +++ b/tools/gbagfx/main.c @@ -333,6 +333,9 @@ void HandleJascToGbaPaletteCommand(char *inputPath, char *outputPath, int argc, if (numColors < 1) FATAL_ERROR("Number of colors must be positive.\n"); + + if (numColors > 255) + FATAL_ERROR("Number of colors must be less than 256.\n"); } else { From 8e8813e5933692bd309dbdbdf0e6a84ead54eb15 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 22 Jul 2025 18:58:15 +0200 Subject: [PATCH 125/283] Show chosen move in the battle debug menu (#7382) --- src/battle_debug.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/battle_debug.c b/src/battle_debug.c index e746ee619d..6b8998de8f 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -813,11 +813,16 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) if (gAiLogicData->shouldSwitch & (1u << data->aiBattlerId)) { u32 switchMon = GetMonData(&gEnemyParty[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES); - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Switching to "), 74, 64, 0, NULL); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, gSpeciesInfo[switchMon].speciesName, 74 + 68, 64, 0, NULL); } - + else + { + u32 chosenMoveIndex = gAiBattleData->chosenMoveIndex[data->aiBattlerId]; + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Chosen move: "), 74, 64, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, GetMoveName(gBattleMons[data->aiBattlerId].moves[chosenMoveIndex]), 74 + 68, 64, 0, NULL); + } + CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); Free(text); } From c544fee140d5e9c4b3543df7d895e3e7e0d67462 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:13:10 -0400 Subject: [PATCH 126/283] Improve AI's Sucker Punch handling (#7389) --- include/config/ai.h | 2 ++ include/random.h | 1 + src/battle_ai_main.c | 9 ++++----- test/battle/ai/ai.c | 13 +++++++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/config/ai.h b/include/config/ai.h index 99283ee90a..f5d0496c20 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -58,6 +58,8 @@ #define BOOST_INTO_HAZE_CHANCE 0 // Chance the AI will use a stat boosting move if the player has used Haze #define SHOULD_RECOVER_CHANCE 50 // Chance the AI will give recovery moves score increase if less than ENABLE_RECOVERY_THRESHOLD and in no immediate danger #define ENABLE_RECOVERY_THRESHOLD 60 // HP percentage beneath which SHOULD_RECOVER_CHANCE is active +#define SUCKER_PUNCH_CHANCE 50 // Chance for the AI to not use Sucker Punch if the player has a status move +#define SUCKER_PUNCH_PREDICTION_CHANCE 50 // Additional chance for the AI to not use Sucker Punch if actively predicting a status move if SUCKER_PUNCH_CHANCE fails // AI damage calc considerations #define RISKY_AI_CRIT_STAGE_THRESHOLD 2 // Stat stages at which Risky will assume it gets a crit diff --git a/include/random.h b/include/random.h index f00ace1f8c..89ccb9779a 100644 --- a/include/random.h +++ b/include/random.h @@ -193,6 +193,7 @@ enum RandomTag RNG_AI_CONSERVE_TERA, RNG_AI_SWITCH_ALL_SCORES_BAD, RNG_AI_PP_STALL_DISREGARD_MOVE, + RNG_AI_SUCKER_PUNCH, RNG_SHELL_SIDE_ARM, RNG_RANDOM_TARGET, RNG_AI_PREDICT_ABILITY, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b6ddd0dc91..0f9bf432c9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2745,11 +2745,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_SUCKER_PUNCH: - if (predictedMove != MOVE_NONE) - { - if (IsBattleMoveStatus(predictedMove) || AI_IsSlower(battlerAtk, battlerDef, move)) // Opponent going first - ADJUST_SCORE(-10); - } + if ((HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_STATUS) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_CHANCE)) // Player has a status move + || (IsBattleMoveStatus(predictedMove) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_PREDICTION_CHANCE) && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_PREDICT_MOVE)) // AI actively predicting incoming status move + || AI_IsSlower(battlerAtk, battlerDef, move)) // Opponent going first + ADJUST_SCORE(-10); break; case EFFECT_TAILWIND: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 4eb99e481e..25999df746 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -675,6 +675,19 @@ AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a move of the sam } } +AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a status move a percentage of the time") +{ + PASSES_RANDOMLY(SUCKER_PUNCH_CHANCE, 100, RNG_AI_SUCKER_PUNCH); + GIVEN { + ASSUME(GetMoveEffect(MOVE_SUCKER_PUNCH) == EFFECT_SUCKER_PUNCH); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_GROWL, MOVE_SCRATCH); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SUCKER_PUNCH, MOVE_SCRATCH); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SUCKER_PUNCH); } + } +} + AI_SINGLE_BATTLE_TEST("AI won't use thawing moves if target is frozen unless it is super effective or it has no other options") { u32 aiFlags = 0; u32 status = 0; u32 aiMove = 0; From 6f8a1bbdb8a5ef75c4372cc625164a41e95ec2a4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 23 Jul 2025 04:28:34 -0400 Subject: [PATCH 127/283] Add pack/unpack for data masks (#2163) --- include/global.fieldmap.h | 17 +++++++++++++ include/global.h | 3 +++ src/battle_pyramid.c | 1 + src/braille_puzzles.c | 12 +++++----- src/decoration.c | 21 ++++++++++++---- src/field_specials.c | 50 +++++++++++++++++++-------------------- src/fieldmap.c | 18 +++++++------- src/fldeff_escalator.c | 4 ++-- src/fldeff_misc.c | 8 +++---- src/scrcmd.c | 2 +- src/secret_base.c | 14 +++++------ src/trainer_hill.c | 12 +++++----- 12 files changed, 98 insertions(+), 64 deletions(-) diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index d3e260e192..1207bd80ea 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -7,19 +7,36 @@ #define MAPGRID_METATILE_ID_MASK 0x03FF // Bits 0-9 #define MAPGRID_COLLISION_MASK 0x0C00 // Bits 10-11 #define MAPGRID_ELEVATION_MASK 0xF000 // Bits 12-15 +#define MAPGRID_METATILE_ID_SHIFT 0 #define MAPGRID_COLLISION_SHIFT 10 #define MAPGRID_ELEVATION_SHIFT 12 +#define PACK_METATILE(metatileId) PACK(metatileId, MAPGRID_METATILE_ID_SHIFT, MAPGRID_METATILE_ID_MASK) +#define PACK_COLLISION(collision) PACK(collision, MAPGRID_COLLISION_SHIFT, MAPGRID_COLLISION_MASK) +#define PACK_ELEVATION(elevation) PACK(elevation, MAPGRID_ELEVATION_SHIFT, MAPGRID_ELEVATION_MASK) +#define UNPACK_METATILE(data) UNPACK(data, MAPGRID_METATILE_ID_SHIFT, MAPGRID_METATILE_ID_MASK) +#define UNPACK_COLLISION(data) UNPACK(data, MAPGRID_COLLISION_SHIFT, MAPGRID_COLLISION_MASK) +#define UNPACK_ELEVATION(data) UNPACK(data, MAPGRID_ELEVATION_SHIFT, MAPGRID_ELEVATION_MASK) + // An undefined map grid block has all metatile id bits set and nothing else #define MAPGRID_UNDEFINED MAPGRID_METATILE_ID_MASK +// When setting impassability manually GF sets all the collision bits +#define MAPGRID_IMPASSABLE MAPGRID_COLLISION_MASK + // Masks/shifts for metatile attributes // Metatile attributes consist of an 8 bit behavior value, 4 unused bits, and a 4 bit layer type value // This is the data stored in each data/tilesets/*/*/metatile_attributes.bin file #define METATILE_ATTR_BEHAVIOR_MASK 0x00FF // Bits 0-7 #define METATILE_ATTR_LAYER_MASK 0xF000 // Bits 12-15 +#define METATILE_ATTR_BEHAVIOR_SHIFT 0 #define METATILE_ATTR_LAYER_SHIFT 12 +#define PACK_BEHAVIOR(behavior) PACK(behavior, METATILE_ATTR_BEHAVIOR_SHIFT, METATILE_ATTR_BEHAVIOR_MASK) +#define PACK_LAYER_TYPE(layerType) PACK(layerType, METATILE_ATTR_LAYER_SHIFT, METATILE_ATTR_LAYER_MASK) +#define UNPACK_BEHAVIOR(data) UNPACK(data, METATILE_ATTR_BEHAVIOR_SHIFT, METATILE_ATTR_BEHAVIOR_MASK) +#define UNPACK_LAYER_TYPE(data) UNPACK(data, METATILE_ATTR_LAYER_SHIFT, METATILE_ATTR_LAYER_MASK) + enum { METATILE_LAYER_TYPE_NORMAL, // Metatile uses middle and top bg layers METATILE_LAYER_TYPE_COVERED, // Metatile uses bottom and middle bg layers diff --git a/include/global.h b/include/global.h index ad29e4897b..f0882710e5 100644 --- a/include/global.h +++ b/include/global.h @@ -119,6 +119,9 @@ #define T2_READ_32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) #define T2_READ_PTR(ptr) (void *) T2_READ_32(ptr) +#define PACK(data, shift, mask) ( ((data) << (shift)) & (mask) ) +#define UNPACK(data, shift, mask) ( ((data) & (mask)) >> (shift) ) + // Macros for checking the joypad #define TEST_BUTTON(field, button) ((field) & (button)) #define JOY_NEW(button) TEST_BUTTON(gMain.newKeys, button) diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index d78cd38417..dc604a5207 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -1557,6 +1557,7 @@ void GenerateBattlePyramidFloorLayout(u16 *backupMapData, bool8 setPlayerPositio gSaveBlock1Ptr->pos.x = (mapLayout->width * (i % PYRAMID_FLOOR_SQUARES_WIDE)) + x; gSaveBlock1Ptr->pos.y = (mapLayout->height * (i / PYRAMID_FLOOR_SQUARES_WIDE)) + y; } + // Copy the elevation and collision, but overwrite the metatile ID map[x] = (layoutMap[x] & (MAPGRID_ELEVATION_MASK | MAPGRID_COLLISION_MASK)) | METATILE_BattlePyramid_Floor; } else diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c index 28ed8cdf5f..7ac88091ef 100644 --- a/src/braille_puzzles.c +++ b/src/braille_puzzles.c @@ -80,9 +80,9 @@ void DoBrailleDigEffect(void) MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(10 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(10 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_BRAILLE_DIG); @@ -207,9 +207,9 @@ static void DoBrailleRegirockEffect(void) MapGridSetMetatileIdAt(7 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(9 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_REGIROCK_PUZZLE_COMPLETED); @@ -246,9 +246,9 @@ static void DoBrailleRegisteelEffect(void) MapGridSetMetatileIdAt(7 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(9 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_REGISTEEL_PUZZLE_COMPLETED); diff --git a/src/decoration.c b/src/decoration.c index 98c6dba176..2bb97893e1 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -1221,9 +1221,9 @@ static void ShowDecorationOnMap_(u16 mapX, u16 mapY, u8 decWidth, u8 decHeight, { x = mapX + i; attributes = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + gDecorations[decoration].tiles[j * decWidth + i]); - if (MetatileBehavior_IsSecretBaseImpassable(attributes & METATILE_ATTR_BEHAVIOR_MASK) == TRUE + if (MetatileBehavior_IsSecretBaseImpassable(UNPACK_BEHAVIOR(attributes)) == TRUE || (gDecorations[decoration].permission != DECORPERM_PASS_FLOOR && (attributes >> METATILE_ATTR_LAYER_SHIFT) != METATILE_LAYER_TYPE_NORMAL)) - impassableFlag = MAPGRID_COLLISION_MASK; + impassableFlag = MAPGRID_IMPASSABLE; else impassableFlag = 0; @@ -1514,6 +1514,17 @@ static bool8 IsFloorOrBoardAndHole(u16 behaviorAt, const struct Decoration *deco return FALSE; } +#ifdef BUGFIX +#define GetLayerType(tileId) UNPACK_LAYER_TYPE(GetMetatileAttributesById(tileId)) +#else +// This incompletely extracts the layer type data. The result is that comparisons against any nonzero +// value in the valid range always have the same result. +// Because GF only compares against 0 (METATILE_LAYER_TYPE_NORMAL) there are no ill effects and it's possible this +// is what they intended. We use the named constant for the comparisons, which implies you can use nonzero constants at +// those locations (which you can't), so to avoid this trap and keep the better documentation this is included as a bug fix. +#define GetLayerType(tileId) GetMetatileAttributesById(tileId) & METATILE_ATTR_LAYER_MASK +#endif + static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { u8 i; @@ -1538,7 +1549,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]); if (!IsFloorOrBoardAndHole(behaviorAt, decoration)) return FALSE; @@ -1559,7 +1570,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]); if (!MetatileBehavior_IsNormal(behaviorAt) && !IsSecretBaseTrainerSpot(behaviorAt, layerType)) return FALSE; @@ -1576,7 +1587,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[j]); if (!MetatileBehavior_IsNormal(behaviorAt) && !MetatileBehavior_IsSecretBaseNorthWall(behaviorAt)) return FALSE; diff --git a/src/field_specials.c b/src/field_specials.c index 98384d52ab..b92efa14ed 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -659,10 +659,10 @@ void MauvilleGymSetDefaultBarriers(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH2_On); break; case METATILE_MauvilleGym_GreenBeamH3_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH3_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH3_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamH4_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH4_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH4_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamH1_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH1_Off); @@ -683,37 +683,37 @@ void MauvilleGymSetDefaultBarriers(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH2_On); break; case METATILE_MauvilleGym_RedBeamH3_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH3_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH3_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamH4_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV2_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_FloorTile); break; case METATILE_MauvilleGym_RedBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamV2_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_FloorTile); break; case METATILE_MauvilleGym_PoleBottom_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV1_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV1_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_FloorTile: if (MapGridGetMetatileIdAt(x, y - 1) == METATILE_MauvilleGym_GreenBeamV1_On) - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV2_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV2_On | MAPGRID_IMPASSABLE); else - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV2_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV2_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleBottom_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV1_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV1_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleTop_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleTop_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_Off); @@ -764,10 +764,10 @@ void MauvilleGymDeactivatePuzzle(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_Off); break; case METATILE_MauvilleGym_GreenBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV2_On: case METATILE_MauvilleGym_RedBeamV2_On: @@ -876,8 +876,8 @@ static void PetalburgGymSetDoorMetatiles(u8 roomNumber, u16 metatileId) } for (i = 0; i < nDoors; i++) { - MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET + 1, (metatileId + METATILE_ROW_WIDTH) | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET + 1, (metatileId + METATILE_ROW_WIDTH) | MAPGRID_IMPASSABLE); } DrawWholeMapView(); } @@ -1066,7 +1066,7 @@ static void PCTurnOnEffect_SetMetatile(s16 isScreenOn, s8 dx, s8 dy) else if (gSpecialVar_0x8004 == PC_LOCATION_MAYS_HOUSE) metatileId = METATILE_BrendansMaysHouse_MayPC_On; } - MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); } // For this special, gSpecialVar_0x8004 is expected to be some PC_LOCATION_* value. @@ -1106,7 +1106,7 @@ static void PCTurnOffEffect(void) else if (gSpecialVar_0x8004 == PC_LOCATION_MAYS_HOUSE) metatileId = METATILE_BrendansMaysHouse_MayPC_Off; - MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); DrawWholeMapView(); } @@ -1138,14 +1138,14 @@ static void LotteryCornerComputerEffect(struct Task *task) if (task->tIsScreenOn) { // Screen is on, set it off - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_IMPASSABLE); } else { // Screen is off, set it on - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Flash | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Flash | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Flash | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Flash | MAPGRID_IMPASSABLE); } DrawWholeMapView(); @@ -1160,8 +1160,8 @@ static void LotteryCornerComputerEffect(struct Task *task) void EndLotteryCornerComputerEffect(void) { - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_IMPASSABLE); DrawWholeMapView(); } @@ -1941,7 +1941,7 @@ static void Task_MoveElevatorWindowLights(u8 taskId) for (y = 0; y < ELEVATOR_WINDOW_HEIGHT; y++) { for (x = 0; x < ELEVATOR_WINDOW_WIDTH; x++) - MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Ascending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Ascending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_IMPASSABLE); } } else @@ -1950,7 +1950,7 @@ static void Task_MoveElevatorWindowLights(u8 taskId) for (y = 0; y < ELEVATOR_WINDOW_HEIGHT; y++) { for (x = 0; x < ELEVATOR_WINDOW_WIDTH; x++) - MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Descending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Descending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_IMPASSABLE); } } DrawWholeMapView(); diff --git a/src/fieldmap.c b/src/fieldmap.c index 8c0e416f45..97db758caa 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -56,7 +56,7 @@ static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, i = (x + 1) & 1; \ i += ((y + 1) & 1) * 2; \ \ - block = gMapHeader.mapLayout->border[i] | MAPGRID_COLLISION_MASK; \ + block = gMapHeader.mapLayout->border[i] | MAPGRID_IMPASSABLE; \ }) #define AreCoordsWithinMapGridBounds(x, y) (x >= 0 && x < gBackupMapLayout.width && y >= 0 && y < gBackupMapLayout.height) @@ -349,7 +349,7 @@ u8 MapGridGetElevationAt(int x, int y) if (block == MAPGRID_UNDEFINED) return 0; - return block >> MAPGRID_ELEVATION_SHIFT; + return UNPACK_ELEVATION(block); } u8 MapGridGetCollisionAt(int x, int y) @@ -359,7 +359,7 @@ u8 MapGridGetCollisionAt(int x, int y) if (block == MAPGRID_UNDEFINED) return TRUE; - return (block & MAPGRID_COLLISION_MASK) >> MAPGRID_COLLISION_SHIFT; + return UNPACK_COLLISION(block); } u32 MapGridGetMetatileIdAt(int x, int y) @@ -367,21 +367,21 @@ u32 MapGridGetMetatileIdAt(int x, int y) u16 block = GetMapGridBlockAt(x, y); if (block == MAPGRID_UNDEFINED) - return GetBorderBlockAt(x, y) & MAPGRID_METATILE_ID_MASK; + return UNPACK_METATILE(GetBorderBlockAt(x, y)); - return block & MAPGRID_METATILE_ID_MASK; + return UNPACK_METATILE(block); } u32 MapGridGetMetatileBehaviorAt(int x, int y) { u16 metatile = MapGridGetMetatileIdAt(x, y); - return GetMetatileAttributesById(metatile) & METATILE_ATTR_BEHAVIOR_MASK; + return UNPACK_BEHAVIOR(GetMetatileAttributesById(metatile)); } u8 MapGridGetMetatileLayerTypeAt(int x, int y) { u16 metatile = MapGridGetMetatileIdAt(x, y); - return (GetMetatileAttributesById(metatile) & METATILE_ATTR_LAYER_MASK) >> METATILE_ATTR_LAYER_SHIFT; + return UNPACK_LAYER_TYPE(GetMetatileAttributesById(metatile)); } void MapGridSetMetatileIdAt(int x, int y, u16 metatile) @@ -390,6 +390,8 @@ void MapGridSetMetatileIdAt(int x, int y, u16 metatile) if (AreCoordsWithinMapGridBounds(x, y)) { i = x + y * gBackupMapLayout.width; + + // Elevation is ignored in the argument, but copy metatile ID and collision gBackupMapLayout.map[i] = (gBackupMapLayout.map[i] & MAPGRID_ELEVATION_MASK) | (metatile & ~MAPGRID_ELEVATION_MASK); } } @@ -832,7 +834,7 @@ static bool8 SkipCopyingMetatileFromSavedMap(u16 *mapBlock, u16 mapWidth, u8 yMo else mapBlock += mapWidth; - if (IsLargeBreakableDecoration(*mapBlock & MAPGRID_METATILE_ID_MASK, yMode) == TRUE) + if (IsLargeBreakableDecoration(UNPACK_METATILE(*mapBlock), yMode) == TRUE) return TRUE; return FALSE; } diff --git a/src/fldeff_escalator.c b/src/fldeff_escalator.c index eabbd53549..f49b97b0c8 100644 --- a/src/fldeff_escalator.c +++ b/src/fldeff_escalator.c @@ -126,13 +126,13 @@ static void Task_DrawEscalator(u8 taskId) SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_1, 0); break; case 2: - SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_2, MAPGRID_COLLISION_MASK); + SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_2, MAPGRID_IMPASSABLE); break; case 3: SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_3, 0); break; case 4: - SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_0, MAPGRID_COLLISION_MASK); + SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_0, MAPGRID_IMPASSABLE); break; case 5: SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_1, 0); diff --git a/src/fldeff_misc.c b/src/fldeff_misc.c index 513cd13e76..1c361fb6f0 100644 --- a/src/fldeff_misc.c +++ b/src/fldeff_misc.c @@ -840,9 +840,9 @@ void DoSecretBasePCTurnOffEffect(void) PlaySE(SE_PC_OFF); if (!VarGet(VAR_CURRENT_SECRET_BASE)) - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_IMPASSABLE); else - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_RegisterPC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_RegisterPC | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); } @@ -1083,7 +1083,7 @@ static void SpriteCB_SandPillar_BreakTop(struct Sprite *sprite) PlaySE(SE_M_ROCK_THROW); if (MapGridGetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1) == METATILE_SecretBase_SandOrnament_TopWall) - MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_Wall_TopMid | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_Wall_TopMid | MAPGRID_IMPASSABLE); else MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_SandOrnament_BrokenTop); @@ -1103,7 +1103,7 @@ static void SpriteCB_SandPillar_BreakBase(struct Sprite *sprite) } else { - MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6], METATILE_SecretBase_SandOrnament_BrokenBase | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6], METATILE_SecretBase_SandOrnament_BrokenBase | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(gFieldEffectArguments[5], gFieldEffectArguments[6]); sprite->data[0] = 0; sprite->callback = SpriteCB_SandPillar_End; diff --git a/src/scrcmd.c b/src/scrcmd.c index 32502e97ce..9c7dd864e5 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -2043,7 +2043,7 @@ bool8 ScrCmd_setmetatile(struct ScriptContext *ctx) if (!isImpassable) MapGridSetMetatileIdAt(x, y, metatileId); else - MapGridSetMetatileIdAt(x, y, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, metatileId | MAPGRID_IMPASSABLE); return FALSE; } diff --git a/src/secret_base.c b/src/secret_base.c index df06f9120c..41b0f78339 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -332,7 +332,7 @@ void ToggleSecretBaseEntranceMetatile(void) { if (sSecretBaseEntranceMetatiles[i].closedMetatileId == metatileId) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); return; } @@ -343,7 +343,7 @@ void ToggleSecretBaseEntranceMetatile(void) { if (sSecretBaseEntranceMetatiles[i].openMetatileId == metatileId) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].closedMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].closedMetatileId | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); return; } @@ -398,7 +398,7 @@ void SetOccupiedSecretBaseEntranceMetatiles(struct MapEvents const *events) { if (sSecretBaseEntranceMetatiles[i].closedMetatileId == tile_id) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_IMPASSABLE); break; } } @@ -477,7 +477,7 @@ static void EnterNewlyCreatedSecretBase_StartFadeIn(void) FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); x += MAP_OFFSET; y += MAP_OFFSET; - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); FadeInFromBlack(); CreateTask(EnterNewlyCreatedSecretBase_WaitFadeIn, 0); @@ -538,13 +538,13 @@ void InitSecretBaseAppearance(bool8 hidePC) { // Another player's secret base. Change PC type to the "Register" PC. FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); - MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_RegisterPC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_RegisterPC | MAPGRID_IMPASSABLE); } else if (hidePC == TRUE && VarGet(VAR_SECRET_BASE_INITIALIZED) == 1) { // Change PC to regular ground tile. FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); - MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_Ground | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_Ground | MAPGRID_IMPASSABLE); } } } @@ -840,7 +840,7 @@ static void ClosePlayerSecretBaseEntrance(void) { MapGridSetMetatileIdAt(events->bgEvents[i].x + MAP_OFFSET, events->bgEvents[i].y + MAP_OFFSET, - sSecretBaseEntranceMetatiles[j].closedMetatileId | MAPGRID_COLLISION_MASK); + sSecretBaseEntranceMetatiles[j].closedMetatileId | MAPGRID_IMPASSABLE); break; } } diff --git a/src/trainer_hill.c b/src/trainer_hill.c index a42b988305..f2037b20d8 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -669,17 +669,17 @@ bool32 LoadTrainerHillFloorObjectEventScripts(void) return TRUE; } -static u16 GetMetatileForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floorWidth is always 16 +static u16 GetMapDataForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floorWidth is always 16 { bool8 impassable; - u16 metatile; + u16 metatileId; u16 elevation; impassable = (sHillData->floors[floorId].map.collisionData[y] >> (15 - x) & 1); - metatile = sHillData->floors[floorId].map.metatileData[floorWidth * y + x] + NUM_METATILES_IN_PRIMARY; - elevation = 3 << MAPGRID_ELEVATION_SHIFT; + metatileId = sHillData->floors[floorId].map.metatileData[floorWidth * y + x] + NUM_METATILES_IN_PRIMARY; + elevation = PACK_ELEVATION(3); - return ((impassable << MAPGRID_COLLISION_SHIFT) & MAPGRID_COLLISION_MASK) | elevation | (metatile & MAPGRID_METATILE_ID_MASK); + return PACK_COLLISION(impassable) | elevation | PACK_METATILE(metatileId); } void GenerateTrainerHillFloorLayout(u16 *mapArg) @@ -724,7 +724,7 @@ void GenerateTrainerHillFloorLayout(u16 *mapArg) for (y = 0; y < HILL_FLOOR_HEIGHT_MAIN; y++) { for (x = 0; x < HILL_FLOOR_WIDTH; x++) - dst[x] = GetMetatileForFloor(mapId, x, y, HILL_FLOOR_WIDTH); + dst[x] = GetMapDataForFloor(mapId, x, y, HILL_FLOOR_WIDTH); dst += 31; } From 219823f9a9d09d02780b23f7809f0578419c6293 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 25 Jul 2025 04:49:15 -0400 Subject: [PATCH 128/283] Fix Incompatible Z-Move Activation (#7399) Co-authored-by: ghoulslash Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_controller_player.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index a0b4e73ece..1a258e18fb 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -897,7 +897,10 @@ void HandleInputChooseMove(u32 battler) } else if (JOY_NEW(START_BUTTON)) { - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler])) + if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE + && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler]) + && !(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE + && GetUsableZMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]]) == MOVE_NONE)) { gBattleStruct->gimmick.playerSelect ^= 1; ReloadMoveNames(battler); From e222b725d26236207231a6d1b1278d5fb939b110 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:32:20 +0200 Subject: [PATCH 129/283] Remove leftover code (#7397) --- src/battle_util.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index a7e375b9b2..8e2627c262 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6037,29 +6037,6 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item return ITEM_NO_EFFECT; } -static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID) -{ - if (gProtectStructs[battler].tryEjectPack - && !gProtectStructs[battler].disableEjectPack - && CountUsablePartyMons(battler) > 0 - && !(GetMoveEffect(gCurrentMove) == EFFECT_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out - { - gProtectStructs[battler].tryEjectPack = FALSE; - gBattleScripting.battler = battler; - gAiLogicData->ejectPackSwitch = TRUE; - if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN) - { - BattleScriptExecute(BattleScript_EjectPackActivate_End2); - } - else - { - BattleScriptCall(BattleScript_EjectPackActivate_Ret); - } - return ITEM_STATS_CHANGE; - } - return ITEM_NO_EFFECT; -} - static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID) { if (CanBeInfinitelyConfused(battler)) @@ -6723,9 +6700,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) break; } break; - case HOLD_EFFECT_EJECT_PACK: - effect = TryEjectPack(battler, caseID); - break; case HOLD_EFFECT_BERSERK_GENE: effect = ConsumeBerserkGene(battler, caseID); break; From 845838bbc0281ab2ca7b69c92b6576e649c22bd5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:32:45 +0200 Subject: [PATCH 130/283] Fixes bug for affectionScore in doubles for spread moves (#7395) --- src/battle_script_commands.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fcd325305c..eb0738a24e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2177,7 +2177,7 @@ static void Cmd_adjustdamage(void) u8 param; u32 battlerDef; u32 rand = Random() % 100; - u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); + u32 affectionScore; u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); @@ -2221,7 +2221,8 @@ static void Cmd_adjustdamage(void) holdEffect = GetBattlerHoldEffect(battlerDef, TRUE); param = GetBattlerHoldEffectParam(battlerDef); - + affectionScore = GetBattlerAffectionHearts(battlerDef); + gPotentialItemEffectBattler = battlerDef; if (moveEffect == EFFECT_FALSE_SWIPE) From e7cf1621805540d8b87a21948f11c39e0bbe77e3 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 16:18:30 +0200 Subject: [PATCH 131/283] Fixes various Choice lock issues (#7383) --- include/battle_util.h | 1 + include/constants/battle_script_commands.h | 1 - include/constants/hold_effects.h | 2 -- include/item.h | 3 +++ src/battle_ai_main.c | 6 ++--- src/battle_ai_switch_items.c | 6 ++--- src/battle_script_commands.c | 31 ---------------------- src/battle_util.c | 28 +++++++++++++++++-- src/item.c | 9 ++++++- 9 files changed, 44 insertions(+), 43 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index aac39b3641..b9566e2512 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -123,6 +123,7 @@ enum MoveSuccessOrder CANCELLER_BIDE, CANCELLER_THAW, CANCELLER_STANCE_CHANGE_2, + CANCELLER_CHOICE_LOCK, CANCELLER_WEATHER_PRIMAL, CANCELLER_DYNAMAX_BLOCKED, CANCELLER_POWDER_STATUS, diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 4e4902f4b2..78c2200018 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -137,7 +137,6 @@ enum MoveEndEffects MOVEEND_ABILITIES_ATTACKER, MOVEEND_STATUS_IMMUNITY_ABILITIES, MOVEEND_SYNCHRONIZE_ATTACKER, - MOVEEND_CHOICE_MOVE, MOVEEND_ATTACKER_INVISIBLE, MOVEEND_ATTACKER_VISIBLE, MOVEEND_TARGET_VISIBLE, diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index e5ec842f1a..101a198b81 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -145,8 +145,6 @@ enum ItemHoldEffect HOLD_EFFECT_COUNT }; -#define HOLD_EFFECT_CHOICE(holdEffect) ((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) - // Terrain seed params #define HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN 0 #define HOLD_EFFECT_PARAM_GRASSY_TERRAIN 1 diff --git a/include/item.h b/include/item.h index 5fbb12ec43..5622786c91 100644 --- a/include/item.h +++ b/include/item.h @@ -6,6 +6,8 @@ #include "constants/items.h" #include "constants/moves.h" #include "constants/tms_hms.h" +#include "constants/item_effects.h" +#include "constants/hold_effects.h" /* Expands to: * enum @@ -190,5 +192,6 @@ u32 GetItemFlingPower(u32 itemId); u32 GetItemStatus1Mask(u16 itemId); bool32 ItemHasVolatileFlag(u16 itemId, enum Volatile volatile); u32 GetItemSellPrice(u32 itemId); +bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect); #endif // GUARD_ITEM_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 0f9bf432c9..1b22be4ac5 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2889,7 +2889,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // Choice items - if (HOLD_EFFECT_CHOICE(aiData->holdEffects[battlerAtk]) && IsBattlerItemEnabled(battlerAtk)) + if (IsHoldEffectChoice(aiData->holdEffects[battlerAtk]) && IsBattlerItemEnabled(battlerAtk)) { // Don't use user-target moves ie. Swords Dance, with exceptions if ((moveTarget & MOVE_TARGET_USER) @@ -3060,7 +3060,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. // This unsets Trick Room and resets it with a full timer. case EFFECT_TRICK_ROOM: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM) && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) @@ -3068,7 +3068,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_TAILWIND: // Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind. - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter && RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE)) ADJUST_SCORE(BEST_EFFECT); break; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 84cba174b2..976c06c0b6 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -165,7 +165,7 @@ static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) { // Choice locked into something else if (gAiLogicData->lastUsedMove[battler] != MOVE_NONE && gAiLogicData->lastUsedMove[battler] != move - && ((HOLD_EFFECT_CHOICE(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) + && ((IsHoldEffectChoice(GetBattlerHoldEffect(battler, FALSE)) && IsBattlerItemEnabled(battler)) || gBattleMons[battler].ability == ABILITY_GORILLA_TACTICS)) return TRUE; return FALSE; @@ -1003,7 +1003,7 @@ static bool32 ShouldSwitchIfBadChoiceLock(u32 battler) || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, AI_CHECK))) moveAffectsTarget = FALSE; - if (HOLD_EFFECT_CHOICE(holdEffect) && IsBattlerItemEnabled(battler)) + if (IsHoldEffectChoice(holdEffect) && IsBattlerItemEnabled(battler)) { if ((GetMoveCategory(lastUsedMove) == DAMAGE_CATEGORY_STATUS || !moveAffectsTarget) && RandomPercentage(RNG_AI_SWITCH_CHOICE_LOCKED, GetSwitchChance(SHOULD_SWITCH_CHOICE_LOCKED))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); @@ -1902,7 +1902,7 @@ static u32 GetBattleMonTypeMatchup(struct BattlePokemon opposingBattleMon, struc typeEffectiveness1 = uq4_12_multiply(typeEffectiveness1, (GetTypeModifier(atkType1, defType2))); if (typeEffectiveness1 == 0) // Immunity typeEffectiveness1 = UQ_4_12(0.1); - + if (atkType2 != atkType1) { typeEffectiveness2 = uq4_12_multiply(typeEffectiveness2, (GetTypeModifier(atkType2, defType1))); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3c70f4b583..f834742279 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5939,7 +5939,6 @@ static void Cmd_moveend(void) s32 i; bool32 effect = FALSE; u32 moveType = 0; - enum ItemHoldEffect holdEffectAtk = HOLD_EFFECT_NONE; u32 endMode, endState; u32 originallyUsedMove; @@ -5951,7 +5950,6 @@ static void Cmd_moveend(void) endMode = cmd->endMode; endState = cmd->endState; - holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); moveType = GetBattleMoveType(gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); @@ -6149,35 +6147,6 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.moveendState++; break; - case MOVEEND_CHOICE_MOVE: // update choice band move - { - u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker]; - if (gHitMarker & HITMARKER_OBEYS - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && gChosenMove != MOVE_STRUGGLE - && (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE) - && (HOLD_EFFECT_CHOICE(holdEffectAtk) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)) - { - if ((moveEffect == EFFECT_BATON_PASS || moveEffect == EFFECT_HEALING_WISH) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_FAILED)) - { - gBattleScripting.moveendState++; - break; - } - *choicedMoveAtk = gChosenMove; - } - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (gBattleMons[gBattlerAttacker].moves[i] == *choicedMoveAtk) - break; - } - if (i == MAX_MON_MOVES) - { - *choicedMoveAtk = MOVE_NONE; - } - gBattleScripting.moveendState++; - break; - } case MOVEEND_ITEM_EFFECTS_TARGET: if (ItemBattleEffects(ITEMEFFECT_TARGET, gBattlerTarget)) effect = TRUE; diff --git a/src/battle_util.c b/src/battle_util.c index 8e2627c262..d62d41af58 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1481,7 +1481,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler) } gPotentialItemEffectBattler = battler; - if (DYNAMAX_BYPASS_CHECK && HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) + if (DYNAMAX_BYPASS_CHECK && IsHoldEffectChoice(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) { gCurrentMove = *choicedMove; gLastUsedItem = gBattleMons[battler].item; @@ -1600,7 +1600,7 @@ u32 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check) else if (check & MOVE_LIMITATION_ENCORE && gDisableStructs[battler].encoreTimer && gDisableStructs[battler].encoredMove != move) unusableMoves |= 1u << i; // Choice Items - else if (check & MOVE_LIMITATION_CHOICE_ITEM && HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) + else if (check & MOVE_LIMITATION_CHOICE_ITEM && IsHoldEffectChoice(holdEffect) && *choicedMove != MOVE_NONE && *choicedMove != MOVE_UNAVAILABLE && *choicedMove != move) unusableMoves |= 1u << i; // Assault Vest else if (check & MOVE_LIMITATION_ASSAULT_VEST && holdEffect == HOLD_EFFECT_ASSAULT_VEST && IsBattleMoveStatus(move) && moveEffect != EFFECT_ME_FIRST) @@ -2295,6 +2295,29 @@ static enum MoveCanceller CancellerStanceChangeTwo(void) return MOVE_STEP_SUCCESS; } +static enum MoveCanceller CancellerChoiceLock(void) +{ + u16 *choicedMoveAtk = &gBattleStruct->choicedMove[gBattlerAttacker]; + enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + + if (gChosenMove != MOVE_STRUGGLE + && (*choicedMoveAtk == MOVE_NONE || *choicedMoveAtk == MOVE_UNAVAILABLE) + && (IsHoldEffectChoice(holdEffect) || GetBattlerAbility(gBattlerAttacker) == ABILITY_GORILLA_TACTICS)) + *choicedMoveAtk = gChosenMove; + + u32 moveIndex; + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (gBattleMons[gBattlerAttacker].moves[moveIndex] == *choicedMoveAtk) + break; + } + + if (moveIndex == MAX_MON_MOVES) + *choicedMoveAtk = MOVE_NONE; + + return MOVE_STEP_SUCCESS; +} + static enum MoveCanceller CancellerWeatherPrimal(void) { enum MoveCanceller effect = MOVE_STEP_SUCCESS; @@ -2564,6 +2587,7 @@ static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(void) = [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, diff --git a/src/item.c b/src/item.c index 52d52923ca..b25f38b058 100644 --- a/src/item.c +++ b/src/item.c @@ -50,7 +50,7 @@ const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = FOREACH_HM(UNPACK_HM_ITEM_ID) /* * Expands to the following: - * + * * [1] = { ITEM_TM_FOCUS_PUNCH, MOVE_FOCUS_PUNCH }, * [2] = { ITEM_TM_DRAGON_CLAW, MOVE_DRAGON_CLAW }, * [3] = { ITEM_TM_WATER_PULSE, MOVE_WATER_PULSE }, @@ -976,3 +976,10 @@ u32 GetItemSellPrice(u32 itemId) { return GetItemPrice(itemId) / ITEM_SELL_FACTOR; } + +bool32 IsHoldEffectChoice(enum ItemHoldEffect holdEffect) +{ + return holdEffect == HOLD_EFFECT_CHOICE_BAND + || holdEffect == HOLD_EFFECT_CHOICE_SCARF + || holdEffect == HOLD_EFFECT_CHOICE_SPECS; +} From 38964e4f0a7e556a68ed6e995de6ea325f92a951 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:26:12 +0200 Subject: [PATCH 132/283] Fixes Wandering Spirit overwriting battlers (#7407) --- data/battle_scripts_1.s | 4 ++++ test/battle/hold_effect/eject_button.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6d36b2b530..4db067a4b9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8189,6 +8189,8 @@ BattleScript_MummyActivates:: return BattleScript_WanderingSpiritActivates:: + saveattacker + savetarget .if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget sethword sABILITY_OVERWRITE, ABILITY_WANDERING_SPIRIT @@ -8205,6 +8207,8 @@ BattleScript_WanderingSpiritActivates:: jumpiffainted BS_TARGET, TRUE, BattleScript_WanderingSpiritActivatesRet switchinabilities BS_TARGET BattleScript_WanderingSpiritActivatesRet: + restoreattacker + restoretarget return BattleScript_TargetsStatWasMaxedOut:: diff --git a/test/battle/hold_effect/eject_button.c b/test/battle/hold_effect/eject_button.c index 9dd73833a5..681858605b 100644 --- a/test/battle/hold_effect/eject_button.c +++ b/test/battle/hold_effect/eject_button.c @@ -232,3 +232,21 @@ DOUBLE_BATTLE_TEST("Eject Button activation will not trigger an attack from the } } } + +SINGLE_BATTLE_TEST("Eject Button activates after Wandring Spirit") +{ + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_YAMASK_GALAR) { Item(ITEM_EJECT_BUTTON); Ability(ABILITY_WANDERING_SPIRIT); } + } WHEN { + TURN { + SWITCH(opponent, 1); + MOVE(player, MOVE_DRAGON_CLAW); + SEND_OUT(opponent, 0); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CLAW, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} From fa129ba906ea3a330f98d198eb3885f7c3fc24a7 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:28:24 -0400 Subject: [PATCH 133/283] Fix hit escape switching hardcode (#7403) --- src/battle_controller_opponent.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index f6fae5ae57..a139c9bfc3 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -623,6 +623,7 @@ static void OpponentHandleChoosePokemon(u32 battler) { s32 chosenMonId; s32 pokemonInBattle = 1; + enum SwitchType switchType = SWITCH_AFTER_KO; // Choosing Revival Blessing target if ((gBattleResources->bufferA[battler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) @@ -632,7 +633,9 @@ static void OpponentHandleChoosePokemon(u32 battler) // Switching out else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { - chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO); + if (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch) + switchType = SWITCH_MID_BATTLE; + chosenMonId = GetMostSuitableMonToSwitchInto(battler, switchType); if (chosenMonId == PARTY_SIZE) { s32 battler1, battler2, firstId, lastId; From cf4bb3e286c5f11d681f7b6e31926a9aa6a99846 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 25 Jul 2025 16:16:35 -0400 Subject: [PATCH 134/283] Moved some fields to BattlerState/PartyState (#7409) --- include/battle.h | 17 +++++--- include/constants/form_change_types.h | 4 +- src/battle_ai_main.c | 2 + src/battle_anim_new.c | 6 +-- src/battle_gfx_sfx_util.c | 2 +- src/battle_main.c | 16 ++++---- src/battle_script_commands.c | 46 ++++++++++----------- src/battle_util.c | 59 ++++++++++++++------------- src/pokemon.c | 4 +- 9 files changed, 80 insertions(+), 76 deletions(-) diff --git a/include/battle.h b/include/battle.h index b834fc195b..176adf7343 100644 --- a/include/battle.h +++ b/include/battle.h @@ -582,7 +582,9 @@ struct BattlerState u32 stompingTantrumTimer:2; u32 canPickupItem:1; u32 itemCanBeKnockedOff:1; - u32 padding:16; + u32 ateBoost:1; + u32 commanderSpecies:11; + u32 padding:4; // End of Word }; @@ -594,7 +596,9 @@ struct PartyState u32 battleBondBoost:1; u32 transformZeroToHero:1; u32 supersweetSyrup:1; - u32 padding:26; + u32 timesGotHit:5; + u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon. + u32 padding:10; }; // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. @@ -702,7 +706,6 @@ struct BattleStruct u8 savedBattlerAttacker[5]; u8 savedTargetCount:4; u8 savedAttackerCount:4; - bool8 ateBoost[MAX_BATTLERS_COUNT]; u8 abilityPopUpSpriteIds[MAX_BATTLERS_COUNT][NUM_BATTLE_SIDES]; // two per battler struct ZMoveData zmove; struct DynamaxData dynamax; @@ -717,7 +720,6 @@ struct BattleStruct u8 soulheartBattlerId; u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles. u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. - u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; struct LostItem itemLost[NUM_BATTLE_SIDES][PARTY_SIZE]; // Pokemon that had items consumed or stolen (two bytes per party member per side) u8 blunderPolicy:1; // should blunder policy activate @@ -745,13 +747,11 @@ struct BattleStruct s32 aiDelayTimer; // Counts number of frames AI takes to choose an action. s32 aiDelayFrames; // Number of frames it took to choose an action. s32 aiDelayCycles; // Number of cycles it took to choose an action. - u8 timesGotHit[NUM_BATTLE_SIDES][PARTY_SIZE]; u8 stickySyrupdBy[MAX_BATTLERS_COUNT]; u8 supremeOverlordCounter[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. enum DamageCategory categoryOverride:8; // for Z-Moves and Max Moves - u16 commanderActive[MAX_BATTLERS_COUNT]; u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party u16 opponentMonCanTera:6; @@ -1218,6 +1218,11 @@ static inline struct Pokemon *GetBattlerParty(u32 battler) return GetSideParty(GetBattlerSide(battler)); } +static inline struct PartyState *GetBattlerPartyState(u32 battler) +{ + return &gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]]; +} + static inline bool32 IsDoubleBattle(void) { return gBattleTypeFlags & BATTLE_TYPE_DOUBLE; diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index 10de5f785f..f43f3bddc6 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -48,7 +48,7 @@ enum FormChanges FORM_CHANGE_WITHDRAW, // Form change that activates when the Pokémon faints, either in battle or in the overworld by poison. // If species is not specified and it's on the player's side, it will try to use the value - // saved in gBattleStruct->changedSpecies from a previous form change. + // saved in gBattleStruct->partyState[x][y].changedSpecies from a previous form change. // - No parameters. FORM_CHANGE_FAINT, // Form change that activates when the Pokémon is sent out at the beginning of a battle @@ -56,7 +56,7 @@ enum FormChanges // param2: a move that will be replaced, optional // param3: a new move to replace it with, optional FORM_CHANGE_BEGIN_BATTLE, - // Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. + // Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->partyState[x][y].changedSpecies from a previous form change. // param1: item to hold, optional // param2: a move that will be replaced, optional // param3: a new move to replace it with, optional diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 1b22be4ac5..f06a4e8f6d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3878,6 +3878,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_STRENGTH_SAP: + { u32 atkStat = gBattleMons[battlerDef].attack; u32 atkStage = gBattleMons[battlerDef].statStages[STAT_ATK]; atkStat *= gStatStageRatios[atkStage][0]; @@ -3890,6 +3891,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); } break; + } case EFFECT_EXPLOSION: case EFFECT_MISTY_EXPLOSION: case EFFECT_MEMENTO: diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 00281253fa..1263632ab7 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -9632,7 +9632,7 @@ void AnimTask_RandomBool(u8 taskId) // Credit to Skeli #define PRIMAL_PULSE_SCALE_SIZE 16 #define PRIMAL_PULSE_FRAME_COUNT 4 -static const union AffineAnimCmd sSpriteAffineAnim_PrimalSymbol[] = +static const union AffineAnimCmd sSpriteAffineAnim_PrimalSymbol[] = { AFFINEANIMCMD_FRAME(16, 16, 0, 0), AFFINEANIMCMD_FRAME(32, 32, 0, 15), @@ -9679,7 +9679,7 @@ const union AffineAnimCmd* const gSpriteAffineAnimTable_MegaSymbol[] = // Used for determining which animation to use for Order Up void AnimTask_GetCommanderType(u8 taskId) { - switch (gBattleStruct->commanderActive[gEffectBattler]) + switch (gBattleStruct->battlerState[gEffectBattler].commanderSpecies) { case SPECIES_TATSUGIRI_CURLY: gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_CURLY; @@ -9694,6 +9694,6 @@ void AnimTask_GetCommanderType(u8 taskId) gBattleAnimArgs[ARG_RET_ID] = ANIM_ORDER_UP_NONE; break; } - + DestroyAnimVisualTask(taskId); } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 7135cb8905..37c5b12d60 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -940,7 +940,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo { // Get base form if its currently Gigantamax if (IsGigantamaxed(battlerDef)) - targetSpecies = gBattleStruct->changedSpecies[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]]; + targetSpecies = GetBattlerPartyState(battlerDef)->changedSpecies; else if (gBattleStruct->illusion[battlerDef].state == ILLUSION_ON) targetSpecies = GetIllusionMonSpecies(battlerDef); else diff --git a/src/battle_main.c b/src/battle_main.c index 8c4ba46261..2b3edabad2 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3367,7 +3367,7 @@ const u8* FaintClearSetData(u32 battler) ClearPursuitValuesIfSet(battler); - if (gBattleStruct->commanderActive[battler] != SPECIES_NONE) + if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE) { u32 partner = BATTLE_PARTNER(battler); if (IsBattlerAlive(partner)) @@ -5340,7 +5340,7 @@ static void CheckChangingTurnOrderEffects(void) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { gBattleStruct->battlerState[i].focusPunchBattlers = FALSE; - gBattleStruct->ateBoost[i] = FALSE; + gBattleStruct->battlerState[i].ateBoost = FALSE; gSpecialStatuses[i].gemBoost = FALSE; } @@ -5612,8 +5612,8 @@ static void HandleEndTurn_FinishBattle(void) changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); // Clear original species field - gBattleStruct->changedSpecies[B_SIDE_PLAYER][i] = SPECIES_NONE; - gBattleStruct->changedSpecies[B_SIDE_OPPONENT][i] = SPECIES_NONE; + gBattleStruct->partyState[B_SIDE_PLAYER][i].changedSpecies = SPECIES_NONE; + gBattleStruct->partyState[B_SIDE_OPPONENT][i].changedSpecies = SPECIES_NONE; // Recalculate the stats of every party member before the end if (!changedForm && B_RECALCULATE_STATS >= GEN_5) @@ -6045,7 +6045,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState { u32 ateType = TrySetAteType(move, battler, ability); if (ateType != TYPE_NONE && state == MON_IN_BATTLE) - gBattleStruct->ateBoost[battler] = TRUE; + gBattleStruct->battlerState[battler].ateBoost = TRUE; return ateType; } else if (moveEffect != EFFECT_CHANGE_TYPE_ON_ITEM @@ -6057,7 +6057,7 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState && gimmick != GIMMICK_Z_MOVE) { if (state == MON_IN_BATTLE && gimmick != GIMMICK_DYNAMAX) - gBattleStruct->ateBoost[battler] = TRUE; + gBattleStruct->battlerState[battler].ateBoost = TRUE; return TYPE_NORMAL; } @@ -6071,7 +6071,7 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler) enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); gBattleStruct->dynamicMoveType = 0; - gBattleStruct->ateBoost[battler] = FALSE; + gBattleStruct->battlerState[battler].ateBoost = FALSE; gSpecialStatuses[battler].gemBoost = FALSE; moveType = GetDynamicMoveType(GetBattlerMon(battler), @@ -6165,4 +6165,4 @@ void BattleDebug_WonBattle(void) { gBattleOutcome |= B_OUTCOME_WON; gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; -} \ No newline at end of file +} diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f834742279..8a1e1a1740 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2107,7 +2107,7 @@ static inline bool32 TryActivateWeaknessBerry(u32 battlerDef) { gBattleScripting.battler = battlerDef; gLastUsedItem = gBattleMons[battlerDef].item; - gBattleStruct->partyState[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]].ateBerry = TRUE; + GetBattlerPartyState(battlerDef)->ateBerry = TRUE; BattleScriptCall(BattleScript_BerryReduceDmg); return TRUE; } @@ -2361,10 +2361,9 @@ static void Cmd_datahpupdate(void) else if (DoesDisguiseBlockMove(battler, gCurrentMove)) { // TODO: Convert this to a proper FORM_CHANGE type. - u32 side = GetBattlerSide(battler); gBattleScripting.battler = battler; - if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; + if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; if (gBattleMons[battler].species == SPECIES_MIMIKYU_TOTEM_DISGUISED) gBattleMons[battler].species = SPECIES_MIMIKYU_BUSTED_TOTEM; else @@ -2445,7 +2444,7 @@ static void Cmd_datahpupdate(void) if (gBattlerAttacker != gBattlerTarget && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS && IsBattlerTurnDamaged(gBattlerTarget)) - gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; + GetBattlerPartyState(gBattlerTarget)->timesGotHit++; if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF && IsBattlerTurnDamaged(gBattlerTarget) @@ -2574,9 +2573,8 @@ static void Cmd_resultmessage(void) if (gDisableStructs[gBattlerTarget].iceFaceActivationPrevention) { gDisableStructs[gBattlerTarget].iceFaceActivationPrevention = FALSE; - u32 side = GetBattlerSide(gBattlerTarget); - if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + if (GetBattlerPartyState(gBattlerTarget)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(gBattlerTarget)->changedSpecies = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_EISCUE_NOICE; gBattleScripting.battler = gBattlerTarget; // For STRINGID_PKMNTRANSFORMED BattleScriptCall(BattleScript_IceFaceNullsDamage); @@ -3016,7 +3014,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattleScripting.moveEffect = MOVE_EFFECT_NONE; else if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT) && TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove) - && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->commanderActive[gBattlerAttacker]) + && !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE) && !primary) gBattleScripting.moveEffect = MOVE_EFFECT_NONE; else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint) @@ -3602,7 +3600,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { u32 stat = 0; bool32 commanderAffected = TRUE; - switch (gBattleStruct->commanderActive[gEffectBattler]) + switch (gBattleStruct->battlerState[gEffectBattler].commanderSpecies) { case SPECIES_TATSUGIRI_CURLY: stat = STAT_ATK; @@ -5664,18 +5662,16 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move || NumFaintedBattlersByAttacker(battlerAtk) == 0) break; - u32 side = GetBattlerSide(battlerAtk); - - if (gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost) + if (GetBattlerPartyState(battlerAtk)->battleBondBoost) break; if (GetGenConfig(GEN_CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND) { // TODO: Convert this to a proper FORM_CHANGE type. gLastUsedAbility = abilityAtk; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost = TRUE; + GetBattlerPartyState(battlerAtk)->battleBondBoost = TRUE; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerAtk].species); - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battlerAtk]] = gBattleMons[battlerAtk].species; + GetBattlerPartyState(battlerAtk)->changedSpecies = gBattleMons[battlerAtk].species; gBattleMons[battlerAtk].species = SPECIES_GRENINJA_ASH; BattleScriptCall(BattleScript_BattleBondActivatesOnMoveEndAttacker); effect = TRUE; @@ -5706,7 +5702,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move gLastUsedAbility = abilityAtk; gBattlerAbility = battlerAtk; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battlerAtk]].battleBondBoost = TRUE; + GetBattlerPartyState(battlerAtk)->battleBondBoost = TRUE; BattleScriptCall(BattleScript_EffectBattleBondStatIncrease); effect = TRUE; } @@ -6558,7 +6554,7 @@ static void Cmd_moveend(void) gBattleScripting.battler = battler; gEffectBattler = gBattlerAttacker; BattleScriptPushCursor(); - if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE + if (gBattleStruct->battlerState[gBattlerAttacker].commanderSpecies != SPECIES_NONE || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; @@ -6911,7 +6907,7 @@ static void Cmd_moveend(void) // #endif } gProtectStructs[gBattlerAttacker].shellTrap = FALSE; - gBattleStruct->ateBoost[gBattlerAttacker] = FALSE; + gBattleStruct->battlerState[gBattlerAttacker].ateBoost = FALSE; gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE; @@ -6943,10 +6939,10 @@ static void Cmd_moveend(void) gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE; gProtectStructs[i].tryEjectPack = FALSE; - if (gBattleStruct->commanderActive[i] != SPECIES_NONE && !IsBattlerAlive(i)) + if (gBattleStruct->battlerState[i].commanderSpecies != SPECIES_NONE && !IsBattlerAlive(i)) { u32 partner = BATTLE_PARTNER(i); - gBattleStruct->commanderActive[i] = SPECIES_NONE; + gBattleStruct->battlerState[i].commanderSpecies = SPECIES_NONE; if (IsBattlerAlive(partner)) gStatuses3[partner] &= ~STATUS3_COMMANDER; } @@ -8586,7 +8582,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) if (GetItemPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) - && gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry + && GetBattlerPartyState(battler)->ateBerry && !IsBattlerAtMaxHp(battler)) { gBattleStruct->cheekPouchActivated = TRUE; @@ -11186,8 +11182,8 @@ static void Cmd_transformdataexecution(void) gDisableStructs[gBattlerAttacker].mimickedMoves = 0; gDisableStructs[gBattlerAttacker].usedMoves = 0; - timesGotHit = gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]; - gBattleStruct->timesGotHit[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = timesGotHit; + timesGotHit = GetBattlerPartyState(gBattlerTarget)->timesGotHit; + GetBattlerPartyState(gBattlerAttacker)->timesGotHit = timesGotHit; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].species) @@ -16121,7 +16117,7 @@ void BS_JumpIfCommanderActive(void) { NATIVE_ARGS(const u8 *jumpInstr); - if (gBattleStruct->commanderActive[gBattlerTarget] != SPECIES_NONE) + if (gBattleStruct->battlerState[gBattlerTarget].commanderSpecies != SPECIES_NONE) gBattlescriptCurrInstr = cmd->jumpInstr; else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER) gBattlescriptCurrInstr = cmd->jumpInstr; @@ -18160,7 +18156,7 @@ void BS_ConsumeBerry(void) if (cmd->fromBattler) gLastUsedItem = gBattleMons[battler].item; - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; + GetBattlerPartyState(battler)->ateBerry = TRUE; gBattleScripting.battler = gEffectBattler = gBattlerTarget = battler; // Cover all berry effect battler cases. e.g. ChangeStatBuffs uses target ID if (ItemBattleEffects(ITEMEFFECT_USE_LAST_ITEM, battler)) return; diff --git a/src/battle_util.c b/src/battle_util.c index d62d41af58..1346b9f0da 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1292,7 +1292,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move) if (GetMoveEffect(move) != EFFECT_BELCH) return FALSE; - return !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry; + return !GetBattlerPartyState(battler)->ateBerry; } // Dynamax bypasses all selection prevention except Taunt and Assault Vest. @@ -3291,7 +3291,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 u32 side = 0; u32 i = 0, j = 0; u32 partner = 0; - struct Pokemon *mon; if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) return 0; @@ -3915,12 +3914,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_SUPERSWEET_SYRUP: if (!gSpecialStatuses[battler].switchInAbilityDone - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup) + && !GetBattlerPartyState(battler)->supersweetSyrup) { SaveBattlerAttacker(gBattlerAttacker); gBattlerAttacker = battler; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE; + GetBattlerPartyState(battler)->supersweetSyrup = TRUE; BattleScriptPushCursorAndCallback(BattleScript_SupersweetSyrupActivates); effect++; } @@ -3956,10 +3955,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_INTREPID_SWORD: if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].intrepidSwordBoost) + && !GetBattlerPartyState(battler)->intrepidSwordBoost) { if (B_INTREPID_SWORD == GEN_9) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].intrepidSwordBoost = TRUE; + GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); @@ -3968,10 +3967,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_DAUNTLESS_SHIELD: if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN) - && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].dauntlessShieldBoost) + && !GetBattlerPartyState(battler)->dauntlessShieldBoost) { if (B_DAUNTLESS_SHIELD == GEN_9) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].dauntlessShieldBoost = TRUE; + GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_DEF, 1, FALSE); BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); @@ -4080,15 +4079,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_ZERO_TO_HERO: - side = GetBattlerSide(battler); - mon = GetBattlerMon(battler); - if (!gSpecialStatuses[battler].switchInAbilityDone - && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO - && !gBattleStruct->partyState[side][gBattlerPartyIndexes[battler]].transformZeroToHero) + && GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO + && !GetBattlerPartyState(battler)->transformZeroToHero) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; - gBattleStruct->partyState[side][gBattlerPartyIndexes[battler]].transformZeroToHero = TRUE; + GetBattlerPartyState(battler)->transformZeroToHero = TRUE; BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates); effect++; } @@ -4162,7 +4158,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && IsBattlerAlive(partner) && IsBattlerAlive(battler) - && gBattleStruct->commanderActive[partner] == SPECIES_NONE + && gBattleStruct->battlerState[partner].commanderSpecies == SPECIES_NONE && gBattleMons[partner].species == SPECIES_DONDOZO && GET_BASE_SPECIES_ID(GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)) == SPECIES_TATSUGIRI) { @@ -4170,7 +4166,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattlerAttacker = partner; gBattleStruct->battlerState[battler].commandingDondozo = TRUE; - gBattleStruct->commanderActive[partner] = gBattleMons[battler].species; + gBattleStruct->battlerState[partner].commanderSpecies = gBattleMons[battler].species; gStatuses3[battler] |= STATUS3_COMMANDER; if (gBattleMons[battler].volatiles.confusionTurns > 0 && !(gStatuses4[battler] & STATUS4_INFINITE_CONFUSION)) @@ -4708,6 +4704,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_POISON_POINT, 30) : RandomChance(RNG_POISON_POINT, 1, 3)) { POISON_POINT: + { u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg @@ -4723,11 +4720,13 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } } + } break; case ABILITY_STATIC: if (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_STATIC, 30) : RandomChance(RNG_STATIC, 1, 3)) { STATIC: + { u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if (IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg @@ -4743,6 +4742,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } } + } break; case ABILITY_FLAME_BODY: if (IsBattlerAlive(gBattlerAttacker) @@ -5490,7 +5490,7 @@ u32 IsAbilityPreventingEscape(u32 battler) bool32 CanBattlerEscape(u32 battler) // no ability check { - if (gBattleStruct->commanderActive[battler] != SPECIES_NONE) + if (gBattleStruct->battlerState[battler].commanderSpecies != SPECIES_NONE) return FALSE; else if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SHED_SHELL) return TRUE; @@ -7289,7 +7289,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) // Berry was successfully used on a Pokemon. if (effect && (gLastUsedItem >= FIRST_BERRY_INDEX && gLastUsedItem <= LAST_BERRY_INDEX)) - gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].ateBerry = TRUE; + GetBattlerPartyState(battler)->ateBerry = TRUE; return effect; } @@ -8213,7 +8213,7 @@ static inline u32 CalcMoveBasePower(struct DamageContext *ctx) basePower = GetMaxMovePower(gBattleMons[battlerAtk].moves[gBattleStruct->chosenMovePositions[battlerAtk]]); break; case EFFECT_RAGE_FIST: - basePower += 50 * gBattleStruct->timesGotHit[GetBattlerSide(battlerAtk)][gBattlerPartyIndexes[battlerAtk]]; + basePower += 50 * GetBattlerPartyState(battlerAtk)->timesGotHit; basePower = (basePower > 350) ? 350 : basePower; break; case EFFECT_FICKLE_BEAM: @@ -8382,23 +8382,23 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); break; case ABILITY_PIXILATE: - if (moveType == TYPE_FAIRY && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_FAIRY && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_GALVANIZE: - if (moveType == TYPE_ELECTRIC && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_ELECTRIC && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_REFRIGERATE: - if (moveType == TYPE_ICE && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_ICE && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_AERILATE: - if (moveType == TYPE_FLYING && gBattleStruct->ateBoost[battlerAtk]) + if (moveType == TYPE_FLYING && gBattleStruct->battlerState[battlerAtk].ateBoost) modifier = uq4_12_multiply(modifier, UQ_4_12(GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7 ? 1.2 : 1.3)); break; case ABILITY_NORMALIZE: - if (moveType == TYPE_NORMAL && gBattleStruct->ateBoost[battlerAtk] && GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7) + if (moveType == TYPE_NORMAL && gBattleStruct->battlerState[battlerAtk].ateBoost && GetGenConfig(GEN_CONFIG_ATE_MULTIPLIER) >= GEN_7) modifier = uq4_12_multiply(modifier, UQ_4_12(1.2)); break; case ABILITY_PUNK_ROCK: @@ -10160,7 +10160,6 @@ bool32 CanBattlerFormChange(u32 battler, enum FormChanges method) bool32 TryBattleFormChange(u32 battler, enum FormChanges method) { u32 monId = gBattlerPartyIndexes[battler]; - u32 side = GetBattlerSide(battler); struct Pokemon *party = GetBattlerParty(battler); u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); u32 targetSpecies; @@ -10174,8 +10173,9 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) if (targetSpecies != currentSpecies) { // Saves the original species on the first form change. - if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][monId] = gBattleMons[battler].species; + + if (GetBattlerPartyState(battler)->changedSpecies == SPECIES_NONE) + GetBattlerPartyState(battler)->changedSpecies = gBattleMons[battler].species; TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); @@ -10183,7 +10183,7 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); return TRUE; } - else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) + else if (GetBattlerPartyState(battler)->changedSpecies != SPECIES_NONE) { bool32 restoreSpecies = FALSE; @@ -10204,7 +10204,8 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method) u32 abilityForm = gBattleMons[battler].ability; // Reverts the original species TryToSetBattleFormChangeMoves(&party[monId], method); - SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]); + u32 changedSpecies = GetBattlerPartyState(battler)->changedSpecies; + SetMonData(&party[monId], MON_DATA_SPECIES, &changedSpecies); RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); // Battler data is not updated with regular form's ability, not doing so could cause wrong ability activation. if (method == FORM_CHANGE_FAINT) diff --git a/src/pokemon.c b/src/pokemon.c index 85ef8a2fc9..6433acd701 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6829,8 +6829,8 @@ bool32 TryFormChange(u32 monId, u32 side, enum FormChanges method) u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); u32 targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies == currentSpecies && gBattleStruct != NULL && gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) - targetSpecies = gBattleStruct->changedSpecies[side][monId]; + if (targetSpecies == currentSpecies && gBattleStruct != NULL && gBattleStruct->partyState[side][monId].changedSpecies != SPECIES_NONE) + targetSpecies = gBattleStruct->partyState[side][monId].changedSpecies; if (targetSpecies != currentSpecies) { From 57fda0d060b87785d3b93eb1ed9ee26bb7637206 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 26 Jul 2025 12:22:47 -0400 Subject: [PATCH 135/283] Improve AI's priority handling (#7337) --- include/battle_ai_main.h | 7 ++ include/battle_ai_util.h | 24 +++-- include/config/ai.h | 1 + include/random.h | 1 + src/battle_ai_main.c | 173 ++++++++++++++++++++++++---------- src/battle_ai_switch_items.c | 142 ++++++++++++++++++++-------- src/battle_ai_util.c | 99 +++++++++---------- test/battle/ai/ai.c | 12 +++ test/battle/ai/ai_switching.c | 40 ++++++++ 9 files changed, 353 insertions(+), 146 deletions(-) diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 547395d480..b3bc57c4e9 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -45,6 +45,13 @@ enum AIScore WORST_EFFECT = -10 }; +enum MoveComparisonResult +{ + MOVE_NEUTRAL_COMPARISON, + MOVE_WON_COMPARISON, + MOVE_LOST_COMPARISON, +}; + // AI_TryToFaint #define FAST_KILL 6 // AI is faster and faints target #define SLOW_KILL 4 // AI is slower and faints target diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 4dfea63dfe..ec8c250fd2 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -29,8 +29,10 @@ enum DamageCalcContext enum AiCompareMovesPriority { PRIORITY_EFFECT, + PRIORITY_GUARANTEE, PRIORITY_ACCURACY, - PRIORITY_NOT_CHARGING + PRIORITY_NOT_CHARGING, + PRIORITY_SPEED, }; enum AIPivot @@ -54,6 +56,12 @@ enum AIConsiderGimmick USE_GIMMICK, }; +enum ConsiderPriority +{ + DONT_CONSIDER_PRIORITY, + CONSIDER_PRIORITY, +}; + static inline bool32 IsMoveUnusable(u32 moveIndex, u32 move, u32 moveLimitations) { return move == MOVE_NONE @@ -63,8 +71,10 @@ static inline bool32 IsMoveUnusable(u32 moveIndex, u32 move, u32 moveLimitations typedef bool32 (*MoveFlag)(u32 move); -bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move); -bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move); +bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsPartyMonFaster(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); +bool32 AI_IsPartyMonSlower(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority); bool32 AI_RandLessThan(u32 val); u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext, struct AiLogicData *aiData); bool32 IsAiVsAiBattle(void); @@ -92,7 +102,7 @@ bool32 AI_BattlerAtMaxHp(u32 battler); u32 GetHealthPercentage(u32 battler); bool32 AI_CanBattlerEscape(u32 battler); bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef); -s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority); bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk); u32 NoOfHitsForTargetToFaintBattler(u32 battlerDef, u32 battlerAtk); u32 GetBestDmgMoveFromBattler(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); @@ -107,7 +117,6 @@ u32 AI_GetSwitchinWeather(struct BattlePokemon battleMon); enum WeatherState IsWeatherActive(u32 flags); bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits); bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, enum DamageCalcContext calcContext); -bool32 CanIndexMoveGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index); bool32 HasDamagingMove(u32 battlerId); bool32 HasDamagingMoveOfType(u32 battlerId, u32 type); u32 GetBattlerSecondaryDamage(u32 battlerId); @@ -131,6 +140,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove); void SetAIUsingGimmick(u32 battler, enum AIConsiderGimmick use); bool32 IsAIUsingGimmick(u32 battler); void DecideTerastal(u32 battler); +bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move); // stat stage checks bool32 AnyStatIsRaised(u32 battlerId); @@ -143,7 +153,7 @@ u32 CountNegativeStatStages(u32 battlerId); // move checks bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category); -s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); +enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef); struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef, u32 weather); bool32 AI_IsDamagedByRecoil(u32 battler); @@ -269,7 +279,7 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, enum DamageCalcContext calcContext); -u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 moveConsidered); +u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle); bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); diff --git a/include/config/ai.h b/include/config/ai.h index f5d0496c20..c82e46773a 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -60,6 +60,7 @@ #define ENABLE_RECOVERY_THRESHOLD 60 // HP percentage beneath which SHOULD_RECOVER_CHANCE is active #define SUCKER_PUNCH_CHANCE 50 // Chance for the AI to not use Sucker Punch if the player has a status move #define SUCKER_PUNCH_PREDICTION_CHANCE 50 // Additional chance for the AI to not use Sucker Punch if actively predicting a status move if SUCKER_PUNCH_CHANCE fails +#define PRIORITIZE_LAST_CHANCE_CHANCE 50 // Chance the AI will prioritize Last Chance (priority move in the face of being outsped and KO'd) over Slow KO // AI damage calc considerations #define RISKY_AI_CRIT_STAGE_THRESHOLD 2 // Stat stages at which Risky will assume it gets a crit diff --git a/include/random.h b/include/random.h index 89ccb9779a..38a464e457 100644 --- a/include/random.h +++ b/include/random.h @@ -202,6 +202,7 @@ enum RandomTag RNG_AI_STATUS_FOCUS_PUNCH, RNG_AI_BOOST_INTO_HAZE, RNG_AI_SHOULD_RECOVER, + RNG_AI_PRIORITIZE_LAST_CHANCE, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, RNG_AI_ASSUME_STATUS_SLEEP, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index f06a4e8f6d..d29becb2ea 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1083,7 +1083,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); - if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move)) + if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) RETURN_SCORE_MINUS(10); if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk)) @@ -1309,7 +1309,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (moveEffect) { case EFFECT_HIT: // only applies to Vital Throw - if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40) + if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && aiData->hpPercents[battlerAtk] < 40) ADJUST_SCORE(-2); // don't want to move last break; default: @@ -1759,7 +1759,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to disable @@ -1781,7 +1781,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to encore @@ -2163,7 +2163,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SPITE: case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) @@ -2320,7 +2320,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (isDoubleBattle) { if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards - && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove)) // partner is going to set up before the potential Defog + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the potential Defog { ADJUST_SCORE(-10); break; // Don't use Defog if partner is going to set up hazards @@ -2348,7 +2348,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SEMI_INVULNERABLE: if (predictedMove != MOVE_NONE - && AI_IsSlower(battlerAtk, battlerDef, move) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && GetMoveEffect(predictedMove) == EFFECT_SEMI_INVULNERABLE) ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you @@ -2495,7 +2495,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ME_FIRST: if (predictedMove != MOVE_NONE) { - if (AI_IsSlower(battlerAtk, battlerDef, move)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail else if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); @@ -2664,7 +2664,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_ELECTRIFY: - if (AI_IsSlower(battlerAtk, battlerDef, move) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) //|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -2696,7 +2696,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INSTRUCT: { u32 instructedMove; - if (AI_IsSlower(battlerAtk, battlerDef, move)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) instructedMove = predictedMove; else instructedMove = gLastMoves[battlerDef]; @@ -2733,21 +2733,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_QUASH: if (!isDoubleBattle - || AI_IsSlower(battlerAtk, battlerDef, move) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: if (!IsTargetingPartner(battlerAtk, battlerDef) || !isDoubleBattle - || AI_IsSlower(battlerAtk, battlerDef, move) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_SUCKER_PUNCH: if ((HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_STATUS) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_CHANCE)) // Player has a status move || (IsBattleMoveStatus(predictedMove) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_PREDICTION_CHANCE) && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_PREDICT_MOVE)) // AI actively predicting incoming status move - || AI_IsSlower(battlerAtk, battlerDef, move)) // Opponent going first + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Opponent going first ADJUST_SCORE(-10); break; case EFFECT_TAILWIND: @@ -2782,7 +2782,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_FLAIL: - if (AI_IsSlower(battlerAtk, battlerDef, move) // Opponent should go first + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) // Opponent should go first || aiData->hpPercents[battlerAtk] > 50) ADJUST_SCORE(-4); break; @@ -2817,7 +2817,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) ADJUST_SCORE(-10); else if (CanTargetFaintAi(battlerDef, battlerAtk) - && AI_IsSlower(battlerAtk, battlerDef, move)) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); break; case EFFECT_JUNGLE_HEALING: @@ -2848,7 +2848,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 defPrio = GetBattleMovePriority(battlerDef, aiData->abilities[battlerDef], predictedMove); if (predictedMove == MOVE_NONE || IsBattleMoveStatus(predictedMove) - || AI_IsSlower(battlerAtk, battlerDef, move) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) || defPrio < 1 || defPrio > 3) // Opponent going first or not using priority move ADJUST_SCORE(-10); @@ -2924,9 +2924,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, AI_ATTACKING) && effect != EFFECT_EXPLOSION && effect != EFFECT_MISTY_EXPLOSION) { - if (CanIndexMoveGuaranteeFaintTarget(battlerAtk, battlerDef, movesetIndex)) - ADJUST_SCORE(1); // Bonus point if the KO is guaranteed - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) ADJUST_SCORE(FAST_KILL); else ADJUST_SCORE(SLOW_KILL); @@ -2935,7 +2933,10 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && GetWhichBattlerFasterOrTies(battlerAtk, battlerDef, TRUE) != AI_IS_FASTER && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) > 0) { - ADJUST_SCORE(LAST_CHANCE); + if (RandomPercentage(RNG_AI_PRIORITIZE_LAST_CHANCE, PRIORITIZE_LAST_CHANCE_CHANCE)) + ADJUST_SCORE(SLOW_KILL + 2); // Don't outscore Fast Kill (which gets a bonus point in AI_CompareDamagingMoves), but do outscore Slow Kill getting the same + else + ADJUST_SCORE(LAST_CHANCE); } return score; @@ -3009,7 +3010,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Adjust for always crit moves if (MoveAlwaysCrits(aiData->partnerMove) && aiData->abilities[battlerAtk] == ABILITY_ANGER_POINT) { - if (AI_IsSlower(battlerAtk, battlerAtkPartner, move)) // Partner moving first + if (AI_IsSlower(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY)) // Partner moving first { // discourage raising our attack since it's about to be maxed out if (IsAttackBoostMoveEffect(effect)) @@ -3182,7 +3183,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_ANGER_POINT: if (MoveAlwaysCrits(move) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && AI_IsFaster(battlerAtk, battlerAtkPartner, move) + && AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY) && isFriendlyFireOK) { if (MoveAlwaysCrits(move)) @@ -3501,7 +3502,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INSTRUCT: { u16 instructedMove; - if (AI_IsFaster(battlerAtk, battlerAtkPartner, move)) + if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY)) instructedMove = aiData->partnerMove; else instructedMove = gLastMoves[battlerAtkPartner]; @@ -3518,8 +3519,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); - if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove) // Opponent mon 1 goes before partner - && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove)) // Opponent mon 2 goes before partner + if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove, predictedMove, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner + && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner { if (partnerEffect == EFFECT_COUNTER || partnerEffect == EFFECT_MIRROR_COAT) break; // These moves need to go last @@ -3528,8 +3529,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_HEAL_PULSE: case EFFECT_HIT_ENEMY_HEAL_ALLY: - if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move) - && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move) + if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move, predictedMove, CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move, predictedMove, CONSIDER_PRIORITY) && gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2) RETURN_SCORE_PLUS(WEAK_EFFECT); break; @@ -3635,16 +3636,50 @@ static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect) } } -static s32 CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) +static enum MoveComparisonResult CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, u32 moveSlot2) { u32 acc1 = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][moveSlot1]; u32 acc2 = gAiLogicData->moveAccuracy[battlerAtk][battlerDef][moveSlot2]; if (acc1 > acc2) - return 1; + return MOVE_WON_COMPARISON; else if (acc2 > acc1) - return -1; - return 0; + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; +} + +static enum MoveComparisonResult CompareMoveSpeeds(u32 battlerAtk, u32 battlerDef, u16 move1, u16 move2) +{ + u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 speed1 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move1, predictedMove, CONSIDER_PRIORITY); + u32 speed2 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move2, predictedMove, CONSIDER_PRIORITY); + + if (speed1 == AI_IS_FASTER && speed2 == AI_IS_SLOWER) + return MOVE_WON_COMPARISON; + if (speed2 == AI_IS_FASTER && speed1 == AI_IS_SLOWER) + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; +} + +static enum MoveComparisonResult CompareGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u16 moveSlot1, u16 moveSlot2, u16 *moves) +{ + s32 dmg1, dmg2; + bool32 guarantee1, guarantee2; + + if (!(gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT)) + return 0; + + // Explictly care about guaranteed KOs universally + dmg1 = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveSlot1].minimum; + guarantee1 = (gBattleMons[battlerDef].hp <= dmg1 && !CanEndureHit(battlerAtk, battlerDef, moves[moveSlot1])); + dmg2 = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveSlot2].minimum; + guarantee2 = (gBattleMons[battlerDef].hp <= dmg2 && !CanEndureHit(battlerAtk, battlerDef, moves[moveSlot2])); + + if (guarantee1 && !guarantee2) + return MOVE_WON_COMPARISON; + if (guarantee2 && !guarantee1) + return MOVE_LOST_COMPARISON; + return MOVE_NEUTRAL_COMPARISON; } static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 moveIndex, u32 hitsToFaintOpposingBattler) @@ -3718,9 +3753,11 @@ static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef) // Priority list: // 1. Less no of hits to ko - // 2. Not charging - // 3. More accuracy - // 4. Better effect + // 2. Priority if outsped and a OHKO + // 3. Not charging + // 4. More accuracy + // 5. Guaranteed KO + // 6. Better effect // Current move requires the least hits to KO. Compare with other moves. if (leastHits == noOfHits[currId]) @@ -3738,23 +3775,55 @@ static void AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef) else if (!isTwoTurnNotSemiInvulnerableMove[i] && isTwoTurnNotSemiInvulnerableMove[currId]) tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_NOT_CHARGING); + // Comparing KOs + if (noOfHits[currId] == 1) + { + // Use priority to get fast KO if outsped + switch (CompareMoveSpeeds(battlerAtk, battlerDef, moves[currId], moves[i])) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_SPEED); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_SPEED); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + // Min roll KOs + switch (CompareGuaranteeFaintTarget(battlerAtk, battlerDef, currId, i, moves)) + { + case MOVE_WON_COMPARISON: + tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_GUARANTEE); + break; + case MOVE_LOST_COMPARISON: + tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_GUARANTEE); + break; + case MOVE_NEUTRAL_COMPARISON: + break; + } + } switch (CompareMoveAccuracies(battlerAtk, battlerDef, currId, i)) { - case 1: + case MOVE_WON_COMPARISON: tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); break; - case -1: + case MOVE_LOST_COMPARISON: tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_ACCURACY); break; + case MOVE_NEUTRAL_COMPARISON: + break; } switch (AI_WhichMoveBetter(moves[currId], moves[i], battlerAtk, battlerDef, noOfHits[currId])) { - case 1: + case MOVE_WON_COMPARISON: tempMoveScores[currId] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); break; - case -1: + case MOVE_LOST_COMPARISON: tempMoveScores[i] += MathUtil_Exponent(MAX_MON_MOVES, PRIORITY_EFFECT); break; + case MOVE_NEUTRAL_COMPARISON: + break; } } } @@ -4111,7 +4180,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move)); break; case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) { if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) @@ -4180,7 +4249,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) && (gLastMoves[battlerDef] != MOVE_NONE) && (gLastMoves[battlerDef] != 0xFFFF) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) - && (AI_IsFaster(battlerAtk, battlerDef, move))) + && (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY))) { if (CanTargetMoveFaintAi(gLastMoves[battlerDef], battlerDef, battlerAtk, 1)) ADJUST_SCORE(GOOD_EFFECT); // Disable move that can kill attacker @@ -4220,7 +4289,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_DESTINY_BOND: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - else if (AI_IsFaster(battlerAtk, battlerDef, move) && CanTargetFaintAi(battlerDef, battlerAtk)) + else if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SPITE: @@ -4435,7 +4504,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (predictedMove != MOVE_NONE && !isDoubleBattle) { enum BattleMoveEffects predictedEffect = GetMoveEffect(predictedMove); - if ((AI_IsFaster(battlerAtk, battlerDef, move)) + if ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) && (predictedEffect == EFFECT_EXPLOSION || predictedEffect == EFFECT_MISTY_EXPLOSION || predictedEffect == EFFECT_PROTECT)) @@ -4486,7 +4555,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_ATTRACT: if (!isDoubleBattle - && (AI_IsSlower(battlerAtk, battlerDef, move)) + && (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) && BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef])) break; // Don't use if the attract won't have a change to activate if (gBattleMons[battlerDef].status1 & STATUS1_ANY @@ -4513,7 +4582,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (isDoubleBattle) { if (IsHazardMove(aiData->partnerMove) // Partner is going to set up hazards - && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move)) // Partner going first + && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move, predictedMove, CONSIDER_PRIORITY)) // Partner going first break; // Don't use Defog if partner is going to set up hazards } ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_EVASION)); @@ -5007,7 +5076,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEAL_BLOCK: - if (AI_IsFaster(battlerAtk, battlerDef, move) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) ADJUST_SCORE(DECENT_EFFECT); // Try to cancel healing move else if (HasHealingEffect(battlerDef) || aiData->holdEffects[battlerDef] == HOLD_EFFECT_LEFTOVERS || (aiData->holdEffects[battlerDef] == HOLD_EFFECT_BLACK_SLUDGE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_POISON))) @@ -5041,7 +5110,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_QUASH: - if (isDoubleBattle && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove)) + if (isDoubleBattle && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target break; case EFFECT_TAILWIND: @@ -5056,7 +5125,7 @@ case EFFECT_GUARD_SPLIT: if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) && !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move { - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker goes first { if (predictedType == TYPE_GROUND) ADJUST_SCORE(GOOD_EFFECT); // Cause the enemy's move to fail @@ -5071,7 +5140,7 @@ case EFFECT_GUARD_SPLIT: } break; case EFFECT_CAMOUFLAGE: - if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move) // Attacker goes first + if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) // Attacker goes first && !IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(DECENT_EFFECT); break; @@ -5098,7 +5167,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_ENDEAVOR: - if (AI_IsSlower(battlerAtk, battlerDef, move) && !CanTargetFaintAi(battlerDef, battlerAtk)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && !CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_REVIVAL_BLESSING: @@ -5377,7 +5446,7 @@ case EFFECT_GUARD_SPLIT: case MOVE_EFFECT_THROAT_CHOP: if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) { - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(DECENT_EFFECT); @@ -5433,7 +5502,7 @@ static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 return score; if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING - && AI_IsSlower(battlerAtk, battlerDef, move) + && AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk) && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) == 0) { @@ -6009,7 +6078,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(GOOD_EFFECT); else if (hitsToKO == 1) ADJUST_SCORE(BEST_EFFECT); - else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER) // Pursuit against fast U-Turn + else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) == AI_IS_SLOWER) // Pursuit against fast U-Turn ADJUST_SCORE(DECENT_EFFECT); break; } diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 976c06c0b6..7c5348176f 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -171,6 +171,34 @@ static bool32 AI_DoesChoiceEffectBlockMove(u32 battler, u32 move) return FALSE; } +static inline bool32 CanBattlerWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool32 isBattlerFirst) +{ + // Player's best move deals 0 damage + if (hitsToKOAI == 0 && hitsToKOPlayer > 0) + return TRUE; + + // AI's best move deals 0 damage + if (hitsToKOPlayer == 0 && hitsToKOAI > 0) + return FALSE; + + // Neither mon can damage the other + if (hitsToKOPlayer == 0 && hitsToKOAI == 0) + return FALSE; + + // Different KO thresholds depending on who goes first + if (isBattlerFirst) + { + if (hitsToKOAI >= hitsToKOPlayer) + return TRUE; + } + else + { + if (hitsToKOAI > hitsToKOPlayer) + return TRUE; + } + return FALSE; +} + // Note that as many return statements as possible are INTENTIONALLY put after all of the loops; // the function can take a max of about 0.06s to run, and this prevents the player from identifying // whether the mon will switch or not by seeing how long the delay is before they select a move @@ -178,12 +206,13 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) { //Variable initialization u8 opposingPosition; - s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0; - u32 aiMove, playerMove, aiBestMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; + s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0, maxDamageTakenPriority = 0; + u32 aiMove, playerMove, bestPlayerPriorityMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE; u32 typeMatchup; enum BattleMoveEffects aiMoveEffect; - u32 hitsToKoPlayer = 0, hitsToKoAI = 0; + u32 hitsToKoAI = 0, hitsToKoAIPriority = 0, hitsToKoPlayer = 0; + bool32 canBattlerWin1v1 = FALSE, isBattlerFirst, isBattlerFirstPriority; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) @@ -197,6 +226,28 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) opposingBattler = GetBattlerAtPosition(opposingPosition); u16 *playerMoves = GetMovesArray(opposingBattler); + // Get max damage mon could take + for (i = 0; i < MAX_MON_MOVES; i++) + { + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + { + damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); + if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) + { + maxDamageTaken = damageTaken; + } + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[battler], playerMove) > 0 && damageTaken > maxDamageTakenPriority && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) + { + maxDamageTakenPriority = damageTaken; + bestPlayerPriorityMove = playerMove; + } + } + } + + hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler); + hitsToKoAIPriority = GetNoOfHitsToKOBattlerDmg(maxDamageTakenPriority, battler); + for (i = 0; i < MAX_MON_MOVES; i++) { aiMove = gBattleMons[battler].moves[i]; @@ -220,53 +271,37 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) } // Only check damage if it's a damaging move - if (!IsBattleMoveStatus(aiMove)) + if (!IsBattleMoveStatus(aiMove) && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) { // Check if mon has a super effective move - if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0) && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) + if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0)) hasSuperEffectiveMove = TRUE; // Get maximum damage mon can deal damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData); - if (damageDealt > maxDamageDealt && !AI_DoesChoiceEffectBlockMove(battler, aiMove)) + if (!canBattlerWin1v1 ) // Once we can win a 1v1 we don't need to track this, but want to run the rest of the function to keep the runtime the same regardless of when we find the winning move { - maxDamageDealt = damageDealt; - aiBestMove = aiMove; + hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); + isBattlerFirst = AI_IsFaster(battler, opposingBattler, aiMove, GetIncomingMove(battler, opposingBattler, gAiLogicData), CONSIDER_PRIORITY); + isBattlerFirstPriority = AI_IsFaster(battler, opposingBattler, aiMove, bestPlayerPriorityMove, CONSIDER_PRIORITY); + canBattlerWin1v1 = CanBattlerWin1v1(hitsToKoAI, hitsToKoPlayer, isBattlerFirst) && CanBattlerWin1v1(hitsToKoAIPriority, hitsToKoPlayer, isBattlerFirstPriority); } } } } - hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(maxDamageDealt, opposingBattler); - // Calculate type advantage typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gBattleMons[battler]); - // Get max damage mon could take - for (i = 0; i < MAX_MON_MOVES; i++) - { - playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) - { - damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); - if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) - { - maxDamageTaken = damageTaken; - } - } - } - - hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler); - // Check if mon gets one shot if (maxDamageTaken > gBattleMons[battler].hp - && !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gBattleMons[opposingBattler].ability) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY))) + && !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gAiLogicData->abilities[opposingBattler]) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY))) { getsOneShot = TRUE; } // Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can - if ((hitsToKoPlayer != 0 && (hitsToKoPlayer < hitsToKoAI || hitsToKoAI == 0)) || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove))) + if (canBattlerWin1v1) return FALSE; // If we don't have any other viable options, don't switch out @@ -384,8 +419,8 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler) { aiMove = gBattleMons[battler].moves[moveIndex]; if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE - && !CanAbilityAbsorbMove(battler, opposingBattler, gBattleMons[opposingBattler].ability, aiMove, GetBattleMoveType(aiMove), AI_CHECK) - && !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gBattleMons[opposingBattler].ability, aiMove, AI_CHECK) + && !CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], aiMove, GetBattleMoveType(aiMove), AI_CHECK) + && !CanAbilityBlockMove(battler, opposingBattler, gBattleMons[battler].ability, gAiLogicData->abilities[opposingBattler], aiMove, AI_CHECK) && (!ALL_MOVES_BAD_STATUS_MOVES_BAD || gMovesInfo[aiMove].power != 0)) // If using ALL_MOVES_BAD_STATUS_MOVES_BAD, then need power to be non-zero return FALSE; } @@ -1788,7 +1823,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) u16 maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, item = gAiLogicData->switchinCandidate.battleMon.item, heldItemEffect = GetItemHoldEffect(item); u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = GetItemHoldEffectParam(item); u32 opposingBattler = GetOppositeBattler(battler); - u32 opposingAbility = gBattleMons[opposingBattler].ability, ability = gAiLogicData->switchinCandidate.battleMon.ability; + u32 opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->switchinCandidate.battleMon.ability; bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility); s32 currentHP = startingHP; @@ -1939,7 +1974,7 @@ static int GetRandomSwitchinWithBatonPass(int aliveCount, int bits, int firstId, return PARTY_SIZE; } -static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon) +static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon, u32 *bestPlayerMove) { int i = 0; u32 playerMove; @@ -1955,7 +1990,35 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move return damageTaken; if (damageTaken > maxDamageTaken) + { maxDamageTaken = damageTaken; + *bestPlayerMove = playerMove; + } + } + } + return maxDamageTaken; +} + +static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattler, struct BattlePokemon battleMon, u32 *bestPlayerPriorityMove) +{ + int i = 0; + u32 playerMove; + u16 *playerMoves = GetMovesArray(opposingBattler); + s32 damageTaken = 0, maxDamageTaken = 0; + + for (i = 0; i < MAX_MON_MOVES; i++) + { + playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 && playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + { + damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); + if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move + return damageTaken; + if (damageTaken > maxDamageTaken) + { + maxDamageTaken = damageTaken; + *bestPlayerPriorityMove = playerMove; + } } } return maxDamageTaken; @@ -2044,9 +2107,9 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, int i, j, aliveCount = 0, bits = 0, aceMonCount = 0; s32 defensiveMonHitKOThreshold = 3; // 3HKO threshold that candidate defensive mons must exceed s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0; - u32 aiMove, hitsToKOAI, maxHitsToKO = 0; + u32 aiMove, hitsToKOAI, hitsToKOPlayer, hitsToKOAIPriority, bestPlayerMove = MOVE_NONE, bestPlayerPriorityMove = MOVE_NONE, maxHitsToKO = 0; u32 bestResist = UQ_4_12(2.0), bestResistEffective = UQ_4_12(2.0), typeMatchup; // 2.0 is the default "Neutral" matchup from GetBattleMonTypeMatchup - bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1; + bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, isSwitchinFirstPriority, canSwitchinWin1v1; // Iterate through mons for (i = firstId; i < lastId; i++) @@ -2077,7 +2140,8 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, continue; // Get max number of hits for player to KO AI mon and type matchup for defensive switching - hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon), battler); + hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &bestPlayerMove), battler); + hitsToKOAIPriority = GetSwitchinHitsToKO(GetMaxPriorityDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, &bestPlayerPriorityMove), battler); typeMatchup = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); // Check through current mon's moves @@ -2085,10 +2149,12 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); + hitsToKOPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); // Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1 - isSwitchinFirst = AI_WhoStrikesFirstPartyMon(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove); - canSwitchinWin1v1 = CanSwitchinWin1v1(hitsToKOAI, GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler), isSwitchinFirst, isFreeSwitch); + isSwitchinFirst = AI_IsPartyMonFaster(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove, bestPlayerMove, CONSIDER_PRIORITY); + isSwitchinFirstPriority = AI_IsPartyMonFaster(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, aiMove, bestPlayerPriorityMove, CONSIDER_PRIORITY); + canSwitchinWin1v1 = CanSwitchinWin1v1(hitsToKOAI, hitsToKOPlayer, isSwitchinFirst, isFreeSwitch) && CanSwitchinWin1v1(hitsToKOAIPriority, hitsToKOPlayer, isSwitchinFirstPriority, isFreeSwitch); // AI must successfully 1v1 with and without priority to be considered a good option // Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not if (GetMoveEffect(aiMove) == EFFECT_BATON_PASS) @@ -2346,7 +2412,7 @@ static bool32 AiExpectsToFaintPlayer(u32 battler) if (!IsBattlerAlly(target, battler) && CanIndexMoveFaintTarget(battler, target, gAiBattleData->chosenMoveIndex[battler], AI_ATTACKING) - && AI_IsFaster(battler, target, GetAIChosenMove(battler))) + && AI_IsFaster(battler, target, GetAIChosenMove(battler), GetIncomingMove(battler, target, gAiLogicData), CONSIDER_PRIORITY)) { // We expect to faint the target and move first -> dont use an item return TRUE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 61d8021de6..4443aa1f59 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -76,14 +76,24 @@ u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcC } } -bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move) +bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) { - return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_FASTER); + return (AI_WhoStrikesFirst(battlerAi, battlerDef, aiMove, playerMove, considerPriority) == AI_IS_FASTER); } -bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move) +bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) { - return (AI_WhoStrikesFirst(battlerAi, battlerDef, move) == AI_IS_SLOWER); + return (AI_WhoStrikesFirst(battlerAi, battlerDef, aiMove, playerMove, considerPriority) == AI_IS_SLOWER); +} + +bool32 AI_IsPartyMonFaster(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) +{ + return (AI_WhoStrikesFirstPartyMon(battlerAi, battlerDef, switchinCandidate, aiMove, playerMove, considerPriority) == AI_IS_FASTER); +} + +bool32 AI_IsPartyMonSlower(u32 battlerAi, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMove, u32 playerMove, enum ConsiderPriority considerPriority) +{ + return (AI_WhoStrikesFirstPartyMon(battlerAi, battlerDef, switchinCandidate, aiMove, playerMove, considerPriority) == AI_IS_SLOWER); } u32 GetAIChosenMove(u32 battlerId) @@ -484,7 +494,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_PROTECT && move != MOVE_ENDURE) return TRUE; - if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI))) + if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI), GetIncomingMove(battlerAI, opposingBattler, gAiLogicData), CONSIDER_PRIORITY)) return TRUE; } return FALSE; @@ -1164,7 +1174,7 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s } // Checks if one of the moves has side effects or perks, assuming equal dmg or equal no of hits to KO -s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) +enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo) { bool32 effect1, effect2; u32 defAbility = gAiLogicData->abilities[battlerDef]; @@ -1178,27 +1188,27 @@ s32 AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 bool32 moveContact1 = MoveMakesContact(move1); bool32 moveContact2 = MoveMakesContact(move2); if (moveContact1 && !moveContact2) - return -1; + return MOVE_LOST_COMPARISON; if (moveContact2 && !moveContact1) - return 1; + return MOVE_WON_COMPARISON; } // Check additional effects. effect1 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInMinus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return 1; + return MOVE_WON_COMPARISON; if (effect1 && !effect2) - return -1; + return MOVE_LOST_COMPARISON; effect1 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move1, noOfHitsToKo); effect2 = AI_IsMoveEffectInPlus(battlerAtk, battlerDef, move2, noOfHitsToKo); if (effect2 && !effect1) - return -1; + return MOVE_LOST_COMPARISON; if (effect1 && !effect2) - return 1; + return MOVE_WON_COMPARISON; - return 0; + return MOVE_NEUTRAL_COMPARISON; } u32 GetNoOfHitsToKO(u32 dmg, s32 hp) @@ -1261,7 +1271,7 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef) * AI_IS_FASTER: is user(ai) faster * AI_IS_SLOWER: is target faster */ -s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) +s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority) { u32 speedBattlerAI, speedBattler; enum ItemHoldEffect holdEffectAI = gAiLogicData->holdEffects[battlerAI]; @@ -1269,15 +1279,16 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) u32 abilityAI = gAiLogicData->abilities[battlerAI]; u32 abilityPlayer = gAiLogicData->abilities[battler]; - u32 predictedMove = GetIncomingMove(battlerAI, battler, gAiLogicData); - - s8 aiPriority = GetBattleMovePriority(battlerAI, abilityAI, moveConsidered); - s8 playerPriority = GetBattleMovePriority(battler, abilityPlayer, predictedMove); + if (considerPriority == CONSIDER_PRIORITY) + { + s8 aiPriority = GetBattleMovePriority(battlerAI, abilityAI, aiMoveConsidered); + s8 playerPriority = GetBattleMovePriority(battler, abilityPlayer, playerMoveConsidered); - if (aiPriority > playerPriority) - return AI_IS_FASTER; - else if (aiPriority < playerPriority) - return AI_IS_SLOWER; + if (aiPriority > playerPriority) + return AI_IS_FASTER; + else if (aiPriority < playerPriority) + return AI_IS_SLOWER; + } speedBattlerAI = GetBattlerTotalSpeedStatArgs(battlerAI, abilityAI, holdEffectAI); speedBattler = GetBattlerTotalSpeedStatArgs(battler, abilityPlayer, holdEffectPlayer); @@ -1314,7 +1325,7 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) return AI_IS_SLOWER; } -static bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) +bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) { enum BattleMoveEffects effect = GetMoveEffect(move); if (!AI_BattlerAtMaxHp(battlerTarget) || effect == EFFECT_MULTI_HIT) @@ -2043,7 +2054,7 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat) if (stat == STAT_SPEED) { // If AI is faster and doesn't have any mons left, lowering speed doesn't give any - return !(AI_IsFaster(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered) + return !(AI_IsFaster(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY) && CountUsablePartyMons(battlerAtk) == 0 && !HasMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); } @@ -2085,7 +2096,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_SPEED: - if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered)) + if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY)) tempScore += DECENT_EFFECT; break; case STAT_SPATK: @@ -2191,18 +2202,6 @@ bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 moveIndex, en return FALSE; } -bool32 CanIndexMoveGuaranteeFaintTarget(u32 battlerAtk, u32 battlerDef, u32 moveIndex) -{ - s32 dmg; - u16 *moves = gBattleMons[battlerAtk].moves; - - dmg = gAiLogicData->simulatedDmg[battlerAtk][battlerDef][moveIndex].minimum; // Explictly care about guaranteed KOs universally - - if (gBattleMons[battlerDef].hp <= dmg && !CanEndureHit(battlerAtk, battlerDef, moves[moveIndex])) - return TRUE; - return FALSE; -} - u16 *GetMovesArray(u32 battler) { if (IsAiBattlerAware(battler) || IsAiBattlerAware(BATTLE_PARTNER(battler))) @@ -3127,7 +3126,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (IsBattlerPredictedToSwitch(battlerDef)) return SHOULD_PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent - if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) // Attacker goes first { if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise { @@ -3512,7 +3511,7 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi if (((!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) || gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - || AI_IsSlower(battlerAtk, battlerDef, move))) // Opponent goes first + || AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY))) // Opponent goes first { return 0; } @@ -3520,7 +3519,7 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi || gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS || gBattleMons[battlerDef].volatiles.infatuation || gBattleMons[battlerDef].volatiles.confusionTurns > 0) - || ((AI_IsFaster(battlerAtk, battlerDef, move)) && CanTargetFaintAi(battlerDef, battlerAtk))) + || ((AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) && CanTargetFaintAi(battlerDef, battlerAtk))) { return 2; // good idea to flinch } @@ -3666,7 +3665,7 @@ bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 mo bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) { - if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move)) + if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) { // using item or user goes first s32 healDmg = (GetMoveAbsorbPercentage(move) * damage) / 100; @@ -3698,7 +3697,7 @@ bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent) healAmount = maxHP; if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) healAmount = 0; - if (AI_IsFaster(battlerAtk, battlerDef, move)) + if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) { if (CanTargetFaintAi(battlerDef, battlerAtk) && !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healAmount, 0)) @@ -4040,17 +4039,17 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl return dmg.median; } -u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 moveConsidered) +u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority considerPriority) { struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); gBattleMons[battlerAtk] = switchinCandidate; SetBattlerAiData(battlerAtk, gAiLogicData); - u32 aiMonFaster = AI_IsFaster(battlerAtk, battlerDef, moveConsidered); + u32 aiWhoStrikesFirst = AI_WhoStrikesFirst(battlerAtk, battlerDef, aiMoveConsidered, playerMoveConsidered, considerPriority); FreeRestoreBattleMons(savedBattleMons); SetBattlerAiData(battlerAtk, gAiLogicData); - return aiMonFaster; + return aiWhoStrikesFirst; } s32 CountUsablePartyMons(u32 battlerId) @@ -4291,7 +4290,7 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, { enum AIScore tempScore = NO_INCREASE; u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk); - u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, TRUE); + u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; u32 statId = GetStatBeingChanged(statChange); @@ -4841,7 +4840,7 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str else { // will we go first? - if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) + if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove, GetIncomingMove(battler, opposingBattler, gAiLogicData), CONSIDER_PRIORITY) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) return USE_GIMMICK; } } @@ -4954,7 +4953,7 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerDef) != 0) ADJUST_SCORE_PTR(-2); - if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move)) + if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY)) ADJUST_SCORE_PTR(-10); if (gBattleMons[battlerDef].volatiles.substitute) ADJUST_SCORE_PTR(GOOD_EFFECT); @@ -4970,6 +4969,8 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st u32 preventsStatLoss; u32 partnerAbility; u32 partnerHoldEffect = aiData->holdEffects[battlerAtkPartner]; + u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battlerAtk)); + u32 opposingBattler = GetBattlerAtPosition(opposingPosition); if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) partnerAbility = ABILITY_NONE; @@ -5002,7 +5003,7 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st } return (preventsStatLoss - && AI_IsFaster(battlerAtk, battlerAtkPartner, TRUE) + && AI_IsFaster(battlerAtk, battlerAtkPartner, MOVE_NONE, GetIncomingMove(battlerAtk, opposingBattler, gAiLogicData), CONSIDER_PRIORITY) && HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)); } diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 25999df746..4c65a23489 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -1010,3 +1010,15 @@ AI_SINGLE_BATTLE_TEST("AI will use recovery move if is in no immediate danger be TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_RECOVER); } } } + +AI_SINGLE_BATTLE_TEST("AI has a chance to prioritize last chance priority damage over slow KO") +{ + PASSES_RANDOMLY(PRIORITIZE_LAST_CHANCE_CHANCE, 100, RNG_AI_PRIORITIZE_LAST_CHANCE); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_CAMERUPT) { Speed(2); Moves(MOVE_FLAMETHROWER, MOVE_CELEBRATE); } + OPPONENT(SPECIES_FLOATZEL) { Level(90); Speed(1); HP(1); Moves(MOVE_WAVE_CRASH, MOVE_AQUA_JET); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_AQUA_JET); } + } +} diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 4d1fa5d746..4c05c620a5 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1164,6 +1164,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if all moves ASSUME(GetMoveType(MOVE_RETURN) == TYPE_NORMAL); ASSUME(GetMoveType(MOVE_DRAIN_PUNCH) == TYPE_FIGHTING); ASSUME(gSpeciesInfo[SPECIES_MAROWAK_ALOLA].types[1] == TYPE_GHOST); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_OMNISCIENT); PLAYER(SPECIES_MAROWAK_ALOLA) { Ability(ABILITY_LIGHTNING_ROD); Moves(MOVE_SHADOW_BONE); } OPPONENT(SPECIES_LOPUNNY) { Moves(MOVE_FAKE_OUT, MOVE_RETURN, MOVE_DRAIN_PUNCH, MOVE_THUNDER_PUNCH); Ability(ABILITY_LIMBER); } OPPONENT(SPECIES_CHANDELURE) { Moves(MOVE_SHADOW_BALL); } @@ -1299,3 +1300,42 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will properly consider immu TURN { MOVE(player, MOVE_KARATE_CHOP); EXPECT_MOVE(opponent, MOVE_SCRATCH); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out due to bad odds if it can OHKO with a priority move") +{ + PASSES_RANDOMLY(100, 100, RNG_AI_SWITCH_HASBADODDS); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + OPPONENT(SPECIES_CETODDLE) { Level(14); HP(30); Speed(1); Moves(MOVE_ICE_FANG, MOVE_ROCK_SMASH, MOVE_BULLDOZE, MOVE_ICE_SHARD); } + OPPONENT(SPECIES_SPHEAL) { Level(14); Speed(1); Ability(ABILITY_THICK_FAT); Moves(MOVE_ICY_WIND, MOVE_BRINE, MOVE_HIDDEN_POWER, MOVE_SIGNAL_BEAM); } + PLAYER(SPECIES_LITTEN) { Level(15); HP(1); Speed(2); Ability(ABILITY_BLAZE); Moves(MOVE_FIRE_FANG, MOVE_EMBER, MOVE_LICK, MOVE_FAKE_OUT); } + } WHEN { + TURN { MOVE(player, MOVE_FIRE_FANG); EXPECT_MOVE(opponent, MOVE_ICE_SHARD); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will consider player's priority when evaluating switchin candidates") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + OPPONENT(SPECIES_ZIGZAGOON) { Speed(1); HP(1); Moves(MOVE_HEADBUTT); } + OPPONENT(SPECIES_ANNIHILAPE) { Speed(5); Moves(MOVE_DRAIN_PUNCH); } + OPPONENT(SPECIES_GENGAR) { Speed(10); Moves(MOVE_FOCUS_BLAST); } + PLAYER(SPECIES_KINGAMBIT) { Speed(2); Moves(MOVE_SUCKER_PUNCH, MOVE_KNOCK_OFF); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); EXPECT_MOVE(opponent, MOVE_HEADBUTT); EXPECT_SEND_OUT(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will consider player's priority when evaluating Bad Odds 1v1") +{ + PASSES_RANDOMLY(SHOULD_SWITCH_HASBADODDS_PERCENTAGE, 100, RNG_AI_SWITCH_HASBADODDS); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + OPPONENT(SPECIES_GENGAR) { Speed(10); Moves(MOVE_FOCUS_BLAST); } + OPPONENT(SPECIES_SCRAFTY) { Speed(5); Moves(MOVE_DRAIN_PUNCH); } + PLAYER(SPECIES_KINGAMBIT) { Speed(2); Moves(MOVE_SUCKER_PUNCH, MOVE_KNOCK_OFF); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); EXPECT_SWITCH(opponent, 1); } + } +} From b12fcd8c7e4818b5d18f6f22f9c5c2930a7addf5 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 26 Jul 2025 13:59:17 -0400 Subject: [PATCH 136/283] Fix dynamic move types in switching (#7415) --- include/config/ai.h | 1 + include/random.h | 1 + src/battle_ai_switch_items.c | 6 ++++-- test/battle/ai/ai_switching.c | 15 +++++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/config/ai.h b/include/config/ai.h index c82e46773a..d5f42696eb 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -13,6 +13,7 @@ // AI smart switching chances; if you want more complex behaviour, modify GetSwitchChance #define SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE 100 +#define SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE 50 #define SHOULD_SWITCH_TRAPPER_PERCENTAGE 100 #define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 100 #define STAY_IN_ABSORBING_PERCENTAGE 66 // Chance to stay in if outgoing mon has super effective move against player, will prevent switching out for an absorber with this likelihood diff --git a/include/random.h b/include/random.h index 38a464e457..283813b1b1 100644 --- a/include/random.h +++ b/include/random.h @@ -192,6 +192,7 @@ enum RandomTag RNG_AI_SWITCH_ALL_MOVES_BAD, RNG_AI_CONSERVE_TERA, RNG_AI_SWITCH_ALL_SCORES_BAD, + RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER, RNG_AI_PP_STALL_DISREGARD_MOVE, RNG_AI_SUCKER_PUNCH, RNG_SHELL_SIDE_ARM, diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 7c5348176f..526c81c7ca 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -481,12 +481,14 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) u16 monAbility, aiMove; u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); - u32 incomingType = GetMoveType(incomingMove); + u32 incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE); bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); s32 i, j; if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; + if (GetMoveEffect(incomingMove) == EFFECT_HIDDEN_POWER && RandomPercentage(RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER, SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE)) + return FALSE; if (gBattleStruct->prevTurnSpecies[battler] != gBattleMons[battler].species && !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE)) // AI mon has changed, player's behaviour no longer reliable; override this if using AI_FLAG_PREDICT_MOVE return FALSE; if (CanUseSuperEffectiveMoveAgainstOpponents(battler) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING_STAY_IN, STAY_IN_ABSORBING_PERCENTAGE) || gAiLogicData->aiPredictionInProgress)) @@ -1034,7 +1036,7 @@ static bool32 ShouldSwitchIfBadChoiceLock(u32 battler) bool32 moveAffectsTarget = TRUE; if (lastUsedMove != MOVE_NONE && (AI_GetMoveEffectiveness(lastUsedMove, battler, opposingBattler) == UQ_4_12(0.0) - || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, GetMoveType(lastUsedMove), AI_CHECK) + || CanAbilityAbsorbMove(battler, opposingBattler, gAiLogicData->abilities[opposingBattler], lastUsedMove, CheckDynamicMoveType(GetBattlerMon(battler), lastUsedMove, battler, MON_IN_BATTLE), AI_CHECK) || CanAbilityBlockMove(battler, opposingBattler, gAiLogicData->abilities[battler], gAiLogicData->abilities[opposingBattler], lastUsedMove, AI_CHECK))) moveAffectsTarget = FALSE; diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 4c05c620a5..e8eb9f7ec4 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1339,3 +1339,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will consider player's priori TURN { MOVE(player, MOVE_KNOCK_OFF); EXPECT_SWITCH(opponent, 1); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will consider Hidden Power when triggering absorbing switches") +{ + PASSES_RANDOMLY(SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE, 100, RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER); + GIVEN { + ASSUME(B_REDIRECT_ABILITY_IMMUNITY >= GEN_5); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_HIDDEN_POWER); HPIV(31); AttackIV(30); DefenseIV(31); SpAttackIV(30); SpDefenseIV(31); SpeedIV(30); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } + OPPONENT(SPECIES_NINETALES) { Moves(MOVE_SCRATCH); Ability(ABILITY_FLASH_FIRE); } + } WHEN { + TURN { MOVE(player, MOVE_HIDDEN_POWER); EXPECT_MOVE(opponent, MOVE_SCRATCH); } + TURN { MOVE(player, MOVE_HIDDEN_POWER); EXPECT_SWITCH(opponent, 1); } + } +} From 5da5cb4c8cd9103b6c97c3857eebb91e3390e955 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Sat, 26 Jul 2025 20:19:45 +0200 Subject: [PATCH 137/283] document shop menu palette --- src/shop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shop.c b/src/shop.c index 587060f024..338e067938 100644 --- a/src/shop.c +++ b/src/shop.c @@ -43,6 +43,7 @@ #define TAG_ITEM_ICON_BASE 2110 #define MAX_ITEMS_SHOWN 8 +#define SHOP_MENU_PALETTE_ID 12 enum { WIN_BUY_SELL_QUIT, @@ -740,7 +741,7 @@ static void BuyMenuDecompressBgGraphics(void) { DecompressAndCopyTileDataToVram(1, gShopMenu_Gfx, 0x3A0, 0x3E3, 0); LZDecompressWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]); - LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(12), PLTT_SIZE_4BPP); + LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(SHOP_MENU_PALETTE_ID), PLTT_SIZE_4BPP); } static void BuyMenuInitWindows(void) @@ -941,7 +942,7 @@ static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void) for (i = 0; i < 1024; i++) { if (src[i] != 0) - dest[i] = src[i] + 0xC3E3; + dest[i] = src[i] + ((SHOP_MENU_PALETTE_ID << 12) | 0x3E3); } } From 7c6cff1fb3f93e0b8220db34269c74bb81183c84 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Mon, 28 Jul 2025 13:42:28 +0300 Subject: [PATCH 138/283] Get/SetMonData optimisation (#7313) --- include/gba/defines.h | 1 + include/pokemon.h | 10 +- src/pokemon.c | 602 +++++++++++++++++++++--------------------- test/pokemon.c | 25 ++ 4 files changed, 329 insertions(+), 309 deletions(-) diff --git a/include/gba/defines.h b/include/gba/defines.h index 674c5fdc14..754e95a6dd 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -26,6 +26,7 @@ #define ALIGNED(n) __attribute__((aligned(n))) #define PACKED __attribute__((packed)) #define TRANSPARENT __attribute__ ((__transparent_union__)) +#define ALWAYS_INLINE inline __attribute__((always_inline)) #define NONNULL __attribute__((__nonnull__)) #define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) diff --git a/include/pokemon.h b/include/pokemon.h index ac525624cc..f3eea90000 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -16,7 +16,7 @@ #define FORM_SPECIES_END (0xffff) // Property labels for Get(Box)MonData / Set(Box)MonData -enum { +enum MonData { MON_DATA_PERSONALITY, MON_DATA_STATUS, MON_DATA_OT_ID, @@ -232,6 +232,14 @@ struct PokemonSubstruct3 max(sizeof(struct PokemonSubstruct2), \ sizeof(struct PokemonSubstruct3))))) +enum SubstructType +{ + SUBSTRUCT_TYPE_0, + SUBSTRUCT_TYPE_1, + SUBSTRUCT_TYPE_2, + SUBSTRUCT_TYPE_3, +}; + union PokemonSubstruct { struct PokemonSubstruct0 type0; diff --git a/src/pokemon.c b/src/pokemon.c index 6433acd701..8ddfd5d5b4 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -76,7 +76,9 @@ struct SpeciesItem }; static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); -static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); +static u16 CalculateBoxMonChecksumDecrypt(struct BoxPokemon *boxMon); +static u16 CalculateBoxMonChecksumReencrypt(struct BoxPokemon *boxMon); +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, enum SubstructType substructType); static void EncryptBoxMon(struct BoxPokemon *boxMon); static void DecryptBoxMon(struct BoxPokemon *boxMon); static void Task_PlayMapChosenOrBattleBGM(u8 taskId); @@ -1656,24 +1658,36 @@ void CreateEnemyEventMon(void) static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) { - u16 checksum = 0; - union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0); - union PokemonSubstruct *substruct1 = GetSubstruct(boxMon, boxMon->personality, 1); - union PokemonSubstruct *substruct2 = GetSubstruct(boxMon, boxMon->personality, 2); - union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3); - s32 i; + u32 checksum = 0; - for (i = 0; i < (s32)ARRAY_COUNT(substruct0->raw); i++) - checksum += substruct0->raw[i]; + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); - for (i = 0; i < (s32)ARRAY_COUNT(substruct1->raw); i++) - checksum += substruct1->raw[i]; + return checksum; +} - for (i = 0; i < (s32)ARRAY_COUNT(substruct2->raw); i++) - checksum += substruct2->raw[i]; +static u16 CalculateBoxMonChecksumDecrypt(struct BoxPokemon *boxMon) +{ + u32 checksum = 0; - for (i = 0; i < (s32)ARRAY_COUNT(substruct3->raw); i++) - checksum += substruct3->raw[i]; + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + { + boxMon->secure.raw[i] ^= (boxMon->otId ^ boxMon->personality); + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); + } + + return checksum; +} + +static u16 CalculateBoxMonChecksumReencrypt(struct BoxPokemon *boxMon) +{ + u32 checksum = 0; + + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + { + checksum += boxMon->secure.raw[i] + (boxMon->secure.raw[i] >> 16); + boxMon->secure.raw[i] ^= (boxMon->otId ^ boxMon->personality); + } return checksum; } @@ -2194,8 +2208,7 @@ void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPositio static void EncryptBoxMon(struct BoxPokemon *boxMon) { - u32 i; - for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->personality; boxMon->secure.raw[i] ^= boxMon->otId; @@ -2204,70 +2217,26 @@ static void EncryptBoxMon(struct BoxPokemon *boxMon) static void DecryptBoxMon(struct BoxPokemon *boxMon) { - u32 i; - for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) + for (u32 i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->otId; boxMon->secure.raw[i] ^= boxMon->personality; } } -#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \ -case n: \ - { \ - \ - switch (substructType) \ - { \ - case 0: \ - substruct = &boxMon->secure.substructs[v1]; \ - break; \ - case 1: \ - substruct = &boxMon->secure.substructs[v2]; \ - break; \ - case 2: \ - substruct = &boxMon->secure.substructs[v3]; \ - break; \ - case 3: \ - substruct = &boxMon->secure.substructs[v4]; \ - break; \ - } \ - break; \ - } \ - - -static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) -{ - union PokemonSubstruct *substruct = NULL; - - switch (personality % 24) - { - SUBSTRUCT_CASE( 0,0,1,2,3) - SUBSTRUCT_CASE( 1,0,1,3,2) - SUBSTRUCT_CASE( 2,0,2,1,3) - SUBSTRUCT_CASE( 3,0,3,1,2) - SUBSTRUCT_CASE( 4,0,2,3,1) - SUBSTRUCT_CASE( 5,0,3,2,1) - SUBSTRUCT_CASE( 6,1,0,2,3) - SUBSTRUCT_CASE( 7,1,0,3,2) - SUBSTRUCT_CASE( 8,2,0,1,3) - SUBSTRUCT_CASE( 9,3,0,1,2) - SUBSTRUCT_CASE(10,2,0,3,1) - SUBSTRUCT_CASE(11,3,0,2,1) - SUBSTRUCT_CASE(12,1,2,0,3) - SUBSTRUCT_CASE(13,1,3,0,2) - SUBSTRUCT_CASE(14,2,1,0,3) - SUBSTRUCT_CASE(15,3,1,0,2) - SUBSTRUCT_CASE(16,2,3,0,1) - SUBSTRUCT_CASE(17,3,2,0,1) - SUBSTRUCT_CASE(18,1,2,3,0) - SUBSTRUCT_CASE(19,1,3,2,0) - SUBSTRUCT_CASE(20,2,1,3,0) - SUBSTRUCT_CASE(21,3,1,2,0) - SUBSTRUCT_CASE(22,2,3,1,0) - SUBSTRUCT_CASE(23,3,2,1,0) - } - - return substruct; +static const u8 sSubstructOffsets[4][24] = +{ + [SUBSTRUCT_TYPE_0] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}, + [SUBSTRUCT_TYPE_1] = {1, 1, 2, 2, 3, 3, 0, 0, 2, 2, 3, 3, 0, 0, 1, 1, 3, 3, 0, 0, 1, 1, 2, 2}, + [SUBSTRUCT_TYPE_2] = {2, 3, 1, 3, 1, 2, 2, 3, 0, 3, 0, 2, 1, 3, 0, 3, 0, 1, 1, 2, 0, 2, 0, 1}, + [SUBSTRUCT_TYPE_3] = {3, 2, 3, 1, 2, 1, 3, 2, 3, 0, 2, 0, 3, 1, 3, 0, 1, 0, 2, 1, 2, 0, 1, 0} +}; + +ARM_FUNC NOINLINE static u32 ConstantMod24(u32 a) { return a % 24; } + +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, enum SubstructType substructType) +{ + return &boxMon->secure.substructs[sSubstructOffsets[substructType][ConstantMod24(personality)]]; } /* GameFreak called GetMonData with either 2 or 3 arguments, for type @@ -2337,19 +2306,58 @@ u32 GetMonData2(struct Pokemon *mon, s32 field) return GetMonData3(mon, field, NULL); } -struct EvolutionTrackerBitfield -{ - u16 a: 5; - u16 b: 5; - u16 unused: 6; -}; union EvolutionTracker { - u16 value; - struct EvolutionTrackerBitfield asField; + u16 combinedValue:10; + struct { + u16 tracker1: 5; + u16 tracker2: 5; + }; }; +static ALWAYS_INLINE struct PokemonSubstruct0 *GetSubstruct0(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_0)->type0); +} + +static ALWAYS_INLINE struct PokemonSubstruct1 *GetSubstruct1(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_1)->type1); +} + +static ALWAYS_INLINE struct PokemonSubstruct2 *GetSubstruct2(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_2)->type2); +} + +static ALWAYS_INLINE struct PokemonSubstruct3 *GetSubstruct3(struct BoxPokemon *boxMon) +{ + return &(GetSubstruct(boxMon, boxMon->personality, SUBSTRUCT_TYPE_3)->type3); +} + +static bool32 IsBadEgg(struct BoxPokemon *boxMon) +{ + if (boxMon->isBadEgg) + return TRUE; + + if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + { + boxMon->isBadEgg = TRUE; + boxMon->isEgg = TRUE; + GetSubstruct3(boxMon)->isEgg = TRUE; + + return TRUE; + } + + return FALSE; +} + +static ALWAYS_INLINE bool32 IsEggOrBadEgg(struct BoxPokemon *boxMon) +{ + return GetSubstruct3(boxMon)->isEgg || IsBadEgg(boxMon); +} + /* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type * safety we have a GetBoxMonData macro (in include/pokemon.h) which * dispatches to either GetBoxMonData2 or GetBoxMonData3 based on the @@ -2358,35 +2366,18 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) { s32 i; u32 retVal = 0; - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - union EvolutionTracker evoTracker; // Any field greater than MON_DATA_ENCRYPT_SEPARATOR is encrypted and must be treated as such if (field > MON_DATA_ENCRYPT_SEPARATOR) { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - DecryptBoxMon(boxMon); - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) - { - boxMon->isBadEgg = TRUE; - boxMon->isEgg = TRUE; - substruct3->isEgg = TRUE; - } - switch (field) { case MON_DATA_NICKNAME: case MON_DATA_NICKNAME10: { - if (boxMon->isBadEgg) + if (IsBadEgg(boxMon)) { for (retVal = 0; retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; @@ -2425,6 +2416,7 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) // so if both are 0 we assume that this is a vanilla // Pokémon and replace them with EOS. This means that // two CHAR_SPACE at the end of a nickname are trimmed. + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); if (field != MON_DATA_NICKNAME10 && POKEMON_NAME_LENGTH >= 12) { if (substruct0->nickname11 == 0 && substruct0->nickname12 == 0) @@ -2455,182 +2447,184 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) break; } case MON_DATA_SPECIES: - retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species; + retVal = IsBadEgg(boxMon) ? SPECIES_EGG : GetSubstruct0(boxMon)->species; break; case MON_DATA_HELD_ITEM: - retVal = substruct0->heldItem; + retVal = GetSubstruct0(boxMon)->heldItem; break; case MON_DATA_EXP: - retVal = substruct0->experience; + retVal = GetSubstruct0(boxMon)->experience; break; case MON_DATA_PP_BONUSES: - retVal = substruct0->ppBonuses; + retVal = GetSubstruct0(boxMon)->ppBonuses; break; case MON_DATA_FRIENDSHIP: - retVal = substruct0->friendship; + retVal = GetSubstruct0(boxMon)->friendship; break; case MON_DATA_MOVE1: - retVal = substruct1->move1; + retVal = GetSubstruct1(boxMon)->move1; break; case MON_DATA_MOVE2: - retVal = substruct1->move2; + retVal = GetSubstruct1(boxMon)->move2; break; case MON_DATA_MOVE3: - retVal = substruct1->move3; + retVal = GetSubstruct1(boxMon)->move3; break; case MON_DATA_MOVE4: - retVal = substruct1->move4; + retVal = GetSubstruct1(boxMon)->move4; break; case MON_DATA_PP1: - retVal = substruct1->pp1; + retVal = GetSubstruct1(boxMon)->pp1; break; case MON_DATA_PP2: - retVal = substruct1->pp2; + retVal = GetSubstruct1(boxMon)->pp2; break; case MON_DATA_PP3: - retVal = substruct1->pp3; + retVal = GetSubstruct1(boxMon)->pp3; break; case MON_DATA_PP4: - retVal = substruct1->pp4; + retVal = GetSubstruct1(boxMon)->pp4; break; case MON_DATA_HP_EV: - retVal = substruct2->hpEV; + retVal = GetSubstruct2(boxMon)->hpEV; break; case MON_DATA_ATK_EV: - retVal = substruct2->attackEV; + retVal = GetSubstruct2(boxMon)->attackEV; break; case MON_DATA_DEF_EV: - retVal = substruct2->defenseEV; + retVal = GetSubstruct2(boxMon)->defenseEV; break; case MON_DATA_SPEED_EV: - retVal = substruct2->speedEV; + retVal = GetSubstruct2(boxMon)->speedEV; break; case MON_DATA_SPATK_EV: - retVal = substruct2->spAttackEV; + retVal = GetSubstruct2(boxMon)->spAttackEV; break; case MON_DATA_SPDEF_EV: - retVal = substruct2->spDefenseEV; + retVal = GetSubstruct2(boxMon)->spDefenseEV; break; case MON_DATA_COOL: - retVal = substruct2->cool; + retVal = GetSubstruct2(boxMon)->cool; break; case MON_DATA_BEAUTY: - retVal = substruct2->beauty; + retVal = GetSubstruct2(boxMon)->beauty; break; case MON_DATA_CUTE: - retVal = substruct2->cute; + retVal = GetSubstruct2(boxMon)->cute; break; case MON_DATA_SMART: - retVal = substruct2->smart; + retVal = GetSubstruct2(boxMon)->smart; break; case MON_DATA_TOUGH: - retVal = substruct2->tough; + retVal = GetSubstruct2(boxMon)->tough; break; case MON_DATA_SHEEN: - retVal = substruct2->sheen; + retVal = GetSubstruct2(boxMon)->sheen; break; case MON_DATA_POKERUS: - retVal = substruct3->pokerus; + retVal = GetSubstruct3(boxMon)->pokerus; break; case MON_DATA_MET_LOCATION: - retVal = substruct3->metLocation; + retVal = GetSubstruct3(boxMon)->metLocation; break; case MON_DATA_MET_LEVEL: - retVal = substruct3->metLevel; + retVal = GetSubstruct3(boxMon)->metLevel; break; case MON_DATA_MET_GAME: - retVal = substruct3->metGame; + retVal = GetSubstruct3(boxMon)->metGame; break; case MON_DATA_POKEBALL: - retVal = substruct0->pokeball; + retVal = GetSubstruct0(boxMon)->pokeball; break; case MON_DATA_OT_GENDER: - retVal = substruct3->otGender; + retVal = GetSubstruct3(boxMon)->otGender; break; case MON_DATA_HP_IV: - retVal = substruct3->hpIV; + retVal = GetSubstruct3(boxMon)->hpIV; break; case MON_DATA_ATK_IV: - retVal = substruct3->attackIV; + retVal = GetSubstruct3(boxMon)->attackIV; break; case MON_DATA_DEF_IV: - retVal = substruct3->defenseIV; + retVal = GetSubstruct3(boxMon)->defenseIV; break; case MON_DATA_SPEED_IV: - retVal = substruct3->speedIV; + retVal = GetSubstruct3(boxMon)->speedIV; break; case MON_DATA_SPATK_IV: - retVal = substruct3->spAttackIV; + retVal = GetSubstruct3(boxMon)->spAttackIV; break; case MON_DATA_SPDEF_IV: - retVal = substruct3->spDefenseIV; + retVal = GetSubstruct3(boxMon)->spDefenseIV; break; case MON_DATA_IS_EGG: - retVal = substruct3->isEgg; + retVal = IsEggOrBadEgg(boxMon); break; case MON_DATA_ABILITY_NUM: - retVal = substruct3->abilityNum; + retVal = GetSubstruct3(boxMon)->abilityNum; break; case MON_DATA_COOL_RIBBON: - retVal = substruct3->coolRibbon; + retVal = GetSubstruct3(boxMon)->coolRibbon; break; case MON_DATA_BEAUTY_RIBBON: - retVal = substruct3->beautyRibbon; + retVal = GetSubstruct3(boxMon)->beautyRibbon; break; case MON_DATA_CUTE_RIBBON: - retVal = substruct3->cuteRibbon; + retVal = GetSubstruct3(boxMon)->cuteRibbon; break; case MON_DATA_SMART_RIBBON: - retVal = substruct3->smartRibbon; + retVal = GetSubstruct3(boxMon)->smartRibbon; break; case MON_DATA_TOUGH_RIBBON: - retVal = substruct3->toughRibbon; + retVal = GetSubstruct3(boxMon)->toughRibbon; break; case MON_DATA_CHAMPION_RIBBON: - retVal = substruct3->championRibbon; + retVal = GetSubstruct3(boxMon)->championRibbon; break; case MON_DATA_WINNING_RIBBON: - retVal = substruct3->winningRibbon; + retVal = GetSubstruct3(boxMon)->winningRibbon; break; case MON_DATA_VICTORY_RIBBON: - retVal = substruct3->victoryRibbon; + retVal = GetSubstruct3(boxMon)->victoryRibbon; break; case MON_DATA_ARTIST_RIBBON: - retVal = substruct3->artistRibbon; + retVal = GetSubstruct3(boxMon)->artistRibbon; break; case MON_DATA_EFFORT_RIBBON: - retVal = substruct3->effortRibbon; + retVal = GetSubstruct3(boxMon)->effortRibbon; break; case MON_DATA_MARINE_RIBBON: - retVal = substruct3->marineRibbon; + retVal = GetSubstruct3(boxMon)->marineRibbon; break; case MON_DATA_LAND_RIBBON: - retVal = substruct3->landRibbon; + retVal = GetSubstruct3(boxMon)->landRibbon; break; case MON_DATA_SKY_RIBBON: - retVal = substruct3->skyRibbon; + retVal = GetSubstruct3(boxMon)->skyRibbon; break; case MON_DATA_COUNTRY_RIBBON: - retVal = substruct3->countryRibbon; + retVal = GetSubstruct3(boxMon)->countryRibbon; break; case MON_DATA_NATIONAL_RIBBON: - retVal = substruct3->nationalRibbon; + retVal = GetSubstruct3(boxMon)->nationalRibbon; break; case MON_DATA_EARTH_RIBBON: - retVal = substruct3->earthRibbon; + retVal = GetSubstruct3(boxMon)->earthRibbon; break; case MON_DATA_WORLD_RIBBON: - retVal = substruct3->worldRibbon; + retVal = GetSubstruct3(boxMon)->worldRibbon; break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: - retVal = substruct3->modernFatefulEncounter; + retVal = GetSubstruct3(boxMon)->modernFatefulEncounter; break; case MON_DATA_SPECIES_OR_EGG: - retVal = substruct0->species; - if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg)) + retVal = GetSubstruct0(boxMon)->species; + if (retVal && IsEggOrBadEgg(boxMon)) retVal = SPECIES_EGG; break; case MON_DATA_IVS: + { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) @@ -2638,9 +2632,11 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); break; + } case MON_DATA_KNOWN_MOVES: - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); u16 *moves = (u16 *)data; s32 i = 0; @@ -2657,9 +2653,10 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) } break; case MON_DATA_RIBBON_COUNT: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); + retVal = 0; retVal += substruct3->coolRibbon; retVal += substruct3->beautyRibbon; retVal += substruct3->cuteRibbon; @@ -2680,75 +2677,81 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) } break; case MON_DATA_RIBBONS: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) + if (GetSubstruct0(boxMon)->species && !IsEggOrBadEgg(boxMon)) { + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); retVal = substruct3->championRibbon - | (substruct3->coolRibbon << 1) - | (substruct3->beautyRibbon << 4) - | (substruct3->cuteRibbon << 7) - | (substruct3->smartRibbon << 10) - | (substruct3->toughRibbon << 13) - | (substruct3->winningRibbon << 16) - | (substruct3->victoryRibbon << 17) - | (substruct3->artistRibbon << 18) - | (substruct3->effortRibbon << 19) - | (substruct3->marineRibbon << 20) - | (substruct3->landRibbon << 21) - | (substruct3->skyRibbon << 22) - | (substruct3->countryRibbon << 23) - | (substruct3->nationalRibbon << 24) - | (substruct3->earthRibbon << 25) - | (substruct3->worldRibbon << 26); + | (substruct3->coolRibbon << 1) + | (substruct3->beautyRibbon << 4) + | (substruct3->cuteRibbon << 7) + | (substruct3->smartRibbon << 10) + | (substruct3->toughRibbon << 13) + | (substruct3->winningRibbon << 16) + | (substruct3->victoryRibbon << 17) + | (substruct3->artistRibbon << 18) + | (substruct3->effortRibbon << 19) + | (substruct3->marineRibbon << 20) + | (substruct3->landRibbon << 21) + | (substruct3->skyRibbon << 22) + | (substruct3->countryRibbon << 23) + | (substruct3->nationalRibbon << 24) + | (substruct3->earthRibbon << 25) + | (substruct3->worldRibbon << 26); } break; case MON_DATA_HYPER_TRAINED_HP: - retVal = substruct1->hyperTrainedHP; + retVal = GetSubstruct1(boxMon)->hyperTrainedHP; break; case MON_DATA_HYPER_TRAINED_ATK: - retVal = substruct1->hyperTrainedAttack; + retVal = GetSubstruct1(boxMon)->hyperTrainedAttack; break; case MON_DATA_HYPER_TRAINED_DEF: - retVal = substruct1->hyperTrainedDefense; + retVal = GetSubstruct1(boxMon)->hyperTrainedDefense; break; case MON_DATA_HYPER_TRAINED_SPEED: - retVal = substruct1->hyperTrainedSpeed; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpeed; break; case MON_DATA_HYPER_TRAINED_SPATK: - retVal = substruct1->hyperTrainedSpAttack; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpAttack; break; case MON_DATA_HYPER_TRAINED_SPDEF: - retVal = substruct1->hyperTrainedSpDefense; + retVal = GetSubstruct1(boxMon)->hyperTrainedSpDefense; break; case MON_DATA_IS_SHADOW: - retVal = substruct3->isShadow; + retVal = GetSubstruct3(boxMon)->isShadow; break; case MON_DATA_DYNAMAX_LEVEL: - retVal = substruct3->dynamaxLevel; + retVal = GetSubstruct3(boxMon)->dynamaxLevel; break; case MON_DATA_GIGANTAMAX_FACTOR: - retVal = substruct3->gigantamaxFactor; + retVal = GetSubstruct3(boxMon)->gigantamaxFactor; break; case MON_DATA_TERA_TYPE: - if (gSpeciesInfo[substruct0->species].forceTeraType) - { - retVal = gSpeciesInfo[substruct0->species].forceTeraType; - } - else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality - { - const u8 *types = gSpeciesInfo[substruct0->species].types; - retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; - } - else { - retVal = substruct0->teraType; + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); + if (gSpeciesInfo[substruct0->species].forceTeraType) + { + retVal = gSpeciesInfo[substruct0->species].forceTeraType; + } + else if (substruct0->teraType == TYPE_NONE) // Tera Type hasn't been modified so we can just use the personality + { + const u8 *types = gSpeciesInfo[substruct0->species].types; + retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; + } + else + { + retVal = substruct0->teraType; + } } break; case MON_DATA_EVOLUTION_TRACKER: - evoTracker.asField.a = substruct1->evolutionTracker1; - evoTracker.asField.b = substruct1->evolutionTracker2; - evoTracker.asField.unused = 0; - retVal = evoTracker.value; + { + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); + retVal = (union EvolutionTracker) { + .tracker1 = substruct1->evolutionTracker1, + .tracker2 = substruct1->evolutionTracker2, + }.combinedValue; + } break; default: break; @@ -2898,25 +2901,13 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) { const u8 *data = dataArg; - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - if (field > MON_DATA_ENCRYPT_SEPARATOR) { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - - DecryptBoxMon(boxMon); - - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + if (CalculateBoxMonChecksumDecrypt(boxMon) != boxMon->checksum) { boxMon->isBadEgg = TRUE; boxMon->isEgg = TRUE; - substruct3->isEgg = TRUE; + GetSubstruct3(boxMon)->isEgg = TRUE; EncryptBoxMon(boxMon); return; } @@ -2927,6 +2918,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) case MON_DATA_NICKNAME10: { s32 i; + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); for (i = 0; i < min(sizeof(boxMon->nickname), POKEMON_NAME_LENGTH); i++) boxMon->nickname[i] = data[i]; if (field != MON_DATA_NICKNAME10) @@ -2945,6 +2937,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) } case MON_DATA_SPECIES: { + struct PokemonSubstruct0 *substruct0 = GetSubstruct0(boxMon); SET16(substruct0->species); if (substruct0->species) boxMon->hasSpecies = TRUE; @@ -2953,180 +2946,178 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) break; } case MON_DATA_HELD_ITEM: - SET16(substruct0->heldItem); + SET16(GetSubstruct0(boxMon)->heldItem); break; case MON_DATA_EXP: - SET32(substruct0->experience); + SET32(GetSubstruct0(boxMon)->experience); break; case MON_DATA_PP_BONUSES: - SET8(substruct0->ppBonuses); + SET8(GetSubstruct0(boxMon)->ppBonuses); break; case MON_DATA_FRIENDSHIP: - SET8(substruct0->friendship); + SET8(GetSubstruct0(boxMon)->friendship); break; case MON_DATA_MOVE1: - SET16(substruct1->move1); + SET16(GetSubstruct1(boxMon)->move1); break; case MON_DATA_MOVE2: - SET16(substruct1->move2); + SET16(GetSubstruct1(boxMon)->move2); break; case MON_DATA_MOVE3: - SET16(substruct1->move3); + SET16(GetSubstruct1(boxMon)->move3); break; case MON_DATA_MOVE4: - SET16(substruct1->move4); + SET16(GetSubstruct1(boxMon)->move4); break; case MON_DATA_PP1: - SET8(substruct1->pp1); + SET8(GetSubstruct1(boxMon)->pp1); break; case MON_DATA_PP2: - SET8(substruct1->pp2); + SET8(GetSubstruct1(boxMon)->pp2); break; case MON_DATA_PP3: - SET8(substruct1->pp3); + SET8(GetSubstruct1(boxMon)->pp3); break; case MON_DATA_PP4: - SET8(substruct1->pp4); + SET8(GetSubstruct1(boxMon)->pp4); break; case MON_DATA_HP_EV: - SET8(substruct2->hpEV); + SET8(GetSubstruct2(boxMon)->hpEV); break; case MON_DATA_ATK_EV: - SET8(substruct2->attackEV); + SET8(GetSubstruct2(boxMon)->attackEV); break; case MON_DATA_DEF_EV: - SET8(substruct2->defenseEV); + SET8(GetSubstruct2(boxMon)->defenseEV); break; case MON_DATA_SPEED_EV: - SET8(substruct2->speedEV); + SET8(GetSubstruct2(boxMon)->speedEV); break; case MON_DATA_SPATK_EV: - SET8(substruct2->spAttackEV); + SET8(GetSubstruct2(boxMon)->spAttackEV); break; case MON_DATA_SPDEF_EV: - SET8(substruct2->spDefenseEV); + SET8(GetSubstruct2(boxMon)->spDefenseEV); break; case MON_DATA_COOL: - SET8(substruct2->cool); + SET8(GetSubstruct2(boxMon)->cool); break; case MON_DATA_BEAUTY: - SET8(substruct2->beauty); + SET8(GetSubstruct2(boxMon)->beauty); break; case MON_DATA_CUTE: - SET8(substruct2->cute); + SET8(GetSubstruct2(boxMon)->cute); break; case MON_DATA_SMART: - SET8(substruct2->smart); + SET8(GetSubstruct2(boxMon)->smart); break; case MON_DATA_TOUGH: - SET8(substruct2->tough); + SET8(GetSubstruct2(boxMon)->tough); break; case MON_DATA_SHEEN: - SET8(substruct2->sheen); + SET8(GetSubstruct2(boxMon)->sheen); break; case MON_DATA_POKERUS: - SET8(substruct3->pokerus); + SET8(GetSubstruct3(boxMon)->pokerus); break; case MON_DATA_MET_LOCATION: - SET8(substruct3->metLocation); + SET8(GetSubstruct3(boxMon)->metLocation); break; case MON_DATA_MET_LEVEL: - SET8(substruct3->metLevel); + SET8(GetSubstruct3(boxMon)->metLevel); break; case MON_DATA_MET_GAME: - SET8(substruct3->metGame); + SET8(GetSubstruct3(boxMon)->metGame); break; case MON_DATA_POKEBALL: - SET8(substruct0->pokeball); + SET8(GetSubstruct0(boxMon)->pokeball); break; case MON_DATA_OT_GENDER: - SET8(substruct3->otGender); + SET8(GetSubstruct3(boxMon)->otGender); break; case MON_DATA_HP_IV: - SET8(substruct3->hpIV); + SET8(GetSubstruct3(boxMon)->hpIV); break; case MON_DATA_ATK_IV: - SET8(substruct3->attackIV); + SET8(GetSubstruct3(boxMon)->attackIV); break; case MON_DATA_DEF_IV: - SET8(substruct3->defenseIV); + SET8(GetSubstruct3(boxMon)->defenseIV); break; case MON_DATA_SPEED_IV: - SET8(substruct3->speedIV); + SET8(GetSubstruct3(boxMon)->speedIV); break; case MON_DATA_SPATK_IV: - SET8(substruct3->spAttackIV); + SET8(GetSubstruct3(boxMon)->spAttackIV); break; case MON_DATA_SPDEF_IV: - SET8(substruct3->spDefenseIV); + SET8(GetSubstruct3(boxMon)->spDefenseIV); break; case MON_DATA_IS_EGG: - SET8(substruct3->isEgg); - if (substruct3->isEgg) - boxMon->isEgg = TRUE; - else - boxMon->isEgg = FALSE; + SET8(GetSubstruct3(boxMon)->isEgg); + SET8(boxMon->isEgg); break; case MON_DATA_ABILITY_NUM: - SET8(substruct3->abilityNum); + SET8(GetSubstruct3(boxMon)->abilityNum); break; case MON_DATA_COOL_RIBBON: - SET8(substruct3->coolRibbon); + SET8(GetSubstruct3(boxMon)->coolRibbon); break; case MON_DATA_BEAUTY_RIBBON: - SET8(substruct3->beautyRibbon); + SET8(GetSubstruct3(boxMon)->beautyRibbon); break; case MON_DATA_CUTE_RIBBON: - SET8(substruct3->cuteRibbon); + SET8(GetSubstruct3(boxMon)->cuteRibbon); break; case MON_DATA_SMART_RIBBON: - SET8(substruct3->smartRibbon); + SET8(GetSubstruct3(boxMon)->smartRibbon); break; case MON_DATA_TOUGH_RIBBON: - SET8(substruct3->toughRibbon); + SET8(GetSubstruct3(boxMon)->toughRibbon); break; case MON_DATA_CHAMPION_RIBBON: - SET8(substruct3->championRibbon); + SET8(GetSubstruct3(boxMon)->championRibbon); break; case MON_DATA_WINNING_RIBBON: - SET8(substruct3->winningRibbon); + SET8(GetSubstruct3(boxMon)->winningRibbon); break; case MON_DATA_VICTORY_RIBBON: - SET8(substruct3->victoryRibbon); + SET8(GetSubstruct3(boxMon)->victoryRibbon); break; case MON_DATA_ARTIST_RIBBON: - SET8(substruct3->artistRibbon); + SET8(GetSubstruct3(boxMon)->artistRibbon); break; case MON_DATA_EFFORT_RIBBON: - SET8(substruct3->effortRibbon); + SET8(GetSubstruct3(boxMon)->effortRibbon); break; case MON_DATA_MARINE_RIBBON: - SET8(substruct3->marineRibbon); + SET8(GetSubstruct3(boxMon)->marineRibbon); break; case MON_DATA_LAND_RIBBON: - SET8(substruct3->landRibbon); + SET8(GetSubstruct3(boxMon)->landRibbon); break; case MON_DATA_SKY_RIBBON: - SET8(substruct3->skyRibbon); + SET8(GetSubstruct3(boxMon)->skyRibbon); break; case MON_DATA_COUNTRY_RIBBON: - SET8(substruct3->countryRibbon); + SET8(GetSubstruct3(boxMon)->countryRibbon); break; case MON_DATA_NATIONAL_RIBBON: - SET8(substruct3->nationalRibbon); + SET8(GetSubstruct3(boxMon)->nationalRibbon); break; case MON_DATA_EARTH_RIBBON: - SET8(substruct3->earthRibbon); + SET8(GetSubstruct3(boxMon)->earthRibbon); break; case MON_DATA_WORLD_RIBBON: - SET8(substruct3->worldRibbon); + SET8(GetSubstruct3(boxMon)->worldRibbon); break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: - SET8(substruct3->modernFatefulEncounter); + SET8(GetSubstruct3(boxMon)->modernFatefulEncounter); break; case MON_DATA_IVS: { u32 ivs; + struct PokemonSubstruct3 *substruct3 = GetSubstruct3(boxMon); SET32(ivs); substruct3->hpIV = ivs & MAX_IV_MASK; substruct3->attackIV = (ivs >> 5) & MAX_IV_MASK; @@ -3137,43 +3128,42 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) break; } case MON_DATA_HYPER_TRAINED_HP: - SET8(substruct1->hyperTrainedHP); + SET8(GetSubstruct1(boxMon)->hyperTrainedHP); break; case MON_DATA_HYPER_TRAINED_ATK: - SET8(substruct1->hyperTrainedAttack); + SET8(GetSubstruct1(boxMon)->hyperTrainedAttack); break; case MON_DATA_HYPER_TRAINED_DEF: - SET8(substruct1->hyperTrainedDefense); + SET8(GetSubstruct1(boxMon)->hyperTrainedDefense); break; case MON_DATA_HYPER_TRAINED_SPEED: - SET8(substruct1->hyperTrainedSpeed); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpeed); break; case MON_DATA_HYPER_TRAINED_SPATK: - SET8(substruct1->hyperTrainedSpAttack); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpAttack); break; case MON_DATA_HYPER_TRAINED_SPDEF: - SET8(substruct1->hyperTrainedSpDefense); + SET8(GetSubstruct1(boxMon)->hyperTrainedSpDefense); break; case MON_DATA_IS_SHADOW: - SET8(substruct3->isShadow); + SET8(GetSubstruct3(boxMon)->isShadow); break; case MON_DATA_DYNAMAX_LEVEL: - SET8(substruct3->dynamaxLevel); + SET8(GetSubstruct3(boxMon)->dynamaxLevel); break; case MON_DATA_GIGANTAMAX_FACTOR: - SET8(substruct3->gigantamaxFactor); + SET8(GetSubstruct3(boxMon)->gigantamaxFactor); break; case MON_DATA_TERA_TYPE: - SET8(substruct0->teraType); + SET8(GetSubstruct0(boxMon)->teraType); break; case MON_DATA_EVOLUTION_TRACKER: { union EvolutionTracker evoTracker; - u32 evoTrackerValue; - SET32(evoTrackerValue); - evoTracker.value = evoTrackerValue; - substruct1->evolutionTracker1 = evoTracker.asField.a; - substruct1->evolutionTracker2 = evoTracker.asField.b; + struct PokemonSubstruct1 *substruct1 = GetSubstruct1(boxMon); + SET32(evoTracker.combinedValue); + substruct1->evolutionTracker1 = evoTracker.tracker1; + substruct1->evolutionTracker2 = evoTracker.tracker2; break; } default: @@ -3248,10 +3238,7 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) } if (field > MON_DATA_ENCRYPT_SEPARATOR) - { - boxMon->checksum = CalculateBoxMonChecksum(boxMon); - EncryptBoxMon(boxMon); - } + boxMon->checksum = CalculateBoxMonChecksumReencrypt(boxMon); } void CopyMon(void *dest, void *src, size_t size) @@ -6939,15 +6926,15 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) u32 teraType = GetBoxMonData(boxMon, MON_DATA_TERA_TYPE, NULL); old = *boxMon; - old0 = &(GetSubstruct(&old, old.personality, 0)->type0); - old1 = &(GetSubstruct(&old, old.personality, 1)->type1); - old2 = &(GetSubstruct(&old, old.personality, 2)->type2); - old3 = &(GetSubstruct(&old, old.personality, 3)->type3); + old0 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_0)->type0); + old1 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_1)->type1); + old2 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_2)->type2); + old3 = &(GetSubstruct(&old, old.personality, SUBSTRUCT_TYPE_3)->type3); - new0 = &(GetSubstruct(boxMon, personality, 0)->type0); - new1 = &(GetSubstruct(boxMon, personality, 1)->type1); - new2 = &(GetSubstruct(boxMon, personality, 2)->type2); - new3 = &(GetSubstruct(boxMon, personality, 3)->type3); + new0 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_0)->type0); + new1 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_1)->type1); + new2 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_2)->type2); + new3 = &(GetSubstruct(boxMon, personality, SUBSTRUCT_TYPE_3)->type3); DecryptBoxMon(&old); boxMon->personality = personality; @@ -6955,8 +6942,7 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) *new1 = *old1; *new2 = *old2; *new3 = *old3; - boxMon->checksum = CalculateBoxMonChecksum(boxMon); - EncryptBoxMon(boxMon); + boxMon->checksum = CalculateBoxMonChecksumReencrypt(boxMon); SetBoxMonData(boxMon, MON_DATA_IS_SHINY, &isShiny); SetBoxMonData(boxMon, MON_DATA_HIDDEN_NATURE, &hiddenNature); diff --git a/test/pokemon.c b/test/pokemon.c index 00a4a4485b..c83b42e478 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -450,3 +450,28 @@ TEST("Pokémon level up learnsets fit within MAX_LEVEL_UP_MOVES and MAX_RELEARNE EXPECT_LT(count, MAX_LEVEL_UP_MOVES); EXPECT_LT(count, MAX_RELEARNER_MOVES - 1); // - 1 because at least one move is already known } + +TEST("Optimised GetMonData") +{ + CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 5, 0, FALSE, 0, OT_ID_PRESET, 0x12345678); + u32 exp = 0x123456; + SetMonData(&gPlayerParty[0], MON_DATA_EXP, &exp); + struct Benchmark optimised, + vanilla = (struct Benchmark) { .ticks = 137 }; // From prior testing + u32 expGet = 0; + BENCHMARK(&optimised) { expGet = GetMonData(&gPlayerParty[0], MON_DATA_EXP); } + EXPECT_EQ(exp, expGet); + EXPECT_FASTER(optimised, vanilla); +} + +TEST("Optimised SetMonData") +{ + CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 5, 0, FALSE, 0, OT_ID_PRESET, 0x12345678); + u32 exp = 0x123456; + struct Benchmark optimised, + vanilla = (struct Benchmark) { .ticks = 205 }; // From prior testing + BENCHMARK(&optimised) { SetMonData(&gPlayerParty[0], MON_DATA_EXP, &exp); } + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_BAD_EGG), FALSE); + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_EXP), exp); + EXPECT_FASTER(optimised, vanilla); +} From 7b2fe32050c72bf00a9cce96a6ec2bcd15e1c4a2 Mon Sep 17 00:00:00 2001 From: surskitty Date: Mon, 28 Jul 2025 07:11:04 -0400 Subject: [PATCH 139/283] Make B_VAR_STARTING_STATUS tests run in CI (#7419) --- include/config/test.h | 4 ++++ include/constants/vars.h | 18 +++++++++--------- test/battle/starting_status/terrain.c | 27 ++++++++++++++------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/config/test.h b/include/config/test.h index 6122d14aa1..9e880d57c7 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1132,6 +1132,10 @@ // Vars #undef B_VAR_DIFFICULTY #define B_VAR_DIFFICULTY TESTING_VAR_DIFFICULTY +#undef B_VAR_STARTING_STATUS +#define B_VAR_STARTING_STATUS TESTING_VAR_STARTING_STATUS +#undef B_VAR_STARTING_STATUS_TIMER +#define B_VAR_STARTING_STATUS_TIMER TESTING_VAR_STARTING_STATUS_TIMER // Flags #undef B_FLAG_SLEEP_CLAUSE diff --git a/include/constants/vars.h b/include/constants/vars.h index aac52dec0e..a12c2ff3a5 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -325,15 +325,15 @@ #define VAR_TEMP_TRANSFERRED_SPECIES VAR_TEMP_1 #if TESTING -#define TESTING_VARS_START 0x9000 -#define TESTING_VAR_DIFFICULTY (TESTING_VARS_START + 0x0) -#define TESTING_VAR_UNUSED_1 (TESTING_VARS_START + 0x1) -#define TESTING_VAR_UNUSED_2 (TESTING_VARS_START + 0x2) -#define TESTING_VAR_UNUSED_3 (TESTING_VARS_START + 0x3) -#define TESTING_VAR_UNUSED_4 (TESTING_VARS_START + 0x4) -#define TESTING_VAR_UNUSED_5 (TESTING_VARS_START + 0x5) -#define TESTING_VAR_UNUSED_6 (TESTING_VARS_START + 0x6) -#define TESTING_VAR_UNUSED_7 (TESTING_VARS_START + 0x7) +#define TESTING_VARS_START 0x9000 +#define TESTING_VAR_DIFFICULTY (TESTING_VARS_START + 0x0) +#define TESTING_VAR_STARTING_STATUS (TESTING_VARS_START + 0x1) +#define TESTING_VAR_STARTING_STATUS_TIMER (TESTING_VARS_START + 0x2) +#define TESTING_VAR_UNUSED_3 (TESTING_VARS_START + 0x3) +#define TESTING_VAR_UNUSED_4 (TESTING_VARS_START + 0x4) +#define TESTING_VAR_UNUSED_5 (TESTING_VARS_START + 0x5) +#define TESTING_VAR_UNUSED_6 (TESTING_VARS_START + 0x6) +#define TESTING_VAR_UNUSED_7 (TESTING_VARS_START + 0x7) #endif // TESTING #endif // GUARD_CONSTANTS_VARS_H diff --git a/test/battle/starting_status/terrain.c b/test/battle/starting_status/terrain.c index ab31bbbb96..3d84dba000 100644 --- a/test/battle/starting_status/terrain.c +++ b/test/battle/starting_status/terrain.c @@ -29,19 +29,20 @@ SINGLE_BATTLE_TEST("B_VAR_STARTING_STATUS starts a chosen terrain at the beginni TURN { ; } TURN { ; } } SCENE { - switch (terrain) { - case STARTING_STATUS_GRASSY_TERRAIN: - MESSAGE("Grass grew to cover the battlefield!"); - break; - case STARTING_STATUS_PSYCHIC_TERRAIN: - MESSAGE("The battlefield got weird!"); - break; - case STARTING_STATUS_MISTY_TERRAIN: - MESSAGE("Mist swirled around the battlefield!"); - break; - case STARTING_STATUS_ELECTRIC_TERRAIN: - MESSAGE("An electric current is running across the battlefield!"); - break; + switch (terrain) + { + case STARTING_STATUS_GRASSY_TERRAIN: + MESSAGE("The battlefield is covered with grass!"); + break; + case STARTING_STATUS_PSYCHIC_TERRAIN: + MESSAGE("The battlefield seems weird!"); + break; + case STARTING_STATUS_MISTY_TERRAIN: + MESSAGE("Mist swirls around the battlefield!"); + break; + case STARTING_STATUS_ELECTRIC_TERRAIN: + MESSAGE("An electric current is running across the battlefield!"); + break; } ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG); NONE_OF { From 95e45b5568e8692d770ccd8258bb02174ad60058 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 28 Jul 2025 08:10:03 -0400 Subject: [PATCH 140/283] Fix Echoing Voice calcs (#7416) --- src/battle_util.c | 2 +- test/battle/ai/ai_switching.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index b5e68f9cbd..7c9ff8d03e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8219,7 +8219,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData } case EFFECT_ECHOED_VOICE: // gBattleStruct->sameMoveTurns incremented in ppreduce - if (gBattleStruct->sameMoveTurns[battlerAtk] != 0) + if (gBattleStruct->sameMoveTurns[battlerAtk] != 0 && GetMoveEffect(gLastResultingMoves[battlerAtk]) == EFFECT_ECHOED_VOICE) { basePower += (basePower * gBattleStruct->sameMoveTurns[battlerAtk]); if (basePower > 200) diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 0c9e94695e..03334e04c2 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1268,3 +1268,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as los TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI sees Echoed Voice damage correctly") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Speed(5); Moves(MOVE_SCRATCH, MOVE_ECHOED_VOICE); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(4); Level(55); Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_DRAPION) { Speed(4); SpDefense(25); Moves(MOVE_WICKED_BLOW); Ability(ABILITY_SNIPER); } + OPPONENT(SPECIES_GASTLY) { Speed(4); Level(1); Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); EXPECT_SEND_OUT(opponent, 1); } + } +} From 1fbee7cce015163786581e3885b943a42c10ead3 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Mon, 28 Jul 2025 13:10:34 +0100 Subject: [PATCH 141/283] fixed-damage-move-ai-calc-fix (#7385) --- include/battle_util.h | 1 + src/battle_ai_util.c | 7 ++++++- src/battle_util.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index b9566e2512..272ccf3d1e 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -280,6 +280,7 @@ u32 CalcRolloutBasePower(u32 battlerAtk, u32 basePower, u32 rolloutTimer); u32 CalcFuryCutterBasePower(u32 basePower, u32 furyCutterCounter); s32 CalculateMoveDamage(struct DamageContext *ctx); s32 CalculateMoveDamageVars(struct DamageContext *ctx); +s32 DoFixedDamageMoveCalc(struct DamageContext *ctx); s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg); uq4_12_t CalcTypeEffectivenessMultiplier(struct DamageContext *ctx); uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 4443aa1f59..dc766c9ee8 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -893,7 +893,12 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u AI_StoreBattlerTypes(battlerAtk, types); ProteanTryChangeType(battlerAtk, aiData->abilities[battlerAtk], move, ctx.moveType); - if (moveEffect == EFFECT_TRIPLE_KICK) + s32 fixedDamage = DoFixedDamageMoveCalc(&ctx); + if (fixedDamage != INT32_MAX) + { + simDamage.minimum = simDamage.median = simDamage.maximum = fixedDamage; + } + else if (moveEffect == EFFECT_TRIPLE_KICK) { for (gMultiHitCounter = GetMoveStrikeCount(move); gMultiHitCounter > 0; gMultiHitCounter--) // The global is used to simulate actual damage done { diff --git a/src/battle_util.c b/src/battle_util.c index 1346b9f0da..1c7a2b7073 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9392,7 +9392,7 @@ s32 ApplyModifiersAfterDmgRoll(struct DamageContext *ctx, s32 dmg) return dmg; } -static inline s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) +s32 DoFixedDamageMoveCalc(struct DamageContext *ctx) { s32 dmg = 0; s32 randDamage; From 8bfc5b3093b457548ccf3afda4479ee5425ea3de Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 28 Jul 2025 13:21:12 +0100 Subject: [PATCH 142/283] Fixes Razor Wind not activating after hit effects after the first target (#7413) --- data/battle_scripts_1.s | 1 + test/battle/move_effect/two_turns_attack.c | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4db067a4b9..31835383dd 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3529,6 +3529,7 @@ BattleScript_PowerHerbActivation: BattleScript_EffectTwoTurnsAttack:: jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_EffectHit @ if it's not the first hit tryfiretwoturnmovewithoutcharging BS_ATTACKER, BattleScript_EffectHit @ e.g. Solar Beam call BattleScript_FirstChargingTurn tryfiretwoturnmoveaftercharging BS_ATTACKER, BattleScript_TwoTurnMovesSecondTurn @ e.g. Electro Shot diff --git a/test/battle/move_effect/two_turns_attack.c b/test/battle/move_effect/two_turns_attack.c index 4dd79ade46..661a45c110 100644 --- a/test/battle/move_effect/two_turns_attack.c +++ b/test/battle/move_effect/two_turns_attack.c @@ -67,6 +67,36 @@ SINGLE_BATTLE_TEST("Razor Wind doesn't need to charge with Power Herb") } } +DOUBLE_BATTLE_TEST("Razor Wind successfully KOs both opponents") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WYNAUT) { HP(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_RAZOR_WIND); } + } SCENE { + if (B_UPDATED_MOVE_DATA >= GEN_5) { + NOT MESSAGE("Wobbuffet whipped up a whirlwind!"); + MESSAGE("Wobbuffet used Razor Wind!"); + } else + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + if (B_UPDATED_MOVE_DATA < GEN_5) + MESSAGE("Wobbuffet whipped up a whirlwind!"); + else + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet became fully charged due to its Power Herb!"); + if (B_UPDATED_MOVE_DATA < GEN_5) + MESSAGE("Wobbuffet used Razor Wind!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + HP_BAR(opponentLeft); + MESSAGE("The opposing Wobbuffet fainted!"); + MESSAGE("The opposing Wynaut fainted!"); + } +} + SINGLE_BATTLE_TEST("Skull Bash needs a charging turn") { GIVEN { From 689bf0bcbc090ebc733216ebc9309706a67bb483 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Tue, 29 Jul 2025 11:28:12 +0300 Subject: [PATCH 143/283] Fixed item swapping bug (#7428) (#7430) --- src/item.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/item.c b/src/item.c index b25f38b058..4e7e514938 100644 --- a/src/item.c +++ b/src/item.c @@ -567,7 +567,7 @@ static inline void NONNULL BagPocket_MoveItemSlot(struct BagPocket *pocket, u32 BagPocket_GetSlotData(pocket, from, &fromItemId, &fromQuantity); // Shuffle items between "to" and "from" - for (u32 i = from; i == to - shift; i += shift) + for (u32 i = from; i != to; i += shift) { BagPocket_GetSlotData(pocket, i + shift, &tempItemId, &tempQuantity); BagPocket_SetSlotData(pocket, i, &tempItemId, &tempQuantity); From 2eeb346387f64fe2e6e414f71de12fb06e0ef7e1 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Tue, 29 Jul 2025 11:47:32 +0300 Subject: [PATCH 144/283] Bag refactor3 + Ghoulslash's sorting feature port (#7330) --- include/constants/item.h | 3 +- include/item.h | 72 ++++- include/item_menu.h | 12 +- src/data/items.h | 550 +++++++++++++++++++++++++++++++++++++++ src/item.c | 230 +++++++--------- src/item_menu.c | 397 ++++++++++++++++++++++++++-- src/menu_helpers.c | 3 +- test/bag.c | 49 +++- 8 files changed, 1133 insertions(+), 183 deletions(-) diff --git a/include/constants/item.h b/include/constants/item.h index bd35bdb861..2d8c3f9419 100644 --- a/include/constants/item.h +++ b/include/constants/item.h @@ -9,10 +9,9 @@ enum Pocket POCKET_BERRIES, POCKET_KEY_ITEMS, POCKETS_COUNT, + POCKET_DUMMY = POCKETS_COUNT, }; -#define POCKET_DUMMY POCKETS_COUNT - #define REPEL_LURE_MASK (1 << 15) #define IS_LAST_USED_LURE(var) (var & REPEL_LURE_MASK) #define REPEL_LURE_STEPS(var) (var & (REPEL_LURE_MASK - 1)) diff --git a/include/item.h b/include/item.h index 5622786c91..9cecce661a 100644 --- a/include/item.h +++ b/include/item.h @@ -44,6 +44,46 @@ enum TMHMIndex #undef UNPACK_TM_HM_ENUM +enum PACKED ItemSortType +{ + ITEM_TYPE_UNCATEGORIZED, + ITEM_TYPE_FIELD_USE, + ITEM_TYPE_LEVEL_UP_ITEM, + ITEM_TYPE_HEALTH_RECOVERY, + ITEM_TYPE_STATUS_RECOVERY, + ITEM_TYPE_PP_RECOVERY, + ITEM_TYPE_NATURE_MINT, + ITEM_TYPE_STAT_BOOST_DRINK, + ITEM_TYPE_STAT_BOOST_FEATHER, + ITEM_TYPE_STAT_BOOST_MOCHI, + ITEM_TYPE_BATTLE_ITEM, + ITEM_TYPE_FLUTE, + ITEM_TYPE_X_ITEM, + ITEM_TYPE_AUX_ITEM, + ITEM_TYPE_EVOLUTION_STONE, + ITEM_TYPE_EVOLUTION_ITEM, + ITEM_TYPE_SPECIAL_HELD_ITEM, + ITEM_TYPE_MEGA_STONE, + ITEM_TYPE_Z_CRYSTAL, + ITEM_TYPE_TERA_SHARD, + ITEM_TYPE_HELD_ITEM, + ITEM_TYPE_TYPE_BOOST_HELD_ITEM, + ITEM_TYPE_CONTEST_HELD_ITEM, + ITEM_TYPE_EV_BOOST_HELD_ITEM, + ITEM_TYPE_GEM, + ITEM_TYPE_PLATE, + ITEM_TYPE_MEMORY, + ITEM_TYPE_DRIVE, + ITEM_TYPE_INCENSE, + ITEM_TYPE_NECTAR, + ITEM_TYPE_GROWTH, + ITEM_TYPE_SHARD, + ITEM_TYPE_SELLABLE, + ITEM_TYPE_RELIC, + ITEM_TYPE_FOSSIL, + ITEM_TYPE_MAIL, +}; + typedef void (*ItemUseFunc)(u8); struct Item @@ -60,7 +100,7 @@ struct Item u8 importance:2; u8 notConsumed:1; enum Pocket pocket:5; - u8 padding; + enum ItemSortType sortType; u8 type; u8 battleUsage; u8 flingPower; @@ -139,16 +179,29 @@ static inline u16 GetTMHMMoveId(enum TMHMIndex index) return gTMHMItemMoveIds[index].moveId; } -enum SortPocket +void BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot); +struct ItemSlot BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos); + +static inline void BagPocket_SetSlotItemIdAndCount(struct BagPocket *pocket, u32 pocketPos, u16 itemId, u16 quantity) +{ + BagPocket_SetSlotData(pocket, pocketPos, (struct ItemSlot) {itemId, quantity}); +} + +static inline u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos) { - SORT_NONE, - SORT_POCKET_BY_ITEM_ID, - SORT_POCKET_TM_HM, -}; + return BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos).itemId; +} + +static inline u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos) +{ + return BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos).quantity; +} + +static inline struct ItemSlot GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos) +{ + return BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos); +} -void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity); -u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos); -u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos); void ApplyNewEncryptionKeyToBagItems(u32 newKey); void SetBagItemsPointers(void); u8 *CopyItemName(u16 itemId, u8 *dst); @@ -168,7 +221,6 @@ void RemovePCItem(u8 index, u16 count); void CompactPCItems(void); void SwapRegisteredBike(void); void CompactItemsInBagPocket(enum Pocket pocketId); -void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket); void MoveItemSlotInPocket(enum Pocket pocketId, u32 from, u32 to); void MoveItemSlotInPC(struct ItemSlot *itemSlots, u32 from, u32 to); void ClearBag(void); diff --git a/include/item_menu.h b/include/item_menu.h index 84137da1de..64d9f7628e 100644 --- a/include/item_menu.h +++ b/include/item_menu.h @@ -36,6 +36,15 @@ enum { ITEMWIN_COUNT }; +//bag sort +enum BagSortOptions +{ + SORT_ALPHABETICALLY, + SORT_BY_TYPE, + SORT_BY_AMOUNT, //greatest->least + SORT_BY_INDEX, +}; + #define ITEMMENU_SWAP_LINE_LENGTH 8 // Swap line is 8 sprites long enum { ITEMMENUSPRITE_BAG, @@ -105,10 +114,11 @@ void CB2_ChooseBerry(void); void CB2_ChooseMulch(void); void Task_FadeAndCloseBagMenu(u8 taskId); void BagMenu_YesNo(u8 taskId, u8 windowType, const struct YesNoFuncTable *funcTable); -void UpdatePocketItemList(u8 pocketId); +void UpdatePocketItemList(enum Pocket pocketId); void DisplayItemMessage(u8 taskId, u8 fontId, const u8 *str, void (*callback)(u8 taskId)); void DisplayItemMessageOnField(u8 taskId, const u8 *string, TaskFunc callback); void CloseItemMessage(u8 taskId); void ItemMenu_RotomCatalog(u8 taskId); +void SortItemsInBag(struct BagPocket *pocket, enum BagSortOptions type); #endif //GUARD_ITEM_MENU_H diff --git a/src/data/items.h b/src/data/items.h index d1d7ae3125..1a39f409b5 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -146,6 +146,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_QuestionMark, @@ -617,6 +618,7 @@ const struct Item gItemsInfo[] = "a Pokémon by\n" "20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -640,6 +642,7 @@ const struct Item gItemsInfo[] = "50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -663,6 +666,7 @@ const struct Item gItemsInfo[] = "200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -681,6 +685,7 @@ const struct Item gItemsInfo[] = "Fully restores the\n" "HP of a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -700,6 +705,7 @@ const struct Item gItemsInfo[] = "HP and status of a\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_HEAL_AND_CURE_STATUS, @@ -718,6 +724,7 @@ const struct Item gItemsInfo[] = "Pokémon with half\n" "its HP."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -733,6 +740,7 @@ const struct Item gItemsInfo[] = .price = 4000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -756,6 +764,7 @@ const struct Item gItemsInfo[] = "by 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -779,6 +788,7 @@ const struct Item gItemsInfo[] = "by 60 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -805,6 +815,7 @@ const struct Item gItemsInfo[] = "by 80 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -825,6 +836,7 @@ const struct Item gItemsInfo[] = "that restores HP\n" "by 100 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -848,6 +860,7 @@ const struct Item gItemsInfo[] = "by 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -870,6 +883,7 @@ const struct Item gItemsInfo[] = "by 200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -889,6 +903,7 @@ const struct Item gItemsInfo[] = "that heals all\n" "status problems."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -907,6 +922,7 @@ const struct Item gItemsInfo[] = "that revives a\n" "fainted Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -924,6 +940,7 @@ const struct Item gItemsInfo[] = "Heals a poisoned\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -941,6 +958,7 @@ const struct Item gItemsInfo[] = "Heals a paralyzed\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -958,6 +976,7 @@ const struct Item gItemsInfo[] = "Heals Pokémon\n" "of a burn."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -975,6 +994,7 @@ const struct Item gItemsInfo[] = "Defrosts a frozen\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -992,6 +1012,7 @@ const struct Item gItemsInfo[] = "Awakens a sleeping\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1007,6 +1028,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 400 : 600, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1026,6 +1048,7 @@ const struct Item gItemsInfo[] = "of a selected move\n" "by 10."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1045,6 +1068,7 @@ const struct Item gItemsInfo[] = "PP of a selected\n" "move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1063,6 +1087,7 @@ const struct Item gItemsInfo[] = "Restores the PP\n" "of all moves by 10."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1082,6 +1107,7 @@ const struct Item gItemsInfo[] = "PP of a Pokémon's\n" "moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PP_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, .battleUsage = EFFECT_ITEM_RESTORE_PP, @@ -1103,6 +1129,7 @@ const struct Item gItemsInfo[] = "that restores HP\n" "by 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1122,6 +1149,7 @@ const struct Item gItemsInfo[] = "restores all\n" "fainted Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_SacredAsh, .effect = gItemEffect_SacredAsh, @@ -1140,6 +1168,7 @@ const struct Item gItemsInfo[] = "that restores HP\n" "by 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -1156,6 +1185,7 @@ const struct Item gItemsInfo[] = .price = 8000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_REVIVE, @@ -1174,6 +1204,7 @@ const struct Item gItemsInfo[] = .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1189,6 +1220,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 300, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1207,6 +1239,7 @@ const struct Item gItemsInfo[] = "that heals all\n" "status problems."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1223,6 +1256,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1238,6 +1272,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 100, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1253,6 +1288,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1268,6 +1304,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1283,6 +1320,7 @@ const struct Item gItemsInfo[] = .price = 350, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -1302,6 +1340,7 @@ const struct Item gItemsInfo[] = "Raises the base HP\n" "of one Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HPUp, @@ -1319,6 +1358,7 @@ const struct Item gItemsInfo[] = "Attack stat of one\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Protein, @@ -1336,6 +1376,7 @@ const struct Item gItemsInfo[] = "Defense stat of\n" "one Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Iron, @@ -1353,6 +1394,7 @@ const struct Item gItemsInfo[] = "Sp. Atk stat of one\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Calcium, @@ -1370,6 +1412,7 @@ const struct Item gItemsInfo[] = "Sp. Def stat of one\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Zinc, @@ -1388,6 +1431,7 @@ const struct Item gItemsInfo[] = "Speed stat of one\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_Carbos, @@ -1405,6 +1449,7 @@ const struct Item gItemsInfo[] = "PP of a selected\n" "move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPUp, @@ -1423,6 +1468,7 @@ const struct Item gItemsInfo[] = "move to its maximum\n" "points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_DRINK, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPUp, .effect = gItemEffect_PPMax, @@ -1439,6 +1485,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpFeather, @@ -1453,6 +1500,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkFeather, @@ -1467,6 +1515,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefFeather, @@ -1481,6 +1530,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkFeather, @@ -1495,6 +1545,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefFeather, @@ -1509,6 +1560,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_FEATHER, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedFeather, @@ -1528,6 +1580,7 @@ const struct Item gItemsInfo[] = "Switches a Poké-\n" "mon's ability."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityCapsule, .iconPic = gItemIcon_AbilityCapsule, @@ -1545,6 +1598,7 @@ const struct Item gItemsInfo[] = "of a Pokémon into\n" "a rare ability."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_AbilityPatch, .iconPic = gItemIcon_AbilityPatch, @@ -1562,6 +1616,7 @@ const struct Item gItemsInfo[] = "ups Attack, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LONELY, @@ -1579,6 +1634,7 @@ const struct Item gItemsInfo[] = "ups Attack, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_ADAMANT, @@ -1596,6 +1652,7 @@ const struct Item gItemsInfo[] = "ups Attack, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAUGHTY, @@ -1613,6 +1670,7 @@ const struct Item gItemsInfo[] = "ups Attack, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BRAVE, @@ -1630,6 +1688,7 @@ const struct Item gItemsInfo[] = "ups Defense, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_BOLD, @@ -1647,6 +1706,7 @@ const struct Item gItemsInfo[] = "ups Defense, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_IMPISH, @@ -1664,6 +1724,7 @@ const struct Item gItemsInfo[] = "ups Defense, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_LAX, @@ -1681,6 +1742,7 @@ const struct Item gItemsInfo[] = "ups Defense, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RELAXED, @@ -1698,6 +1760,7 @@ const struct Item gItemsInfo[] = "ups Sp. Atk, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MODEST, @@ -1715,6 +1778,7 @@ const struct Item gItemsInfo[] = "ups Sp. Atk, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_MILD, @@ -1732,6 +1796,7 @@ const struct Item gItemsInfo[] = "ups Sp. Atk, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_RASH, @@ -1749,6 +1814,7 @@ const struct Item gItemsInfo[] = "ups Sp. Atk, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_QUIET, @@ -1766,6 +1832,7 @@ const struct Item gItemsInfo[] = "ups Sp. Def, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CALM, @@ -1783,6 +1850,7 @@ const struct Item gItemsInfo[] = "ups Sp. Def, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_GENTLE, @@ -1800,6 +1868,7 @@ const struct Item gItemsInfo[] = "ups Sp. Def, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_CAREFUL, @@ -1817,6 +1886,7 @@ const struct Item gItemsInfo[] = "ups Sp. Def, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SASSY, @@ -1834,6 +1904,7 @@ const struct Item gItemsInfo[] = "ups Speed, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_TIMID, @@ -1851,6 +1922,7 @@ const struct Item gItemsInfo[] = "ups Speed, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_HASTY, @@ -1868,6 +1940,7 @@ const struct Item gItemsInfo[] = "ups Speed, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_JOLLY, @@ -1885,6 +1958,7 @@ const struct Item gItemsInfo[] = "ups Speed, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_NAIVE, @@ -1902,6 +1976,7 @@ const struct Item gItemsInfo[] = "makes each stat\n" "grow equally."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NATURE_MINT, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Mint, .secondaryId = NATURE_SERIOUS, @@ -1922,6 +1997,7 @@ const struct Item gItemsInfo[] = "of a Pokémon by\n" "one."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1941,6 +2017,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to\n" "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1960,6 +2037,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to\n" "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1979,6 +2057,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to\n" "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -1998,6 +2077,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to\n" "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -2017,6 +2097,7 @@ const struct Item gItemsInfo[] = "amount of Exp. to\n" "a single Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_RareCandy, .effect = gItemEffect_RareCandy, @@ -2035,6 +2116,7 @@ const struct Item gItemsInfo[] = "Level of a single\n" "Pokémon by one."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_LEVEL_UP_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_DynamaxCandy, .flingPower = 30, @@ -2054,6 +2136,7 @@ const struct Item gItemsInfo[] = "Pokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2073,6 +2156,7 @@ const struct Item gItemsInfo[] = "out of confusion."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2092,6 +2176,7 @@ const struct Item gItemsInfo[] = "out of attraction."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -2114,6 +2199,7 @@ const struct Item gItemsInfo[] = "Pokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2131,6 +2217,7 @@ const struct Item gItemsInfo[] = "lures wild Pokémon."), .notConsumed = TRUE, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FLUTE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_BlackWhiteFlute, .flingPower = 30, @@ -2150,6 +2237,7 @@ const struct Item gItemsInfo[] = "Pokémon for 100\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2167,6 +2255,7 @@ const struct Item gItemsInfo[] = "Pokémon for 200\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2184,6 +2273,7 @@ const struct Item gItemsInfo[] = "Pokémon for 250\n" "steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Repel, .flingPower = 30, @@ -2201,6 +2291,7 @@ const struct Item gItemsInfo[] = "likely to appear\n" "for 100 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2219,6 +2310,7 @@ const struct Item gItemsInfo[] = "likely to appear\n" "for 200 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2237,6 +2329,7 @@ const struct Item gItemsInfo[] = "likely to appear\n" "for 250 steps."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_Lure, .secondaryId = 0, @@ -2259,6 +2352,7 @@ const struct Item gItemsInfo[] = #else .price = (I_PRICE >= GEN_7) ? 1000 : 550, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FIELD_USE, #endif .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_EscapeRope, @@ -2285,6 +2379,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2310,6 +2405,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2335,6 +2431,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2360,6 +2457,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2385,6 +2483,7 @@ const struct Item gItemsInfo[] = "battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2411,6 +2510,7 @@ const struct Item gItemsInfo[] = "during one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_STAT, @@ -2429,6 +2529,7 @@ const struct Item gItemsInfo[] = "critical-hit ratio\n" "during one battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_FOCUS_ENERGY, @@ -2448,6 +2549,7 @@ const struct Item gItemsInfo[] = "reduction when\n" "used in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_X_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_SET_MIST, @@ -2463,6 +2565,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE == GEN_7) ? 100 : 300), .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2477,6 +2580,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2491,6 +2595,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_ESCAPE, @@ -2509,6 +2614,7 @@ const struct Item gItemsInfo[] = "during one battle\n" "by one stage."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_BATTLE_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .battleUsage = EFFECT_ITEM_INCREASE_ALL_STATS, @@ -2528,6 +2634,7 @@ const struct Item gItemsInfo[] = "cap that gives off\n" "a silver gleam."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2544,6 +2651,7 @@ const struct Item gItemsInfo[] = "cap that gives off\n" "a golden gleam."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2560,6 +2668,7 @@ const struct Item gItemsInfo[] = "gold. Can be sold at\n" "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2576,6 +2685,7 @@ const struct Item gItemsInfo[] = "of gold, sellable\n" "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -2592,6 +2702,7 @@ const struct Item gItemsInfo[] = "that would sell\n" "at a cheap price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2605,6 +2716,7 @@ const struct Item gItemsInfo[] = .price = 5000 * TREASURE_FACTOR, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2618,6 +2730,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 15000 * TREASURE_FACTOR: 12500, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2634,6 +2747,7 @@ const struct Item gItemsInfo[] = "that would sell at a\n" "cheap price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2650,6 +2764,7 @@ const struct Item gItemsInfo[] = "that would sell at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2666,6 +2781,7 @@ const struct Item gItemsInfo[] = "that would sell at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2683,6 +2799,7 @@ const struct Item gItemsInfo[] = "Can be sold at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2699,6 +2816,7 @@ const struct Item gItemsInfo[] = "It would sell for a\n" "very high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2715,6 +2833,7 @@ const struct Item gItemsInfo[] = "It would sell for a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2732,6 +2851,7 @@ const struct Item gItemsInfo[] = "deep inside the\n" "Shoal Cave."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2748,6 +2868,7 @@ const struct Item gItemsInfo[] = "deep inside the\n" "Shoal Cave."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2761,6 +2882,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2774,6 +2896,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2787,6 +2910,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2800,6 +2924,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2816,6 +2941,7 @@ const struct Item gItemsInfo[] = "It is coveted by\n" "collectors."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2833,6 +2959,7 @@ const struct Item gItemsInfo[] = "attracts wild\n" "Pokémon when used."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_Honey, .flingPower = 30, @@ -2849,6 +2976,7 @@ const struct Item gItemsInfo[] = "It can be sold at\n" "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -2865,6 +2993,7 @@ const struct Item gItemsInfo[] = "from this odd stone\n" "occasionally."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -2881,6 +3010,7 @@ const struct Item gItemsInfo[] = "plain feather that\n" "does nothing."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 20, @@ -2897,6 +3027,7 @@ const struct Item gItemsInfo[] = "long ago. It sells\n" "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2913,6 +3044,7 @@ const struct Item gItemsInfo[] = "long ago. It sells\n" "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2929,6 +3061,7 @@ const struct Item gItemsInfo[] = "long ago. It sells\n" "at a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2945,6 +3078,7 @@ const struct Item gItemsInfo[] = "ago. It sells at\n" "a high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2961,6 +3095,7 @@ const struct Item gItemsInfo[] = "It sells at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2977,6 +3112,7 @@ const struct Item gItemsInfo[] = "It sells at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -2993,6 +3129,7 @@ const struct Item gItemsInfo[] = "It sells at a\n" "high price."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3009,6 +3146,7 @@ const struct Item gItemsInfo[] = "depicts a Pokémon\n" "from Alola."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_RELIC, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3028,6 +3166,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3050,6 +3189,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3072,6 +3212,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3091,6 +3232,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3110,6 +3252,7 @@ const struct Item gItemsInfo[] = #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, #else .price = 0, .importance = 1, @@ -3131,6 +3274,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's head."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3147,6 +3291,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's collar."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3163,6 +3308,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's back."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3179,6 +3325,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's wing."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3195,6 +3342,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's large jaw."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3211,6 +3359,7 @@ const struct Item gItemsInfo[] = "prehistoric Poké-\n" "mon's skin sail."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3227,6 +3376,7 @@ const struct Item gItemsInfo[] = "ancient, sky-\n" "soaring Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3241,6 +3391,7 @@ const struct Item gItemsInfo[] = .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3257,6 +3408,7 @@ const struct Item gItemsInfo[] = "ancient, land-\n" "roaming Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3270,6 +3422,7 @@ const struct Item gItemsInfo[] = .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_FOSSIL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -3293,6 +3446,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GROWTH_MULCH), @@ -3315,6 +3469,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_DAMP_MULCH), @@ -3337,6 +3492,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_STABLE_MULCH), @@ -3359,6 +3515,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_GOOEY_MULCH), @@ -3381,6 +3538,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_RICH_MULCH), @@ -3403,6 +3561,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_SURPRISE_MULCH), @@ -3425,6 +3584,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_BOOST_MULCH), @@ -3447,6 +3607,7 @@ const struct Item gItemsInfo[] = .description = sGenericMulchDesc, #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = ITEM_TO_MULCH(ITEM_AMAZE_MULCH), @@ -3466,6 +3627,7 @@ const struct Item gItemsInfo[] = "It assails your\n" "nostrils."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedApricorn, @@ -3481,6 +3643,7 @@ const struct Item gItemsInfo[] = "It smells a bit\n" "like grass."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueApricorn, @@ -3496,6 +3659,7 @@ const struct Item gItemsInfo[] = "It has an invigor-\n" "ating scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_YellowApricorn, @@ -3511,6 +3675,7 @@ const struct Item gItemsInfo[] = "It has a strange,\n" "aromatic scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GreenApricorn, @@ -3526,6 +3691,7 @@ const struct Item gItemsInfo[] = "It has a nice,\n" "sweet scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PinkApricorn, @@ -3541,6 +3707,7 @@ const struct Item gItemsInfo[] = "It doesn't smell\n" "like anything."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WhiteApricorn, @@ -3556,6 +3723,7 @@ const struct Item gItemsInfo[] = "It has an inde-\n" "scribable scent."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GROWTH, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlackApricorn, @@ -3571,6 +3739,7 @@ const struct Item gItemsInfo[] = "{PKMN} Den to attract\n" "Dynamax Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo .flingPower = 50, @@ -3587,6 +3756,7 @@ const struct Item gItemsInfo[] = "in Galar called\n" "Galarica."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3604,6 +3774,7 @@ const struct Item gItemsInfo[] = "found in the Isle\n" "of Armor at Galar."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3621,6 +3792,7 @@ const struct Item gItemsInfo[] = "It can be found in\n" "Galar's Max Lair."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -3640,6 +3812,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_ORANGE_MAIL), @@ -3657,6 +3830,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_HARBOR_MAIL), @@ -3674,6 +3848,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_GLITTER_MAIL), @@ -3691,6 +3866,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_MECH_MAIL), @@ -3708,6 +3884,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WOOD_MAIL), @@ -3725,6 +3902,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_WAVE_MAIL), @@ -3739,6 +3917,7 @@ const struct Item gItemsInfo[] = .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_BEAD_MAIL), @@ -3756,6 +3935,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_SHADOW_MAIL), @@ -3773,6 +3953,7 @@ const struct Item gItemsInfo[] = "Mail to be held by\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_TROPIC_MAIL), @@ -3787,6 +3968,7 @@ const struct Item gItemsInfo[] = .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_DREAM_MAIL), @@ -3804,6 +3986,7 @@ const struct Item gItemsInfo[] = "Mail to be held\n" "by a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_FAB_MAIL), @@ -3821,6 +4004,7 @@ const struct Item gItemsInfo[] = "drawings of three\n" "Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MAIL, .type = ITEM_USE_MAIL, .fieldUseFunc = ItemUseOutOfBattle_Mail, .secondaryId = ITEM_TO_MAIL(ITEM_RETRO_MAIL), @@ -3836,6 +4020,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3850,6 +4035,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3864,6 +4050,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3878,6 +4065,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3892,6 +4080,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3906,6 +4095,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3920,6 +4110,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3934,6 +4125,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3948,6 +4140,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3962,6 +4155,7 @@ const struct Item gItemsInfo[] = .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_STONE, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3979,6 +4173,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -3996,6 +4191,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4013,6 +4209,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4030,6 +4227,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4047,6 +4245,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4065,6 +4264,7 @@ const struct Item gItemsInfo[] = "Galar. Makes some\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -4084,6 +4284,7 @@ const struct Item gItemsInfo[] = "held by Dragon-\n" "type Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4101,6 +4302,7 @@ const struct Item gItemsInfo[] = "A peculiar box made\n" "by Silph Co."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4118,6 +4320,7 @@ const struct Item gItemsInfo[] = "Pokémon. It's stiff\n" "and heavy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4135,6 +4338,7 @@ const struct Item gItemsInfo[] = "Pokémon. It's full\n" "of electric energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4152,6 +4356,7 @@ const struct Item gItemsInfo[] = "Pokémon. It's full\n" "of magma energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4169,6 +4374,7 @@ const struct Item gItemsInfo[] = "overflowing with\n" "dubious data."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4187,6 +4393,7 @@ const struct Item gItemsInfo[] = "Pokémon. Imbued\n" "with spirit energy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4204,6 +4411,7 @@ const struct Item gItemsInfo[] = "that evolves a\n" "certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4222,6 +4430,7 @@ const struct Item gItemsInfo[] = "treat loved by\n" "a certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4239,6 +4448,7 @@ const struct Item gItemsInfo[] = "perfumes, loved by\n" "a certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4256,6 +4466,7 @@ const struct Item gItemsInfo[] = "that evolves a\n" "certain Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -4273,6 +4484,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4289,6 +4501,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4305,6 +4518,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4321,6 +4535,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4337,6 +4552,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4353,6 +4569,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4369,6 +4586,7 @@ const struct Item gItemsInfo[] = "sweet loved by\n" "Milcery."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -4386,6 +4604,7 @@ const struct Item gItemsInfo[] = "item that prevents\n" "evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -4402,6 +4621,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4416,6 +4636,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4430,6 +4651,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4444,6 +4666,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 0, .description = sNectarDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_NECTAR, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, .flingPower = 10, @@ -4464,6 +4687,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Fire-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4483,6 +4707,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Water-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4502,6 +4727,7 @@ const struct Item gItemsInfo[] = "the power of Elec-\n" "tric-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4521,6 +4747,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Grass-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4540,6 +4767,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Ice-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4559,6 +4787,7 @@ const struct Item gItemsInfo[] = "the power of Fight-\n" "ing-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4578,6 +4807,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Poison-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -4597,6 +4827,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Ground-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -4616,6 +4847,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Flying-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -4635,6 +4867,7 @@ const struct Item gItemsInfo[] = "the power of Psy\n" "chic-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -4654,6 +4887,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Bug-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -4673,6 +4907,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Rock-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -4692,6 +4927,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Ghost-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -4711,6 +4947,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Dragon-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -4730,6 +4967,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Dark-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -4749,6 +4987,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Steel-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -4768,6 +5007,7 @@ const struct Item gItemsInfo[] = "the power of\n" "Fairy-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_PLATE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -4806,6 +5046,7 @@ const struct Item gItemsInfo[] = "Techno Blast to\n" "Electric-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4824,6 +5065,7 @@ const struct Item gItemsInfo[] = "Techno Blast to\n" "Fire-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4842,6 +5084,7 @@ const struct Item gItemsInfo[] = "Techno Blast to\n" "Ice-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4864,6 +5107,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -4884,6 +5128,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -4904,6 +5149,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -4924,6 +5170,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -4944,6 +5191,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -4964,6 +5212,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -4984,6 +5233,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -5004,6 +5254,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -5024,6 +5275,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -5044,6 +5296,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -5064,6 +5317,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -5084,6 +5338,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -5104,6 +5359,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -5124,6 +5380,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -5144,6 +5401,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -5164,6 +5422,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -5184,6 +5443,7 @@ const struct Item gItemsInfo[] = "type data. It swaps\n" "Silvally's type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEMORY, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -5201,6 +5461,7 @@ const struct Item gItemsInfo[] = "hero used it to\n" "halt a disaster."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedSword, @@ -5216,6 +5477,7 @@ const struct Item gItemsInfo[] = "hero used it to\n" "halt a disaster."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RustedShield, @@ -5234,6 +5496,7 @@ const struct Item gItemsInfo[] = "said to contain an\n" "ancient power."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_RedOrb, @@ -5250,6 +5513,7 @@ const struct Item gItemsInfo[] = "said to contain an\n" "ancient power."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_BlueOrb, @@ -5268,6 +5532,7 @@ const struct Item gItemsInfo[] = "Venusaur to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5283,6 +5548,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5298,6 +5564,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5315,6 +5582,7 @@ const struct Item gItemsInfo[] = "Blastoise to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5332,6 +5600,7 @@ const struct Item gItemsInfo[] = "Beedrill to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5349,6 +5618,7 @@ const struct Item gItemsInfo[] = "Pidgeot to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5366,6 +5636,7 @@ const struct Item gItemsInfo[] = "Alakazam to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5383,6 +5654,7 @@ const struct Item gItemsInfo[] = "Slowbro to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5400,6 +5672,7 @@ const struct Item gItemsInfo[] = "Gengar to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5417,6 +5690,7 @@ const struct Item gItemsInfo[] = "Kangaskhan to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5434,6 +5708,7 @@ const struct Item gItemsInfo[] = "Pinsir to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5451,6 +5726,7 @@ const struct Item gItemsInfo[] = "Gyarados to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5468,6 +5744,7 @@ const struct Item gItemsInfo[] = "Aerodactyl to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5483,6 +5760,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5498,6 +5776,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5515,6 +5794,7 @@ const struct Item gItemsInfo[] = "Ampharos to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5532,6 +5812,7 @@ const struct Item gItemsInfo[] = "Steelix to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5549,6 +5830,7 @@ const struct Item gItemsInfo[] = "Scizor to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5566,6 +5848,7 @@ const struct Item gItemsInfo[] = "Heracross to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5583,6 +5866,7 @@ const struct Item gItemsInfo[] = "Houndoom to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5600,6 +5884,7 @@ const struct Item gItemsInfo[] = "Tyranitar to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5617,6 +5902,7 @@ const struct Item gItemsInfo[] = "Sceptile to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5634,6 +5920,7 @@ const struct Item gItemsInfo[] = "Blaziken to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5651,6 +5938,7 @@ const struct Item gItemsInfo[] = "Swampert to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5668,6 +5956,7 @@ const struct Item gItemsInfo[] = "Gardevoir to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5685,6 +5974,7 @@ const struct Item gItemsInfo[] = "Sableye to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5702,6 +5992,7 @@ const struct Item gItemsInfo[] = "Mawile to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5719,6 +6010,7 @@ const struct Item gItemsInfo[] = "Aggron to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5736,6 +6028,7 @@ const struct Item gItemsInfo[] = "Medicham to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5753,6 +6046,7 @@ const struct Item gItemsInfo[] = "Manectric to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5770,6 +6064,7 @@ const struct Item gItemsInfo[] = "Sharpedo to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5787,6 +6082,7 @@ const struct Item gItemsInfo[] = "Camerupt to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5804,6 +6100,7 @@ const struct Item gItemsInfo[] = "Altaria to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5821,6 +6118,7 @@ const struct Item gItemsInfo[] = "Banette to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5838,6 +6136,7 @@ const struct Item gItemsInfo[] = "Absol to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5855,6 +6154,7 @@ const struct Item gItemsInfo[] = "Glalie to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5872,6 +6172,7 @@ const struct Item gItemsInfo[] = "Salamence to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5889,6 +6190,7 @@ const struct Item gItemsInfo[] = "Metagross to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5906,6 +6208,7 @@ const struct Item gItemsInfo[] = "Latias to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5923,6 +6226,7 @@ const struct Item gItemsInfo[] = "Latios to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5940,6 +6244,7 @@ const struct Item gItemsInfo[] = "Lopunny to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5957,6 +6262,7 @@ const struct Item gItemsInfo[] = "Garchomp to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5974,6 +6280,7 @@ const struct Item gItemsInfo[] = "Lucario to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -5991,6 +6298,7 @@ const struct Item gItemsInfo[] = "Abomasnow to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6008,6 +6316,7 @@ const struct Item gItemsInfo[] = "Gallade to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6025,6 +6334,7 @@ const struct Item gItemsInfo[] = "Audino to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6042,6 +6352,7 @@ const struct Item gItemsInfo[] = "Diancie to Mega\n" "Evolve in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_MEGA_STONE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -6062,6 +6373,7 @@ const struct Item gItemsInfo[] = "power of Normal\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -6080,6 +6392,7 @@ const struct Item gItemsInfo[] = "power of Fire\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -6098,6 +6411,7 @@ const struct Item gItemsInfo[] = "power of Water\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -6116,6 +6430,7 @@ const struct Item gItemsInfo[] = "power of Electric\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -6134,6 +6449,7 @@ const struct Item gItemsInfo[] = "power of Grass\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6152,6 +6468,7 @@ const struct Item gItemsInfo[] = "power of Ice\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6170,6 +6487,7 @@ const struct Item gItemsInfo[] = "power of Fighting\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6188,6 +6506,7 @@ const struct Item gItemsInfo[] = "power of Poison\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6206,6 +6525,7 @@ const struct Item gItemsInfo[] = "power of Ground\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6224,6 +6544,7 @@ const struct Item gItemsInfo[] = "power of Flying\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6242,6 +6563,7 @@ const struct Item gItemsInfo[] = "power of Psychic\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6260,6 +6582,7 @@ const struct Item gItemsInfo[] = "power of Bug\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6278,6 +6601,7 @@ const struct Item gItemsInfo[] = "power of Rock\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6296,6 +6620,7 @@ const struct Item gItemsInfo[] = "power of Ghost\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6314,6 +6639,7 @@ const struct Item gItemsInfo[] = "power of Dragon\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6332,6 +6658,7 @@ const struct Item gItemsInfo[] = "power of Dark\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6350,6 +6677,7 @@ const struct Item gItemsInfo[] = "power of Steel\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6368,6 +6696,7 @@ const struct Item gItemsInfo[] = "power of Fairy\n" "Type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_GEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6387,6 +6716,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -6404,6 +6734,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -6421,6 +6752,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -6438,6 +6770,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -6455,6 +6788,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -6472,6 +6806,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -6489,6 +6824,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -6506,6 +6842,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -6523,6 +6860,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -6540,6 +6878,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -6557,6 +6896,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -6574,6 +6914,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -6591,6 +6932,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -6608,6 +6950,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -6625,6 +6968,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -6642,6 +6986,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -6659,6 +7004,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_STEEL, @@ -6676,6 +7022,7 @@ const struct Item gItemsInfo[] = "type moves into\n" "Z-Moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -6693,6 +7040,7 @@ const struct Item gItemsInfo[] = "Volt Tackle\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6710,6 +7058,7 @@ const struct Item gItemsInfo[] = "Last Resort\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6727,6 +7076,7 @@ const struct Item gItemsInfo[] = "Giga Impact\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6744,6 +7094,7 @@ const struct Item gItemsInfo[] = "Psychic into\n" "a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6761,6 +7112,7 @@ const struct Item gItemsInfo[] = "eye's Spirit Sha-\n" "ckle into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6778,6 +7130,7 @@ const struct Item gItemsInfo[] = "roar's Darkest La-\n" "riat into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6795,6 +7148,7 @@ const struct Item gItemsInfo[] = "Sparkling Aria\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6812,6 +7166,7 @@ const struct Item gItemsInfo[] = "Stone Edge\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6829,6 +7184,7 @@ const struct Item gItemsInfo[] = "Play Rough\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6846,6 +7202,7 @@ const struct Item gItemsInfo[] = "Clanging Scales\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6863,6 +7220,7 @@ const struct Item gItemsInfo[] = "Nature's Madness\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6880,6 +7238,7 @@ const struct Item gItemsInfo[] = "Sunsteel Strike\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6897,6 +7256,7 @@ const struct Item gItemsInfo[] = "Moongeist Beam\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6914,6 +7274,7 @@ const struct Item gItemsInfo[] = "dow's Spectral Thi-\n" "ef into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6931,6 +7292,7 @@ const struct Item gItemsInfo[] = "Raichu's Thunder-\n" "bolt into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6948,6 +7310,7 @@ const struct Item gItemsInfo[] = "a cap's Thunderbolt\n" "into a Z-Move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, // signature z move @@ -6965,6 +7328,7 @@ const struct Item gItemsInfo[] = "fused Necrozma\n" "into a new form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_Z_CRYSTAL, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = 255, //signature z move @@ -6984,6 +7348,7 @@ const struct Item gItemsInfo[] = "raises the Atk and\n" "Sp. Atk of Pikachu."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7001,6 +7366,7 @@ const struct Item gItemsInfo[] = "raises Farfetch'd's\n" "critical-hit ratio."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7018,6 +7384,7 @@ const struct Item gItemsInfo[] = "raises Cubone or\n" "Marowak's Attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -7036,6 +7403,7 @@ const struct Item gItemsInfo[] = "raises Chansey's\n" "critical-hit rate."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -7054,6 +7422,7 @@ const struct Item gItemsInfo[] = "raises Ditto's\n" "Defense."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7072,6 +7441,7 @@ const struct Item gItemsInfo[] = "raises the Speed\n" "of Ditto."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7089,6 +7459,7 @@ const struct Item gItemsInfo[] = "raises the Sp. Def\n" "of Clamperl."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7108,6 +7479,7 @@ const struct Item gItemsInfo[] = "raises the Sp. Atk\n" "of Clamperl."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7133,6 +7505,7 @@ const struct Item gItemsInfo[] = "Latios & Latias."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7151,6 +7524,7 @@ const struct Item gItemsInfo[] = "Dragon and Steel-\n" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7169,6 +7543,7 @@ const struct Item gItemsInfo[] = "Dragon and Water-\n" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7187,6 +7562,7 @@ const struct Item gItemsInfo[] = "Dragon and Ghost-\n" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7204,6 +7580,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7223,6 +7600,7 @@ const struct Item gItemsInfo[] = "slightly lowers the\n" "foe's accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7238,6 +7616,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7254,6 +7633,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7270,6 +7650,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 5, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7285,6 +7666,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sSeaIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7301,6 +7683,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 20, .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7316,6 +7699,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7330,6 +7714,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_INCENSE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7349,6 +7734,7 @@ const struct Item gItemsInfo[] = "raises Cool in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7366,6 +7752,7 @@ const struct Item gItemsInfo[] = "raises Beauty in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7383,6 +7770,7 @@ const struct Item gItemsInfo[] = "raises Cute in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7400,6 +7788,7 @@ const struct Item gItemsInfo[] = "raises Smart in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7417,6 +7806,7 @@ const struct Item gItemsInfo[] = "raises Tough in\n" "Contests."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_CONTEST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7436,6 +7826,7 @@ const struct Item gItemsInfo[] = "promotes growth,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -7454,6 +7845,7 @@ const struct Item gItemsInfo[] = "promotes HP gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_HP, @@ -7473,6 +7865,7 @@ const struct Item gItemsInfo[] = "promotes Atk gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_ATK, @@ -7492,6 +7885,7 @@ const struct Item gItemsInfo[] = "promotes Def gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_DEF, @@ -7512,6 +7906,7 @@ const struct Item gItemsInfo[] = "motes Sp. Atk gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPATK, @@ -7531,6 +7926,7 @@ const struct Item gItemsInfo[] = "motes Sp. Def gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPDEF, @@ -7550,6 +7946,7 @@ const struct Item gItemsInfo[] = "promotes Spd gain,\n" "but reduces Speed."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EV_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = STAT_SPEED, @@ -7572,6 +7969,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Normal-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_NORMAL, @@ -7591,6 +7989,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Fire-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIRE, @@ -7611,6 +8010,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Water-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, @@ -7630,6 +8030,7 @@ const struct Item gItemsInfo[] = "boosts Electric-\n" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ELECTRIC, @@ -7646,6 +8047,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = TYPE_BOOST_PARAM, .description = sRoseIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GRASS, @@ -7666,6 +8068,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Ice-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ICE, @@ -7685,6 +8088,7 @@ const struct Item gItemsInfo[] = "boosts Fighting-\n" "type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FIGHTING, @@ -7704,6 +8108,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Poison-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_POISON, @@ -7724,6 +8129,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Ground-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GROUND, @@ -7743,6 +8149,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Flying-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FLYING, @@ -7759,6 +8166,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = TYPE_BOOST_PARAM, .description = sOddIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_PSYCHIC, @@ -7779,6 +8187,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Bug-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_BUG, @@ -7795,6 +8204,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = TYPE_BOOST_PARAM, .description = sRockIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_ROCK, @@ -7814,6 +8224,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Ghost-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_GHOST, @@ -7833,6 +8244,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Dragon-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DRAGON, @@ -7853,6 +8265,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Dark-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_DARK, @@ -7872,6 +8285,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Steel-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -7893,6 +8307,7 @@ const struct Item gItemsInfo[] = "allows the use of\n" "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7911,6 +8326,7 @@ const struct Item gItemsInfo[] = "allows the use of\n" "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7929,6 +8345,7 @@ const struct Item gItemsInfo[] = "allows the use of\n" "only one move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -7948,6 +8365,7 @@ const struct Item gItemsInfo[] = "inflicts a burn on\n" "holder in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7965,6 +8383,7 @@ const struct Item gItemsInfo[] = "badly poisons the\n" "holder in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -7984,6 +8403,7 @@ const struct Item gItemsInfo[] = "of Rain Dance if\n" "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8001,6 +8421,7 @@ const struct Item gItemsInfo[] = "of Sunny Day if\n" "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8018,6 +8439,7 @@ const struct Item gItemsInfo[] = "of Sandstorm if\n" "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8047,6 +8469,7 @@ const struct Item gItemsInfo[] = "used by the holder."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -8067,6 +8490,7 @@ const struct Item gItemsInfo[] = "Electric Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8085,6 +8509,7 @@ const struct Item gItemsInfo[] = "Psychic Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8103,6 +8528,7 @@ const struct Item gItemsInfo[] = "Misty Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8121,6 +8547,7 @@ const struct Item gItemsInfo[] = "Grassy Terrain,\n" "but only one time."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8141,6 +8568,7 @@ const struct Item gItemsInfo[] = "the holder is hit by\n" "a Water-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8160,6 +8588,7 @@ const struct Item gItemsInfo[] = "the holder is hit by\n" "an Electric move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8179,6 +8608,7 @@ const struct Item gItemsInfo[] = "the holder is hit by\n" "a Water-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8197,6 +8627,7 @@ const struct Item gItemsInfo[] = "holder is hit by an\n" "Ice-type move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8218,6 +8649,7 @@ const struct Item gItemsInfo[] = "casts a glare to\n" "reduce accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8235,6 +8667,7 @@ const struct Item gItemsInfo[] = "restores any\n" "lowered stat."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8260,6 +8693,7 @@ const struct Item gItemsInfo[] = "from battles."), #endif .pocket = I_EXP_SHARE_ITEM >= GEN_6 ? POCKET_KEY_ITEMS : POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_FIELD, .fieldUseFunc = ItemUseOutOfBattle_ExpShare, .flingPower = 30, @@ -8278,6 +8712,7 @@ const struct Item gItemsInfo[] = "occasionally allows\n" "the first strike."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8295,6 +8730,7 @@ const struct Item gItemsInfo[] = "calms spirits and\n" "fosters friendship."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8318,6 +8754,7 @@ const struct Item gItemsInfo[] = "of infatuation."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8333,6 +8770,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8348,6 +8786,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8362,6 +8801,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8379,6 +8819,7 @@ const struct Item gItemsInfo[] = "assures fleeing\n" "from wild Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8397,6 +8838,7 @@ const struct Item gItemsInfo[] = "occasionally\n" "prevents fainting."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8414,6 +8856,7 @@ const struct Item gItemsInfo[] = "boosts Exp. points\n" "earned in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8432,6 +8875,7 @@ const struct Item gItemsInfo[] = "improves the\n" "critical-hit rate."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8451,6 +8895,7 @@ const struct Item gItemsInfo[] = "gradually restores\n" "HP in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8469,6 +8914,7 @@ const struct Item gItemsInfo[] = "restores HP upon\n" "striking the foe."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8488,6 +8934,7 @@ const struct Item gItemsInfo[] = "that boosts the\n" "accuracy of moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8506,6 +8953,7 @@ const struct Item gItemsInfo[] = "boosts the power\n" "of physical moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8525,6 +8973,7 @@ const struct Item gItemsInfo[] = "that ups the power\n" "of special moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8543,6 +8992,7 @@ const struct Item gItemsInfo[] = "the power of super\n" "effective moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8561,6 +9011,7 @@ const struct Item gItemsInfo[] = "of barrier moves\n" "used by the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8578,6 +9029,7 @@ const struct Item gItemsInfo[] = "but holder loses HP\n" "with each attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8595,6 +9047,7 @@ const struct Item gItemsInfo[] = "use of a move that\n" "charges first."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8613,6 +9066,7 @@ const struct Item gItemsInfo[] = "full HP, it endures\n" "KO hits with 1 HP."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8632,6 +9086,7 @@ const struct Item gItemsInfo[] = "after the foe, it'll\n" "boost accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8650,6 +9105,7 @@ const struct Item gItemsInfo[] = "boosts a move used\n" "consecutively."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8667,6 +9123,7 @@ const struct Item gItemsInfo[] = "becomes vulnerable\n" "to Ground moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 130, @@ -8681,6 +9138,7 @@ const struct Item gItemsInfo[] = .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8698,6 +9156,7 @@ const struct Item gItemsInfo[] = "in love, the foe\n" "does too."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8716,6 +9175,7 @@ const struct Item gItemsInfo[] = "Poison-types.\n" "Damages all others."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8733,6 +9193,7 @@ const struct Item gItemsInfo[] = "extends binding\n" "moves like Wrap."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 90, @@ -8750,6 +9211,7 @@ const struct Item gItemsInfo[] = "each turn. May\n" "latch on to foes."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8767,6 +9229,7 @@ const struct Item gItemsInfo[] = "to switch out\n" "without fail."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8785,6 +9248,7 @@ const struct Item gItemsInfo[] = "ups the power of\n" "HP-stealing moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8802,6 +9266,7 @@ const struct Item gItemsInfo[] = "ups the holder's\n" "critical-hit ratio."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8818,6 +9283,7 @@ const struct Item gItemsInfo[] = .holdEffectParam = 10, .description = sKingsRockDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = EVO_HELD_ITEM_TYPE, .fieldUseFunc = EVO_HELD_ITEM_FIELD_FUNC, .effect = gItemEffect_EvoItem, @@ -8837,6 +9303,7 @@ const struct Item gItemsInfo[] = "Sp. Def of Pokémon\n" "that can evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 40, @@ -8854,6 +9321,7 @@ const struct Item gItemsInfo[] = "when held, it halves\n" "a Pokémon's weight."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8872,6 +9340,7 @@ const struct Item gItemsInfo[] = "they touch its\n" "holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -8890,6 +9359,7 @@ const struct Item gItemsInfo[] = "float but bursts\n" "if hit by an attack."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8908,6 +9378,7 @@ const struct Item gItemsInfo[] = "foe if they hit the\n" "holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8926,6 +9397,7 @@ const struct Item gItemsInfo[] = "have no effect will\n" "hit the holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -8943,6 +9415,7 @@ const struct Item gItemsInfo[] = "power of binding\n" "moves when held."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8961,6 +9434,7 @@ const struct Item gItemsInfo[] = "user if they're hit\n" "by the foe."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -8980,6 +9454,7 @@ const struct Item gItemsInfo[] = "effective move,\n" "ups Atk and Sp. Atk."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -8998,6 +9473,7 @@ const struct Item gItemsInfo[] = "prevents the use\n" "of status moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9016,6 +9492,7 @@ const struct Item gItemsInfo[] = "weather damage and\n" "powder moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9033,6 +9510,7 @@ const struct Item gItemsInfo[] = "Speed if the holder\n" "is intimidated."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9050,6 +9528,7 @@ const struct Item gItemsInfo[] = "of the active\n" "battle terrain."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -9068,6 +9547,7 @@ const struct Item gItemsInfo[] = "from contact move\n" "effects."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9085,6 +9565,7 @@ const struct Item gItemsInfo[] = "the holder uses a\n" "sound-based move."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -9102,6 +9583,7 @@ const struct Item gItemsInfo[] = "switch if its stats\n" "are lowered."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 50, @@ -9120,6 +9602,7 @@ const struct Item gItemsInfo[] = "effects of traps\n" "set in the field."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9138,6 +9621,7 @@ const struct Item gItemsInfo[] = "the user misses\n" "due to Accuracy."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 80, @@ -9155,6 +9639,7 @@ const struct Item gItemsInfo[] = "Trick Room is\n" "active."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 100, @@ -9172,6 +9657,7 @@ const struct Item gItemsInfo[] = "protects from\n" "weather effects."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -12961,6 +13447,7 @@ const struct Item gItemsInfo[] = "prevented for this\n" "items's holder."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12978,6 +13465,7 @@ const struct Item gItemsInfo[] = "moves and removes\n" "their contact."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -12995,6 +13483,7 @@ const struct Item gItemsInfo[] = "from additional\n" "effects of moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13013,6 +13502,7 @@ const struct Item gItemsInfo[] = "Multihit strikes\n" "hit more times."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13029,6 +13519,7 @@ const struct Item gItemsInfo[] = "auspicious wishes.\n" "Causes evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13048,6 +13539,7 @@ const struct Item gItemsInfo[] = "ups Pokémon with\n" "certain Abilities."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13064,6 +13556,7 @@ const struct Item gItemsInfo[] = "bamboo shoot. Best\n" "sold to gourmands."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13080,6 +13573,7 @@ const struct Item gItemsInfo[] = "and treasure these\n" "curious coins."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_GimmighoulCoin, @@ -13095,6 +13589,7 @@ const struct Item gItemsInfo[] = "blade of some sort.\n" "Held by Bisharp."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_LeadersCrest, @@ -13110,6 +13605,7 @@ const struct Item gItemsInfo[] = "malicious will.\n" "Causes evolution."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13128,6 +13624,7 @@ const struct Item gItemsInfo[] = "stat increases\n" "but only once."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13146,6 +13643,7 @@ const struct Item gItemsInfo[] = "the dark path."), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13164,6 +13662,7 @@ const struct Item gItemsInfo[] = "the water path."), .importance = 1, .pocket = POCKET_KEY_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13196,6 +13695,7 @@ const struct Item gItemsInfo[] = "bamboo shoot. Best\n" "sold to gourmands."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 30, @@ -13209,6 +13709,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13221,6 +13722,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13233,6 +13735,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13245,6 +13748,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13257,6 +13761,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13269,6 +13774,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13281,6 +13787,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13293,6 +13800,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13305,6 +13813,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13317,6 +13826,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13329,6 +13839,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13341,6 +13852,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13353,6 +13865,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13365,6 +13878,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13377,6 +13891,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13389,6 +13904,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13401,6 +13917,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13413,6 +13930,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_TeraShard, @@ -13430,6 +13948,7 @@ const struct Item gItemsInfo[] = "that lets Dialga\n" "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13448,6 +13967,7 @@ const struct Item gItemsInfo[] = "that lets Giratina\n" "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13466,6 +13986,7 @@ const struct Item gItemsInfo[] = "that lets Palkia\n" "change form."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, @@ -13482,6 +14003,7 @@ const struct Item gItemsInfo[] = "makes some Pokémon\n" "evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13499,6 +14021,7 @@ const struct Item gItemsInfo[] = "that makes some\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13516,6 +14039,7 @@ const struct Item gItemsInfo[] = "that makes some\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13534,6 +14058,7 @@ const struct Item gItemsInfo[] = "Attack, but causes\n" "lasting confusion."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, @@ -13552,6 +14077,7 @@ const struct Item gItemsInfo[] = "raises the power of\n" "Fairy-type moves."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TYPE_BOOST_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_FAIRY, @@ -13569,6 +14095,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13586,6 +14113,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13603,6 +14131,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13622,6 +14151,7 @@ const struct Item gItemsInfo[] = "wield the Rock-\n" "type in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_CornerstoneMask, @@ -13639,6 +14169,7 @@ const struct Item gItemsInfo[] = "wield the Water-\n" "type in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_WellspringMask, @@ -13656,6 +14187,7 @@ const struct Item gItemsInfo[] = "wield the Fire-\n" "type in battle."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SPECIAL_HELD_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_HearthflameMask, @@ -13669,6 +14201,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_HpMochi, @@ -13684,6 +14217,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_AtkMochi, @@ -13699,6 +14233,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_DefMochi, @@ -13714,6 +14249,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpatkMochi, @@ -13729,6 +14265,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpdefMochi, @@ -13744,6 +14281,7 @@ const struct Item gItemsInfo[] = .price = 500, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .effect = gItemEffect_SpeedMochi, @@ -13762,6 +14300,7 @@ const struct Item gItemsInfo[] = "all base points of\n" "a Pokémon."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STAT_BOOST_MOCHI, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_ResetEVs, .effect = gItemEffect_ResetMochi, @@ -13795,6 +14334,7 @@ const struct Item gItemsInfo[] = "that makes certain\n" "Pokémon evolve."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_EVOLUTION_ITEM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, .effect = gItemEffect_EvoItem, @@ -13808,6 +14348,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_TERA_SHARD, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_StellarTeraShard, @@ -13820,6 +14361,7 @@ const struct Item gItemsInfo[] = .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_STATUS_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_CURE_STATUS, @@ -13838,6 +14380,7 @@ const struct Item gItemsInfo[] = "that restores HP\n" "by 20 points."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13860,6 +14403,7 @@ const struct Item gItemsInfo[] = "by 50 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13882,6 +14426,7 @@ const struct Item gItemsInfo[] = "by 200 points."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_HEALTH_RECOVERY, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, .battleUsage = EFFECT_ITEM_RESTORE_HP, @@ -13906,6 +14451,7 @@ const struct Item gItemsInfo[] = "during one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13928,6 +14474,7 @@ const struct Item gItemsInfo[] = "during one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13950,6 +14497,7 @@ const struct Item gItemsInfo[] = "during one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -13973,6 +14521,7 @@ const struct Item gItemsInfo[] = "one battle."), #endif .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_AUX_ITEM, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, //.effect = currently missing @@ -14028,6 +14577,7 @@ const struct Item gItemsInfo[] = "resembling a Poké-.\n" "mon. Can be sold."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_SELLABLE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_PokeshiDoll, diff --git a/src/item.c b/src/item.c index 4e7e514938..b155cbb903 100644 --- a/src/item.c +++ b/src/item.c @@ -32,8 +32,6 @@ static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count); static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count); static const u8 *GetItemPluralName(u16); static bool32 DoesItemHavePluralName(u16); -static void BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); -static void BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting); EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; @@ -61,71 +59,72 @@ const struct TmHmIndexKey gTMHMItemMoveIds[NUM_ALL_MACHINES + 1] = #undef UNPACK_TM_ITEM_ID #undef UNPACK_HM_ITEM_ID -static void (*const sBagPocket_GetSetSlotDataFuncs[])(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) = +static inline struct ItemSlot NONNULL BagPocket_GetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos) { - [POCKET_ITEMS] = BagPocket_GetSetSlotDataGeneric, - [POCKET_KEY_ITEMS] = BagPocket_GetSetSlotDataGeneric, - [POCKET_POKE_BALLS] = BagPocket_GetSetSlotDataGeneric, - [POCKET_TM_HM] = BagPocket_GetSetSlotDataGeneric, - [POCKET_BERRIES] = BagPocket_GetSetSlotDataGeneric, - [POCKET_DUMMY] = BagPocket_GetSetSlotDataPC, -}; - -static void NONNULL BagPocket_GetSetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) -{ - if (isSetting) - { - pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero - pocket->itemSlots[pocketPos].quantity = *quantity ^ gSaveBlock2Ptr->encryptionKey; - } - else - { - *itemId = pocket->itemSlots[pocketPos].itemId; - *quantity = pocket->itemSlots[pocketPos].quantity ^ gSaveBlock2Ptr->encryptionKey; - } + return (struct ItemSlot) { + .itemId = pocket->itemSlots[pocketPos].itemId, + .quantity = pocket->itemSlots[pocketPos].quantity ^ gSaveBlock2Ptr->encryptionKey, + }; } -static void NONNULL BagPocket_GetSetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity, bool32 isSetting) +static inline struct ItemSlot NONNULL BagPocket_GetSlotDataPC(struct BagPocket *pocket, u32 pocketPos) { - if (isSetting) - { - pocket->itemSlots[pocketPos].itemId = *quantity ? *itemId : ITEM_NONE; // Sets to zero if quantity is zero - pocket->itemSlots[pocketPos].quantity = *quantity; - } - else - { - *itemId = pocket->itemSlots[pocketPos].itemId; - *quantity = pocket->itemSlots[pocketPos].quantity; - } + return (struct ItemSlot) { + .itemId = pocket->itemSlots[pocketPos].itemId, + .quantity = pocket->itemSlots[pocketPos].quantity, + }; } -static inline void NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) +static inline void NONNULL BagPocket_SetSlotDataGeneric(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot) { - sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, FALSE); + pocket->itemSlots[pocketPos].itemId = newSlot.itemId; + pocket->itemSlots[pocketPos].quantity = newSlot.quantity ^ gSaveBlock2Ptr->encryptionKey; } -static inline void NONNULL BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, u16 *itemId, u16 *quantity) +static inline void NONNULL BagPocket_SetSlotDataPC(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot) { - sBagPocket_GetSetSlotDataFuncs[pocket->id](pocket, pocketPos, itemId, quantity, TRUE); + pocket->itemSlots[pocketPos].itemId = newSlot.itemId; + pocket->itemSlots[pocketPos].quantity = newSlot.quantity; } -void GetBagItemIdAndQuantity(enum Pocket pocketId, u32 pocketPos, u16 *itemId, u16 *quantity) +struct ItemSlot NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos) { - BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, itemId, quantity); -} + switch (pocket->id) + { + case POCKET_ITEMS: + case POCKET_KEY_ITEMS: + case POCKET_POKE_BALLS: + case POCKET_TM_HM: + case POCKET_BERRIES: + return BagPocket_GetSlotDataGeneric(pocket, pocketPos); + case POCKET_DUMMY: + return BagPocket_GetSlotDataPC(pocket, pocketPos); + } -u16 GetBagItemId(enum Pocket pocketId, u32 pocketPos) -{ - u16 itemId, quantity; - BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); - return itemId; + return (struct ItemSlot) {0}; // Because compiler complains } -u16 GetBagItemQuantity(enum Pocket pocketId, u32 pocketPos) +void NONNULL BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot) { - u16 itemId, quantity; - BagPocket_GetSlotData(&gBagPockets[pocketId], pocketPos, &itemId, &quantity); - return quantity; + if (newSlot.itemId == ITEM_NONE || newSlot.quantity == 0) // Sets to zero if quantity or itemId is zero + { + newSlot.itemId = ITEM_NONE; + newSlot.quantity = 0; + } + + switch (pocket->id) + { + case POCKET_ITEMS: + case POCKET_KEY_ITEMS: + case POCKET_POKE_BALLS: + case POCKET_TM_HM: + case POCKET_BERRIES: + BagPocket_SetSlotDataGeneric(pocket, pocketPos, newSlot); + break; + case POCKET_DUMMY: + BagPocket_SetSlotDataPC(pocket, pocketPos, newSlot); + break; + } } void ApplyNewEncryptionKeyToBagItems(u32 newKey) @@ -200,14 +199,14 @@ bool32 IsBagPocketNonEmpty(enum Pocket pocketId) static bool32 NONNULL BagPocket_CheckHasItem(struct BagPocket *pocket, u16 itemId, u16 count) { - u16 tempItemId, tempQuantity; + struct ItemSlot tempItem; // Check for item slots that contain the item for (u32 i = 0; i < pocket->capacity && count > 0; i++) { - BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); - if (tempItemId == itemId) - count -= min(count, tempQuantity); + tempItem = BagPocket_GetSlotData(pocket, i); + if (tempItem.itemId == itemId) + count -= min(count, tempItem.quantity); } return count == 0; @@ -257,14 +256,14 @@ bool32 CheckBagHasSpace(u16 itemId, u16 count) static u32 NONNULL BagPocket_GetFreeSpaceForItem(struct BagPocket *pocket, u16 itemId) { u32 spaceForItem = 0; - u16 tempItemId, tempQuantity; + struct ItemSlot tempItem; // Check space in any existing item slots that already contain this item for (u32 i = 0; i < pocket->capacity; i++) { - BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); - if (tempItemId == ITEM_NONE || tempItemId == itemId) - spaceForItem += (tempItemId ? (MAX_BAG_ITEM_CAPACITY - tempQuantity) : MAX_BAG_ITEM_CAPACITY); + tempItem = BagPocket_GetSlotData(pocket, i); + if (tempItem.itemId == ITEM_NONE || tempItem.itemId == itemId) + spaceForItem += (tempItem.itemId ? (MAX_BAG_ITEM_CAPACITY - tempItem.quantity) : MAX_BAG_ITEM_CAPACITY); } return spaceForItem; @@ -280,17 +279,16 @@ u32 GetFreeSpaceForItemInBag(u16 itemId) static inline bool32 NONNULL CheckSlotAndUpdateCount(struct BagPocket *pocket, u16 itemId, u32 pocketPos, u32 *nextPocketPos, u16 *count, u16 *tempPocketSlotQuantities) { - u16 tempItemId, tempQuantity; - BagPocket_GetSlotData(pocket, pocketPos, &tempItemId, &tempQuantity); - if (tempItemId == ITEM_NONE || tempItemId == itemId) + struct ItemSlot tempItem = BagPocket_GetSlotData(pocket, pocketPos); + if (tempItem.itemId == ITEM_NONE || tempItem.itemId == itemId) { // The quantity already at the slot - zero if an empty slot - if (!tempItemId) - tempQuantity = 0; + if (tempItem.itemId == ITEM_NONE) + tempItem.quantity = 0; // Record slot quantity in tempPocketSlotQuantities, adjust count - tempPocketSlotQuantities[pocketPos] = min(MAX_BAG_ITEM_CAPACITY, *count + tempQuantity); - *count -= min(*count, MAX_BAG_ITEM_CAPACITY - tempQuantity); + tempPocketSlotQuantities[pocketPos] = min(MAX_BAG_ITEM_CAPACITY, *count + tempItem.quantity); + *count -= min(*count, MAX_BAG_ITEM_CAPACITY - tempItem.quantity); // Set the starting index for the next loop to set items (shifted by one) if (!*nextPocketPos) @@ -336,7 +334,7 @@ static bool32 NONNULL BagPocket_AddItem(struct BagPocket *pocket, u16 itemId, u1 for (--itemAddIndex; itemAddIndex < itemLookupIndex; itemAddIndex++) { if (tempPocketSlotQuantities[itemAddIndex] > 0) - BagPocket_SetSlotData(pocket, itemAddIndex, &itemId, &tempPocketSlotQuantities[itemAddIndex]); + BagPocket_SetSlotItemIdAndCount(pocket, itemAddIndex, itemId, tempPocketSlotQuantities[itemAddIndex]); } } @@ -359,21 +357,21 @@ bool32 AddBagItem(u16 itemId, u16 count) static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, u16 itemId, u16 count) { u32 itemLookupIndex, itemRemoveIndex = 0, totalQuantity = 0; - u16 tempItemId, tempQuantity; + struct ItemSlot tempItem; u16 *tempPocketSlotQuantities = AllocZeroed(sizeof(u16) * pocket->capacity); for (itemLookupIndex = 0; itemLookupIndex < pocket->capacity && totalQuantity < count; itemLookupIndex++) { - BagPocket_GetSlotData(pocket, itemLookupIndex, &tempItemId, &tempQuantity); - if (tempItemId == itemId) + tempItem = BagPocket_GetSlotData(pocket, itemLookupIndex); + if (tempItem.itemId == itemId) { // Index for the next loop - where we should start removing items if (!itemRemoveIndex) itemRemoveIndex = itemLookupIndex + 1; // Gather quantities (+ 1 to tempPocketSlotQuantities so that even if setting to 0 we know which indices to target) - totalQuantity += tempQuantity; - tempPocketSlotQuantities[itemLookupIndex] = (tempQuantity <= count ? 0 : tempQuantity - count) + 1; + totalQuantity += tempItem.quantity; + tempPocketSlotQuantities[itemLookupIndex] = (tempItem.quantity <= count ? 0 : tempItem.quantity - count) + 1; } } @@ -389,10 +387,7 @@ static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, u16 itemId, for (--itemRemoveIndex; itemRemoveIndex < itemLookupIndex; itemRemoveIndex++) { if (tempPocketSlotQuantities[itemRemoveIndex] > 0) - { - tempPocketSlotQuantities[itemRemoveIndex]--; // Reverse the +1 shift - BagPocket_SetSlotData(pocket, itemRemoveIndex, &itemId, &tempPocketSlotQuantities[itemRemoveIndex]); - } + BagPocket_SetSlotItemIdAndCount(pocket, itemRemoveIndex, itemId, tempPocketSlotQuantities[itemRemoveIndex] - 1); } } @@ -415,12 +410,10 @@ bool32 RemoveBagItem(u16 itemId, u16 count) static u8 NONNULL BagPocket_CountUsedItemSlots(struct BagPocket *pocket) { u8 usedSlots = 0; - u16 tempItemId, tempQuantity; for (u32 i = 0; i < pocket->capacity; i++) { - BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); - if (tempItemId) + if (BagPocket_GetSlotData(pocket, i).itemId != ITEM_NONE) usedSlots++; } return usedSlots; @@ -434,12 +427,12 @@ u8 CountUsedPCItemSlots(void) static bool32 NONNULL BagPocket_CheckPocketForItemCount(struct BagPocket *pocket, u16 itemId, u16 count) { - u16 tempItemId, tempQuantity; + struct ItemSlot tempItem; for (u32 i = 0; i < pocket->capacity; i++) { - BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); - if (tempItemId == itemId && tempQuantity >= count) + tempItem = BagPocket_GetSlotData(pocket, i); + if (tempItem.itemId == itemId && tempItem.quantity >= count) return TRUE; } return FALSE; @@ -459,20 +452,20 @@ bool32 AddPCItem(u16 itemId, u16 count) static void NONNULL BagPocket_CompactItems(struct BagPocket *pocket) { - u16 itemId, quantity, zero = 0, slotCursor = 0; + struct ItemSlot tempItem; + u32 slotCursor = 0; for (u32 i = 0; i < pocket->capacity; i++) { - BagPocket_GetSlotData(pocket, i, &itemId, &quantity); - if (itemId == ITEM_NONE) + tempItem = BagPocket_GetSlotData(pocket, i); + if (tempItem.itemId == ITEM_NONE) { if (!slotCursor) slotCursor = i + 1; } else if (slotCursor > 0) { - BagPocket_SetSlotData(pocket, slotCursor - 1, &itemId, &quantity); - BagPocket_SetSlotData(pocket, i, &zero, &zero); - slotCursor++; + BagPocket_SetSlotData(pocket, slotCursor++ - 1, tempItem); + BagPocket_SetSlotItemIdAndCount(pocket, i, ITEM_NONE, 0); } } } @@ -482,15 +475,13 @@ void RemovePCItem(u8 index, u16 count) struct BagPocket dummyPocket = DUMMY_PC_BAG_POCKET; // Get id, quantity at slot - u16 tempItemId, tempQuantity; - BagPocket_GetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + struct ItemSlot tempItem = BagPocket_GetSlotData(&dummyPocket, index); // Remove quantity - tempQuantity -= count; - BagPocket_SetSlotData(&dummyPocket, index, &tempItemId, &tempQuantity); + BagPocket_SetSlotItemIdAndCount(&dummyPocket, index, tempItem.itemId, tempItem.quantity - count); // Compact if necessary - if (tempQuantity == 0) + if (tempItem.quantity == 0) BagPocket_CompactItems(&dummyPocket); } @@ -518,42 +509,6 @@ void CompactItemsInBagPocket(enum Pocket pocketId) BagPocket_CompactItems(&gBagPockets[pocketId]); } -// Opens the possibility of sorting by other means e.g. ghoulslash's advanced sorting -static inline bool32 ItemIndexCompare(u16 itemA, u16 itemB, enum SortPocket sortPocket) -{ - switch (sortPocket) - { - case SORT_POCKET_BY_ITEM_ID: - return itemA > itemB; - case SORT_POCKET_TM_HM: - return GetItemTMHMIndex(itemA) > GetItemTMHMIndex(itemB); - default: - return FALSE; - } -} - -void SortPocket(enum Pocket pocketId, enum SortPocket sortPocket) -{ - u16 itemId_i, quantity_i, itemId_j, quantity_j; - struct BagPocket *pocket = &gBagPockets[pocketId]; - - for (u32 i = 0; i < pocket->capacity - 1; i++) - { - BagPocket_GetSlotData(pocket, i, &itemId_i, &quantity_i); - for (u32 j = i + 1; j < pocket->capacity; j++) - { - BagPocket_GetSlotData(pocket, j, &itemId_j, &quantity_j); - if (itemId_j && (!itemId_i || ItemIndexCompare(itemId_i, itemId_j, sortPocket))) - { - BagPocket_SetSlotData(pocket, i, &itemId_j, &quantity_j); - BagPocket_SetSlotData(pocket, j, &itemId_i, &quantity_i); - itemId_i = itemId_j; - quantity_i = quantity_j; - } - } - } -} - static inline void NONNULL BagPocket_MoveItemSlot(struct BagPocket *pocket, u32 from, u32 to) { if (from != to) @@ -563,18 +518,14 @@ static inline void NONNULL BagPocket_MoveItemSlot(struct BagPocket *pocket, u32 to--; // Record the values at "from" - u16 fromItemId, fromQuantity, tempItemId, tempQuantity; - BagPocket_GetSlotData(pocket, from, &fromItemId, &fromQuantity); + struct ItemSlot fromSlot = BagPocket_GetSlotData(pocket, from); // Shuffle items between "to" and "from" for (u32 i = from; i != to; i += shift) - { - BagPocket_GetSlotData(pocket, i + shift, &tempItemId, &tempQuantity); - BagPocket_SetSlotData(pocket, i, &tempItemId, &tempQuantity); - } + BagPocket_SetSlotData(pocket, i, BagPocket_GetSlotData(pocket, i + shift)); // Move the saved "from" to "to" - BagPocket_SetSlotData(pocket, to, &fromItemId, &fromQuantity); + BagPocket_SetSlotData(pocket, to, fromSlot); } } @@ -596,13 +547,14 @@ void ClearBag(void) static inline u16 NONNULL BagPocket_CountTotalItemQuantity(struct BagPocket *pocket, u16 itemId) { - u16 tempItemId, tempQuantity, ownedCount = 0; + u32 ownedCount = 0; + struct ItemSlot tempItem; for (u32 i = 0; i < pocket->capacity; i++) { - BagPocket_GetSlotData(pocket, i, &tempItemId, &tempQuantity); - if (tempItemId == itemId) - ownedCount += tempQuantity; + tempItem = BagPocket_GetSlotData(pocket, i); + if (tempItem.itemId == itemId) + ownedCount += tempItem.quantity; } return ownedCount; diff --git a/src/item_menu.c b/src/item_menu.c index d6e3598b58..6d1fb43077 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -89,6 +89,10 @@ enum { ACTION_SHOW, ACTION_GIVE_FAVOR_LADY, ACTION_CONFIRM_QUIZ_LADY, + ACTION_BY_NAME, + ACTION_BY_TYPE, + ACTION_BY_AMOUNT, + ACTION_BY_INDEX, ACTION_DUMMY, }; @@ -218,6 +222,19 @@ static const u8 sText_DepositedVar2Var1s[] = _("Deposited {STR_VAR_2}\n{STR_VAR_ static const u8 sText_NoRoomForItems[] = _("There's no room to\nstore items."); static const u8 sText_CantStoreImportantItems[] = _("Important items\ncan't be stored in\nthe PC!"); +static void Task_LoadBagSortOptions(u8 taskId); +static void ItemMenu_SortByName(u8 taskId); +static void ItemMenu_SortByType(u8 taskId); +static void ItemMenu_SortByAmount(u8 taskId); +static void ItemMenu_SortByIndex(u8 taskId); +static void SortBagItems(u8 taskId); +static void Task_SortFinish(u8 taskId); +static void MergeSort(struct BagPocket *pocket, s32 (*comparator)(enum Pocket, struct ItemSlot, struct ItemSlot)); +static s32 CompareItemsAlphabetically(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2); +static s32 CompareItemsByMost(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2); +static s32 CompareItemsByType(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2); +static s32 CompareItemsByIndex(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2); + static const struct BgTemplate sBgTemplates_ItemMenu[] = { { @@ -271,6 +288,7 @@ static const struct ListMenuTemplate sItemListMenu = .cursorKind = CURSOR_BLACK_ARROW }; +static const u8 sText_NothingToSort[] = _("There's nothing to sort!"); static const struct MenuAction sItemMenuActions[] = { [ACTION_USE] = {gMenuText_Use, {ItemMenu_UseOutOfBattle}}, [ACTION_TOSS] = {gMenuText_Toss, {ItemMenu_Toss}}, @@ -286,6 +304,10 @@ static const struct MenuAction sItemMenuActions[] = { [ACTION_SHOW] = {COMPOUND_STRING("SHOW"), {ItemMenu_Show}}, [ACTION_GIVE_FAVOR_LADY] = {gMenuText_Give2, {ItemMenu_GiveFavorLady}}, [ACTION_CONFIRM_QUIZ_LADY] = {gMenuText_Confirm, {ItemMenu_ConfirmQuizLady}}, + [ACTION_BY_NAME] = {COMPOUND_STRING("Name"), {ItemMenu_SortByName}}, + [ACTION_BY_TYPE] = {COMPOUND_STRING("Type"), {ItemMenu_SortByType}}, + [ACTION_BY_AMOUNT] = {COMPOUND_STRING("Amount"), {ItemMenu_SortByAmount}}, + [ACTION_BY_INDEX] = {COMPOUND_STRING("Index"), {ItemMenu_SortByIndex}}, [ACTION_DUMMY] = {gText_EmptyString2, {NULL}} }; @@ -966,7 +988,6 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) { if (itemIndex != LIST_CANCEL) { - u16 itemId, itemQuantity; s32 offset; if (gBagMenu->toSwapPos != NOT_SWAPPING) @@ -978,16 +999,16 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) BagMenu_PrintCursorAtPos(y, COLORID_NONE); } - GetBagItemIdAndQuantity(gBagPosition.pocket, itemIndex, &itemId, &itemQuantity); + struct ItemSlot itemSlot = GetBagItemIdAndQuantity(gBagPosition.pocket, itemIndex); // Draw HM icon - if (gBagPosition.pocket == POCKET_TM_HM && GetItemTMHMIndex(itemId) > NUM_TECHNICAL_MACHINES) + if (gBagPosition.pocket == POCKET_TM_HM && GetItemTMHMIndex(itemSlot.itemId) > NUM_TECHNICAL_MACHINES) BlitBitmapToWindow(windowId, gBagMenuHMIcon_Gfx, 8, y - 1, 16, 16); - if (gBagPosition.pocket != POCKET_KEY_ITEMS && GetItemImportance(itemId) == FALSE) + if (gBagPosition.pocket != POCKET_KEY_ITEMS && GetItemImportance(itemSlot.itemId) == FALSE) { // Print item quantity - ConvertIntToDecimalStringN(gStringVar1, itemQuantity, STR_CONV_MODE_RIGHT_ALIGN, MAX_ITEM_DIGITS); + ConvertIntToDecimalStringN(gStringVar1, itemSlot.quantity, STR_CONV_MODE_RIGHT_ALIGN, MAX_ITEM_DIGITS); StringExpandPlaceholders(gStringVar4, gText_xVar1); offset = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 119); BagMenu_Print(windowId, FONT_NARROW, gStringVar4, offset, y, 0, 0, TEXT_SKIP_DRAW, COLORID_NORMAL); @@ -995,7 +1016,7 @@ static void BagMenu_ItemPrintCallback(u8 windowId, u32 itemIndex, u8 y) else { // Print registered icon - if (gSaveBlock1Ptr->registeredItem != ITEM_NONE && gSaveBlock1Ptr->registeredItem == itemId) + if (gSaveBlock1Ptr->registeredItem != ITEM_NONE && gSaveBlock1Ptr->registeredItem == itemSlot.itemId) BlitBitmapToWindow(windowId, sRegisteredSelect_Gfx, 96, y - 1, 24, 16); } } @@ -1125,16 +1146,17 @@ static void Task_CloseBagMenu(u8 taskId) } } -void UpdatePocketItemList(u8 pocketId) +void UpdatePocketItemList(enum Pocket pocketId) { - u16 i; + if (pocketId >= POCKETS_COUNT) + return; // shouldn't even get here + + struct BagPocket *pocket = &gBagPockets[pocketId]; switch (pocketId) { case POCKET_TM_HM: - SortPocket(pocketId, SORT_POCKET_TM_HM); - break; case POCKET_BERRIES: - SortPocket(pocketId, SORT_POCKET_BY_ITEM_ID); + SortItemsInBag(pocket, SORT_BY_INDEX); break; default: CompactItemsInBagPocket(pocketId); @@ -1143,7 +1165,7 @@ void UpdatePocketItemList(u8 pocketId) gBagMenu->numItemStacks[pocketId] = 0; - for (i = 0; i < gBagPockets[pocketId].capacity && GetBagItemId(pocketId, i); i++) + for (u32 i = 0; i < pocket->capacity && BagPocket_GetSlotData(pocket, i).itemId; i++) gBagMenu->numItemStacks[pocketId]++; if (!gBagMenu->hideCloseBagText) @@ -1263,6 +1285,34 @@ static void Task_BagMenu_HandleInput(u8 taskId) } return; } + else if (JOY_NEW(START_BUTTON)) + { + if ((gBagMenu->numItemStacks[gBagPosition.pocket] - 1) <= 1) //can't sort with 0 or 1 item in bag + { + static const u8 sText_NothingToSort[] = _("There's nothing to sort!"); + PlaySE(SE_FAILURE); + DisplayItemMessage(taskId, 1, sText_NothingToSort, HandleErrorMessage); + break; + } + else + { + struct ItemSlot tempItem; + data[1] = GetItemListPosition(gBagPosition.pocket); + tempItem = GetBagItemIdAndQuantity(gBagPosition.pocket, data[1]); + data[2] = tempItem.quantity; + if (gBagPosition.cursorPosition[gBagPosition.pocket] == gBagMenu->numItemStacks[gBagPosition.pocket]) + break; + else + gSpecialVar_ItemId = tempItem.itemId; + + PlaySE(SE_SELECT); + BagDestroyPocketScrollArrowPair(); + BagMenu_PrintCursor(tListTaskId, COLORID_GRAY_CURSOR); + ListMenuGetScrollAndRow(data[0], scrollPos, cursorPos); + gTasks[taskId].func = Task_LoadBagSortOptions; + return; + } + } break; } @@ -1283,12 +1333,16 @@ static void Task_BagMenu_HandleInput(u8 taskId) gTasks[taskId].func = Task_FadeAndCloseBagMenu; break; default: // A_BUTTON - PlaySE(SE_SELECT); - BagDestroyPocketScrollArrowPair(); - BagMenu_PrintCursor(tListTaskId, COLORID_GRAY_CURSOR); - tListPosition = listPosition; - GetBagItemIdAndQuantity(gBagPosition.pocket, listPosition, &gSpecialVar_ItemId, (u16*)&tQuantity); - sContextMenuFuncs[gBagPosition.location](taskId); + { + struct ItemSlot itemSlot = GetBagItemIdAndQuantity(gBagPosition.pocket, listPosition); + PlaySE(SE_SELECT); + BagDestroyPocketScrollArrowPair(); + BagMenu_PrintCursor(tListTaskId, COLORID_GRAY_CURSOR); + tListPosition = listPosition; + gSpecialVar_ItemId = itemSlot.itemId; + tQuantity = itemSlot.quantity; + sContextMenuFuncs[gBagPosition.location](taskId); + } break; } } @@ -2639,3 +2693,310 @@ static void PrintTMHMMoveData(u16 itemId) CopyWindowToVram(WIN_TMHM_INFO, COPYWIN_GFX); } } + +static const u8 sText_SortItemsHow[] = _("Sort items how?"); +static const u8 sText_ItemsSorted[] = _("Items sorted by {STR_VAR_1}!"); +static const u8 *const sSortTypeStrings[] = +{ + [SORT_ALPHABETICALLY] = COMPOUND_STRING("name"), + [SORT_BY_TYPE] = COMPOUND_STRING("type"), + [SORT_BY_AMOUNT] = COMPOUND_STRING("amount"), + [SORT_BY_INDEX] = COMPOUND_STRING("index") +}; + +static const u8 sBagMenuSortItems[] = +{ + ACTION_BY_NAME, + ACTION_BY_TYPE, + ACTION_BY_AMOUNT, + ACTION_CANCEL, +}; + +static const u8 sBagMenuSortKeyItems[] = +{ + ACTION_BY_NAME, + ACTION_CANCEL, +}; + +static const u8 sBagMenuSortPokeBalls[] = +{ + ACTION_BY_NAME, + ACTION_BY_AMOUNT, + ACTION_DUMMY, + ACTION_CANCEL, +}; + +static const u8 sBagMenuSortBerriesTMsHMs[] = +{ + ACTION_BY_NAME, + ACTION_BY_AMOUNT, + ACTION_BY_INDEX, + ACTION_CANCEL, +}; + +static void AddBagSortSubMenu(void) +{ + switch (gBagPosition.pocket) + { + case POCKET_KEY_ITEMS: + gBagMenu->contextMenuItemsPtr = sBagMenuSortKeyItems; + memcpy(&gBagMenu->contextMenuItemsBuffer, &sBagMenuSortKeyItems, NELEMS(sBagMenuSortKeyItems)); + gBagMenu->contextMenuNumItems = NELEMS(sBagMenuSortKeyItems); + break; + case POCKET_POKE_BALLS: + gBagMenu->contextMenuItemsPtr = sBagMenuSortPokeBalls; + memcpy(&gBagMenu->contextMenuItemsBuffer, &sBagMenuSortPokeBalls, NELEMS(sBagMenuSortPokeBalls)); + gBagMenu->contextMenuNumItems = NELEMS(sBagMenuSortPokeBalls); + break; + case POCKET_BERRIES: + case POCKET_TM_HM: + gBagMenu->contextMenuItemsPtr = sBagMenuSortBerriesTMsHMs; + memcpy(&gBagMenu->contextMenuItemsBuffer, &sBagMenuSortBerriesTMsHMs, NELEMS(sBagMenuSortBerriesTMsHMs)); + gBagMenu->contextMenuNumItems = NELEMS(sBagMenuSortBerriesTMsHMs); + break; + default: + gBagMenu->contextMenuItemsPtr = sBagMenuSortItems; + memcpy(&gBagMenu->contextMenuItemsBuffer, &sBagMenuSortItems, NELEMS(sBagMenuSortItems)); + gBagMenu->contextMenuNumItems = NELEMS(sBagMenuSortItems); + break; + } + + StringExpandPlaceholders(gStringVar4, sText_SortItemsHow); + FillWindowPixelBuffer(1, PIXEL_FILL(0)); + BagMenu_Print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + + if (gBagMenu->contextMenuNumItems == 2) + PrintContextMenuItems(BagMenu_AddWindow(ITEMWIN_1x2)); + else if (gBagMenu->contextMenuNumItems == 4) + PrintContextMenuItemGrid(BagMenu_AddWindow(ITEMWIN_2x2), 2, 2); + else + PrintContextMenuItemGrid(BagMenu_AddWindow(ITEMWIN_2x3), 2, 3); +} + +static void Task_LoadBagSortOptions(u8 taskId) +{ + AddBagSortSubMenu(); + if (gBagMenu->contextMenuNumItems <= 2) + gTasks[taskId].func = Task_ItemContext_SingleRow; + else + gTasks[taskId].func = Task_ItemContext_MultipleRows; +} + +#define tSortType data[2] +static void ItemMenu_SortByName(u8 taskId) +{ + gTasks[taskId].tSortType = SORT_ALPHABETICALLY; + StringCopy(gStringVar1, sSortTypeStrings[SORT_ALPHABETICALLY]); + gTasks[taskId].func = SortBagItems; +} + +static void ItemMenu_SortByType(u8 taskId) +{ + gTasks[taskId].tSortType = SORT_BY_TYPE; + StringCopy(gStringVar1, sSortTypeStrings[SORT_BY_TYPE]); + gTasks[taskId].func = SortBagItems; +} + +static void ItemMenu_SortByAmount(u8 taskId) +{ + gTasks[taskId].tSortType = SORT_BY_AMOUNT; //greatest->least + StringCopy(gStringVar1, sSortTypeStrings[SORT_BY_AMOUNT]); + gTasks[taskId].func = SortBagItems; +} + +static void ItemMenu_SortByIndex(u8 taskId) +{ + gTasks[taskId].tSortType = SORT_BY_INDEX; + StringCopy(gStringVar1, sSortTypeStrings[SORT_BY_INDEX]); + gTasks[taskId].func = SortBagItems; +} + +static void SortBagItems(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u16 *scrollPos = &gBagPosition.scrollPosition[gBagPosition.pocket]; + u16 *cursorPos = &gBagPosition.cursorPosition[gBagPosition.pocket]; + + RemoveContextWindow(); + + SortItemsInBag(&gBagPockets[gBagPosition.pocket], tSortType); + DestroyListMenuTask(data[0], scrollPos, cursorPos); + UpdatePocketListPosition(gBagPosition.pocket); + LoadBagItemListBuffers(gBagPosition.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + ScheduleBgCopyTilemapToVram(0); + + StringCopy(gStringVar1, sSortTypeStrings[tSortType]); + StringExpandPlaceholders(gStringVar4, sText_ItemsSorted); + DisplayItemMessage(taskId, 1, gStringVar4, Task_SortFinish); +} + +#undef tSortType + +static void Task_SortFinish(u8 taskId) +{ + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + RemoveItemMessageWindow(4); + ReturnToItemList(taskId); + } +} + +void SortItemsInBag(struct BagPocket *pocket, enum BagSortOptions type) +{ + switch (type) + { + case SORT_ALPHABETICALLY: + MergeSort(pocket, CompareItemsAlphabetically); + break; + case SORT_BY_AMOUNT: + MergeSort(pocket, CompareItemsByMost); + break; + case SORT_BY_INDEX: + MergeSort(pocket, CompareItemsByIndex); + break; + default: + MergeSort(pocket, CompareItemsByType); + break; + } +} + +static inline __attribute__((always_inline)) void Merge(struct BagPocket *pocket, u32 iLeft, u32 iRight, u32 iEnd, struct ItemSlot *dummySlots, s32 (*comparator)(enum Pocket, struct ItemSlot, struct ItemSlot)) +{ + struct ItemSlot item_i, item_j; + u32 i = iLeft, j = iRight; + for (u32 k = iLeft; k < iEnd; k++) + { + item_i = BagPocket_GetSlotData(pocket, i); + item_j = BagPocket_GetSlotData(pocket, j); + if (i < iRight && (j >= iEnd || comparator(pocket->id, item_i, item_j) < 0)) + { + dummySlots[k] = item_i; + i++; + } + else + { + dummySlots[k] = item_j; + j++; + } + } +} + +// Source: https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation +static void MergeSort(struct BagPocket *pocket, s32 (*comparator)(enum Pocket, struct ItemSlot, struct ItemSlot)) +{ + struct ItemSlot *dummySlots = AllocZeroed(sizeof(struct ItemSlot) * pocket->capacity); + + for (u32 width = 1; width < pocket->capacity; width *= 2) + { + for (u32 i = 0; i < pocket->capacity; i += 2 * width) + Merge(pocket, i, min(i + width, pocket->capacity), min(i + 2 * width, pocket->capacity), dummySlots, comparator); + + for (u32 j = 0; j < pocket->capacity; j++) + BagPocket_SetSlotData(pocket, j, dummySlots[j]); + } + + Free(dummySlots); +} + +static s32 CompareItemsAlphabetically(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) +{ + const u8 *name1, *name2; + + if (item1.itemId == ITEM_NONE) + return 1; + else if (item2.itemId == ITEM_NONE) + return -1; + + if (pocketId == POCKET_TM_HM) + { + name1 = gMovesInfo[GetTMHMMoveId(GetItemTMHMIndex(item1.itemId))].name; + name2 = gMovesInfo[GetTMHMMoveId(GetItemTMHMIndex(item2.itemId))].name; + } + else + { + name1 = GetItemName(item1.itemId); + name2 = GetItemName(item2.itemId); + } + + for (u32 i = 0; ; ++i) + { + if (name1[i] == EOS && name2[i] != EOS) + return -1; + else if (name1[i] != EOS && name2[i] == EOS) + return 1; + else if (name1[i] == EOS && name2[i] == EOS) + return 0; + + if (name1[i] < name2[i]) + return -1; + else if (name1[i] > name2[i]) + return 1; + } + + return 0; // Will never be reached +} + +static s32 CompareItemsByMost(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) +{ + if (item1.itemId == ITEM_NONE) + return 1; + else if (item2.itemId == ITEM_NONE) + return -1; + + if (item1.quantity < item2.quantity) + return 1; + else if (item1.quantity > item2.quantity) + return -1; + + return CompareItemsAlphabetically(pocketId, item1, item2); // Items have same quantity so sort alphabetically +} + +static s32 CompareItemsByType(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) +{ + enum ItemSortType type1 = gItemsInfo[item1.itemId].sortType; + enum ItemSortType type2 = gItemsInfo[item2.itemId].sortType; + + // Null and uncategorized items go last + if (type1 && !type2) + return -1; + else if (type2 && !type1) + return 1; + else if (type1 < type2) + return -1; + else if (type1 > type2) + return 1; + + return CompareItemsAlphabetically(pocketId, item1, item2); // Items are of same type so sort alphabetically +} + +static s32 CompareItemsByIndex(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) +{ + u16 index1 = 0, index2 = 0; + + if (item1.itemId == ITEM_NONE) + return 1; + else if (item2.itemId == ITEM_NONE) + return -1; + + switch (pocketId) + { + case POCKET_TM_HM: + index1 = GetItemTMHMIndex(item1.itemId); + index2 = GetItemTMHMIndex(item2.itemId); + break; + case POCKET_BERRIES: // To do - requires #7305 + index1 = item1.itemId; + index2 = item2.itemId; + break; + default: + return 0; + } + + if (index1 < index2) + return -1; + else if (index1 > index2) + return 1; + + return 0; // Cannot have multiple stacks of indexed items +} diff --git a/src/menu_helpers.c b/src/menu_helpers.c index e1483c9579..3b97d1f404 100644 --- a/src/menu_helpers.c +++ b/src/menu_helpers.c @@ -322,13 +322,12 @@ bool8 MenuHelpers_ShouldWaitForLinkRecv(void) void SetItemListPerPageCount(struct ItemSlot *slots, u8 slotsCount, u8 *pageItems, u8 *totalItems, u8 maxPerPage) { u16 i; - struct ItemSlot *slots_ = slots; // Count the number of non-empty item slots *totalItems = 0; for (i = 0; i < slotsCount; i++) { - if (slots_[i].itemId != ITEM_NONE) + if (slots[i].itemId != ITEM_NONE) (*totalItems)++; } (*totalItems)++; // + 1 for 'Cancel' diff --git a/test/bag.c b/test/bag.c index 6d0620dd6e..fe33d01eee 100644 --- a/test/bag.c +++ b/test/bag.c @@ -1,7 +1,7 @@ #include "global.h" #include "battle.h" #include "event_data.h" -#include "item.h" +#include "item_menu.h" #include "pokemon.h" #include "test/overworld_script.h" #include "test/test.h" @@ -19,6 +19,11 @@ TEST("TMs and HMs are sorted correctly in the bag") ASSUME(GetItemPocket(ITEM_TM01) == POCKET_TM_HM); ASSUME(GetItemPocket(ITEM_HM02) == POCKET_TM_HM); + /* + * Note: I would add a test to make sure that TMs are sorted correctly by move name, + * but downstream users are likely to rearrange TMs so this would just be a nuisance. + */ + RUN_OVERWORLD_SCRIPT( additem ITEM_HM07; additem ITEM_TM25; @@ -30,7 +35,7 @@ TEST("TMs and HMs are sorted correctly in the bag") additem ITEM_HM02; ); - SortPocket(POCKET_TM_HM, SORT_POCKET_TM_HM); + SortItemsInBag(&gBagPockets[POCKET_TM_HM], SORT_BY_INDEX); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_TM01); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_TM05); @@ -67,7 +72,7 @@ TEST("Berries are sorted correctly in the bag") additem ITEM_CHERI_BERRY; ); - SortPocket(POCKET_BERRIES, SORT_POCKET_BY_ITEM_ID); + SortItemsInBag(&gBagPockets[POCKET_BERRIES], SORT_BY_INDEX); EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_CHERI_BERRY); EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_ORAN_BERRY); @@ -78,9 +83,21 @@ TEST("Berries are sorted correctly in the bag") EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_GANLON_BERRY); EXPECT_EQ(pocket->itemSlots[7].itemId, ITEM_MICLE_BERRY); EXPECT_EQ(pocket->itemSlots[8].itemId, ITEM_NONE); + + SortItemsInBag(&gBagPockets[POCKET_BERRIES], SORT_ALPHABETICALLY); + + EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_CHARTI_BERRY); + EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_CHERI_BERRY); + EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_GANLON_BERRY); + EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_KELPSY_BERRY); + EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_MAGOST_BERRY); + EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_MICLE_BERRY); + EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_ORAN_BERRY); + EXPECT_EQ(pocket->itemSlots[7].itemId, ITEM_POMEG_BERRY); + EXPECT_EQ(pocket->itemSlots[8].itemId, ITEM_NONE); } -TEST("Items are correctly compacted in the bag") +TEST("Items are correctly sorted and compacted in the bag") { struct BagPocket *pocket = &gBagPockets[POCKET_ITEMS]; memset(pocket->itemSlots, 0, sizeof(gSaveBlock1Ptr->bag.items)); @@ -115,21 +132,31 @@ TEST("Items are correctly compacted in the bag") EXPECT_EQ(pocket->itemSlots[5].quantity, 1); EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); - // Try removing the small items, check that everything is compacted correctly + SortItemsInBag(&gBagPockets[POCKET_ITEMS], SORT_ALPHABETICALLY); + + EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_NUGGET); + EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_PEARL); + EXPECT_EQ(pocket->itemSlots[5].itemId, ITEM_TINY_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[6].itemId, ITEM_NONE); + + // Try removing the big items, check that everything is compacted correctly RUN_OVERWORLD_SCRIPT( - removeitem ITEM_NUGGET; - removeitem ITEM_TINY_MUSHROOM; - removeitem ITEM_PEARL; + removeitem ITEM_BIG_NUGGET; + removeitem ITEM_BIG_MUSHROOM; + removeitem ITEM_BIG_PEARL; ); CompactItemsInBagPocket(POCKET_ITEMS); - EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_BIG_NUGGET); + EXPECT_EQ(pocket->itemSlots[0].itemId, ITEM_NUGGET); EXPECT_EQ(pocket->itemSlots[0].quantity, 1); - EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_BIG_MUSHROOM); + EXPECT_EQ(pocket->itemSlots[1].itemId, ITEM_PEARL); EXPECT_EQ(pocket->itemSlots[1].quantity, 1); - EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_BIG_PEARL); + EXPECT_EQ(pocket->itemSlots[2].itemId, ITEM_TINY_MUSHROOM); EXPECT_EQ(pocket->itemSlots[2].quantity, 1); EXPECT_EQ(pocket->itemSlots[3].itemId, ITEM_NONE); EXPECT_EQ(pocket->itemSlots[4].itemId, ITEM_NONE); From dc1abb72dc7e64ad225cd556dca256eb47942e6a Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Tue, 29 Jul 2025 12:13:29 +0100 Subject: [PATCH 145/283] Fix substruct offsets from #7313 (#7431) --- src/pokemon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index 8ddfd5d5b4..bcbf672bd9 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2226,10 +2226,10 @@ static void DecryptBoxMon(struct BoxPokemon *boxMon) static const u8 sSubstructOffsets[4][24] = { - [SUBSTRUCT_TYPE_0] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}, - [SUBSTRUCT_TYPE_1] = {1, 1, 2, 2, 3, 3, 0, 0, 2, 2, 3, 3, 0, 0, 1, 1, 3, 3, 0, 0, 1, 1, 2, 2}, - [SUBSTRUCT_TYPE_2] = {2, 3, 1, 3, 1, 2, 2, 3, 0, 3, 0, 2, 1, 3, 0, 3, 0, 1, 1, 2, 0, 2, 0, 1}, - [SUBSTRUCT_TYPE_3] = {3, 2, 3, 1, 2, 1, 3, 2, 3, 0, 2, 0, 3, 1, 3, 0, 1, 0, 2, 1, 2, 0, 1, 0} + [SUBSTRUCT_TYPE_0] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3}, + [SUBSTRUCT_TYPE_1] = {1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2}, + [SUBSTRUCT_TYPE_2] = {2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 3, 2, 3, 2, 1, 1}, + [SUBSTRUCT_TYPE_3] = {3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0}, }; ARM_FUNC NOINLINE static u32 ConstantMod24(u32 a) { return a % 24; } From 6a96be81818cd9a659c0ebfb1e8e143993013f76 Mon Sep 17 00:00:00 2001 From: Hedara Date: Mon, 28 Jul 2025 19:30:43 +0200 Subject: [PATCH 146/283] Changed incorrect comment --- src/pokenav_main_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokenav_main_menu.c b/src/pokenav_main_menu.c index d2765b6706..547a2d84b5 100644 --- a/src/pokenav_main_menu.c +++ b/src/pokenav_main_menu.c @@ -32,7 +32,7 @@ struct Pokenav_MainMenu // Needed to match LoadLeftHeaderGfxForSubMenu. struct CompressedSpriteSheetNoSize { - const u32 *data; // LZ77 compressed palette data + const u32 *data; // Compressed sprite data u32 tag; }; From cb4450efaf0d62d1817cb44c369ac48f53257d95 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:54:12 +0200 Subject: [PATCH 147/283] Fixes Effect Spore and Baneful Bunker/Burning Bulwark (#7412) --- include/battle.h | 3 ++- src/battle_script_commands.c | 8 ++++-- src/battle_util.c | 20 +++++++++----- test/battle/ability/effect_spore.c | 18 +++++++++++++ test/battle/move_effect/protect.c | 42 ++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 10 deletions(-) diff --git a/include/battle.h b/include/battle.h index d59432e6c1..79cc591980 100644 --- a/include/battle.h +++ b/include/battle.h @@ -666,7 +666,8 @@ struct BattleStruct u8 anyMonHasTransformed:1; // Only used in battle_tv.c u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; - u8 padding1:2; + u8 sleepClauseNotBlocked:1; + u8 padding1:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f39c7a2386..6798b9bd9c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6543,7 +6543,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BANEFUL_BUNKER: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_POISON | MOVE_EFFECT_AFFECTS_USER; @@ -6554,7 +6555,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BURNING_BULWARK: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER; @@ -6728,6 +6730,7 @@ static void Cmd_moveend(void) { BestowItem(BATTLE_PARTNER(i), i); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; + gEffectBattler = i; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); gBattlerAttacker = i; BattleScriptPushCursor(); @@ -9231,6 +9234,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; + gEffectBattler = battler; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); if (moveEnd) BattleScriptPushCursor(); diff --git a/src/battle_util.c b/src/battle_util.c index d2303bca8a..e580c63616 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4627,9 +4627,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_EFFECT_SPORE: { - u32 ability = GetBattlerAbility(gBattlerAttacker); + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if ((!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) || B_POWDER_GRASS < GEN_6) - && ability != ABILITY_OVERCOAT + && abilityAtk != ABILITY_OVERCOAT && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { u32 poison, paralysis, sleep; @@ -4657,7 +4657,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) + && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { if (IsSleepClauseEnabled()) @@ -5553,17 +5553,23 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause) { - if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause) + if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE) return FALSE; + if (isBlockedBySleepClause == NOT_BLOCKED_BY_SLEEP_CLAUSE) + gBattleStruct->sleepClauseNotBlocked = TRUE; + + bool32 effect = FALSE; if (CanSetNonVolatileStatus(battlerAtk, battlerDef, ABILITY_NONE, // attacker ability does not matter abilityDef, MOVE_EFFECT_SLEEP, // also covers yawn STATUS_CHECK_TRIGGER)) - return TRUE; - return FALSE; + effect = TRUE; + + gBattleStruct->sleepClauseNotBlocked = FALSE; + return effect; } bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) @@ -5714,7 +5720,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_CantMakeAsleep; } - else if (CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) + else if (!gBattleStruct->sleepClauseNotBlocked && CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) { battleScript = BattleScript_SleepClauseBlocked; } diff --git a/test/battle/ability/effect_spore.c b/test/battle/ability/effect_spore.c index 57f5399b53..ff61683b54 100644 --- a/test/battle/ability/effect_spore.c +++ b/test/battle/ability/effect_spore.c @@ -88,3 +88,21 @@ SINGLE_BATTLE_TEST("Effect Spore causes sleep 11% of the time") STATUS_ICON(player, sleep: TRUE); } } + +SINGLE_BATTLE_TEST("Effect Spore will check if it can inflict status onto attacker, not itself") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Status1(STATUS1_BURN); Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + } +} diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 09fc4c12bf..6dddfae4e7 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -194,6 +194,27 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making con } } +SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_WILL_O_WISP); } + TURN { MOVE(opponent, MOVE_BANEFUL_BUNKER); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, opponent); + STATUS_ICON(player, STATUS1_BURN); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BANEFUL_BUNKER, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_POISON); + } + } +} + SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making contact") { u16 usedMove = MOVE_NONE; @@ -226,6 +247,27 @@ SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making cont } } +SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TOXIC); } + TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent); + STATUS_ICON(player, STATUS1_TOXIC_POISON); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURNING_BULWARK, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_BURN); + } + } +} + SINGLE_BATTLE_TEST("Protect: Recoil damage is not applied if target was protected") { u32 j, k; From d8059ce3d1879c0fb9d3c834036c31f34684c54d Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 30 Jul 2025 20:34:43 +0200 Subject: [PATCH 148/283] 1.12.2 release version --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 +- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 +- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 +- README.md | 2 +- docs/SUMMARY.md | 1 + docs/changelogs/1.12.x/1.12.2.md | 164 ++++++++++++++++++ include/constants/expansion.h | 4 +- 7 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 docs/changelogs/1.12.x/1.12.2.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 1ab103d6c7..b48cda404c 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 49bf8a5525..95b00ef2d1 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 0d25f6a96a..d955d09cbc 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/README.md b/README.md index 6d86c27a2a..4cd0a5f161 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.12.1 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.12.2 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 258d078cdb..89767de31b 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -20,6 +20,7 @@ - [Day/Night System FAQ](tutorials/dns.md) - [Changelog](./CHANGELOG.md) - [1.12.x]() + - [Version 1.12.2](changelogs/1.12.x/1.12.2.md) - [Version 1.12.1](changelogs/1.12.x/1.12.1.md) - [Version 1.12.0](changelogs/1.12.x/1.12.0.md) - [1.11.x]() diff --git a/docs/changelogs/1.12.x/1.12.2.md b/docs/changelogs/1.12.x/1.12.2.md new file mode 100644 index 0000000000..9f1b210638 --- /dev/null +++ b/docs/changelogs/1.12.x/1.12.2.md @@ -0,0 +1,164 @@ +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.12.1 +`. +``` + + +## 🧬 General 🧬 +### Changed +* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044) +* Update CI to ignore allcontributors commits by @pkmnsnfrn in [#7046](https://github.com/rh-hideout/pokeemerald-expansion/pull/7046) +* add bassforte123 as a contributor for code by @allcontributors[bot] in [#7003](https://github.com/rh-hideout/pokeemerald-expansion/pull/7003) +* add iriv24 as a contributor for code by @allcontributors[bot] in [#7059](https://github.com/rh-hideout/pokeemerald-expansion/pull/7059) +* add Bivurnum as a contributor for code by @allcontributors[bot] in [#7067](https://github.com/rh-hideout/pokeemerald-expansion/pull/7067) +* Fixed CI issue introduced 7046 by @pkmnsnfrn in [#7072](https://github.com/rh-hideout/pokeemerald-expansion/pull/7072) +* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092) +* add Emiliasky as a contributor for test by @allcontributors[bot] in [#7082](https://github.com/rh-hideout/pokeemerald-expansion/pull/7082) +* Update CREDITS.md with correct line placement by @pkmnsnfrn in [#7096](https://github.com/rh-hideout/pokeemerald-expansion/pull/7096) +* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116) +* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133) +* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104) +* add fakuzatsu as a contributor for code by @allcontributors[bot] in [#7136](https://github.com/rh-hideout/pokeemerald-expansion/pull/7136) +* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152) +* add poetahto as a contributor for code by @allcontributors[bot] in [#7162](https://github.com/rh-hideout/pokeemerald-expansion/pull/7162) +* Pret merge (19th of June, 2025) by @Bassoonian in [#7163](https://github.com/rh-hideout/pokeemerald-expansion/pull/7163) +* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184) +* fix: use BackPickId to calculate player intro ball throw animation palette by @pablopenna in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193) +* add pablopenna as a contributor for code by @allcontributors[bot] in [#7202](https://github.com/rh-hideout/pokeemerald-expansion/pull/7202) + +### Fixed +* Added line break between Trainer 1 name and Trainer 2 name in sText_TwoTrainersWantToBattle by @grintoul1 in [#7028](https://github.com/rh-hideout/pokeemerald-expansion/pull/7028) +* Fixed Battle Pyramid mon generation by @hedara90 in [#7146](https://github.com/rh-hideout/pokeemerald-expansion/pull/7146) +* force sGFRomHeader to always be present by @DizzyEggg in [#7186](https://github.com/rh-hideout/pokeemerald-expansion/pull/7186) +* force RHH Rom Header to always be present by @DizzyEggg in [#7187](https://github.com/rh-hideout/pokeemerald-expansion/pull/7187) +* Fixed debug flag menu sound by @AsparagusEduardo in [#7190](https://github.com/rh-hideout/pokeemerald-expansion/pull/7190) +* Fix BtlController_EmitChosenMonReturnValue UB by @DizzyEggg in [#7197](https://github.com/rh-hideout/pokeemerald-expansion/pull/7197) +* Backported Safari catch and add to party fix by @hedara90 in [#7192](https://github.com/rh-hideout/pokeemerald-expansion/pull/7192) +* Fix 01_battle_engine_bugs.yaml by @hedara90 in [#7242](https://github.com/rh-hideout/pokeemerald-expansion/pull/7242) + +## 🗺️ Overworld 🗺️ +### Fixed +* Bug fix: clear saved follower NPC door warp when doing dive warp by @Bivurnum in [#7065](https://github.com/rh-hideout/pokeemerald-expansion/pull/7065) +* Fix Contest Painting load palette error by @ExMingYan in [#7077](https://github.com/rh-hideout/pokeemerald-expansion/pull/7077) +* Bug fix: Follower NPC no longer retains bike sprite after white out by @Bivurnum in [#7120](https://github.com/rh-hideout/pokeemerald-expansion/pull/7120) +* Bug fix: clear follower npc surf blob on white out by @Bivurnum in [#7153](https://github.com/rh-hideout/pokeemerald-expansion/pull/7153) + +## 🐉 Pokémon 🐉 +### Changed +* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181) + +### Fixed +* Fixed text width for a lot of forms in HGSS Dex by @AsparagusEduardo in [#7035](https://github.com/rh-hideout/pokeemerald-expansion/pull/7035) +* Fixes Roamers not saving shininess by @i0brendan0 in [#7185](https://github.com/rh-hideout/pokeemerald-expansion/pull/7185) +* [FIX] Prevent caught Pokémon loss in NPC partner battles by @J2M2 in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177) + + + +## ⚔️ Battle General ⚔️ +### Changed +* Fixes large battle messages being cut off instead of being prompted to advance 2 by @PhallenTree in [#7036](https://github.com/rh-hideout/pokeemerald-expansion/pull/7036) +* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029) +* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107) + +### Fixed +* Fixes multi battle party re-order by @AlexOn1ine in [#7042](https://github.com/rh-hideout/pokeemerald-expansion/pull/7042) +* Fixes Aura Wheel + Normalize and Hunger Switch while Transformed/Terastallized by @PhallenTree in [#7061](https://github.com/rh-hideout/pokeemerald-expansion/pull/7061) +* Fixes speed calculation order by @AlexOn1ine in [#7064](https://github.com/rh-hideout/pokeemerald-expansion/pull/7064) +* Bug fix for Grassy Terrain incorrectly healing non-grounded Pokemon by @LinathanZel in [#7058](https://github.com/rh-hideout/pokeemerald-expansion/pull/7058) +* Fixes Wandering Spirit copied ability activation on fainted mon by @AlexOn1ine in [#7066](https://github.com/rh-hideout/pokeemerald-expansion/pull/7066) +* Chloroblast fix by @LinathanZel in [#7008](https://github.com/rh-hideout/pokeemerald-expansion/pull/7008) + + + * Chloroblast causing recoil damage even if the move fails to connect by @LinathanZel in #7007 + + +* [DRAFT] Fix Normalize not boosting Normal type moves if they were already Normal type by @i0brendan0 in [#7060](https://github.com/rh-hideout/pokeemerald-expansion/pull/7060) +* Fixes freeze during a 1v2 double battle by @AlexOn1ine in [#7075](https://github.com/rh-hideout/pokeemerald-expansion/pull/7075) +* Fixes Pursuit potentially causing both battlers to switch into the same mon by @PhallenTree in [#7084](https://github.com/rh-hideout/pokeemerald-expansion/pull/7084) +* Fixed potential mismatch between players and battlers in tests by @AsparagusEduardo in [#7101](https://github.com/rh-hideout/pokeemerald-expansion/pull/7101) +* Fixes Ally Switch in multi battles by @AlexOn1ine in [#7109](https://github.com/rh-hideout/pokeemerald-expansion/pull/7109) +* Add missing flag for Berserk Gene by @AlexOn1ine in [#7151](https://github.com/rh-hideout/pokeemerald-expansion/pull/7151) +* Fixes Neutralizing Gas leaving the field activating unsuppressable abilities again by @PhallenTree in [#7170](https://github.com/rh-hideout/pokeemerald-expansion/pull/7170) +* Fixes Enigma, Kee and Maranga Berry activation timing by @AlexOn1ine in [#7171](https://github.com/rh-hideout/pokeemerald-expansion/pull/7171) +* Fixes wrong Future Sight indexing by @AlexOn1ine in [#7198](https://github.com/rh-hideout/pokeemerald-expansion/pull/7198) +* Fixes OOB for Teatime and Flower Shield by @AlexOn1ine in [#7214](https://github.com/rh-hideout/pokeemerald-expansion/pull/7214) +* Fixes wrong assignment in TrySymbiosis by @AlexOn1ine in [#7221](https://github.com/rh-hideout/pokeemerald-expansion/pull/7221) +* Adds missing healBlockTimer for Baton Pass by @AlexOn1ine in [#7220](https://github.com/rh-hideout/pokeemerald-expansion/pull/7220) +* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237) +* Fixes Scald defrosting target while asleep by @AlexOn1ine in [#7233](https://github.com/rh-hideout/pokeemerald-expansion/pull/7233) +* Fixes Emergency Exit sometimes causing an unrelated battler to become invisible by @PhallenTree in [#7241](https://github.com/rh-hideout/pokeemerald-expansion/pull/7241) + +## 🤹 Moves 🤹 +### Changed +* Fix ScaryFace anim for Bitter Malice by @TLM-PsIQ in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476) + + + +### Fixed +* Fix savage spin out spider web template by @ghoulslash in [#7137](https://github.com/rh-hideout/pokeemerald-expansion/pull/7137) + +## 🎭 Abilities 🎭 +### Changed +* Flush textbox for Truant Popup by @ghoulslash in [#7252](https://github.com/rh-hideout/pokeemerald-expansion/pull/7252) + +## 🧶 Items 🧶 +### Fixed +* Fix sell price display by @cawtds in [#7123](https://github.com/rh-hideout/pokeemerald-expansion/pull/7123) + +## 🤖 Battle AI 🤖 +### Fixed +* Added AI_FLAG_PP_STALL_PREVENTION to AI_FLAG_SMART_TRAINER by @AlexOn1ine in [#7112](https://github.com/rh-hideout/pokeemerald-expansion/pull/7112) +* Fix incorrect function parameters used in AI damage calc by @Pawkkie in [#7130](https://github.com/rh-hideout/pokeemerald-expansion/pull/7130) + +## 🧹 Other Cleanup 🧹 +* Update CI to ignore allcontributors commits by @pkmnsnfrn in [#7046](https://github.com/rh-hideout/pokeemerald-expansion/pull/7046) +* Update CREDITS.md with correct line placement by @pkmnsnfrn in [#7096](https://github.com/rh-hideout/pokeemerald-expansion/pull/7096) +* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107) +* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116) +* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152) +* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159) +* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181) + +## 🧪 Test Runner 🧪 +### Changed +* Wrote some missing tests by @AsparagusEduardo in [#7094](https://github.com/rh-hideout/pokeemerald-expansion/pull/7094) +* Fixed KNOWN_FAILING Tera test by @AsparagusEduardo in [#6949](https://github.com/rh-hideout/pokeemerald-expansion/pull/6949) +* Add some tests by @ghoulslash in [#7234](https://github.com/rh-hideout/pokeemerald-expansion/pull/7234) +* Added tests for Toxic Thread by @hedara90 in [#7244](https://github.com/rh-hideout/pokeemerald-expansion/pull/7244) + +### Fixed +* Test runner fixes by @hedara90 in [#7100](https://github.com/rh-hideout/pokeemerald-expansion/pull/7100) +* Fixed Aura Wheel `KNOWN_FAILING` test by @AsparagusEduardo in [#7135](https://github.com/rh-hideout/pokeemerald-expansion/pull/7135) +* Fix AI party count calc being maintained between tests by @AsparagusEduardo in [#7200](https://github.com/rh-hideout/pokeemerald-expansion/pull/7200) +* Fix tests failing with `B_FRIENDSHIP_BOOST` being `TRUE` by @AsparagusEduardo in [#7194](https://github.com/rh-hideout/pokeemerald-expansion/pull/7194) +* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237) + +## 📚 Documentation 📚 +* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044) +* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029) +* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092) +* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133) +* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104) +* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159) +* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184) + +## 📦 Branch Synchronisation 📦 +### pret +* 24th of June, 2025 in [#7206](https://github.com/rh-hideout/pokeemerald-expansion/pull/7206) + * Move gTradePlatform_Tilemap to header and change to u32 by @DizzyEggg in [pret#2088](https://github.com/pret/pokeemerald/pull/2088) + * Fix wrong keep temps files directory in makefile by @DizzyEggg in [pret#2156](https://github.com/pret/pokeemerald/pull/2156) + * Fix collision comparison in PlayerNotOnBikeMoving by @GriffinRichards in [pret#2104](https://github.com/pret/pokeemerald/pull/2104) + * Match graphics declarations with externs in graphics.h by @DizzyEggg in [pret#2089](https://github.com/pret/pokeemerald/pull/2089) + +## New Contributors +* @TLM-PsIQ made their first contribution in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476) +* @pablopenna made their first contribution in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193) +* @J2M2 made their first contribution in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.0...expansion/1.12.1 + + + + diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 11822f8510..b8987abb43 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,13 +1,13 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.12.1 +// Last version: 1.12.2 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 #define EXPANSION_VERSION_PATCH 2 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE FALSE +#define EXPANSION_TAGGED_RELEASE TRUE #endif From 637f7dff46d7f270b015e4311373c8d32b9ebcb0 Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 30 Jul 2025 20:35:16 +0200 Subject: [PATCH 149/283] Start of 1.12.3 cycle --- include/constants/expansion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/expansion.h b/include/constants/expansion.h index b8987abb43..cdfaa6228e 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -4,10 +4,10 @@ // Last version: 1.12.2 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 -#define EXPANSION_VERSION_PATCH 2 +#define EXPANSION_VERSION_PATCH 3 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE TRUE +#define EXPANSION_TAGGED_RELEASE FALSE #endif From 0dfec24967e94ff047ee210e362ecca0b53656ad Mon Sep 17 00:00:00 2001 From: Josh <32826900+ShinyDragonHunter@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:43:08 +0100 Subject: [PATCH 150/283] Allow names for voicegroups and use a macro for use with drumsets (#2149) mid2agb has been modified to allow more than just numbers when naming voicegroups and voicegroups have been renamed to match. A "voice_group" macro has been set up with a optional parameter for the starting note will shift the offset by the specified amount * 0xC which is the length of 1 voice in a voicegroup. All drumset voicegroups have a "starting_note" of 36. --- asm/macros/m4a.inc | 10 + include/gba/m4a_internal.h | 2 +- sound/songs/midi/midi.cfg | 830 +++++++++--------- sound/songs/se_dex_page.s | 2 +- sound/songs/se_dex_scroll.s | 2 +- sound/songs/se_m_absorb.s | 2 +- sound/songs/se_m_absorb_2.s | 2 +- sound/songs/se_m_acid_armor.s | 2 +- sound/songs/se_m_attract.s | 2 +- sound/songs/se_m_attract2.s | 2 +- sound/songs/se_m_barrier.s | 2 +- sound/songs/se_m_baton_pass.s | 2 +- sound/songs/se_m_belly_drum.s | 2 +- sound/songs/se_m_bite.s | 2 +- sound/songs/se_m_blizzard.s | 2 +- sound/songs/se_m_blizzard2.s | 2 +- sound/songs/se_m_bonemerang.s | 2 +- sound/songs/se_m_brick_break.s | 2 +- sound/songs/se_m_bubble.s | 2 +- sound/songs/se_m_bubble2.s | 2 +- sound/songs/se_m_bubble3.s | 2 +- sound/songs/se_m_bubble_beam.s | 2 +- sound/songs/se_m_bubble_beam2.s | 2 +- sound/songs/se_m_charge.s | 2 +- sound/songs/se_m_charm.s | 2 +- sound/songs/se_m_confuse_ray.s | 2 +- sound/songs/se_m_cosmic_power.s | 2 +- sound/songs/se_m_crabhammer.s | 2 +- sound/songs/se_m_detect.s | 2 +- sound/songs/se_m_dig.s | 2 +- sound/songs/se_m_dive.s | 2 +- sound/songs/se_m_dizzy_punch.s | 2 +- sound/songs/se_m_double_team.s | 2 +- sound/songs/se_m_dragon_rage.s | 2 +- sound/songs/se_m_earthquake.s | 2 +- sound/songs/se_m_ember.s | 2 +- sound/songs/se_m_encore.s | 2 +- sound/songs/se_m_encore2.s | 2 +- sound/songs/se_m_explosion.s | 2 +- sound/songs/se_m_faint_attack.s | 2 +- sound/songs/se_m_flame_wheel.s | 2 +- sound/songs/se_m_flame_wheel2.s | 2 +- sound/songs/se_m_flamethrower.s | 2 +- sound/songs/se_m_flatter.s | 2 +- sound/songs/se_m_giga_drain.s | 2 +- sound/songs/se_m_grasswhistle.s | 2 +- sound/songs/se_m_hail.s | 2 +- sound/songs/se_m_harden.s | 2 +- sound/songs/se_m_haze.s | 2 +- sound/songs/se_m_heal_bell.s | 2 +- sound/songs/se_m_heat_wave.s | 2 +- sound/songs/se_m_hydro_pump.s | 2 +- sound/songs/se_m_hyper_beam.s | 2 +- sound/songs/se_m_hyper_beam2.s | 2 +- sound/songs/se_m_icy_wind.s | 2 +- sound/songs/se_m_lick.s | 2 +- sound/songs/se_m_lock_on.s | 2 +- sound/songs/se_m_metronome.s | 2 +- sound/songs/se_m_milk_drink.s | 2 +- sound/songs/se_m_minimize.s | 2 +- sound/songs/se_m_mist.s | 2 +- sound/songs/se_m_moonlight.s | 2 +- sound/songs/se_m_morning_sun.s | 2 +- sound/songs/se_m_nightmare.s | 2 +- sound/songs/se_m_perish_song.s | 2 +- sound/songs/se_m_petal_dance.s | 2 +- sound/songs/se_m_poison_powder.s | 2 +- sound/songs/se_m_psybeam.s | 2 +- sound/songs/se_m_psybeam2.s | 2 +- sound/songs/se_m_rain_dance.s | 2 +- sound/songs/se_m_reflect.s | 2 +- sound/songs/se_m_reversal.s | 2 +- sound/songs/se_m_rock_throw.s | 2 +- sound/songs/se_m_sacred_fire.s | 2 +- sound/songs/se_m_sacred_fire2.s | 2 +- sound/songs/se_m_sand_tomb.s | 2 +- sound/songs/se_m_sandstorm.s | 2 +- sound/songs/se_m_screech.s | 2 +- sound/songs/se_m_self_destruct.s | 2 +- sound/songs/se_m_sing.s | 2 +- sound/songs/se_m_sketch.s | 2 +- sound/songs/se_m_sky_uppercut.s | 2 +- sound/songs/se_m_snore.s | 2 +- sound/songs/se_m_solar_beam.s | 2 +- sound/songs/se_m_spit_up.s | 2 +- sound/songs/se_m_stat_decrease.s | 2 +- sound/songs/se_m_stat_increase.s | 2 +- sound/songs/se_m_strength.s | 2 +- sound/songs/se_m_string_shot.s | 2 +- sound/songs/se_m_string_shot2.s | 2 +- sound/songs/se_m_supersonic.s | 2 +- sound/songs/se_m_surf.s | 2 +- sound/songs/se_m_swagger.s | 2 +- sound/songs/se_m_swagger2.s | 2 +- sound/songs/se_m_sweet_scent.s | 2 +- sound/songs/se_m_swift.s | 2 +- sound/songs/se_m_teeter_dance.s | 2 +- sound/songs/se_m_teleport.s | 2 +- sound/songs/se_m_thunder_wave.s | 2 +- sound/songs/se_m_thunderbolt.s | 2 +- sound/songs/se_m_thunderbolt2.s | 2 +- sound/songs/se_m_toxic.s | 2 +- sound/songs/se_m_tri_attack.s | 2 +- sound/songs/se_m_tri_attack2.s | 2 +- sound/songs/se_m_twister.s | 2 +- sound/songs/se_m_uproar.s | 2 +- sound/songs/se_m_vital_throw.s | 2 +- sound/songs/se_m_vital_throw2.s | 2 +- sound/songs/se_m_waterfall.s | 2 +- sound/songs/se_m_whirlpool.s | 2 +- sound/songs/se_m_yawn.s | 2 +- sound/songs/se_wall_hit.s | 2 +- sound/songs/se_win_open.s | 2 +- sound/voice_groups.inc | 393 +++++---- sound/voicegroups/abandoned_ship.inc | 97 ++ ...voicegroup089.inc => abnormal_weather.inc} | 10 +- ...icegroup076.inc => aqua_magma_hideout.inc} | 7 +- .../{voicegroup104.inc => b_arena.inc} | 5 +- .../{voicegroup111.inc => b_dome.inc} | 5 +- .../{voicegroup113.inc => b_factory.inc} | 9 +- .../{voicegroup103.inc => b_frontier.inc} | 11 +- .../{voicegroup108.inc => b_palace.inc} | 7 +- .../{voicegroup112.inc => b_pike.inc} | 11 +- .../{voicegroup106.inc => b_pyramid.inc} | 13 +- .../{voicegroup107.inc => b_pyramid_top.inc} | 9 +- .../{voicegroup110.inc => b_tower.inc} | 13 +- .../{voicegroup035.inc => b_tower_rs.inc} | 13 +- sound/voicegroups/bard.inc | 53 ++ .../{voicegroup033.inc => birch_lab.inc} | 9 +- .../{voicegroup071.inc => cable_car.inc} | 11 +- .../{voicegroup037.inc => cave_of_origin.inc} | 11 +- .../{voicegroup086.inc => contest.inc} | 11 +- .../{voicegroup098.inc => contest_lobby.inc} | 9 +- ...{voicegroup092.inc => contest_results.inc} | 5 +- .../{voicegroup085.inc => contest_winner.inc} | 7 +- .../{voicegroup101.inc => credits.inc} | 15 +- .../{voicegroup049.inc => cycling.inc} | 13 +- .../{voicegroup073.inc => dewford.inc} | 13 +- sound/voicegroups/drumsets/emerald_1.inc | 56 ++ .../emerald_2.inc} | 39 +- .../{voicegroup003.inc => drumsets/frlg.inc} | 39 +- .../frlg_fanfare_1.inc} | 39 +- .../frlg_fanfare_2.inc} | 9 +- .../petalburg.inc} | 39 +- .../rg_credits.inc} | 40 +- sound/voicegroups/drumsets/route101.inc | 31 + sound/voicegroups/drumsets/route110.inc | 27 + sound/voicegroups/drumsets/rs.inc | 31 + sound/voicegroups/dummy.inc | 100 +++ .../{voicegroup065.inc => encounter_aqua.inc} | 9 +- ...oicegroup067.inc => encounter_brendan.inc} | 9 +- ...icegroup100.inc => encounter_champion.inc} | 7 +- .../{voicegroup063.inc => encounter_cool.inc} | 7 +- ...egroup096.inc => encounter_elite_four.inc} | 7 +- ...voicegroup053.inc => encounter_female.inc} | 9 +- .../{voicegroup027.inc => encounter_girl.inc} | 7 +- ...{voicegroup097.inc => encounter_hiker.inc} | 11 +- ...oicegroup062.inc => encounter_intense.inc} | 7 +- ...group099.inc => encounter_interviewer.inc} | 7 +- ...{voicegroup087.inc => encounter_magma.inc} | 9 +- .../{voicegroup028.inc => encounter_male.inc} | 7 +- .../{voicegroup061.inc => encounter_may.inc} | 7 +- .../{voicegroup043.inc => encounter_rich.inc} | 9 +- ...egroup069.inc => encounter_suspicious.inc} | 9 +- ...oicegroup036.inc => encounter_swimmer.inc} | 9 +- ...{voicegroup095.inc => encounter_twins.inc} | 5 +- .../{voicegroup102.inc => end.inc} | 3 +- .../{voicegroup068.inc => ever_grande.inc} | 9 +- .../{voicegroup026.inc => evolution.inc} | 7 +- .../{voicegroup083.inc => fallarbor.inc} | 13 +- .../{voicegroup012.inc => fanfare.inc} | 15 +- .../{voicegroup066.inc => follow_me.inc} | 5 +- .../{voicegroup032.inc => fortree.inc} | 7 +- .../{voicegroup129.inc => frlg_sfx.inc} | 5 +- .../{voicegroup072.inc => game_corner.inc} | 13 +- .../{voicegroup013.inc => gym.inc} | 11 +- .../{voicegroup082.inc => hall_of_fame.inc} | 13 +- ...oicegroup093.inc => hall_of_fame_room.inc} | 11 +- .../{voicegroup056.inc => help.inc} | 9 +- .../{voicegroup060.inc => intro.inc} | 15 +- .../{voicegroup088.inc => intro_battle.inc} | 15 +- .../french_horn.inc} | 3 +- .../piano.inc} | 3 +- .../strings.inc} | 3 +- sound/voicegroups/keysplits/trumpet.inc | 5 + .../{voicegroup008.inc => keysplits/tuba.inc} | 3 +- .../{voicegroup054.inc => lilycove.inc} | 11 +- ...{voicegroup020.inc => lilycove_museum.inc} | 9 +- ...{voicegroup041.inc => link_contest_p1.inc} | 11 +- ...{voicegroup040.inc => link_contest_p2.inc} | 11 +- ...{voicegroup042.inc => link_contest_p3.inc} | 11 +- ...{voicegroup039.inc => link_contest_p4.inc} | 11 +- .../{voicegroup051.inc => littleroot.inc} | 9 +- ...{voicegroup034.inc => littleroot_test.inc} | 9 +- .../{voicegroup052.inc => mt_chimney.inc} | 13 +- .../{voicegroup078.inc => mt_pyre.inc} | 9 +- ...voicegroup080.inc => mt_pyre_exterior.inc} | 9 +- .../{voicegroup023.inc => oceanic_museum.inc} | 11 +- .../{voicegroup019.inc => oldale.inc} | 9 +- sound/voicegroups/petalburg.inc | 130 +++ ...{voicegroup018.inc => petalburg_woods.inc} | 9 +- .../{voicegroup046.inc => poke_center.inc} | 7 +- .../{voicegroup050.inc => poke_mart.inc} | 7 +- ...voicegroup109.inc => rayquaza_appears.inc} | 5 +- ...cegroup105.inc => register_match_call.inc} | 5 +- ...{voicegroup179.inc => rg_caught_intro.inc} | 17 +- .../{voicegroup168.inc => rg_celadon.inc} | 11 +- .../{voicegroup138.inc => rg_cinnabar.inc} | 11 +- .../{voicegroup149.inc => rg_credits.inc} | 15 +- .../{voicegroup141.inc => rg_cycling.inc} | 11 +- sound/voicegroups/rg_dex_rating.inc | 90 ++ ...voicegroup144.inc => rg_encounter_boy.inc} | 9 +- ...cegroup184.inc => rg_encounter_deoxys.inc} | 3 +- ...oicegroup143.inc => rg_encounter_girl.inc} | 9 +- sound/voicegroups/rg_encounter_rival.inc | 130 +++ ...cegroup142.inc => rg_encounter_rocket.inc} | 5 +- .../{voicegroup131.inc => rg_follow_me.inc} | 7 +- .../{voicegroup167.inc => rg_fuchsia.inc} | 7 +- .../{voicegroup132.inc => rg_game_corner.inc} | 13 +- .../{voicegroup181.inc => rg_game_freak.inc} | 5 +- .../{voicegroup134.inc => rg_gym.inc} | 11 +- ...{voicegroup145.inc => rg_hall_of_fame.inc} | 11 +- .../{voicegroup140.inc => rg_heal.inc} | 5 +- .../{voicegroup136.inc => rg_intro_fight.inc} | 9 +- .../{voicegroup135.inc => rg_jigglypuff.inc} | 5 +- .../{voicegroup139.inc => rg_lavender.inc} | 13 +- .../{voicegroup147.inc => rg_mt_moon.inc} | 9 +- ...{voicegroup183.inc => rg_mystery_gift.inc} | 5 +- .../{voicegroup182.inc => rg_new_game.inc} | 13 +- .../{voicegroup161.inc => rg_oak.inc} | 13 +- .../{voicegroup160.inc => rg_oak_lab.inc} | 7 +- ...icegroup178.inc => rg_obtain_key_item.inc} | 5 +- .../{voicegroup159.inc => rg_pallet.inc} | 5 +- .../{voicegroup173.inc => rg_pewter.inc} | 9 +- .../{voicegroup180.inc => rg_photo.inc} | 5 +- .../{voicegroup162.inc => rg_poke_center.inc} | 7 +- ...{voicegroup148.inc => rg_poke_mansion.inc} | 9 +- .../{voicegroup165.inc => rg_poke_tower.inc} | 13 +- ...oicegroup133.inc => rg_rocket_hideout.inc} | 13 +- .../{voicegroup150.inc => rg_route1.inc} | 5 +- .../{voicegroup153.inc => rg_route11.inc} | 15 +- .../{voicegroup151.inc => rg_route24.inc} | 13 +- .../{voicegroup152.inc => rg_route3.inc} | 13 +- .../{voicegroup188.inc => rg_sevii_45.inc} | 9 +- sound/voicegroups/rg_sevii_67.inc | 130 +++ .../{voicegroup187.inc => rg_sevii_route.inc} | 13 +- .../{voicegroup166.inc => rg_silph.inc} | 13 +- .../{voicegroup163.inc => rg_ss_anne.inc} | 11 +- .../{voicegroup164.inc => rg_surf.inc} | 9 +- ...oicegroup186.inc => rg_teachy_tv_menu.inc} | 5 +- .../{voicegroup137.inc => rg_title.inc} | 13 +- .../{voicegroup001.inc => rg_unused.inc} | 17 +- sound/voicegroups/rg_unused_2.inc | 6 + .../{voicegroup172.inc => rg_vermillion.inc} | 11 +- ...group171.inc => rg_victory_gym_leader.inc} | 11 +- ...{voicegroup154.inc => rg_victory_road.inc} | 13 +- ...icegroup169.inc => rg_victory_trainer.inc} | 9 +- ...{voicegroup025.inc => rg_victory_wild.inc} | 9 +- ...icegroup146.inc => rg_viridian_forest.inc} | 7 +- .../{voicegroup158.inc => rg_vs_champion.inc} | 13 +- .../{voicegroup185.inc => rg_vs_deoxys.inc} | 11 +- ...voicegroup155.inc => rg_vs_gym_leader.inc} | 13 +- .../{voicegroup156.inc => rg_vs_trainer.inc} | 13 +- .../{voicegroup157.inc => rg_vs_wild.inc} | 13 +- .../{voicegroup038.inc => roulette.inc} | 5 +- .../{voicegroup011.inc => route101.inc} | 7 +- .../{voicegroup047.inc => route104.inc} | 13 +- .../{voicegroup010.inc => route110.inc} | 13 +- .../{voicegroup055.inc => route111.inc} | 13 +- .../{voicegroup064.inc => route113.inc} | 9 +- .../{voicegroup048.inc => route119.inc} | 13 +- .../{voicegroup014.inc => route120.inc} | 13 +- sound/voicegroups/route122.inc | 89 ++ .../{voicegroup127.inc => rs_sfx_1.inc} | 5 +- .../{voicegroup128.inc => rs_sfx_2.inc} | 3 +- .../{voicegroup045.inc => rustboro.inc} | 9 +- .../{voicegroup074.inc => safari_zone.inc} | 5 +- .../{voicegroup077.inc => sailing.inc} | 7 +- sound/voicegroups/school.inc | 4 + .../{voicegroup084.inc => sealed_chamber.inc} | 9 +- .../{voicegroup079.inc => slateport.inc} | 9 +- .../{voicegroup091.inc => sootopolis.inc} | 13 +- .../{voicegroup017.inc => surf.inc} | 11 +- .../{voicegroup059.inc => title.inc} | 15 +- .../{voicegroup094.inc => trick_house.inc} | 11 +- .../{voicegroup057.inc => underwater.inc} | 7 +- .../{voicegroup007.inc => unused.inc} | 6 +- sound/voicegroups/unused_2.inc | 130 +++ .../{voicegroup044.inc => verdanturf.inc} | 7 +- ...icegroup070.inc => victory_aqua_magma.inc} | 9 +- ...icegroup024.inc => victory_gym_leader.inc} | 11 +- .../{voicegroup029.inc => victory_league.inc} | 11 +- .../{voicegroup075.inc => victory_road.inc} | 15 +- ...{voicegroup058.inc => victory_trainer.inc} | 9 +- .../{voicegroup170.inc => victory_wild.inc} | 9 +- sound/voicegroups/voicegroup000.inc | 65 -- sound/voicegroups/voicegroup002.inc | 57 -- sound/voicegroups/voicegroup015.inc | 95 -- sound/voicegroups/voicegroup021.inc | 54 -- sound/voicegroups/voicegroup022.inc | 68 -- sound/voicegroups/voicegroup030.inc | 58 -- sound/voicegroups/voicegroup031.inc | 68 -- sound/voicegroups/voicegroup081.inc | 5 - sound/voicegroups/voicegroup130.inc | 182 ---- sound/voicegroups/voicegroup174.inc | 160 ---- sound/voicegroups/voicegroup175.inc | 55 -- sound/voicegroups/voicegroup189.inc | 95 -- .../{voicegroup118.inc => vs_aqua_magma.inc} | 11 +- ...egroup126.inc => vs_aqua_magma_leader.inc} | 11 +- .../{voicegroup121.inc => vs_champion.inc} | 13 +- .../{voicegroup125.inc => vs_elite_four.inc} | 11 +- ...oicegroup115.inc => vs_frontier_brain.inc} | 13 +- .../{voicegroup120.inc => vs_gym_leader.inc} | 13 +- ...oicegroup123.inc => vs_kyogre_groudon.inc} | 11 +- .../{voicegroup116.inc => vs_mew.inc} | 13 +- .../{voicegroup114.inc => vs_rayquaza.inc} | 11 +- .../{voicegroup122.inc => vs_regi.inc} | 9 +- .../{voicegroup124.inc => vs_rival.inc} | 13 +- .../{voicegroup119.inc => vs_trainer.inc} | 13 +- .../{voicegroup117.inc => vs_wild.inc} | 13 +- ...{voicegroup090.inc => weather_groudon.inc} | 5 +- src/m4a_tables.c | 2 +- tools/mid2agb/agb.cpp | 2 +- tools/mid2agb/main.cpp | 6 +- tools/mid2agb/main.h | 2 +- 325 files changed, 2620 insertions(+), 2780 deletions(-) create mode 100644 sound/voicegroups/abandoned_ship.inc rename sound/voicegroups/{voicegroup089.inc => abnormal_weather.inc} (96%) rename sound/voicegroups/{voicegroup076.inc => aqua_magma_hideout.inc} (97%) rename sound/voicegroups/{voicegroup104.inc => b_arena.inc} (98%) rename sound/voicegroups/{voicegroup111.inc => b_dome.inc} (98%) rename sound/voicegroups/{voicegroup113.inc => b_factory.inc} (96%) rename sound/voicegroups/{voicegroup103.inc => b_frontier.inc} (95%) rename sound/voicegroups/{voicegroup108.inc => b_palace.inc} (97%) rename sound/voicegroups/{voicegroup112.inc => b_pike.inc} (95%) rename sound/voicegroups/{voicegroup106.inc => b_pyramid.inc} (94%) rename sound/voicegroups/{voicegroup107.inc => b_pyramid_top.inc} (96%) rename sound/voicegroups/{voicegroup110.inc => b_tower.inc} (94%) rename sound/voicegroups/{voicegroup035.inc => b_tower_rs.inc} (91%) create mode 100644 sound/voicegroups/bard.inc rename sound/voicegroups/{voicegroup033.inc => birch_lab.inc} (94%) rename sound/voicegroups/{voicegroup071.inc => cable_car.inc} (95%) rename sound/voicegroups/{voicegroup037.inc => cave_of_origin.inc} (93%) rename sound/voicegroups/{voicegroup086.inc => contest.inc} (95%) rename sound/voicegroups/{voicegroup098.inc => contest_lobby.inc} (96%) rename sound/voicegroups/{voicegroup092.inc => contest_results.inc} (98%) rename sound/voicegroups/{voicegroup085.inc => contest_winner.inc} (97%) rename sound/voicegroups/{voicegroup101.inc => credits.inc} (92%) rename sound/voicegroups/{voicegroup049.inc => cycling.inc} (94%) rename sound/voicegroups/{voicegroup073.inc => dewford.inc} (94%) create mode 100644 sound/voicegroups/drumsets/emerald_1.inc rename sound/voicegroups/{voicegroup004.inc => drumsets/emerald_2.inc} (60%) rename sound/voicegroups/{voicegroup003.inc => drumsets/frlg.inc} (94%) rename sound/voicegroups/{voicegroup177.inc => drumsets/frlg_fanfare_1.inc} (72%) rename sound/voicegroups/{voicegroup176.inc => drumsets/frlg_fanfare_2.inc} (89%) rename sound/voicegroups/{voicegroup016.inc => drumsets/petalburg.inc} (50%) rename sound/voicegroups/{voicegroup190.inc => drumsets/rg_credits.inc} (68%) create mode 100644 sound/voicegroups/drumsets/route101.inc create mode 100644 sound/voicegroups/drumsets/route110.inc create mode 100644 sound/voicegroups/drumsets/rs.inc create mode 100644 sound/voicegroups/dummy.inc rename sound/voicegroups/{voicegroup065.inc => encounter_aqua.inc} (96%) rename sound/voicegroups/{voicegroup067.inc => encounter_brendan.inc} (96%) rename sound/voicegroups/{voicegroup100.inc => encounter_champion.inc} (97%) rename sound/voicegroups/{voicegroup063.inc => encounter_cool.inc} (97%) rename sound/voicegroups/{voicegroup096.inc => encounter_elite_four.inc} (97%) rename sound/voicegroups/{voicegroup053.inc => encounter_female.inc} (96%) rename sound/voicegroups/{voicegroup027.inc => encounter_girl.inc} (97%) rename sound/voicegroups/{voicegroup097.inc => encounter_hiker.inc} (95%) rename sound/voicegroups/{voicegroup062.inc => encounter_intense.inc} (97%) rename sound/voicegroups/{voicegroup099.inc => encounter_interviewer.inc} (97%) rename sound/voicegroups/{voicegroup087.inc => encounter_magma.inc} (96%) rename sound/voicegroups/{voicegroup028.inc => encounter_male.inc} (96%) rename sound/voicegroups/{voicegroup061.inc => encounter_may.inc} (97%) rename sound/voicegroups/{voicegroup043.inc => encounter_rich.inc} (94%) rename sound/voicegroups/{voicegroup069.inc => encounter_suspicious.inc} (96%) rename sound/voicegroups/{voicegroup036.inc => encounter_swimmer.inc} (96%) rename sound/voicegroups/{voicegroup095.inc => encounter_twins.inc} (98%) rename sound/voicegroups/{voicegroup102.inc => end.inc} (99%) rename sound/voicegroups/{voicegroup068.inc => ever_grande.inc} (96%) rename sound/voicegroups/{voicegroup026.inc => evolution.inc} (96%) rename sound/voicegroups/{voicegroup083.inc => fallarbor.inc} (92%) rename sound/voicegroups/{voicegroup012.inc => fanfare.inc} (92%) rename sound/voicegroups/{voicegroup066.inc => follow_me.inc} (98%) rename sound/voicegroups/{voicegroup032.inc => fortree.inc} (97%) rename sound/voicegroups/{voicegroup129.inc => frlg_sfx.inc} (98%) rename sound/voicegroups/{voicegroup072.inc => game_corner.inc} (94%) rename sound/voicegroups/{voicegroup013.inc => gym.inc} (93%) rename sound/voicegroups/{voicegroup082.inc => hall_of_fame.inc} (94%) rename sound/voicegroups/{voicegroup093.inc => hall_of_fame_room.inc} (95%) rename sound/voicegroups/{voicegroup056.inc => help.inc} (96%) rename sound/voicegroups/{voicegroup060.inc => intro.inc} (93%) rename sound/voicegroups/{voicegroup088.inc => intro_battle.inc} (93%) rename sound/voicegroups/{voicegroup009.inc => keysplits/french_horn.inc} (84%) rename sound/voicegroups/{voicegroup005.inc => keysplits/piano.inc} (92%) rename sound/voicegroups/{voicegroup006.inc => keysplits/strings.inc} (90%) create mode 100644 sound/voicegroups/keysplits/trumpet.inc rename sound/voicegroups/{voicegroup008.inc => keysplits/tuba.inc} (86%) rename sound/voicegroups/{voicegroup054.inc => lilycove.inc} (95%) rename sound/voicegroups/{voicegroup020.inc => lilycove_museum.inc} (94%) rename sound/voicegroups/{voicegroup041.inc => link_contest_p1.inc} (95%) rename sound/voicegroups/{voicegroup040.inc => link_contest_p2.inc} (95%) rename sound/voicegroups/{voicegroup042.inc => link_contest_p3.inc} (95%) rename sound/voicegroups/{voicegroup039.inc => link_contest_p4.inc} (95%) rename sound/voicegroups/{voicegroup051.inc => littleroot.inc} (94%) rename sound/voicegroups/{voicegroup034.inc => littleroot_test.inc} (94%) rename sound/voicegroups/{voicegroup052.inc => mt_chimney.inc} (94%) rename sound/voicegroups/{voicegroup078.inc => mt_pyre.inc} (96%) rename sound/voicegroups/{voicegroup080.inc => mt_pyre_exterior.inc} (96%) rename sound/voicegroups/{voicegroup023.inc => oceanic_museum.inc} (93%) rename sound/voicegroups/{voicegroup019.inc => oldale.inc} (94%) create mode 100644 sound/voicegroups/petalburg.inc rename sound/voicegroups/{voicegroup018.inc => petalburg_woods.inc} (96%) rename sound/voicegroups/{voicegroup046.inc => poke_center.inc} (97%) rename sound/voicegroups/{voicegroup050.inc => poke_mart.inc} (97%) rename sound/voicegroups/{voicegroup109.inc => rayquaza_appears.inc} (97%) rename sound/voicegroups/{voicegroup105.inc => register_match_call.inc} (97%) rename sound/voicegroups/{voicegroup179.inc => rg_caught_intro.inc} (88%) rename sound/voicegroups/{voicegroup168.inc => rg_celadon.inc} (95%) rename sound/voicegroups/{voicegroup138.inc => rg_cinnabar.inc} (95%) rename sound/voicegroups/{voicegroup149.inc => rg_credits.inc} (91%) rename sound/voicegroups/{voicegroup141.inc => rg_cycling.inc} (95%) create mode 100644 sound/voicegroups/rg_dex_rating.inc rename sound/voicegroups/{voicegroup144.inc => rg_encounter_boy.inc} (96%) rename sound/voicegroups/{voicegroup184.inc => rg_encounter_deoxys.inc} (99%) rename sound/voicegroups/{voicegroup143.inc => rg_encounter_girl.inc} (96%) create mode 100644 sound/voicegroups/rg_encounter_rival.inc rename sound/voicegroups/{voicegroup142.inc => rg_encounter_rocket.inc} (98%) rename sound/voicegroups/{voicegroup131.inc => rg_follow_me.inc} (97%) rename sound/voicegroups/{voicegroup167.inc => rg_fuchsia.inc} (97%) rename sound/voicegroups/{voicegroup132.inc => rg_game_corner.inc} (94%) rename sound/voicegroups/{voicegroup181.inc => rg_game_freak.inc} (95%) rename sound/voicegroups/{voicegroup134.inc => rg_gym.inc} (93%) rename sound/voicegroups/{voicegroup145.inc => rg_hall_of_fame.inc} (95%) rename sound/voicegroups/{voicegroup140.inc => rg_heal.inc} (71%) rename sound/voicegroups/{voicegroup136.inc => rg_intro_fight.inc} (96%) rename sound/voicegroups/{voicegroup135.inc => rg_jigglypuff.inc} (97%) rename sound/voicegroups/{voicegroup139.inc => rg_lavender.inc} (94%) rename sound/voicegroups/{voicegroup147.inc => rg_mt_moon.inc} (94%) rename sound/voicegroups/{voicegroup183.inc => rg_mystery_gift.inc} (98%) rename sound/voicegroups/{voicegroup182.inc => rg_new_game.inc} (91%) rename sound/voicegroups/{voicegroup161.inc => rg_oak.inc} (94%) rename sound/voicegroups/{voicegroup160.inc => rg_oak_lab.inc} (96%) rename sound/voicegroups/{voicegroup178.inc => rg_obtain_key_item.inc} (97%) rename sound/voicegroups/{voicegroup159.inc => rg_pallet.inc} (98%) rename sound/voicegroups/{voicegroup173.inc => rg_pewter.inc} (96%) rename sound/voicegroups/{voicegroup180.inc => rg_photo.inc} (98%) rename sound/voicegroups/{voicegroup162.inc => rg_poke_center.inc} (96%) rename sound/voicegroups/{voicegroup148.inc => rg_poke_mansion.inc} (96%) rename sound/voicegroups/{voicegroup165.inc => rg_poke_tower.inc} (94%) rename sound/voicegroups/{voicegroup133.inc => rg_rocket_hideout.inc} (94%) rename sound/voicegroups/{voicegroup150.inc => rg_route1.inc} (98%) rename sound/voicegroups/{voicegroup153.inc => rg_route11.inc} (93%) rename sound/voicegroups/{voicegroup151.inc => rg_route24.inc} (91%) rename sound/voicegroups/{voicegroup152.inc => rg_route3.inc} (94%) rename sound/voicegroups/{voicegroup188.inc => rg_sevii_45.inc} (96%) create mode 100644 sound/voicegroups/rg_sevii_67.inc rename sound/voicegroups/{voicegroup187.inc => rg_sevii_route.inc} (94%) rename sound/voicegroups/{voicegroup166.inc => rg_silph.inc} (94%) rename sound/voicegroups/{voicegroup163.inc => rg_ss_anne.inc} (95%) rename sound/voicegroups/{voicegroup164.inc => rg_surf.inc} (96%) rename sound/voicegroups/{voicegroup186.inc => rg_teachy_tv_menu.inc} (98%) rename sound/voicegroups/{voicegroup137.inc => rg_title.inc} (94%) rename sound/voicegroups/{voicegroup001.inc => rg_unused.inc} (62%) create mode 100644 sound/voicegroups/rg_unused_2.inc rename sound/voicegroups/{voicegroup172.inc => rg_vermillion.inc} (95%) rename sound/voicegroups/{voicegroup171.inc => rg_victory_gym_leader.inc} (93%) rename sound/voicegroups/{voicegroup154.inc => rg_victory_road.inc} (92%) rename sound/voicegroups/{voicegroup169.inc => rg_victory_trainer.inc} (96%) rename sound/voicegroups/{voicegroup025.inc => rg_victory_wild.inc} (94%) rename sound/voicegroups/{voicegroup146.inc => rg_viridian_forest.inc} (97%) rename sound/voicegroups/{voicegroup158.inc => rg_vs_champion.inc} (94%) rename sound/voicegroups/{voicegroup185.inc => rg_vs_deoxys.inc} (95%) rename sound/voicegroups/{voicegroup155.inc => rg_vs_gym_leader.inc} (94%) rename sound/voicegroups/{voicegroup156.inc => rg_vs_trainer.inc} (94%) rename sound/voicegroups/{voicegroup157.inc => rg_vs_wild.inc} (94%) rename sound/voicegroups/{voicegroup038.inc => roulette.inc} (98%) rename sound/voicegroups/{voicegroup011.inc => route101.inc} (97%) rename sound/voicegroups/{voicegroup047.inc => route104.inc} (94%) rename sound/voicegroups/{voicegroup010.inc => route110.inc} (91%) rename sound/voicegroups/{voicegroup055.inc => route111.inc} (94%) rename sound/voicegroups/{voicegroup064.inc => route113.inc} (96%) rename sound/voicegroups/{voicegroup048.inc => route119.inc} (92%) rename sound/voicegroups/{voicegroup014.inc => route120.inc} (92%) create mode 100644 sound/voicegroups/route122.inc rename sound/voicegroups/{voicegroup127.inc => rs_sfx_1.inc} (98%) rename sound/voicegroups/{voicegroup128.inc => rs_sfx_2.inc} (99%) rename sound/voicegroups/{voicegroup045.inc => rustboro.inc} (96%) rename sound/voicegroups/{voicegroup074.inc => safari_zone.inc} (98%) rename sound/voicegroups/{voicegroup077.inc => sailing.inc} (97%) create mode 100644 sound/voicegroups/school.inc rename sound/voicegroups/{voicegroup084.inc => sealed_chamber.inc} (96%) rename sound/voicegroups/{voicegroup079.inc => slateport.inc} (96%) rename sound/voicegroups/{voicegroup091.inc => sootopolis.inc} (94%) rename sound/voicegroups/{voicegroup017.inc => surf.inc} (94%) rename sound/voicegroups/{voicegroup059.inc => title.inc} (91%) rename sound/voicegroups/{voicegroup094.inc => trick_house.inc} (95%) rename sound/voicegroups/{voicegroup057.inc => underwater.inc} (97%) rename sound/voicegroups/{voicegroup007.inc => unused.inc} (95%) create mode 100644 sound/voicegroups/unused_2.inc rename sound/voicegroups/{voicegroup044.inc => verdanturf.inc} (96%) rename sound/voicegroups/{voicegroup070.inc => victory_aqua_magma.inc} (96%) rename sound/voicegroups/{voicegroup024.inc => victory_gym_leader.inc} (93%) rename sound/voicegroups/{voicegroup029.inc => victory_league.inc} (93%) rename sound/voicegroups/{voicegroup075.inc => victory_road.inc} (93%) rename sound/voicegroups/{voicegroup058.inc => victory_trainer.inc} (96%) rename sound/voicegroups/{voicegroup170.inc => victory_wild.inc} (94%) delete mode 100644 sound/voicegroups/voicegroup000.inc delete mode 100644 sound/voicegroups/voicegroup002.inc delete mode 100644 sound/voicegroups/voicegroup015.inc delete mode 100644 sound/voicegroups/voicegroup021.inc delete mode 100644 sound/voicegroups/voicegroup022.inc delete mode 100644 sound/voicegroups/voicegroup030.inc delete mode 100644 sound/voicegroups/voicegroup031.inc delete mode 100644 sound/voicegroups/voicegroup081.inc delete mode 100644 sound/voicegroups/voicegroup130.inc delete mode 100644 sound/voicegroups/voicegroup174.inc delete mode 100644 sound/voicegroups/voicegroup175.inc delete mode 100644 sound/voicegroups/voicegroup189.inc rename sound/voicegroups/{voicegroup118.inc => vs_aqua_magma.inc} (94%) rename sound/voicegroups/{voicegroup126.inc => vs_aqua_magma_leader.inc} (95%) rename sound/voicegroups/{voicegroup121.inc => vs_champion.inc} (91%) rename sound/voicegroups/{voicegroup125.inc => vs_elite_four.inc} (93%) rename sound/voicegroups/{voicegroup115.inc => vs_frontier_brain.inc} (94%) rename sound/voicegroups/{voicegroup120.inc => vs_gym_leader.inc} (92%) rename sound/voicegroups/{voicegroup123.inc => vs_kyogre_groudon.inc} (95%) rename sound/voicegroups/{voicegroup116.inc => vs_mew.inc} (94%) rename sound/voicegroups/{voicegroup114.inc => vs_rayquaza.inc} (95%) rename sound/voicegroups/{voicegroup122.inc => vs_regi.inc} (94%) rename sound/voicegroups/{voicegroup124.inc => vs_rival.inc} (91%) rename sound/voicegroups/{voicegroup119.inc => vs_trainer.inc} (92%) rename sound/voicegroups/{voicegroup117.inc => vs_wild.inc} (91%) rename sound/voicegroups/{voicegroup090.inc => weather_groudon.inc} (98%) diff --git a/asm/macros/m4a.inc b/asm/macros/m4a.inc index b22da3d634..57853c9abd 100644 --- a/asm/macros/m4a.inc +++ b/asm/macros/m4a.inc @@ -11,3 +11,13 @@ .space 1 @ Padding .2byte \unknown .endm + + .macro voice_group label:req, starting_note + .align 2 + .ifb \starting_note + .global voicegroup_\label + voicegroup_\label: + .else + .set voicegroup_\label, . - \starting_note * 0xC + .endif + .endm diff --git a/include/gba/m4a_internal.h b/include/gba/m4a_internal.h index a90771048d..5c3a0872ce 100644 --- a/include/gba/m4a_internal.h +++ b/include/gba/m4a_internal.h @@ -401,7 +401,7 @@ extern const u8 gNoiseTable[]; extern const struct PokemonCrySong gPokemonCrySongTemplate; -extern const struct ToneData voicegroup000; +extern const struct ToneData voicegroup_dummy; extern char gNumMusicPlayers[]; extern char gMaxLines[]; diff --git a/sound/songs/midi/midi.cfg b/sound/songs/midi/midi.cfg index 5802904b41..68df84d7a5 100644 --- a/sound/songs/midi/midi.cfg +++ b/sound/songs/midi/midi.cfg @@ -1,420 +1,420 @@ -mus_abandoned_ship.mid: -E -R50 -G030 -V080 -mus_abnormal_weather.mid: -E -R50 -G089 -V080 -mus_aqua_magma_hideout.mid: -E -R50 -G076 -V084 -mus_awaken_legend.mid: -E -R50 -G012 -V090 -P5 -mus_b_arena.mid: -E -R50 -G104 -V090 -mus_b_dome_lobby.mid: -E -R50 -G111 -V056 -mus_b_dome.mid: -E -R50 -G111 -V090 -mus_b_factory.mid: -E -R50 -G113 -V100 -mus_b_frontier.mid: -E -R50 -G103 -V094 -mus_b_palace.mid: -E -R50 -G108 -V105 -mus_b_pike.mid: -E -R50 -G112 -V092 -mus_b_pyramid_top.mid: -E -R50 -G107 -V077 -mus_b_pyramid.mid: -E -R50 -G106 -V079 -mus_b_tower_rs.mid: -E -R50 -G035 -V080 -mus_b_tower.mid: -E -R50 -G110 -V100 -mus_birch_lab.mid: -E -R50 -G033 -V080 +mus_abandoned_ship.mid: -E -R50 -G_abandoned_ship -V080 +mus_abnormal_weather.mid: -E -R50 -G_abnormal_weather -V080 +mus_aqua_magma_hideout.mid: -E -R50 -G_aqua_magma_hideout -V084 +mus_awaken_legend.mid: -E -R50 -G_fanfare -V090 -P5 +mus_b_arena.mid: -E -R50 -G_b_arena -V090 +mus_b_dome_lobby.mid: -E -R50 -G_b_dome -V056 +mus_b_dome.mid: -E -R50 -G_b_dome -V090 +mus_b_factory.mid: -E -R50 -G_b_factory -V100 +mus_b_frontier.mid: -E -R50 -G_b_frontier -V094 +mus_b_palace.mid: -E -R50 -G_b_palace -V105 +mus_b_pike.mid: -E -R50 -G_b_pike -V092 +mus_b_pyramid_top.mid: -E -R50 -G_b_pyramid_top -V077 +mus_b_pyramid.mid: -E -R50 -G_b_pyramid -V079 +mus_b_tower_rs.mid: -E -R50 -G_b_tower_rs -V080 +mus_b_tower.mid: -E -R50 -G_b_tower -V100 +mus_birch_lab.mid: -E -R50 -G_birch_lab -V080 mus_c_comm_center.mid: -E -R50 -V080 mus_c_vs_legend_beast.mid: -E -R50 -V080 -mus_cable_car.mid: -E -R50 -G071 -V078 -mus_caught.mid: -E -R50 -G025 -V080 -mus_cave_of_origin.mid: -E -R50 -G037 -V080 -mus_contest_lobby.mid: -E -R50 -G098 -V060 -mus_contest_results.mid: -E -R50 -G092 -V080 -mus_contest_winner.mid: -E -R50 -G085 -V100 -mus_contest.mid: -E -R50 -G086 -V088 -mus_credits.mid: -E -R50 -G101 -V100 -mus_cycling.mid: -E -R50 -G049 -V083 -mus_dewford.mid: -E -R50 -G073 -V078 +mus_cable_car.mid: -E -R50 -G_cable_car -V078 +mus_caught.mid: -E -R50 -G_victory_wild -V080 +mus_cave_of_origin.mid: -E -R50 -G_cave_of_origin -V080 +mus_contest_lobby.mid: -E -R50 -G_contest_lobby -V060 +mus_contest_results.mid: -E -R50 -G_contest_results -V080 +mus_contest_winner.mid: -E -R50 -G_contest_winner -V100 +mus_contest.mid: -E -R50 -G_contest -V088 +mus_credits.mid: -E -R50 -G_credits -V100 +mus_cycling.mid: -E -R50 -G_cycling -V083 +mus_dewford.mid: -E -R50 -G_dewford -V078 mus_dummy.mid: -E -R40 -mus_encounter_aqua.mid: -E -R50 -G065 -V086 -mus_encounter_brendan.mid: -E -R50 -G067 -V078 -mus_encounter_champion.mid: -E -R50 -G100 -V076 -mus_encounter_cool.mid: -E -R50 -G063 -V086 -mus_encounter_elite_four.mid: -E -R50 -G096 -V078 -mus_encounter_female.mid: -E -R50 -G053 -V072 -mus_encounter_girl.mid: -E -R50 -G027 -V080 -mus_encounter_hiker.mid: -E -R50 -G097 -V076 -mus_encounter_intense.mid: -E -R50 -G062 -V078 -mus_encounter_interviewer.mid: -E -R50 -G099 -V062 -mus_encounter_magma.mid: -E -R50 -G087 -V072 -mus_encounter_male.mid: -E -R50 -G028 -V080 -mus_encounter_may.mid: -E -R50 -G061 -V078 -mus_encounter_rich.mid: -E -R50 -G043 -V094 -mus_encounter_suspicious.mid: -E -R50 -G069 -V078 -mus_encounter_swimmer.mid: -E -R50 -G036 -V080 -mus_encounter_twins.mid: -E -R50 -G095 -V075 -mus_end.mid: -E -R50 -G102 -V036 -mus_ever_grande.mid: -E -R50 -G068 -V086 -mus_evolution_intro.mid: -E -R50 -G026 -V080 -mus_evolution.mid: -E -R50 -G026 -V080 -mus_evolved.mid: -E -R50 -G012 -V090 -P5 -mus_fallarbor.mid: -E -R50 -G083 -V100 -mus_follow_me.mid: -E -R50 -G066 -V074 -mus_fortree.mid: -E -R50 -G032 -V080 -mus_game_corner.mid: -E -R50 -G072 -V072 +mus_encounter_aqua.mid: -E -R50 -G_encounter_aqua -V086 +mus_encounter_brendan.mid: -E -R50 -G_encounter_brendan -V078 +mus_encounter_champion.mid: -E -R50 -G_encounter_champion -V076 +mus_encounter_cool.mid: -E -R50 -G_encounter_cool -V086 +mus_encounter_elite_four.mid: -E -R50 -G_encounter_elite_four -V078 +mus_encounter_female.mid: -E -R50 -G_encounter_female -V072 +mus_encounter_girl.mid: -E -R50 -G_encounter_girl -V080 +mus_encounter_hiker.mid: -E -R50 -G_encounter_hiker -V076 +mus_encounter_intense.mid: -E -R50 -G_encounter_intense -V078 +mus_encounter_interviewer.mid: -E -R50 -G_encounter_interviewer -V062 +mus_encounter_magma.mid: -E -R50 -G_encounter_magma -V072 +mus_encounter_male.mid: -E -R50 -G_encounter_male -V080 +mus_encounter_may.mid: -E -R50 -G_encounter_may -V078 +mus_encounter_rich.mid: -E -R50 -G_encounter_rich -V094 +mus_encounter_suspicious.mid: -E -R50 -G_encounter_suspicious -V078 +mus_encounter_swimmer.mid: -E -R50 -G_encounter_swimmer -V080 +mus_encounter_twins.mid: -E -R50 -G_encounter_twins -V075 +mus_end.mid: -E -R50 -G_end -V036 +mus_ever_grande.mid: -E -R50 -G_ever_grande -V086 +mus_evolution_intro.mid: -E -R50 -G_evolution -V080 +mus_evolution.mid: -E -R50 -G_evolution -V080 +mus_evolved.mid: -E -R50 -G_fanfare -V090 -P5 +mus_fallarbor.mid: -E -R50 -G_fallarbor -V100 +mus_follow_me.mid: -E -R50 -G_follow_me -V074 +mus_fortree.mid: -E -R50 -G_fortree -V080 +mus_game_corner.mid: -E -R50 -G_game_corner -V072 mus_gsc_pewter.mid: -E -R50 -V080 mus_gsc_route38.mid: -E -R50 -V080 -mus_gym.mid: -E -R50 -G013 -V080 -mus_hall_of_fame_room.mid: -E -R50 -G093 -V080 -mus_hall_of_fame.mid: -E -R50 -G082 -V078 -mus_heal.mid: -E -R50 -G012 -V090 -P5 -mus_help.mid: -E -R50 -G056 -V078 -mus_intro_battle.mid: -E -R50 -G088 -V088 -mus_intro.mid: -E -R50 -G060 -V090 -mus_level_up.mid: -E -R50 -G012 -V090 -P5 -mus_lilycove_museum.mid: -E -R50 -G020 -V080 -mus_lilycove.mid: -E -R50 -G054 -V085 -mus_link_contest_p1.mid: -E -R50 -G039 -V079 -mus_link_contest_p2.mid: -E -R50 -G040 -V090 -mus_link_contest_p3.mid: -E -R50 -G041 -V075 -mus_link_contest_p4.mid: -E -R50 -G042 -V090 -mus_littleroot_test.mid: -E -R50 -G034 -V099 -mus_littleroot.mid: -E -R50 -G051 -V100 -mus_move_deleted.mid: -E -R50 -G012 -V090 -P5 -mus_mt_chimney.mid: -E -R50 -G052 -V078 -mus_mt_pyre_exterior.mid: -E -R50 -G080 -V080 -mus_mt_pyre.mid: -E -R50 -G078 -V088 -mus_obtain_b_points.mid: -E -R50 -G103 -V090 -P5 -mus_obtain_badge.mid: -E -R50 -G012 -V090 -P5 -mus_obtain_berry.mid: -E -R50 -G012 -V090 -P5 -mus_obtain_item.mid: -E -R50 -G012 -V090 -P5 -mus_obtain_symbol.mid: -E -R50 -G103 -V100 -P5 -mus_obtain_tmhm.mid: -E -R50 -G012 -V090 -P5 -mus_oceanic_museum.mid: -E -R50 -G023 -V080 -mus_oldale.mid: -E -R50 -G019 -V080 -mus_petalburg_woods.mid: -E -R50 -G018 -V080 -mus_petalburg.mid: -E -R50 -G015 -V080 -mus_poke_center.mid: -E -R50 -G046 -V092 -mus_poke_mart.mid: -E -R50 -G050 -V085 -mus_rayquaza_appears.mid: -E -R50 -G109 -V090 -mus_register_match_call.mid: -E -R50 -G105 -V090 -P5 -mus_rg_berry_pick.mid: -E -R50 -G132 -V090 -mus_rg_caught_intro.mid: -E -R50 -G179 -V094 -P5 -mus_rg_caught.mid: -E -R50 -G170 -V100 -mus_rg_celadon.mid: -E -R50 -G168 -V070 -mus_rg_cinnabar.mid: -E -R50 -G138 -V090 -mus_rg_credits.mid: -E -R50 -G149 -V090 -mus_rg_cycling.mid: -E -R50 -G141 -V090 -mus_rg_dex_rating.mid: -E -R50 -G175 -V070 -P5 -mus_rg_encounter_boy.mid: -E -R50 -G144 -V090 -mus_rg_encounter_deoxys.mid: -E -R50 -G184 -V079 -mus_rg_encounter_girl.mid: -E -R50 -G143 -V051 -mus_rg_encounter_gym_leader: -E -R50 -G144 -V090 -mus_rg_encounter_rival.mid: -E -R50 -G174 -V079 -mus_rg_encounter_rocket.mid: -E -R50 -G142 -V096 -mus_rg_follow_me.mid: -E -R50 -G131 -V068 -mus_rg_fuchsia.mid: -E -R50 -G167 -V090 -mus_rg_game_corner.mid: -E -R50 -G132 -V090 -mus_rg_game_freak.mid: -E -R50 -G181 -V075 -mus_rg_gym.mid: -E -R50 -G134 -V090 -mus_rg_hall_of_fame.mid: -E -R50 -G145 -V079 -mus_rg_heal.mid: -E -R50 -G140 -V090 -mus_rg_intro_fight.mid: -E -R50 -G136 -V090 -mus_rg_jigglypuff.mid: -E -R50 -G135 -V068 -P5 -mus_rg_lavender.mid: -E -R50 -G139 -V090 -mus_rg_mt_moon.mid: -E -R50 -G147 -V090 -mus_rg_mystery_gift.mid: -E -R50 -G183 -V100 -mus_rg_net_center.mid: -E -R50 -G162 -V096 -mus_rg_new_game_exit.mid: -E -R50 -G182 -V088 -mus_rg_new_game_instruct.mid: -E -R50 -G182 -V085 -mus_rg_new_game_intro.mid: -E -R50 -G182 -V088 -mus_rg_oak_lab.mid: -E -R50 -G160 -V075 -mus_rg_oak.mid: -E -R50 -G161 -V086 -mus_rg_obtain_key_item.mid: -E -R50 -G178 -V077 -P5 -mus_rg_pallet.mid: -E -R50 -G159 -V100 -mus_rg_pewter.mid: -E -R50 -G173 -V084 -mus_rg_photo.mid: -E -R50 -G180 -V100 -P5 -mus_rg_poke_center.mid: -E -R50 -G162 -V096 -mus_rg_poke_flute.mid: -E -R50 -G165 -V048 -P5 -mus_rg_poke_jump.mid: -E -R50 -G132 -V090 -mus_rg_poke_mansion.mid: -E -R50 -G148 -V090 -mus_rg_poke_tower.mid: -E -R50 -G165 -V090 -mus_rg_rival_exit.mid: -E -R50 -G174 -V079 -mus_rg_rocket_hideout.mid: -E -R50 -G133 -V090 -mus_rg_route1.mid: -E -R50 -G150 -V079 -mus_rg_route3.mid: -E -R50 -G152 -V083 -mus_rg_route11.mid: -E -R50 -G153 -V090 -mus_rg_route24.mid: -E -R50 -G151 -V086 -mus_rg_sevii_45.mid: -E -R50 -G188 -V084 -mus_rg_sevii_67.mid: -E -R50 -G189 -V084 -mus_rg_sevii_123.mid: -E -R50 -G173 -V084 -mus_rg_sevii_cave.mid: -E -R50 -G147 -V090 -mus_rg_sevii_dungeon.mid: -E -R50 -G146 -V090 -mus_rg_sevii_route.mid: -E -R50 -G187 -V080 -mus_rg_silph.mid: -E -R50 -G166 -V076 -mus_rg_slow_pallet.mid: -E -R50 -G159 -V092 -mus_rg_ss_anne.mid: -E -R50 -G163 -V090 -mus_rg_surf.mid: -E -R50 -G164 -V071 -mus_rg_teachy_tv_menu.mid: -E -R50 -G186 -V059 -mus_rg_teachy_tv_show.mid: -E -R50 -G131 -V068 -mus_rg_title.mid: -E -R50 -G137 -V090 -mus_rg_trainer_tower.mid: -E -R50 -G134 -V090 -mus_rg_union_room.mid: -E -R50 -G132 -V090 -mus_rg_vermillion.mid: -E -R50 -G172 -V090 -mus_rg_victory_gym_leader.mid: -E -R50 -G171 -V090 -mus_rg_victory_road.mid: -E -R50 -G154 -V090 -mus_rg_victory_trainer.mid: -E -R50 -G169 -V089 -mus_rg_victory_wild.mid: -E -R50 -G170 -V090 -mus_rg_viridian_forest.mid: -E -R50 -G146 -V090 -mus_rg_vs_champion.mid: -E -R50 -G158 -V090 -mus_rg_vs_deoxys.mid: -E -R50 -G185 -V080 -mus_rg_vs_gym_leader.mid: -E -R50 -G155 -V090 -mus_rg_vs_legend.mid: -E -R50 -G157 -V090 -mus_rg_vs_mewtwo.mid: -E -R50 -G157 -V090 -mus_rg_vs_trainer.mid: -E -R50 -G156 -V090 -mus_rg_vs_wild.mid: -E -R50 -G157 -V090 -mus_roulette.mid: -E -R50 -G038 -V080 -mus_route101.mid: -E -R50 -G011 -V080 -mus_route104.mid: -E -R50 -G047 -V097 -mus_route110.mid: -E -R50 -G010 -V080 -mus_route111.mid: -E -R50 -G055 -V076 -mus_route113.mid: -E -R50 -G064 -V084 -mus_route119.mid: -E -R50 -G048 -V096 -mus_route120.mid: -E -R50 -G014 -V080 -mus_route122.mid: -E -R50 -G021 -V080 -mus_rustboro.mid: -E -R50 -G045 -V085 -mus_safari_zone.mid: -E -R50 -G074 -V082 -mus_sailing.mid: -E -R50 -G077 -V086 -mus_school.mid: -E -R50 -G081 -V100 -mus_sealed_chamber.mid: -E -R50 -G084 -V100 -mus_slateport.mid: -E -R50 -G079 -V070 -mus_slots_jackpot.mid: -E -R50 -G012 -V090 -P5 -mus_slots_win.mid: -E -R50 -G012 -V090 -P5 -mus_sootopolis.mid: -E -R50 -G091 -V062 -mus_surf.mid: -E -R50 -G017 -V080 -mus_title.mid: -E -R50 -G059 -V090 -mus_too_bad.mid: -E -R50 -G012 -V090 -P5 -mus_trick_house.mid: -E -R50 -G094 -V070 -mus_underwater.mid: -E -R50 -G057 -V094 -mus_verdanturf.mid: -E -R50 -G044 -V090 -mus_victory_aqua_magma.mid: -E -R50 -G070 -V088 -mus_victory_gym_leader.mid: -E -R50 -G024 -V080 -mus_victory_league.mid: -E -R50 -G029 -V080 -mus_victory_road.mid: -E -R50 -G075 -V076 -mus_victory_trainer.mid: -E -R50 -G058 -V091 -mus_victory_wild.mid: -E -R50 -G025 -V080 -mus_vs_aqua_magma_leader.mid: -E -R50 -G126 -V080 -P1 -mus_vs_aqua_magma.mid: -E -R50 -G118 -V080 -P1 -mus_vs_champion.mid: -E -R50 -G121 -V080 -P1 -mus_vs_elite_four.mid: -E -R50 -G125 -V080 -P1 -mus_vs_frontier_brain.mid: -E -R50 -G115 -V090 -P1 -mus_vs_gym_leader.mid: -E -R50 -G120 -V080 -P1 -mus_vs_kyogre_groudon.mid: -E -R50 -G123 -V080 -P1 -mus_vs_mew.mid: -E -R50 -G116 -V090 -mus_vs_rayquaza.mid: -E -R50 -G114 -V080 -P1 -mus_vs_regi.mid: -E -R50 -G122 -V080 -P1 -mus_vs_rival.mid: -E -R50 -G124 -V080 -P1 -mus_vs_trainer.mid: -E -R50 -G119 -V080 -P1 -mus_vs_wild.mid: -E -R50 -G117 -V080 -P1 -mus_weather_groudon.mid: -E -R50 -G090 -V050 -ph_choice_blend.mid: -E -G130 -P4 -ph_choice_held.mid: -E -G130 -P4 -ph_choice_solo.mid: -E -G130 -P4 -ph_cloth_blend.mid: -E -G130 -P4 -ph_cloth_held.mid: -E -G130 -P4 -ph_cloth_solo.mid: -E -G130 -P4 -ph_cure_blend.mid: -E -G130 -P4 -ph_cure_held.mid: -E -G130 -P4 -ph_cure_solo.mid: -E -G130 -P4 -ph_dress_blend.mid: -E -G130 -P4 -ph_dress_held.mid: -E -G130 -P4 -ph_dress_solo.mid: -E -G130 -P4 -ph_face_blend.mid: -E -G130 -P4 -ph_face_held.mid: -E -G130 -P4 -ph_face_solo.mid: -E -G130 -P4 -ph_fleece_blend.mid: -E -G130 -P4 -ph_fleece_held.mid: -E -G130 -P4 -ph_fleece_solo.mid: -E -G130 -P4 -ph_foot_blend.mid: -E -G130 -P4 -ph_foot_held.mid: -E -G130 -P4 -ph_foot_solo.mid: -E -G130 -P4 -ph_goat_blend.mid: -E -G130 -P4 -ph_goat_held.mid: -E -G130 -P4 -ph_goat_solo.mid: -E -G130 -P4 -ph_goose_blend.mid: -E -G130 -P4 -ph_goose_held.mid: -E -G130 -P4 -ph_goose_solo.mid: -E -G130 -P4 -ph_kit_blend.mid: -E -G130 -P4 -ph_kit_held.mid: -E -G130 -P4 -ph_kit_solo.mid: -E -G130 -P4 -ph_lot_blend.mid: -E -G130 -P4 -ph_lot_held.mid: -E -G130 -P4 -ph_lot_solo.mid: -E -G130 -P4 -ph_mouth_blend.mid: -E -G130 -P4 -ph_mouth_held.mid: -E -G130 -P4 -ph_mouth_solo.mid: -E -G130 -P4 -ph_nurse_blend.mid: -E -G130 -P4 -ph_nurse_held.mid: -E -G130 -P4 -ph_nurse_solo.mid: -E -G130 -P4 -ph_price_blend.mid: -E -G130 -P4 -ph_price_held.mid: -E -G130 -P4 -ph_price_solo.mid: -E -G130 -P4 -ph_strut_blend.mid: -E -G130 -P4 -ph_strut_held.mid: -E -G130 -P4 -ph_strut_solo.mid: -E -G130 -P4 -ph_thought_blend.mid: -E -G130 -P4 -ph_thought_held.mid: -E -G130 -P4 -ph_thought_solo.mid: -E -G130 -P4 -ph_trap_blend.mid: -E -G130 -P4 -ph_trap_held.mid: -E -G130 -P4 -ph_trap_solo.mid: -E -G130 -P4 -se_a.mid: -E -R50 -G128 -V095 -P4 -se_applause.mid: -E -R50 -G128 -V100 -P5 -se_arena_timeup1.mid: -E -R50 -G129 -P5 -se_arena_timeup2.mid: -E -R50 -G129 -P5 -se_ball_bounce_1.mid: -E -R50 -G128 -V100 -P4 -se_ball_bounce_2.mid: -E -R50 -G128 -V100 -P4 -se_ball_bounce_3.mid: -E -R50 -G128 -V100 -P4 -se_ball_bounce_4.mid: -E -R50 -G128 -V100 -P4 -se_ball_open.mid: -E -R50 -G127 -V100 -P5 -se_ball_throw.mid: -E -R50 -G128 -V120 -P5 -se_ball_trade.mid: -E -R50 -G127 -V100 -P5 -se_ball_tray_ball.mid: -E -R50 -G128 -V110 -P5 -se_ball_tray_enter.mid: -E -R50 -G128 -V110 -P5 -se_ball_tray_exit.mid: -E -R50 -G127 -V100 -P5 -se_ball.mid: -E -R50 -G127 -V070 -P4 -se_balloon_blue.mid: -E -R50 -G128 -V105 -P4 -se_balloon_red.mid: -E -R50 -G128 -V105 -P4 -se_balloon_yellow.mid: -E -R50 -G128 -V105 -P4 -se_bang.mid: -E -R50 -G128 -V110 -P4 -se_berry_blender.mid: -E -R50 -G128 -V090 -P4 -se_bike_bell.mid: -E -R50 -G128 -V090 -P4 -se_bike_hop.mid: -E -R50 -G127 -V090 -P4 -se_boo.mid: -E -R50 -G127 -V110 -P4 -se_breakable_door.mid: -E -R50 -G128 -V110 -P4 -se_bridge_walk.mid: -E -R50 -G128 -V095 -P4 -se_card.mid: -E -R50 -G127 -V100 -P4 -se_click.mid: -E -R50 -G127 -V110 -P4 -se_contest_condition_lose.mid: -E -R50 -G127 -V110 -P4 -se_contest_curtain_fall.mid: -E -R50 -G128 -V070 -P5 -se_contest_curtain_rise.mid: -E -R50 -G128 -V070 -P5 -se_contest_heart.mid: -E -R50 -G128 -V090 -P5 -se_contest_icon_change.mid: -E -R50 -G128 -V110 -P5 -se_contest_icon_clear.mid: -E -R50 -G128 -V090 -P5 -se_contest_mons_turn.mid: -E -R50 -G128 -V090 -P5 -se_contest_place.mid: -E -R50 -G127 -V110 -P4 -se_dex_search.mid: -E -R50 -G127 -v100 -P5 -se_ding_dong.mid: -E -R50 -G127 -V090 -P5 -se_door.mid: -E -R50 -G127 -V080 -P5 -se_downpour_stop.mid: -E -R50 -G128 -V100 -P2 -se_downpour.mid: -E -R50 -G128 -V100 -P2 -se_e.mid: -E -R50 -G128 -V120 -P4 -se_effective.mid: -E -R50 -G127 -V110 -P5 -se_egg_hatch.mid: -E -R50 -G128 -V120 -P5 -se_elevator.mid: -E -R50 -G128 -V100 -P4 -se_escalator.mid: -E -R50 -G128 -V100 -P4 -se_exit.mid: -E -R50 -G127 -V120 -P5 -se_exp_max.mid: -E -R50 -G128 -V094 -P5 -se_exp.mid: -E -R50 -G127 -V080 -P5 -se_failure.mid: -E -R50 -G127 -V120 -P4 -se_faint.mid: -E -R50 -G127 -V110 -P5 -se_fall.mid: -E -R50 -G128 -V110 -P4 -se_field_poison.mid: -E -R50 -G127 -V110 -P5 -se_flee.mid: -E -R50 -G127 -V090 -P5 -se_fu_zaku.mid: -E -R50 -G127 -V120 -P4 -se_glass_flute.mid: -E -R50 -G128 -V105 -P5 -se_i.mid: -E -R50 -G128 -V120 -P4 -se_ice_break.mid: -E -R50 -G128 -V100 -P4 -se_ice_crack.mid: -E -R50 -G127 -V100 -P4 -se_ice_stairs.mid: -E -R50 -G128 -V090 -P4 -se_intro_blast.mid: -E -R50 -G127 -V100 -P5 -se_itemfinder.mid: -E -R50 -G127 -V090 -P5 -se_lavaridge_fall_warp.mid: -E -R50 -G127 -P4 -se_ledge.mid: -E -R50 -G127 -V100 -P4 -se_low_health.mid: -E -R50 -G127 -V100 -P3 -se_m_bind.mid: -E -R50 -G128 -V100 -P4 -se_m_comet_punch.mid: -E -R50 -G128 -V120 -P4 -se_m_cut.mid: -E -R50 -G128 -V120 -P4 -se_m_double_slap.mid: -E -R50 -G128 -V110 -P4 -se_m_fire_punch.mid: -E -R50 -G128 -V110 -P4 -se_m_fly.mid: -E -R50 -G128 -V110 -P4 -se_m_gust.mid: -E -R50 -G128 -V110 -P4 -se_m_gust2.mid: -E -R50 -G128 -V110 -P4 -se_m_headbutt.mid: -E -R50 -G128 -V110 -P4 -se_m_horn_attack.mid: -E -R50 -G128 -V110 -P4 -se_m_jump_kick.mid: -E -R50 -G128 -V110 -P4 -se_m_leer.mid: -E -R50 -G128 -V110 -P4 -se_m_mega_kick.mid: -E -R50 -G128 -V090 -P4 -se_m_mega_kick2.mid: -E -R50 -G128 -V110 -P4 -se_m_pay_day.mid: -E -R50 -G128 -V095 -P4 -se_m_razor_wind.mid: -E -R50 -G128 -V110 -P4 -se_m_razor_wind2.mid: -E -R50 -G128 -V090 -P4 -se_m_sand_attack.mid: -E -R50 -G128 -V110 -P4 -se_m_scratch.mid: -E -R50 -G128 -V110 -P4 -se_m_swords_dance.mid: -E -R50 -G128 -V100 -P4 -se_m_tail_whip.mid: -E -R50 -G128 -V110 -P4 -se_m_take_down.mid: -E -R50 -G128 -V105 -P4 -se_m_vicegrip.mid: -E -R50 -G128 -V110 -P4 -se_m_wing_attack.mid: -E -R50 -G128 -V105 -P4 -se_mud_ball.mid: -E -R50 -G128 -V110 -P4 -se_mugshot.mid: -E -R50 -G128 -V090 -P5 -se_n.mid: -E -R50 -G128 -P4 -se_not_effective.mid: -E -R50 -G127 -V110 -P5 -se_note_a.mid: -E -R50 -G128 -V110 -P4 -se_note_b.mid: -E -R50 -G128 -V110 -P4 -se_note_c_high.mid: -E -R50 -G128 -V110 -P4 -se_note_c.mid: -E -R50 -G128 -V110 -P4 -se_note_d.mid: -E -R50 -G128 -V110 -P4 -se_note_e.mid: -E -R50 -G128 -V110 -P4 -se_note_f.mid: -E -R50 -G128 -V110 -P4 -se_note_g.mid: -E -R50 -G128 -V110 -P4 -se_o.mid: -E -R50 -G128 -V120 -P4 -se_orb.mid: -E -R50 -G128 -V100 -P5 -se_pc_login.mid: -E -R50 -G127 -V100 -P5 -se_pc_off.mid: -E -R50 -G127 -V100 -P5 -se_pc_on.mid: -E -R50 -G127 -V100 -P5 -se_pike_curtain_close.mid: -E -R50 -G129 -P5 -se_pike_curtain_open.mid: -E -R50 -G129 -P5 -se_pin.mid: -E -R50 -G127 -V060 -P4 -se_pokenav_call.mid: -E -R50 -G129 -V120 -P5 -se_pokenav_hang_up.mid: -E -R50 -G129 -V110 -P5 -se_pokenav_off.mid: -E -R50 -G127 -V100 -P5 -se_pokenav_on.mid: -E -R50 -G127 -V100 -P5 -se_puddle.mid: -E -R50 -G128 -V020 -P4 -se_rain_stop.mid: -E -R50 -G128 -V080 -P2 -se_rain.mid: -E -R50 -G128 -V080 -P2 -se_repel.mid: -E -R50 -G127 -V090 -P4 -se_rg_bag_cursor.mid: -E -R50 -G129 -P5 -se_rg_bag_pocket.mid: -E -R50 -G129 -P5 -se_rg_ball_click.mid: -E -R50 -G129 -V100 -P5 -se_rg_card_flip.mid: -E -R50 -G129 -P5 -se_rg_card_flipping.mid: -E -R50 -G129 -P5 -se_rg_card_open.mid: -E -R50 -G129 -V112 -P5 -se_rg_deoxys_move.mid: -E -R50 -G129 -V080 -P5 -se_rg_door.mid: -E -R50 -G129 -V100 -P5 -se_rg_help_close.mid: -E -R50 -G129 -V095 -P5 -se_rg_help_error.mid: -E -R50 -G129 -V125 -P5 -se_rg_help_open.mid: -E -R50 -G129 -V096 -P5 -se_rg_poke_jump_failure.mid: -E -R50 -G127 -P5 -se_rg_poke_jump_success.mid: -E -R50 -G128 -V110 -P5 -se_rg_shop.mid: -E -R50 -G129 -V080 -P5 -se_rg_ss_anne_horn.mid: -E -R50 -G129 -V096 -P5 -se_rotating_gate.mid: -E -R50 -G128 -V090 -P4 -se_roulette_ball.mid: -E -R50 -G128 -V110 -P2 -se_roulette_ball2.mid: -E -R50 -G128 -V110 -P2 -se_save.mid: -E -R50 -G128 -V080 -P5 -se_select.mid: -E -R50 -G127 -V080 -P5 -se_shiny.mid: -E -R50 -G128 -V095 -P5 -se_ship.mid: -E -R50 -G127 -V075 -P4 -se_shop.mid: -E -R50 -G127 -V090 -P5 -se_sliding_door.mid: -E -R50 -G128 -V095 -P4 -se_success.mid: -E -R50 -G127 -V080 -P4 -se_sudowoodo_shake.mid: -E -R50 -G129 -V077 -P5 -se_super_effective.mid: -E -R50 -G127 -V110 -P5 -se_switch.mid: -E -R50 -G127 -V100 -P4 -se_taillow_wing_flap.mid: -E -R50 -G128 -V105 -P5 -se_thunder.mid: -E -R50 -G128 -V110 -P3 -se_thunder2.mid: -E -R50 -G128 -V110 -P3 -se_thunderstorm_stop.mid: -E -R50 -G128 -V080 -P2 -se_thunderstorm.mid: -E -R50 -G128 -V080 -P2 -se_truck_door.mid: -E -R50 -G128 -V110 -P4 -se_truck_move.mid: -E -R50 -G128 -P4 -se_truck_stop.mid: -E -R50 -G128 -P4 -se_truck_unload.mid: -E -R50 -G127 -P4 -se_u.mid: -E -R50 -G128 -P4 -se_unlock.mid: -E -R50 -G128 -V100 -P4 -se_use_item.mid: -E -R50 -G127 -V100 -P5 -se_vend.mid: -E -R50 -G128 -V110 -P4 -se_warp_in.mid: -E -R50 -G127 -V090 -P4 -se_warp_out.mid: -E -R50 -G127 -V090 -P4 +mus_gym.mid: -E -R50 -G_gym -V080 +mus_hall_of_fame_room.mid: -E -R50 -G_hall_of_fame_room -V080 +mus_hall_of_fame.mid: -E -R50 -G_hall_of_fame -V078 +mus_heal.mid: -E -R50 -G_fanfare -V090 -P5 +mus_help.mid: -E -R50 -G_help -V078 +mus_intro_battle.mid: -E -R50 -G_intro_battle -V088 +mus_intro.mid: -E -R50 -G_intro -V090 +mus_level_up.mid: -E -R50 -G_fanfare -V090 -P5 +mus_lilycove_museum.mid: -E -R50 -G_lilycove_museum -V080 +mus_lilycove.mid: -E -R50 -G_lilycove -V085 +mus_link_contest_p1.mid: -E -R50 -G_link_contest_p1 -V079 +mus_link_contest_p2.mid: -E -R50 -G_link_contest_p2 -V090 +mus_link_contest_p3.mid: -E -R50 -G_link_contest_p3 -V075 +mus_link_contest_p4.mid: -E -R50 -G_link_contest_p4 -V090 +mus_littleroot_test.mid: -E -R50 -G_littleroot_test -V099 +mus_littleroot.mid: -E -R50 -G_littleroot -V100 +mus_move_deleted.mid: -E -R50 -G_fanfare -V090 -P5 +mus_mt_chimney.mid: -E -R50 -G_mt_chimney -V078 +mus_mt_pyre_exterior.mid: -E -R50 -G_mt_pyre_exterior -V080 +mus_mt_pyre.mid: -E -R50 -G_mt_pyre -V088 +mus_obtain_b_points.mid: -E -R50 -G_b_frontier -V090 -P5 +mus_obtain_badge.mid: -E -R50 -G_fanfare -V090 -P5 +mus_obtain_berry.mid: -E -R50 -G_fanfare -V090 -P5 +mus_obtain_item.mid: -E -R50 -G_fanfare -V090 -P5 +mus_obtain_symbol.mid: -E -R50 -G_b_frontier -V100 -P5 +mus_obtain_tmhm.mid: -E -R50 -G_fanfare -V090 -P5 +mus_oceanic_museum.mid: -E -R50 -G_oceanic_museum -V080 +mus_oldale.mid: -E -R50 -G_oldale -V080 +mus_petalburg_woods.mid: -E -R50 -G_petalburg_woods -V080 +mus_petalburg.mid: -E -R50 -G_petalburg -V080 +mus_poke_center.mid: -E -R50 -G_poke_center -V092 +mus_poke_mart.mid: -E -R50 -G_poke_mart -V085 +mus_rayquaza_appears.mid: -E -R50 -G_rayquaza_appears -V090 +mus_register_match_call.mid: -E -R50 -G_register_match_call -V090 -P5 +mus_rg_berry_pick.mid: -E -R50 -G_rg_game_corner -V090 +mus_rg_caught_intro.mid: -E -R50 -G_rg_caught_intro -V094 -P5 +mus_rg_caught.mid: -E -R50 -G_rg_victory_wild -V100 +mus_rg_celadon.mid: -E -R50 -G_rg_celadon -V070 +mus_rg_cinnabar.mid: -E -R50 -G_rg_cinnabar -V090 +mus_rg_credits.mid: -E -R50 -G_rg_credits -V090 +mus_rg_cycling.mid: -E -R50 -G_rg_cycling -V090 +mus_rg_dex_rating.mid: -E -R50 -G_rg_dex_rating -V070 -P5 +mus_rg_encounter_boy.mid: -E -R50 -G_rg_encounter_boy -V090 +mus_rg_encounter_deoxys.mid: -E -R50 -G_rg_encounter_deoxys -V079 +mus_rg_encounter_girl.mid: -E -R50 -G_rg_encounter_girl -V051 +mus_rg_encounter_gym_leader: -E -R50 -G_rg_encounter_boy -V090 +mus_rg_encounter_rival.mid: -E -R50 -G_rg_encounter_rival -V079 +mus_rg_encounter_rocket.mid: -E -R50 -G_rg_encounter_rocket -V096 +mus_rg_follow_me.mid: -E -R50 -G_rg_follow_me -V068 +mus_rg_fuchsia.mid: -E -R50 -G_rg_fuchsia -V090 +mus_rg_game_corner.mid: -E -R50 -G_rg_game_corner -V090 +mus_rg_game_freak.mid: -E -R50 -G_rg_game_freak -V075 +mus_rg_gym.mid: -E -R50 -G_rg_gym -V090 +mus_rg_hall_of_fame.mid: -E -R50 -G_rg_hall_of_fame -V079 +mus_rg_heal.mid: -E -R50 -G_rg_heal -V090 +mus_rg_intro_fight.mid: -E -R50 -G_rg_intro_fight -V090 +mus_rg_jigglypuff.mid: -E -R50 -G_rg_jigglypuff -V068 -P5 +mus_rg_lavender.mid: -E -R50 -G_rg_lavender -V090 +mus_rg_mt_moon.mid: -E -R50 -G_rg_mt_moon -V090 +mus_rg_mystery_gift.mid: -E -R50 -G_rg_mystery_gift -V100 +mus_rg_net_center.mid: -E -R50 -G_rg_poke_center -V096 +mus_rg_new_game_exit.mid: -E -R50 -G_rg_new_game -V088 +mus_rg_new_game_instruct.mid: -E -R50 -G_rg_new_game -V085 +mus_rg_new_game_intro.mid: -E -R50 -G_rg_new_game -V088 +mus_rg_oak_lab.mid: -E -R50 -G_rg_oak_lab -V075 +mus_rg_oak.mid: -E -R50 -G_rg_oak -V086 +mus_rg_obtain_key_item.mid: -E -R50 -G_rg_obtain_key_item -V077 -P5 +mus_rg_pallet.mid: -E -R50 -G_rg_pallet -V100 +mus_rg_pewter.mid: -E -R50 -G_rg_pewter -V084 +mus_rg_photo.mid: -E -R50 -G_rg_photo -V100 -P5 +mus_rg_poke_center.mid: -E -R50 -G_rg_poke_center -V096 +mus_rg_poke_flute.mid: -E -R50 -G_rg_poke_tower -V048 -P5 +mus_rg_poke_jump.mid: -E -R50 -G_rg_game_corner -V090 +mus_rg_poke_mansion.mid: -E -R50 -G_rg_poke_mansion -V090 +mus_rg_poke_tower.mid: -E -R50 -G_rg_poke_tower -V090 +mus_rg_rival_exit.mid: -E -R50 -G_rg_encounter_rival -V079 +mus_rg_rocket_hideout.mid: -E -R50 -G_rg_rocket_hideout -V090 +mus_rg_route1.mid: -E -R50 -G_rg_route1 -V079 +mus_rg_route3.mid: -E -R50 -G_rg_route3 -V083 +mus_rg_route11.mid: -E -R50 -G_rg_route11 -V090 +mus_rg_route24.mid: -E -R50 -G_rg_route24 -V086 +mus_rg_sevii_45.mid: -E -R50 -G_rg_sevii_45 -V084 +mus_rg_sevii_67.mid: -E -R50 -G_rg_sevii_67 -V084 +mus_rg_sevii_123.mid: -E -R50 -G_rg_pewter -V084 +mus_rg_sevii_cave.mid: -E -R50 -G_rg_mt_moon -V090 +mus_rg_sevii_dungeon.mid: -E -R50 -G_rg_viridian_forest -V090 +mus_rg_sevii_route.mid: -E -R50 -G_rg_sevii_route -V080 +mus_rg_silph.mid: -E -R50 -G_rg_silph -V076 +mus_rg_slow_pallet.mid: -E -R50 -G_rg_pallet -V092 +mus_rg_ss_anne.mid: -E -R50 -G_rg_ss_anne -V090 +mus_rg_surf.mid: -E -R50 -G_rg_surf -V071 +mus_rg_teachy_tv_menu.mid: -E -R50 -G_rg_teachy_tv_menu -V059 +mus_rg_teachy_tv_show.mid: -E -R50 -G_rg_follow_me -V068 +mus_rg_title.mid: -E -R50 -G_rg_title -V090 +mus_rg_trainer_tower.mid: -E -R50 -G_rg_gym -V090 +mus_rg_union_room.mid: -E -R50 -G_rg_game_corner -V090 +mus_rg_vermillion.mid: -E -R50 -G_rg_vermillion -V090 +mus_rg_victory_gym_leader.mid: -E -R50 -G_rg_victory_gym_leader -V090 +mus_rg_victory_road.mid: -E -R50 -G_rg_victory_road -V090 +mus_rg_victory_trainer.mid: -E -R50 -G_rg_victory_trainer -V089 +mus_rg_victory_wild.mid: -E -R50 -G_rg_victory_wild -V090 +mus_rg_viridian_forest.mid: -E -R50 -G_rg_viridian_forest -V090 +mus_rg_vs_champion.mid: -E -R50 -G_rg_vs_champion -V090 +mus_rg_vs_deoxys.mid: -E -R50 -G_rg_vs_deoxys -V080 +mus_rg_vs_gym_leader.mid: -E -R50 -G_rg_vs_gym_leader -V090 +mus_rg_vs_legend.mid: -E -R50 -G_rg_vs_wild -V090 +mus_rg_vs_mewtwo.mid: -E -R50 -G_rg_vs_wild -V090 +mus_rg_vs_trainer.mid: -E -R50 -G_rg_vs_trainer -V090 +mus_rg_vs_wild.mid: -E -R50 -G_rg_vs_wild -V090 +mus_roulette.mid: -E -R50 -G_roulette -V080 +mus_route101.mid: -E -R50 -G_route101 -V080 +mus_route104.mid: -E -R50 -G_route104 -V097 +mus_route110.mid: -E -R50 -G_route110 -V080 +mus_route111.mid: -E -R50 -G_route111 -V076 +mus_route113.mid: -E -R50 -G_route113 -V084 +mus_route119.mid: -E -R50 -G_route119 -V096 +mus_route120.mid: -E -R50 -G_route120 -V080 +mus_route122.mid: -E -R50 -G_route122 -V080 +mus_rustboro.mid: -E -R50 -G_rustboro -V085 +mus_safari_zone.mid: -E -R50 -G_safari_zone -V082 +mus_sailing.mid: -E -R50 -G_sailing -V086 +mus_school.mid: -E -R50 -G_school -V100 +mus_sealed_chamber.mid: -E -R50 -G_sealed_chamber -V100 +mus_slateport.mid: -E -R50 -G_slateport -V070 +mus_slots_jackpot.mid: -E -R50 -G_fanfare -V090 -P5 +mus_slots_win.mid: -E -R50 -G_fanfare -V090 -P5 +mus_sootopolis.mid: -E -R50 -G_sootopolis -V062 +mus_surf.mid: -E -R50 -G_surf -V080 +mus_title.mid: -E -R50 -G_title -V090 +mus_too_bad.mid: -E -R50 -G_fanfare -V090 -P5 +mus_trick_house.mid: -E -R50 -G_trick_house -V070 +mus_underwater.mid: -E -R50 -G_underwater -V094 +mus_verdanturf.mid: -E -R50 -G_verdanturf -V090 +mus_victory_aqua_magma.mid: -E -R50 -G_victory_aqua_magma -V088 +mus_victory_gym_leader.mid: -E -R50 -G_victory_gym_leader -V080 +mus_victory_league.mid: -E -R50 -G_victory_league -V080 +mus_victory_road.mid: -E -R50 -G_victory_road -V076 +mus_victory_trainer.mid: -E -R50 -G_victory_trainer -V091 +mus_victory_wild.mid: -E -R50 -G_victory_wild -V080 +mus_vs_aqua_magma_leader.mid: -E -R50 -G_vs_aqua_magma_leader -V080 -P1 +mus_vs_aqua_magma.mid: -E -R50 -G_vs_aqua_magma -V080 -P1 +mus_vs_champion.mid: -E -R50 -G_vs_champion -V080 -P1 +mus_vs_elite_four.mid: -E -R50 -G_vs_elite_four -V080 -P1 +mus_vs_frontier_brain.mid: -E -R50 -G_vs_frontier_brain -V090 -P1 +mus_vs_gym_leader.mid: -E -R50 -G_vs_gym_leader -V080 -P1 +mus_vs_kyogre_groudon.mid: -E -R50 -G_vs_kyogre_groudon -V080 -P1 +mus_vs_mew.mid: -E -R50 -G_vs_mew -V090 +mus_vs_rayquaza.mid: -E -R50 -G_vs_rayquaza -V080 -P1 +mus_vs_regi.mid: -E -R50 -G_vs_regi -V080 -P1 +mus_vs_rival.mid: -E -R50 -G_vs_rival -V080 -P1 +mus_vs_trainer.mid: -E -R50 -G_vs_trainer -V080 -P1 +mus_vs_wild.mid: -E -R50 -G_vs_wild -V080 -P1 +mus_weather_groudon.mid: -E -R50 -G_weather_groudon -V050 +ph_choice_blend.mid: -E -G_bard -P4 +ph_choice_held.mid: -E -G_bard -P4 +ph_choice_solo.mid: -E -G_bard -P4 +ph_cloth_blend.mid: -E -G_bard -P4 +ph_cloth_held.mid: -E -G_bard -P4 +ph_cloth_solo.mid: -E -G_bard -P4 +ph_cure_blend.mid: -E -G_bard -P4 +ph_cure_held.mid: -E -G_bard -P4 +ph_cure_solo.mid: -E -G_bard -P4 +ph_dress_blend.mid: -E -G_bard -P4 +ph_dress_held.mid: -E -G_bard -P4 +ph_dress_solo.mid: -E -G_bard -P4 +ph_face_blend.mid: -E -G_bard -P4 +ph_face_held.mid: -E -G_bard -P4 +ph_face_solo.mid: -E -G_bard -P4 +ph_fleece_blend.mid: -E -G_bard -P4 +ph_fleece_held.mid: -E -G_bard -P4 +ph_fleece_solo.mid: -E -G_bard -P4 +ph_foot_blend.mid: -E -G_bard -P4 +ph_foot_held.mid: -E -G_bard -P4 +ph_foot_solo.mid: -E -G_bard -P4 +ph_goat_blend.mid: -E -G_bard -P4 +ph_goat_held.mid: -E -G_bard -P4 +ph_goat_solo.mid: -E -G_bard -P4 +ph_goose_blend.mid: -E -G_bard -P4 +ph_goose_held.mid: -E -G_bard -P4 +ph_goose_solo.mid: -E -G_bard -P4 +ph_kit_blend.mid: -E -G_bard -P4 +ph_kit_held.mid: -E -G_bard -P4 +ph_kit_solo.mid: -E -G_bard -P4 +ph_lot_blend.mid: -E -G_bard -P4 +ph_lot_held.mid: -E -G_bard -P4 +ph_lot_solo.mid: -E -G_bard -P4 +ph_mouth_blend.mid: -E -G_bard -P4 +ph_mouth_held.mid: -E -G_bard -P4 +ph_mouth_solo.mid: -E -G_bard -P4 +ph_nurse_blend.mid: -E -G_bard -P4 +ph_nurse_held.mid: -E -G_bard -P4 +ph_nurse_solo.mid: -E -G_bard -P4 +ph_price_blend.mid: -E -G_bard -P4 +ph_price_held.mid: -E -G_bard -P4 +ph_price_solo.mid: -E -G_bard -P4 +ph_strut_blend.mid: -E -G_bard -P4 +ph_strut_held.mid: -E -G_bard -P4 +ph_strut_solo.mid: -E -G_bard -P4 +ph_thought_blend.mid: -E -G_bard -P4 +ph_thought_held.mid: -E -G_bard -P4 +ph_thought_solo.mid: -E -G_bard -P4 +ph_trap_blend.mid: -E -G_bard -P4 +ph_trap_held.mid: -E -G_bard -P4 +ph_trap_solo.mid: -E -G_bard -P4 +se_a.mid: -E -R50 -G_rs_sfx_2 -V095 -P4 +se_applause.mid: -E -R50 -G_rs_sfx_2 -V100 -P5 +se_arena_timeup1.mid: -E -R50 -G_frlg_sfx -P5 +se_arena_timeup2.mid: -E -R50 -G_frlg_sfx -P5 +se_ball_bounce_1.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_ball_bounce_2.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_ball_bounce_3.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_ball_bounce_4.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_ball_open.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_ball_throw.mid: -E -R50 -G_rs_sfx_2 -V120 -P5 +se_ball_trade.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_ball_tray_ball.mid: -E -R50 -G_rs_sfx_2 -V110 -P5 +se_ball_tray_enter.mid: -E -R50 -G_rs_sfx_2 -V110 -P5 +se_ball_tray_exit.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_ball.mid: -E -R50 -G_rs_sfx_1 -V070 -P4 +se_balloon_blue.mid: -E -R50 -G_rs_sfx_2 -V105 -P4 +se_balloon_red.mid: -E -R50 -G_rs_sfx_2 -V105 -P4 +se_balloon_yellow.mid: -E -R50 -G_rs_sfx_2 -V105 -P4 +se_bang.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_berry_blender.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_bike_bell.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_bike_hop.mid: -E -R50 -G_rs_sfx_1 -V090 -P4 +se_boo.mid: -E -R50 -G_rs_sfx_1 -V110 -P4 +se_breakable_door.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_bridge_walk.mid: -E -R50 -G_rs_sfx_2 -V095 -P4 +se_card.mid: -E -R50 -G_rs_sfx_1 -V100 -P4 +se_click.mid: -E -R50 -G_rs_sfx_1 -V110 -P4 +se_contest_condition_lose.mid: -E -R50 -G_rs_sfx_1 -V110 -P4 +se_contest_curtain_fall.mid: -E -R50 -G_rs_sfx_2 -V070 -P5 +se_contest_curtain_rise.mid: -E -R50 -G_rs_sfx_2 -V070 -P5 +se_contest_heart.mid: -E -R50 -G_rs_sfx_2 -V090 -P5 +se_contest_icon_change.mid: -E -R50 -G_rs_sfx_2 -V110 -P5 +se_contest_icon_clear.mid: -E -R50 -G_rs_sfx_2 -V090 -P5 +se_contest_mons_turn.mid: -E -R50 -G_rs_sfx_2 -V090 -P5 +se_contest_place.mid: -E -R50 -G_rs_sfx_1 -V110 -P4 +se_dex_search.mid: -E -R50 -G_rs_sfx_1 -v100 -P5 +se_ding_dong.mid: -E -R50 -G_rs_sfx_1 -V090 -P5 +se_door.mid: -E -R50 -G_rs_sfx_1 -V080 -P5 +se_downpour_stop.mid: -E -R50 -G_rs_sfx_2 -V100 -P2 +se_downpour.mid: -E -R50 -G_rs_sfx_2 -V100 -P2 +se_e.mid: -E -R50 -G_rs_sfx_2 -V120 -P4 +se_effective.mid: -E -R50 -G_rs_sfx_1 -V110 -P5 +se_egg_hatch.mid: -E -R50 -G_rs_sfx_2 -V120 -P5 +se_elevator.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_escalator.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_exit.mid: -E -R50 -G_rs_sfx_1 -V120 -P5 +se_exp_max.mid: -E -R50 -G_rs_sfx_2 -V094 -P5 +se_exp.mid: -E -R50 -G_rs_sfx_1 -V080 -P5 +se_failure.mid: -E -R50 -G_rs_sfx_1 -V120 -P4 +se_faint.mid: -E -R50 -G_rs_sfx_1 -V110 -P5 +se_fall.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_field_poison.mid: -E -R50 -G_rs_sfx_1 -V110 -P5 +se_flee.mid: -E -R50 -G_rs_sfx_1 -V090 -P5 +se_fu_zaku.mid: -E -R50 -G_rs_sfx_1 -V120 -P4 +se_glass_flute.mid: -E -R50 -G_rs_sfx_2 -V105 -P5 +se_i.mid: -E -R50 -G_rs_sfx_2 -V120 -P4 +se_ice_break.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_ice_crack.mid: -E -R50 -G_rs_sfx_1 -V100 -P4 +se_ice_stairs.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_intro_blast.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_itemfinder.mid: -E -R50 -G_rs_sfx_1 -V090 -P5 +se_lavaridge_fall_warp.mid: -E -R50 -G_rs_sfx_1 -P4 +se_ledge.mid: -E -R50 -G_rs_sfx_1 -V100 -P4 +se_low_health.mid: -E -R50 -G_rs_sfx_1 -V100 -P3 +se_m_bind.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_m_comet_punch.mid: -E -R50 -G_rs_sfx_2 -V120 -P4 +se_m_cut.mid: -E -R50 -G_rs_sfx_2 -V120 -P4 +se_m_double_slap.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_fire_punch.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_fly.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_gust.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_gust2.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_headbutt.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_horn_attack.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_jump_kick.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_leer.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_mega_kick.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_m_mega_kick2.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_pay_day.mid: -E -R50 -G_rs_sfx_2 -V095 -P4 +se_m_razor_wind.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_razor_wind2.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_m_sand_attack.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_scratch.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_swords_dance.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_m_tail_whip.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_take_down.mid: -E -R50 -G_rs_sfx_2 -V105 -P4 +se_m_vicegrip.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_m_wing_attack.mid: -E -R50 -G_rs_sfx_2 -V105 -P4 +se_mud_ball.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_mugshot.mid: -E -R50 -G_rs_sfx_2 -V090 -P5 +se_n.mid: -E -R50 -G_rs_sfx_2 -P4 +se_not_effective.mid: -E -R50 -G_rs_sfx_1 -V110 -P5 +se_note_a.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_b.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_c_high.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_c.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_d.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_e.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_f.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_note_g.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_o.mid: -E -R50 -G_rs_sfx_2 -V120 -P4 +se_orb.mid: -E -R50 -G_rs_sfx_2 -V100 -P5 +se_pc_login.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_pc_off.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_pc_on.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_pike_curtain_close.mid: -E -R50 -G_frlg_sfx -P5 +se_pike_curtain_open.mid: -E -R50 -G_frlg_sfx -P5 +se_pin.mid: -E -R50 -G_rs_sfx_1 -V060 -P4 +se_pokenav_call.mid: -E -R50 -G_frlg_sfx -V120 -P5 +se_pokenav_hang_up.mid: -E -R50 -G_frlg_sfx -V110 -P5 +se_pokenav_off.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_pokenav_on.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_puddle.mid: -E -R50 -G_rs_sfx_2 -V020 -P4 +se_rain_stop.mid: -E -R50 -G_rs_sfx_2 -V080 -P2 +se_rain.mid: -E -R50 -G_rs_sfx_2 -V080 -P2 +se_repel.mid: -E -R50 -G_rs_sfx_1 -V090 -P4 +se_rg_bag_cursor.mid: -E -R50 -G_frlg_sfx -P5 +se_rg_bag_pocket.mid: -E -R50 -G_frlg_sfx -P5 +se_rg_ball_click.mid: -E -R50 -G_frlg_sfx -V100 -P5 +se_rg_card_flip.mid: -E -R50 -G_frlg_sfx -P5 +se_rg_card_flipping.mid: -E -R50 -G_frlg_sfx -P5 +se_rg_card_open.mid: -E -R50 -G_frlg_sfx -V112 -P5 +se_rg_deoxys_move.mid: -E -R50 -G_frlg_sfx -V080 -P5 +se_rg_door.mid: -E -R50 -G_frlg_sfx -V100 -P5 +se_rg_help_close.mid: -E -R50 -G_frlg_sfx -V095 -P5 +se_rg_help_error.mid: -E -R50 -G_frlg_sfx -V125 -P5 +se_rg_help_open.mid: -E -R50 -G_frlg_sfx -V096 -P5 +se_rg_poke_jump_failure.mid: -E -R50 -G_rs_sfx_1 -P5 +se_rg_poke_jump_success.mid: -E -R50 -G_rs_sfx_2 -V110 -P5 +se_rg_shop.mid: -E -R50 -G_frlg_sfx -V080 -P5 +se_rg_ss_anne_horn.mid: -E -R50 -G_frlg_sfx -V096 -P5 +se_rotating_gate.mid: -E -R50 -G_rs_sfx_2 -V090 -P4 +se_roulette_ball.mid: -E -R50 -G_rs_sfx_2 -V110 -P2 +se_roulette_ball2.mid: -E -R50 -G_rs_sfx_2 -V110 -P2 +se_save.mid: -E -R50 -G_rs_sfx_2 -V080 -P5 +se_select.mid: -E -R50 -G_rs_sfx_1 -V080 -P5 +se_shiny.mid: -E -R50 -G_rs_sfx_2 -V095 -P5 +se_ship.mid: -E -R50 -G_rs_sfx_1 -V075 -P4 +se_shop.mid: -E -R50 -G_rs_sfx_1 -V090 -P5 +se_sliding_door.mid: -E -R50 -G_rs_sfx_2 -V095 -P4 +se_success.mid: -E -R50 -G_rs_sfx_1 -V080 -P4 +se_sudowoodo_shake.mid: -E -R50 -G_frlg_sfx -V077 -P5 +se_super_effective.mid: -E -R50 -G_rs_sfx_1 -V110 -P5 +se_switch.mid: -E -R50 -G_rs_sfx_1 -V100 -P4 +se_taillow_wing_flap.mid: -E -R50 -G_rs_sfx_2 -V105 -P5 +se_thunder.mid: -E -R50 -G_rs_sfx_2 -V110 -P3 +se_thunder2.mid: -E -R50 -G_rs_sfx_2 -V110 -P3 +se_thunderstorm_stop.mid: -E -R50 -G_rs_sfx_2 -V080 -P2 +se_thunderstorm.mid: -E -R50 -G_rs_sfx_2 -V080 -P2 +se_truck_door.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_truck_move.mid: -E -R50 -G_rs_sfx_2 -P4 +se_truck_stop.mid: -E -R50 -G_rs_sfx_2 -P4 +se_truck_unload.mid: -E -R50 -G_rs_sfx_1 -P4 +se_u.mid: -E -R50 -G_rs_sfx_2 -P4 +se_unlock.mid: -E -R50 -G_rs_sfx_2 -V100 -P4 +se_use_item.mid: -E -R50 -G_rs_sfx_1 -V100 -P5 +se_vend.mid: -E -R50 -G_rs_sfx_2 -V110 -P4 +se_warp_in.mid: -E -R50 -G_rs_sfx_1 -V090 -P4 +se_warp_out.mid: -E -R50 -G_rs_sfx_1 -V090 -P4 diff --git a/sound/songs/se_dex_page.s b/sound/songs/se_dex_page.s index 884f0d12a5..314d11d9fb 100644 --- a/sound/songs/se_dex_page.s +++ b/sound/songs/se_dex_page.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_dex_page_grp, voicegroup127 + .equ se_dex_page_grp, voicegroup_rs_sfx_1 .equ se_dex_page_pri, 5 .equ se_dex_page_rev, reverb_set+50 .equ se_dex_page_mvl, 127 diff --git a/sound/songs/se_dex_scroll.s b/sound/songs/se_dex_scroll.s index 6c7ad77461..6ea8f4783d 100644 --- a/sound/songs/se_dex_scroll.s +++ b/sound/songs/se_dex_scroll.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_dex_scroll_grp, voicegroup127 + .equ se_dex_scroll_grp, voicegroup_rs_sfx_1 .equ se_dex_scroll_pri, 5 .equ se_dex_scroll_rev, reverb_set+50 .equ se_dex_scroll_mvl, 127 diff --git a/sound/songs/se_m_absorb.s b/sound/songs/se_m_absorb.s index 6cd6223664..46b7e1fa20 100644 --- a/sound/songs/se_m_absorb.s +++ b/sound/songs/se_m_absorb.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_absorb_grp, voicegroup128 + .equ se_m_absorb_grp, voicegroup_rs_sfx_2 .equ se_m_absorb_pri, 4 .equ se_m_absorb_rev, reverb_set+50 .equ se_m_absorb_mvl, 127 diff --git a/sound/songs/se_m_absorb_2.s b/sound/songs/se_m_absorb_2.s index 6192013338..54166d9673 100644 --- a/sound/songs/se_m_absorb_2.s +++ b/sound/songs/se_m_absorb_2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_absorb_2_grp, voicegroup128 + .equ se_m_absorb_2_grp, voicegroup_rs_sfx_2 .equ se_m_absorb_2_pri, 4 .equ se_m_absorb_2_rev, reverb_set+50 .equ se_m_absorb_2_mvl, 127 diff --git a/sound/songs/se_m_acid_armor.s b/sound/songs/se_m_acid_armor.s index 346c766047..31f94275a7 100644 --- a/sound/songs/se_m_acid_armor.s +++ b/sound/songs/se_m_acid_armor.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_acid_armor_grp, voicegroup128 + .equ se_m_acid_armor_grp, voicegroup_rs_sfx_2 .equ se_m_acid_armor_pri, 4 .equ se_m_acid_armor_rev, reverb_set+50 .equ se_m_acid_armor_mvl, 127 diff --git a/sound/songs/se_m_attract.s b/sound/songs/se_m_attract.s index 8e18c16dce..ede9f4dd82 100644 --- a/sound/songs/se_m_attract.s +++ b/sound/songs/se_m_attract.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_attract_grp, voicegroup128 + .equ se_m_attract_grp, voicegroup_rs_sfx_2 .equ se_m_attract_pri, 4 .equ se_m_attract_rev, reverb_set+50 .equ se_m_attract_mvl, 127 diff --git a/sound/songs/se_m_attract2.s b/sound/songs/se_m_attract2.s index 9b846f13e4..ddcd230297 100644 --- a/sound/songs/se_m_attract2.s +++ b/sound/songs/se_m_attract2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_attract2_grp, voicegroup128 + .equ se_m_attract2_grp, voicegroup_rs_sfx_2 .equ se_m_attract2_pri, 4 .equ se_m_attract2_rev, reverb_set+50 .equ se_m_attract2_mvl, 127 diff --git a/sound/songs/se_m_barrier.s b/sound/songs/se_m_barrier.s index 54d57700f0..ebf6ddccb9 100644 --- a/sound/songs/se_m_barrier.s +++ b/sound/songs/se_m_barrier.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_barrier_grp, voicegroup128 + .equ se_m_barrier_grp, voicegroup_rs_sfx_2 .equ se_m_barrier_pri, 4 .equ se_m_barrier_rev, reverb_set+50 .equ se_m_barrier_mvl, 127 diff --git a/sound/songs/se_m_baton_pass.s b/sound/songs/se_m_baton_pass.s index 30027e5b68..ec8ddd542a 100644 --- a/sound/songs/se_m_baton_pass.s +++ b/sound/songs/se_m_baton_pass.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_baton_pass_grp, voicegroup128 + .equ se_m_baton_pass_grp, voicegroup_rs_sfx_2 .equ se_m_baton_pass_pri, 4 .equ se_m_baton_pass_rev, reverb_set+50 .equ se_m_baton_pass_mvl, 127 diff --git a/sound/songs/se_m_belly_drum.s b/sound/songs/se_m_belly_drum.s index 919c02b16c..5b5508ed41 100644 --- a/sound/songs/se_m_belly_drum.s +++ b/sound/songs/se_m_belly_drum.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_belly_drum_grp, voicegroup128 + .equ se_m_belly_drum_grp, voicegroup_rs_sfx_2 .equ se_m_belly_drum_pri, 4 .equ se_m_belly_drum_rev, reverb_set+50 .equ se_m_belly_drum_mvl, 127 diff --git a/sound/songs/se_m_bite.s b/sound/songs/se_m_bite.s index 15d690e2e8..c01e160c1a 100644 --- a/sound/songs/se_m_bite.s +++ b/sound/songs/se_m_bite.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bite_grp, voicegroup128 + .equ se_m_bite_grp, voicegroup_rs_sfx_2 .equ se_m_bite_pri, 4 .equ se_m_bite_rev, reverb_set+50 .equ se_m_bite_mvl, 127 diff --git a/sound/songs/se_m_blizzard.s b/sound/songs/se_m_blizzard.s index 6bce3c9872..a274da2211 100644 --- a/sound/songs/se_m_blizzard.s +++ b/sound/songs/se_m_blizzard.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_blizzard_grp, voicegroup128 + .equ se_m_blizzard_grp, voicegroup_rs_sfx_2 .equ se_m_blizzard_pri, 4 .equ se_m_blizzard_rev, reverb_set+50 .equ se_m_blizzard_mvl, 127 diff --git a/sound/songs/se_m_blizzard2.s b/sound/songs/se_m_blizzard2.s index 8c1518e637..2940d80d52 100644 --- a/sound/songs/se_m_blizzard2.s +++ b/sound/songs/se_m_blizzard2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_blizzard2_grp, voicegroup128 + .equ se_m_blizzard2_grp, voicegroup_rs_sfx_2 .equ se_m_blizzard2_pri, 4 .equ se_m_blizzard2_rev, reverb_set+50 .equ se_m_blizzard2_mvl, 127 diff --git a/sound/songs/se_m_bonemerang.s b/sound/songs/se_m_bonemerang.s index 9339809364..16f170b76b 100644 --- a/sound/songs/se_m_bonemerang.s +++ b/sound/songs/se_m_bonemerang.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bonemerang_grp, voicegroup128 + .equ se_m_bonemerang_grp, voicegroup_rs_sfx_2 .equ se_m_bonemerang_pri, 4 .equ se_m_bonemerang_rev, reverb_set+50 .equ se_m_bonemerang_mvl, 127 diff --git a/sound/songs/se_m_brick_break.s b/sound/songs/se_m_brick_break.s index ce13218d24..2270fc24b5 100644 --- a/sound/songs/se_m_brick_break.s +++ b/sound/songs/se_m_brick_break.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_brick_break_grp, voicegroup128 + .equ se_m_brick_break_grp, voicegroup_rs_sfx_2 .equ se_m_brick_break_pri, 4 .equ se_m_brick_break_rev, reverb_set+50 .equ se_m_brick_break_mvl, 127 diff --git a/sound/songs/se_m_bubble.s b/sound/songs/se_m_bubble.s index 4e1b988d59..9c7fb6fadd 100644 --- a/sound/songs/se_m_bubble.s +++ b/sound/songs/se_m_bubble.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bubble_grp, voicegroup128 + .equ se_m_bubble_grp, voicegroup_rs_sfx_2 .equ se_m_bubble_pri, 4 .equ se_m_bubble_rev, reverb_set+50 .equ se_m_bubble_mvl, 127 diff --git a/sound/songs/se_m_bubble2.s b/sound/songs/se_m_bubble2.s index 97e7cbbf85..1b009672bf 100644 --- a/sound/songs/se_m_bubble2.s +++ b/sound/songs/se_m_bubble2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bubble2_grp, voicegroup128 + .equ se_m_bubble2_grp, voicegroup_rs_sfx_2 .equ se_m_bubble2_pri, 4 .equ se_m_bubble2_rev, reverb_set+50 .equ se_m_bubble2_mvl, 127 diff --git a/sound/songs/se_m_bubble3.s b/sound/songs/se_m_bubble3.s index d9a7f1e82b..ea4c1e6fd4 100644 --- a/sound/songs/se_m_bubble3.s +++ b/sound/songs/se_m_bubble3.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bubble3_grp, voicegroup128 + .equ se_m_bubble3_grp, voicegroup_rs_sfx_2 .equ se_m_bubble3_pri, 4 .equ se_m_bubble3_rev, reverb_set+50 .equ se_m_bubble3_mvl, 127 diff --git a/sound/songs/se_m_bubble_beam.s b/sound/songs/se_m_bubble_beam.s index 621882b03f..b1eac882b7 100644 --- a/sound/songs/se_m_bubble_beam.s +++ b/sound/songs/se_m_bubble_beam.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bubble_beam_grp, voicegroup128 + .equ se_m_bubble_beam_grp, voicegroup_rs_sfx_2 .equ se_m_bubble_beam_pri, 4 .equ se_m_bubble_beam_rev, reverb_set+50 .equ se_m_bubble_beam_mvl, 127 diff --git a/sound/songs/se_m_bubble_beam2.s b/sound/songs/se_m_bubble_beam2.s index 0e8cbf5e41..970ef02897 100644 --- a/sound/songs/se_m_bubble_beam2.s +++ b/sound/songs/se_m_bubble_beam2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_bubble_beam2_grp, voicegroup128 + .equ se_m_bubble_beam2_grp, voicegroup_rs_sfx_2 .equ se_m_bubble_beam2_pri, 4 .equ se_m_bubble_beam2_rev, reverb_set+50 .equ se_m_bubble_beam2_mvl, 127 diff --git a/sound/songs/se_m_charge.s b/sound/songs/se_m_charge.s index 47d70a4bff..1ad07164f6 100644 --- a/sound/songs/se_m_charge.s +++ b/sound/songs/se_m_charge.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_charge_grp, voicegroup128 + .equ se_m_charge_grp, voicegroup_rs_sfx_2 .equ se_m_charge_pri, 4 .equ se_m_charge_rev, reverb_set+50 .equ se_m_charge_mvl, 127 diff --git a/sound/songs/se_m_charm.s b/sound/songs/se_m_charm.s index 2bb2e0ef37..9d27f1445a 100644 --- a/sound/songs/se_m_charm.s +++ b/sound/songs/se_m_charm.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_charm_grp, voicegroup128 + .equ se_m_charm_grp, voicegroup_rs_sfx_2 .equ se_m_charm_pri, 4 .equ se_m_charm_rev, reverb_set+50 .equ se_m_charm_mvl, 127 diff --git a/sound/songs/se_m_confuse_ray.s b/sound/songs/se_m_confuse_ray.s index 78407b8c11..e856fe495a 100644 --- a/sound/songs/se_m_confuse_ray.s +++ b/sound/songs/se_m_confuse_ray.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_confuse_ray_grp, voicegroup128 + .equ se_m_confuse_ray_grp, voicegroup_rs_sfx_2 .equ se_m_confuse_ray_pri, 4 .equ se_m_confuse_ray_rev, reverb_set+50 .equ se_m_confuse_ray_mvl, 127 diff --git a/sound/songs/se_m_cosmic_power.s b/sound/songs/se_m_cosmic_power.s index 3e3f53c5ec..3779ea9683 100644 --- a/sound/songs/se_m_cosmic_power.s +++ b/sound/songs/se_m_cosmic_power.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_cosmic_power_grp, voicegroup128 + .equ se_m_cosmic_power_grp, voicegroup_rs_sfx_2 .equ se_m_cosmic_power_pri, 4 .equ se_m_cosmic_power_rev, reverb_set+50 .equ se_m_cosmic_power_mvl, 127 diff --git a/sound/songs/se_m_crabhammer.s b/sound/songs/se_m_crabhammer.s index 6333150dc7..c629edc99c 100644 --- a/sound/songs/se_m_crabhammer.s +++ b/sound/songs/se_m_crabhammer.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_crabhammer_grp, voicegroup128 + .equ se_m_crabhammer_grp, voicegroup_rs_sfx_2 .equ se_m_crabhammer_pri, 4 .equ se_m_crabhammer_rev, reverb_set+50 .equ se_m_crabhammer_mvl, 127 diff --git a/sound/songs/se_m_detect.s b/sound/songs/se_m_detect.s index f06802802a..82196bb2d9 100644 --- a/sound/songs/se_m_detect.s +++ b/sound/songs/se_m_detect.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_detect_grp, voicegroup128 + .equ se_m_detect_grp, voicegroup_rs_sfx_2 .equ se_m_detect_pri, 4 .equ se_m_detect_rev, reverb_set+50 .equ se_m_detect_mvl, 127 diff --git a/sound/songs/se_m_dig.s b/sound/songs/se_m_dig.s index f8d3597d95..be16d77ac5 100644 --- a/sound/songs/se_m_dig.s +++ b/sound/songs/se_m_dig.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_dig_grp, voicegroup128 + .equ se_m_dig_grp, voicegroup_rs_sfx_2 .equ se_m_dig_pri, 4 .equ se_m_dig_rev, reverb_set+50 .equ se_m_dig_mvl, 127 diff --git a/sound/songs/se_m_dive.s b/sound/songs/se_m_dive.s index 83cc423564..879c41eefc 100644 --- a/sound/songs/se_m_dive.s +++ b/sound/songs/se_m_dive.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_dive_grp, voicegroup128 + .equ se_m_dive_grp, voicegroup_rs_sfx_2 .equ se_m_dive_pri, 4 .equ se_m_dive_rev, reverb_set+50 .equ se_m_dive_mvl, 127 diff --git a/sound/songs/se_m_dizzy_punch.s b/sound/songs/se_m_dizzy_punch.s index 31ab74a77f..ccd2a6c956 100644 --- a/sound/songs/se_m_dizzy_punch.s +++ b/sound/songs/se_m_dizzy_punch.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_dizzy_punch_grp, voicegroup128 + .equ se_m_dizzy_punch_grp, voicegroup_rs_sfx_2 .equ se_m_dizzy_punch_pri, 4 .equ se_m_dizzy_punch_rev, reverb_set+50 .equ se_m_dizzy_punch_mvl, 127 diff --git a/sound/songs/se_m_double_team.s b/sound/songs/se_m_double_team.s index 49bcfb13d3..3efab79b04 100644 --- a/sound/songs/se_m_double_team.s +++ b/sound/songs/se_m_double_team.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_double_team_grp, voicegroup128 + .equ se_m_double_team_grp, voicegroup_rs_sfx_2 .equ se_m_double_team_pri, 4 .equ se_m_double_team_rev, reverb_set+50 .equ se_m_double_team_mvl, 127 diff --git a/sound/songs/se_m_dragon_rage.s b/sound/songs/se_m_dragon_rage.s index 608d926115..3a0675c03a 100644 --- a/sound/songs/se_m_dragon_rage.s +++ b/sound/songs/se_m_dragon_rage.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_dragon_rage_grp, voicegroup128 + .equ se_m_dragon_rage_grp, voicegroup_rs_sfx_2 .equ se_m_dragon_rage_pri, 4 .equ se_m_dragon_rage_rev, reverb_set+50 .equ se_m_dragon_rage_mvl, 127 diff --git a/sound/songs/se_m_earthquake.s b/sound/songs/se_m_earthquake.s index 928ddfacd8..76c40d88ca 100644 --- a/sound/songs/se_m_earthquake.s +++ b/sound/songs/se_m_earthquake.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_earthquake_grp, voicegroup128 + .equ se_m_earthquake_grp, voicegroup_rs_sfx_2 .equ se_m_earthquake_pri, 4 .equ se_m_earthquake_rev, reverb_set+50 .equ se_m_earthquake_mvl, 127 diff --git a/sound/songs/se_m_ember.s b/sound/songs/se_m_ember.s index a685ca24c9..010ffaaf1a 100644 --- a/sound/songs/se_m_ember.s +++ b/sound/songs/se_m_ember.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_ember_grp, voicegroup128 + .equ se_m_ember_grp, voicegroup_rs_sfx_2 .equ se_m_ember_pri, 4 .equ se_m_ember_rev, reverb_set+50 .equ se_m_ember_mvl, 127 diff --git a/sound/songs/se_m_encore.s b/sound/songs/se_m_encore.s index cf13ab7618..0f212febb3 100644 --- a/sound/songs/se_m_encore.s +++ b/sound/songs/se_m_encore.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_encore_grp, voicegroup128 + .equ se_m_encore_grp, voicegroup_rs_sfx_2 .equ se_m_encore_pri, 4 .equ se_m_encore_rev, reverb_set+50 .equ se_m_encore_mvl, 127 diff --git a/sound/songs/se_m_encore2.s b/sound/songs/se_m_encore2.s index 61e522acac..86ebb5585b 100644 --- a/sound/songs/se_m_encore2.s +++ b/sound/songs/se_m_encore2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_encore2_grp, voicegroup128 + .equ se_m_encore2_grp, voicegroup_rs_sfx_2 .equ se_m_encore2_pri, 4 .equ se_m_encore2_rev, reverb_set+50 .equ se_m_encore2_mvl, 127 diff --git a/sound/songs/se_m_explosion.s b/sound/songs/se_m_explosion.s index 039c563f78..b0f98c6f40 100644 --- a/sound/songs/se_m_explosion.s +++ b/sound/songs/se_m_explosion.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_explosion_grp, voicegroup128 + .equ se_m_explosion_grp, voicegroup_rs_sfx_2 .equ se_m_explosion_pri, 4 .equ se_m_explosion_rev, reverb_set+50 .equ se_m_explosion_mvl, 127 diff --git a/sound/songs/se_m_faint_attack.s b/sound/songs/se_m_faint_attack.s index ce53c7173e..2011e58b4e 100644 --- a/sound/songs/se_m_faint_attack.s +++ b/sound/songs/se_m_faint_attack.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_faint_attack_grp, voicegroup128 + .equ se_m_faint_attack_grp, voicegroup_rs_sfx_2 .equ se_m_faint_attack_pri, 4 .equ se_m_faint_attack_rev, reverb_set+50 .equ se_m_faint_attack_mvl, 127 diff --git a/sound/songs/se_m_flame_wheel.s b/sound/songs/se_m_flame_wheel.s index 797073466a..f722ae3200 100644 --- a/sound/songs/se_m_flame_wheel.s +++ b/sound/songs/se_m_flame_wheel.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_flame_wheel_grp, voicegroup128 + .equ se_m_flame_wheel_grp, voicegroup_rs_sfx_2 .equ se_m_flame_wheel_pri, 4 .equ se_m_flame_wheel_rev, reverb_set+50 .equ se_m_flame_wheel_mvl, 127 diff --git a/sound/songs/se_m_flame_wheel2.s b/sound/songs/se_m_flame_wheel2.s index 21f911b0ba..09413e52aa 100644 --- a/sound/songs/se_m_flame_wheel2.s +++ b/sound/songs/se_m_flame_wheel2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_flame_wheel2_grp, voicegroup128 + .equ se_m_flame_wheel2_grp, voicegroup_rs_sfx_2 .equ se_m_flame_wheel2_pri, 4 .equ se_m_flame_wheel2_rev, reverb_set+50 .equ se_m_flame_wheel2_mvl, 127 diff --git a/sound/songs/se_m_flamethrower.s b/sound/songs/se_m_flamethrower.s index 4c0c892c1e..0536ae19fd 100644 --- a/sound/songs/se_m_flamethrower.s +++ b/sound/songs/se_m_flamethrower.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_flamethrower_grp, voicegroup128 + .equ se_m_flamethrower_grp, voicegroup_rs_sfx_2 .equ se_m_flamethrower_pri, 4 .equ se_m_flamethrower_rev, reverb_set+50 .equ se_m_flamethrower_mvl, 127 diff --git a/sound/songs/se_m_flatter.s b/sound/songs/se_m_flatter.s index 799fdba912..b6484bbf4f 100644 --- a/sound/songs/se_m_flatter.s +++ b/sound/songs/se_m_flatter.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_flatter_grp, voicegroup128 + .equ se_m_flatter_grp, voicegroup_rs_sfx_2 .equ se_m_flatter_pri, 4 .equ se_m_flatter_rev, reverb_set+50 .equ se_m_flatter_mvl, 127 diff --git a/sound/songs/se_m_giga_drain.s b/sound/songs/se_m_giga_drain.s index 4596a0252c..de8f951755 100644 --- a/sound/songs/se_m_giga_drain.s +++ b/sound/songs/se_m_giga_drain.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_giga_drain_grp, voicegroup128 + .equ se_m_giga_drain_grp, voicegroup_rs_sfx_2 .equ se_m_giga_drain_pri, 4 .equ se_m_giga_drain_rev, reverb_set+50 .equ se_m_giga_drain_mvl, 127 diff --git a/sound/songs/se_m_grasswhistle.s b/sound/songs/se_m_grasswhistle.s index 10c7447873..384908fd8a 100644 --- a/sound/songs/se_m_grasswhistle.s +++ b/sound/songs/se_m_grasswhistle.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_grasswhistle_grp, voicegroup128 + .equ se_m_grasswhistle_grp, voicegroup_rs_sfx_2 .equ se_m_grasswhistle_pri, 4 .equ se_m_grasswhistle_rev, reverb_set+50 .equ se_m_grasswhistle_mvl, 127 diff --git a/sound/songs/se_m_hail.s b/sound/songs/se_m_hail.s index 7f1d1c67da..46b25141b6 100644 --- a/sound/songs/se_m_hail.s +++ b/sound/songs/se_m_hail.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_hail_grp, voicegroup128 + .equ se_m_hail_grp, voicegroup_rs_sfx_2 .equ se_m_hail_pri, 4 .equ se_m_hail_rev, reverb_set+50 .equ se_m_hail_mvl, 127 diff --git a/sound/songs/se_m_harden.s b/sound/songs/se_m_harden.s index e9bd888de8..2171a3e067 100644 --- a/sound/songs/se_m_harden.s +++ b/sound/songs/se_m_harden.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_harden_grp, voicegroup128 + .equ se_m_harden_grp, voicegroup_rs_sfx_2 .equ se_m_harden_pri, 4 .equ se_m_harden_rev, reverb_set+50 .equ se_m_harden_mvl, 127 diff --git a/sound/songs/se_m_haze.s b/sound/songs/se_m_haze.s index 11497c8465..fb134ff042 100644 --- a/sound/songs/se_m_haze.s +++ b/sound/songs/se_m_haze.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_haze_grp, voicegroup128 + .equ se_m_haze_grp, voicegroup_rs_sfx_2 .equ se_m_haze_pri, 4 .equ se_m_haze_rev, reverb_set+50 .equ se_m_haze_mvl, 127 diff --git a/sound/songs/se_m_heal_bell.s b/sound/songs/se_m_heal_bell.s index fbe315c878..407af374fb 100644 --- a/sound/songs/se_m_heal_bell.s +++ b/sound/songs/se_m_heal_bell.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_heal_bell_grp, voicegroup128 + .equ se_m_heal_bell_grp, voicegroup_rs_sfx_2 .equ se_m_heal_bell_pri, 4 .equ se_m_heal_bell_rev, reverb_set+50 .equ se_m_heal_bell_mvl, 127 diff --git a/sound/songs/se_m_heat_wave.s b/sound/songs/se_m_heat_wave.s index da5842f8f8..5430cd4cad 100644 --- a/sound/songs/se_m_heat_wave.s +++ b/sound/songs/se_m_heat_wave.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_heat_wave_grp, voicegroup128 + .equ se_m_heat_wave_grp, voicegroup_rs_sfx_2 .equ se_m_heat_wave_pri, 4 .equ se_m_heat_wave_rev, reverb_set+50 .equ se_m_heat_wave_mvl, 127 diff --git a/sound/songs/se_m_hydro_pump.s b/sound/songs/se_m_hydro_pump.s index c214985e47..93f8459ec1 100644 --- a/sound/songs/se_m_hydro_pump.s +++ b/sound/songs/se_m_hydro_pump.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_hydro_pump_grp, voicegroup128 + .equ se_m_hydro_pump_grp, voicegroup_rs_sfx_2 .equ se_m_hydro_pump_pri, 4 .equ se_m_hydro_pump_rev, reverb_set+50 .equ se_m_hydro_pump_mvl, 127 diff --git a/sound/songs/se_m_hyper_beam.s b/sound/songs/se_m_hyper_beam.s index b6ffcfc2f7..34e49ac460 100644 --- a/sound/songs/se_m_hyper_beam.s +++ b/sound/songs/se_m_hyper_beam.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_hyper_beam_grp, voicegroup128 + .equ se_m_hyper_beam_grp, voicegroup_rs_sfx_2 .equ se_m_hyper_beam_pri, 4 .equ se_m_hyper_beam_rev, reverb_set+50 .equ se_m_hyper_beam_mvl, 127 diff --git a/sound/songs/se_m_hyper_beam2.s b/sound/songs/se_m_hyper_beam2.s index fb21834222..0fffa797c6 100644 --- a/sound/songs/se_m_hyper_beam2.s +++ b/sound/songs/se_m_hyper_beam2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_hyper_beam2_grp, voicegroup128 + .equ se_m_hyper_beam2_grp, voicegroup_rs_sfx_2 .equ se_m_hyper_beam2_pri, 4 .equ se_m_hyper_beam2_rev, reverb_set+50 .equ se_m_hyper_beam2_mvl, 127 diff --git a/sound/songs/se_m_icy_wind.s b/sound/songs/se_m_icy_wind.s index b7e83e0321..dff7f59487 100644 --- a/sound/songs/se_m_icy_wind.s +++ b/sound/songs/se_m_icy_wind.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_icy_wind_grp, voicegroup128 + .equ se_m_icy_wind_grp, voicegroup_rs_sfx_2 .equ se_m_icy_wind_pri, 4 .equ se_m_icy_wind_rev, reverb_set+50 .equ se_m_icy_wind_mvl, 127 diff --git a/sound/songs/se_m_lick.s b/sound/songs/se_m_lick.s index 1aa0c35a28..34f9cbfbbe 100644 --- a/sound/songs/se_m_lick.s +++ b/sound/songs/se_m_lick.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_lick_grp, voicegroup128 + .equ se_m_lick_grp, voicegroup_rs_sfx_2 .equ se_m_lick_pri, 4 .equ se_m_lick_rev, reverb_set+50 .equ se_m_lick_mvl, 127 diff --git a/sound/songs/se_m_lock_on.s b/sound/songs/se_m_lock_on.s index 9c9576d97c..c95eafb3b0 100644 --- a/sound/songs/se_m_lock_on.s +++ b/sound/songs/se_m_lock_on.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_lock_on_grp, voicegroup128 + .equ se_m_lock_on_grp, voicegroup_rs_sfx_2 .equ se_m_lock_on_pri, 4 .equ se_m_lock_on_rev, reverb_set+50 .equ se_m_lock_on_mvl, 127 diff --git a/sound/songs/se_m_metronome.s b/sound/songs/se_m_metronome.s index ba0a55d8b9..de8899b16a 100644 --- a/sound/songs/se_m_metronome.s +++ b/sound/songs/se_m_metronome.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_metronome_grp, voicegroup128 + .equ se_m_metronome_grp, voicegroup_rs_sfx_2 .equ se_m_metronome_pri, 4 .equ se_m_metronome_rev, reverb_set+50 .equ se_m_metronome_mvl, 127 diff --git a/sound/songs/se_m_milk_drink.s b/sound/songs/se_m_milk_drink.s index 57e3a581d6..6380ee398b 100644 --- a/sound/songs/se_m_milk_drink.s +++ b/sound/songs/se_m_milk_drink.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_milk_drink_grp, voicegroup128 + .equ se_m_milk_drink_grp, voicegroup_rs_sfx_2 .equ se_m_milk_drink_pri, 4 .equ se_m_milk_drink_rev, reverb_set+50 .equ se_m_milk_drink_mvl, 127 diff --git a/sound/songs/se_m_minimize.s b/sound/songs/se_m_minimize.s index 778e0ec7c9..32dd545a03 100644 --- a/sound/songs/se_m_minimize.s +++ b/sound/songs/se_m_minimize.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_minimize_grp, voicegroup128 + .equ se_m_minimize_grp, voicegroup_rs_sfx_2 .equ se_m_minimize_pri, 4 .equ se_m_minimize_rev, reverb_set+50 .equ se_m_minimize_mvl, 127 diff --git a/sound/songs/se_m_mist.s b/sound/songs/se_m_mist.s index f46eb130a6..7975b50cc9 100644 --- a/sound/songs/se_m_mist.s +++ b/sound/songs/se_m_mist.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_mist_grp, voicegroup128 + .equ se_m_mist_grp, voicegroup_rs_sfx_2 .equ se_m_mist_pri, 4 .equ se_m_mist_rev, reverb_set+50 .equ se_m_mist_mvl, 127 diff --git a/sound/songs/se_m_moonlight.s b/sound/songs/se_m_moonlight.s index f76181a874..35329544e9 100644 --- a/sound/songs/se_m_moonlight.s +++ b/sound/songs/se_m_moonlight.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_moonlight_grp, voicegroup128 + .equ se_m_moonlight_grp, voicegroup_rs_sfx_2 .equ se_m_moonlight_pri, 4 .equ se_m_moonlight_rev, reverb_set+50 .equ se_m_moonlight_mvl, 127 diff --git a/sound/songs/se_m_morning_sun.s b/sound/songs/se_m_morning_sun.s index 227098da1f..a1196f6fe9 100644 --- a/sound/songs/se_m_morning_sun.s +++ b/sound/songs/se_m_morning_sun.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_morning_sun_grp, voicegroup128 + .equ se_m_morning_sun_grp, voicegroup_rs_sfx_2 .equ se_m_morning_sun_pri, 5 .equ se_m_morning_sun_rev, reverb_set+50 .equ se_m_morning_sun_mvl, 127 diff --git a/sound/songs/se_m_nightmare.s b/sound/songs/se_m_nightmare.s index f995d13103..61e7cde1e3 100644 --- a/sound/songs/se_m_nightmare.s +++ b/sound/songs/se_m_nightmare.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_nightmare_grp, voicegroup128 + .equ se_m_nightmare_grp, voicegroup_rs_sfx_2 .equ se_m_nightmare_pri, 4 .equ se_m_nightmare_rev, reverb_set+50 .equ se_m_nightmare_mvl, 127 diff --git a/sound/songs/se_m_perish_song.s b/sound/songs/se_m_perish_song.s index af30e24579..85614227ed 100644 --- a/sound/songs/se_m_perish_song.s +++ b/sound/songs/se_m_perish_song.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_perish_song_grp, voicegroup128 + .equ se_m_perish_song_grp, voicegroup_rs_sfx_2 .equ se_m_perish_song_pri, 4 .equ se_m_perish_song_rev, reverb_set+50 .equ se_m_perish_song_mvl, 127 diff --git a/sound/songs/se_m_petal_dance.s b/sound/songs/se_m_petal_dance.s index df5752e4bd..6d4e015a77 100644 --- a/sound/songs/se_m_petal_dance.s +++ b/sound/songs/se_m_petal_dance.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_petal_dance_grp, voicegroup128 + .equ se_m_petal_dance_grp, voicegroup_rs_sfx_2 .equ se_m_petal_dance_pri, 4 .equ se_m_petal_dance_rev, reverb_set+50 .equ se_m_petal_dance_mvl, 127 diff --git a/sound/songs/se_m_poison_powder.s b/sound/songs/se_m_poison_powder.s index f48637385b..f9fcd6dc9a 100644 --- a/sound/songs/se_m_poison_powder.s +++ b/sound/songs/se_m_poison_powder.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_poison_powder_grp, voicegroup128 + .equ se_m_poison_powder_grp, voicegroup_rs_sfx_2 .equ se_m_poison_powder_pri, 4 .equ se_m_poison_powder_rev, reverb_set+50 .equ se_m_poison_powder_mvl, 127 diff --git a/sound/songs/se_m_psybeam.s b/sound/songs/se_m_psybeam.s index c7f68cffd6..416a8a9392 100644 --- a/sound/songs/se_m_psybeam.s +++ b/sound/songs/se_m_psybeam.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_psybeam_grp, voicegroup128 + .equ se_m_psybeam_grp, voicegroup_rs_sfx_2 .equ se_m_psybeam_pri, 4 .equ se_m_psybeam_rev, reverb_set+50 .equ se_m_psybeam_mvl, 127 diff --git a/sound/songs/se_m_psybeam2.s b/sound/songs/se_m_psybeam2.s index e26a844c91..2cce6098b1 100644 --- a/sound/songs/se_m_psybeam2.s +++ b/sound/songs/se_m_psybeam2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_psybeam2_grp, voicegroup128 + .equ se_m_psybeam2_grp, voicegroup_rs_sfx_2 .equ se_m_psybeam2_pri, 4 .equ se_m_psybeam2_rev, reverb_set+50 .equ se_m_psybeam2_mvl, 127 diff --git a/sound/songs/se_m_rain_dance.s b/sound/songs/se_m_rain_dance.s index bba4dc2b05..7e5b2d0098 100644 --- a/sound/songs/se_m_rain_dance.s +++ b/sound/songs/se_m_rain_dance.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_rain_dance_grp, voicegroup128 + .equ se_m_rain_dance_grp, voicegroup_rs_sfx_2 .equ se_m_rain_dance_pri, 4 .equ se_m_rain_dance_rev, reverb_set+50 .equ se_m_rain_dance_mvl, 127 diff --git a/sound/songs/se_m_reflect.s b/sound/songs/se_m_reflect.s index 56699c65ea..d5649ab360 100644 --- a/sound/songs/se_m_reflect.s +++ b/sound/songs/se_m_reflect.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_reflect_grp, voicegroup128 + .equ se_m_reflect_grp, voicegroup_rs_sfx_2 .equ se_m_reflect_pri, 4 .equ se_m_reflect_rev, reverb_set+50 .equ se_m_reflect_mvl, 127 diff --git a/sound/songs/se_m_reversal.s b/sound/songs/se_m_reversal.s index 5b62d7156e..56ed6d0576 100644 --- a/sound/songs/se_m_reversal.s +++ b/sound/songs/se_m_reversal.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_reversal_grp, voicegroup128 + .equ se_m_reversal_grp, voicegroup_rs_sfx_2 .equ se_m_reversal_pri, 4 .equ se_m_reversal_rev, reverb_set+50 .equ se_m_reversal_mvl, 127 diff --git a/sound/songs/se_m_rock_throw.s b/sound/songs/se_m_rock_throw.s index 71dddd4475..74ae936b76 100644 --- a/sound/songs/se_m_rock_throw.s +++ b/sound/songs/se_m_rock_throw.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_rock_throw_grp, voicegroup128 + .equ se_m_rock_throw_grp, voicegroup_rs_sfx_2 .equ se_m_rock_throw_pri, 4 .equ se_m_rock_throw_rev, reverb_set+50 .equ se_m_rock_throw_mvl, 127 diff --git a/sound/songs/se_m_sacred_fire.s b/sound/songs/se_m_sacred_fire.s index 0fda9c757a..58a40c9bfb 100644 --- a/sound/songs/se_m_sacred_fire.s +++ b/sound/songs/se_m_sacred_fire.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sacred_fire_grp, voicegroup128 + .equ se_m_sacred_fire_grp, voicegroup_rs_sfx_2 .equ se_m_sacred_fire_pri, 4 .equ se_m_sacred_fire_rev, reverb_set+50 .equ se_m_sacred_fire_mvl, 127 diff --git a/sound/songs/se_m_sacred_fire2.s b/sound/songs/se_m_sacred_fire2.s index f255e712a9..41582debdd 100644 --- a/sound/songs/se_m_sacred_fire2.s +++ b/sound/songs/se_m_sacred_fire2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sacred_fire2_grp, voicegroup128 + .equ se_m_sacred_fire2_grp, voicegroup_rs_sfx_2 .equ se_m_sacred_fire2_pri, 4 .equ se_m_sacred_fire2_rev, reverb_set+50 .equ se_m_sacred_fire2_mvl, 127 diff --git a/sound/songs/se_m_sand_tomb.s b/sound/songs/se_m_sand_tomb.s index 4c14aabcc4..e52a76d108 100644 --- a/sound/songs/se_m_sand_tomb.s +++ b/sound/songs/se_m_sand_tomb.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sand_tomb_grp, voicegroup128 + .equ se_m_sand_tomb_grp, voicegroup_rs_sfx_2 .equ se_m_sand_tomb_pri, 4 .equ se_m_sand_tomb_rev, reverb_set+50 .equ se_m_sand_tomb_mvl, 127 diff --git a/sound/songs/se_m_sandstorm.s b/sound/songs/se_m_sandstorm.s index 4cb12a3892..e4e81dcc62 100644 --- a/sound/songs/se_m_sandstorm.s +++ b/sound/songs/se_m_sandstorm.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sandstorm_grp, voicegroup128 + .equ se_m_sandstorm_grp, voicegroup_rs_sfx_2 .equ se_m_sandstorm_pri, 4 .equ se_m_sandstorm_rev, reverb_set+50 .equ se_m_sandstorm_mvl, 127 diff --git a/sound/songs/se_m_screech.s b/sound/songs/se_m_screech.s index 378cf71281..c28d8d2bbd 100644 --- a/sound/songs/se_m_screech.s +++ b/sound/songs/se_m_screech.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_screech_grp, voicegroup128 + .equ se_m_screech_grp, voicegroup_rs_sfx_2 .equ se_m_screech_pri, 4 .equ se_m_screech_rev, reverb_set+50 .equ se_m_screech_mvl, 127 diff --git a/sound/songs/se_m_self_destruct.s b/sound/songs/se_m_self_destruct.s index 645085e1e5..0ed13b83d4 100644 --- a/sound/songs/se_m_self_destruct.s +++ b/sound/songs/se_m_self_destruct.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_self_destruct_grp, voicegroup128 + .equ se_m_self_destruct_grp, voicegroup_rs_sfx_2 .equ se_m_self_destruct_pri, 4 .equ se_m_self_destruct_rev, reverb_set+50 .equ se_m_self_destruct_mvl, 127 diff --git a/sound/songs/se_m_sing.s b/sound/songs/se_m_sing.s index 8c48c82247..349f6839ce 100644 --- a/sound/songs/se_m_sing.s +++ b/sound/songs/se_m_sing.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sing_grp, voicegroup128 + .equ se_m_sing_grp, voicegroup_rs_sfx_2 .equ se_m_sing_pri, 4 .equ se_m_sing_rev, reverb_set+50 .equ se_m_sing_mvl, 127 diff --git a/sound/songs/se_m_sketch.s b/sound/songs/se_m_sketch.s index c17c4056f2..579a308743 100644 --- a/sound/songs/se_m_sketch.s +++ b/sound/songs/se_m_sketch.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sketch_grp, voicegroup128 + .equ se_m_sketch_grp, voicegroup_rs_sfx_2 .equ se_m_sketch_pri, 4 .equ se_m_sketch_rev, reverb_set+50 .equ se_m_sketch_mvl, 127 diff --git a/sound/songs/se_m_sky_uppercut.s b/sound/songs/se_m_sky_uppercut.s index bed6c19c5f..6a28b5bcd6 100644 --- a/sound/songs/se_m_sky_uppercut.s +++ b/sound/songs/se_m_sky_uppercut.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sky_uppercut_grp, voicegroup128 + .equ se_m_sky_uppercut_grp, voicegroup_rs_sfx_2 .equ se_m_sky_uppercut_pri, 4 .equ se_m_sky_uppercut_rev, reverb_set+50 .equ se_m_sky_uppercut_mvl, 127 diff --git a/sound/songs/se_m_snore.s b/sound/songs/se_m_snore.s index 13e2f6f52b..5774355f21 100644 --- a/sound/songs/se_m_snore.s +++ b/sound/songs/se_m_snore.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_snore_grp, voicegroup128 + .equ se_m_snore_grp, voicegroup_rs_sfx_2 .equ se_m_snore_pri, 4 .equ se_m_snore_rev, reverb_set+50 .equ se_m_snore_mvl, 127 diff --git a/sound/songs/se_m_solar_beam.s b/sound/songs/se_m_solar_beam.s index 6a12b4a10e..0ef97c6be2 100644 --- a/sound/songs/se_m_solar_beam.s +++ b/sound/songs/se_m_solar_beam.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_solar_beam_grp, voicegroup128 + .equ se_m_solar_beam_grp, voicegroup_rs_sfx_2 .equ se_m_solar_beam_pri, 4 .equ se_m_solar_beam_rev, reverb_set+50 .equ se_m_solar_beam_mvl, 127 diff --git a/sound/songs/se_m_spit_up.s b/sound/songs/se_m_spit_up.s index 1073ad01fc..20fe0697d7 100644 --- a/sound/songs/se_m_spit_up.s +++ b/sound/songs/se_m_spit_up.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_spit_up_grp, voicegroup128 + .equ se_m_spit_up_grp, voicegroup_rs_sfx_2 .equ se_m_spit_up_pri, 4 .equ se_m_spit_up_rev, reverb_set+50 .equ se_m_spit_up_mvl, 127 diff --git a/sound/songs/se_m_stat_decrease.s b/sound/songs/se_m_stat_decrease.s index 51218db1e7..8f242be04e 100644 --- a/sound/songs/se_m_stat_decrease.s +++ b/sound/songs/se_m_stat_decrease.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_stat_decrease_grp, voicegroup128 + .equ se_m_stat_decrease_grp, voicegroup_rs_sfx_2 .equ se_m_stat_decrease_pri, 4 .equ se_m_stat_decrease_rev, reverb_set+50 .equ se_m_stat_decrease_mvl, 127 diff --git a/sound/songs/se_m_stat_increase.s b/sound/songs/se_m_stat_increase.s index 2556b6afa7..d5d6b5e918 100644 --- a/sound/songs/se_m_stat_increase.s +++ b/sound/songs/se_m_stat_increase.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_stat_increase_grp, voicegroup128 + .equ se_m_stat_increase_grp, voicegroup_rs_sfx_2 .equ se_m_stat_increase_pri, 4 .equ se_m_stat_increase_rev, reverb_set+50 .equ se_m_stat_increase_mvl, 127 diff --git a/sound/songs/se_m_strength.s b/sound/songs/se_m_strength.s index bda5fc61e5..974a9f976f 100644 --- a/sound/songs/se_m_strength.s +++ b/sound/songs/se_m_strength.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_strength_grp, voicegroup128 + .equ se_m_strength_grp, voicegroup_rs_sfx_2 .equ se_m_strength_pri, 4 .equ se_m_strength_rev, reverb_set+50 .equ se_m_strength_mvl, 127 diff --git a/sound/songs/se_m_string_shot.s b/sound/songs/se_m_string_shot.s index d750d26b9b..ed0701953b 100644 --- a/sound/songs/se_m_string_shot.s +++ b/sound/songs/se_m_string_shot.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_string_shot_grp, voicegroup128 + .equ se_m_string_shot_grp, voicegroup_rs_sfx_2 .equ se_m_string_shot_pri, 4 .equ se_m_string_shot_rev, reverb_set+50 .equ se_m_string_shot_mvl, 127 diff --git a/sound/songs/se_m_string_shot2.s b/sound/songs/se_m_string_shot2.s index b885a7d1a8..ac17f52cc8 100644 --- a/sound/songs/se_m_string_shot2.s +++ b/sound/songs/se_m_string_shot2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_string_shot2_grp, voicegroup128 + .equ se_m_string_shot2_grp, voicegroup_rs_sfx_2 .equ se_m_string_shot2_pri, 4 .equ se_m_string_shot2_rev, reverb_set+50 .equ se_m_string_shot2_mvl, 127 diff --git a/sound/songs/se_m_supersonic.s b/sound/songs/se_m_supersonic.s index c975dad4b6..3029597d1d 100644 --- a/sound/songs/se_m_supersonic.s +++ b/sound/songs/se_m_supersonic.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_supersonic_grp, voicegroup128 + .equ se_m_supersonic_grp, voicegroup_rs_sfx_2 .equ se_m_supersonic_pri, 4 .equ se_m_supersonic_rev, reverb_set+50 .equ se_m_supersonic_mvl, 127 diff --git a/sound/songs/se_m_surf.s b/sound/songs/se_m_surf.s index d3e3077826..1b3fc5cb91 100644 --- a/sound/songs/se_m_surf.s +++ b/sound/songs/se_m_surf.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_surf_grp, voicegroup128 + .equ se_m_surf_grp, voicegroup_rs_sfx_2 .equ se_m_surf_pri, 4 .equ se_m_surf_rev, reverb_set+50 .equ se_m_surf_mvl, 127 diff --git a/sound/songs/se_m_swagger.s b/sound/songs/se_m_swagger.s index 9b4b5756bc..e673444ee4 100644 --- a/sound/songs/se_m_swagger.s +++ b/sound/songs/se_m_swagger.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_swagger_grp, voicegroup128 + .equ se_m_swagger_grp, voicegroup_rs_sfx_2 .equ se_m_swagger_pri, 4 .equ se_m_swagger_rev, reverb_set+50 .equ se_m_swagger_mvl, 127 diff --git a/sound/songs/se_m_swagger2.s b/sound/songs/se_m_swagger2.s index 0a0d767674..9e799ec333 100644 --- a/sound/songs/se_m_swagger2.s +++ b/sound/songs/se_m_swagger2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_swagger2_grp, voicegroup128 + .equ se_m_swagger2_grp, voicegroup_rs_sfx_2 .equ se_m_swagger2_pri, 4 .equ se_m_swagger2_rev, reverb_set+50 .equ se_m_swagger2_mvl, 127 diff --git a/sound/songs/se_m_sweet_scent.s b/sound/songs/se_m_sweet_scent.s index 3b9bd527c8..1099ba3c0f 100644 --- a/sound/songs/se_m_sweet_scent.s +++ b/sound/songs/se_m_sweet_scent.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_sweet_scent_grp, voicegroup128 + .equ se_m_sweet_scent_grp, voicegroup_rs_sfx_2 .equ se_m_sweet_scent_pri, 4 .equ se_m_sweet_scent_rev, reverb_set+50 .equ se_m_sweet_scent_mvl, 127 diff --git a/sound/songs/se_m_swift.s b/sound/songs/se_m_swift.s index c87cbea419..2c01cfcf48 100644 --- a/sound/songs/se_m_swift.s +++ b/sound/songs/se_m_swift.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_swift_grp, voicegroup128 + .equ se_m_swift_grp, voicegroup_rs_sfx_2 .equ se_m_swift_pri, 4 .equ se_m_swift_rev, reverb_set+50 .equ se_m_swift_mvl, 127 diff --git a/sound/songs/se_m_teeter_dance.s b/sound/songs/se_m_teeter_dance.s index 8238afeb27..04a1e61e03 100644 --- a/sound/songs/se_m_teeter_dance.s +++ b/sound/songs/se_m_teeter_dance.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_teeter_dance_grp, voicegroup128 + .equ se_m_teeter_dance_grp, voicegroup_rs_sfx_2 .equ se_m_teeter_dance_pri, 4 .equ se_m_teeter_dance_rev, reverb_set+50 .equ se_m_teeter_dance_mvl, 127 diff --git a/sound/songs/se_m_teleport.s b/sound/songs/se_m_teleport.s index 60f7945d7b..8a4f676ba5 100644 --- a/sound/songs/se_m_teleport.s +++ b/sound/songs/se_m_teleport.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_teleport_grp, voicegroup128 + .equ se_m_teleport_grp, voicegroup_rs_sfx_2 .equ se_m_teleport_pri, 4 .equ se_m_teleport_rev, reverb_set+50 .equ se_m_teleport_mvl, 127 diff --git a/sound/songs/se_m_thunder_wave.s b/sound/songs/se_m_thunder_wave.s index a0b06cb5de..6d0a585e3f 100644 --- a/sound/songs/se_m_thunder_wave.s +++ b/sound/songs/se_m_thunder_wave.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_thunder_wave_grp, voicegroup128 + .equ se_m_thunder_wave_grp, voicegroup_rs_sfx_2 .equ se_m_thunder_wave_pri, 4 .equ se_m_thunder_wave_rev, reverb_set+50 .equ se_m_thunder_wave_mvl, 127 diff --git a/sound/songs/se_m_thunderbolt.s b/sound/songs/se_m_thunderbolt.s index 3b37903131..7b1868fbe6 100644 --- a/sound/songs/se_m_thunderbolt.s +++ b/sound/songs/se_m_thunderbolt.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_thunderbolt_grp, voicegroup128 + .equ se_m_thunderbolt_grp, voicegroup_rs_sfx_2 .equ se_m_thunderbolt_pri, 4 .equ se_m_thunderbolt_rev, reverb_set+50 .equ se_m_thunderbolt_mvl, 127 diff --git a/sound/songs/se_m_thunderbolt2.s b/sound/songs/se_m_thunderbolt2.s index 5068203958..9725b58f52 100644 --- a/sound/songs/se_m_thunderbolt2.s +++ b/sound/songs/se_m_thunderbolt2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_thunderbolt2_grp, voicegroup128 + .equ se_m_thunderbolt2_grp, voicegroup_rs_sfx_2 .equ se_m_thunderbolt2_pri, 4 .equ se_m_thunderbolt2_rev, reverb_set+50 .equ se_m_thunderbolt2_mvl, 127 diff --git a/sound/songs/se_m_toxic.s b/sound/songs/se_m_toxic.s index ae460ad773..3008bc0312 100644 --- a/sound/songs/se_m_toxic.s +++ b/sound/songs/se_m_toxic.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_toxic_grp, voicegroup128 + .equ se_m_toxic_grp, voicegroup_rs_sfx_2 .equ se_m_toxic_pri, 4 .equ se_m_toxic_rev, reverb_set+50 .equ se_m_toxic_mvl, 127 diff --git a/sound/songs/se_m_tri_attack.s b/sound/songs/se_m_tri_attack.s index 13947e6f1a..2a0bd1d4ff 100644 --- a/sound/songs/se_m_tri_attack.s +++ b/sound/songs/se_m_tri_attack.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_tri_attack_grp, voicegroup128 + .equ se_m_tri_attack_grp, voicegroup_rs_sfx_2 .equ se_m_tri_attack_pri, 4 .equ se_m_tri_attack_rev, reverb_set+50 .equ se_m_tri_attack_mvl, 127 diff --git a/sound/songs/se_m_tri_attack2.s b/sound/songs/se_m_tri_attack2.s index 61f11c3967..a54ee3df0e 100644 --- a/sound/songs/se_m_tri_attack2.s +++ b/sound/songs/se_m_tri_attack2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_tri_attack2_grp, voicegroup128 + .equ se_m_tri_attack2_grp, voicegroup_rs_sfx_2 .equ se_m_tri_attack2_pri, 4 .equ se_m_tri_attack2_rev, reverb_set+50 .equ se_m_tri_attack2_mvl, 127 diff --git a/sound/songs/se_m_twister.s b/sound/songs/se_m_twister.s index bbb4f1ec03..a739c89c4f 100644 --- a/sound/songs/se_m_twister.s +++ b/sound/songs/se_m_twister.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_twister_grp, voicegroup128 + .equ se_m_twister_grp, voicegroup_rs_sfx_2 .equ se_m_twister_pri, 4 .equ se_m_twister_rev, reverb_set+50 .equ se_m_twister_mvl, 127 diff --git a/sound/songs/se_m_uproar.s b/sound/songs/se_m_uproar.s index c60cccee4e..2bf7804d52 100644 --- a/sound/songs/se_m_uproar.s +++ b/sound/songs/se_m_uproar.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_uproar_grp, voicegroup128 + .equ se_m_uproar_grp, voicegroup_rs_sfx_2 .equ se_m_uproar_pri, 4 .equ se_m_uproar_rev, reverb_set+50 .equ se_m_uproar_mvl, 127 diff --git a/sound/songs/se_m_vital_throw.s b/sound/songs/se_m_vital_throw.s index 3e04b43e5b..aebda904f2 100644 --- a/sound/songs/se_m_vital_throw.s +++ b/sound/songs/se_m_vital_throw.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_vital_throw_grp, voicegroup128 + .equ se_m_vital_throw_grp, voicegroup_rs_sfx_2 .equ se_m_vital_throw_pri, 4 .equ se_m_vital_throw_rev, reverb_set+50 .equ se_m_vital_throw_mvl, 127 diff --git a/sound/songs/se_m_vital_throw2.s b/sound/songs/se_m_vital_throw2.s index 0d1e64ecb5..34a758c6e2 100644 --- a/sound/songs/se_m_vital_throw2.s +++ b/sound/songs/se_m_vital_throw2.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_vital_throw2_grp, voicegroup128 + .equ se_m_vital_throw2_grp, voicegroup_rs_sfx_2 .equ se_m_vital_throw2_pri, 4 .equ se_m_vital_throw2_rev, reverb_set+50 .equ se_m_vital_throw2_mvl, 127 diff --git a/sound/songs/se_m_waterfall.s b/sound/songs/se_m_waterfall.s index 9e16b9ee76..ad91010e71 100644 --- a/sound/songs/se_m_waterfall.s +++ b/sound/songs/se_m_waterfall.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_waterfall_grp, voicegroup128 + .equ se_m_waterfall_grp, voicegroup_rs_sfx_2 .equ se_m_waterfall_pri, 4 .equ se_m_waterfall_rev, reverb_set+50 .equ se_m_waterfall_mvl, 127 diff --git a/sound/songs/se_m_whirlpool.s b/sound/songs/se_m_whirlpool.s index bf0b9cc722..67563395cc 100644 --- a/sound/songs/se_m_whirlpool.s +++ b/sound/songs/se_m_whirlpool.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_whirlpool_grp, voicegroup128 + .equ se_m_whirlpool_grp, voicegroup_rs_sfx_2 .equ se_m_whirlpool_pri, 4 .equ se_m_whirlpool_rev, reverb_set+50 .equ se_m_whirlpool_mvl, 127 diff --git a/sound/songs/se_m_yawn.s b/sound/songs/se_m_yawn.s index c6af1f3610..fdd6012a22 100644 --- a/sound/songs/se_m_yawn.s +++ b/sound/songs/se_m_yawn.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_m_yawn_grp, voicegroup128 + .equ se_m_yawn_grp, voicegroup_rs_sfx_2 .equ se_m_yawn_pri, 4 .equ se_m_yawn_rev, reverb_set+50 .equ se_m_yawn_mvl, 127 diff --git a/sound/songs/se_wall_hit.s b/sound/songs/se_wall_hit.s index feeeb03b1d..385da03739 100644 --- a/sound/songs/se_wall_hit.s +++ b/sound/songs/se_wall_hit.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_wall_hit_grp, voicegroup127 + .equ se_wall_hit_grp, voicegroup_rs_sfx_1 .equ se_wall_hit_pri, 2 .equ se_wall_hit_rev, reverb_set+50 .equ se_wall_hit_mvl, 127 diff --git a/sound/songs/se_win_open.s b/sound/songs/se_win_open.s index b5d582a8d9..07fb4fadd4 100644 --- a/sound/songs/se_win_open.s +++ b/sound/songs/se_win_open.s @@ -1,6 +1,6 @@ .include "MPlayDef.s" - .equ se_win_open_grp, voicegroup127 + .equ se_win_open_grp, voicegroup_rs_sfx_1 .equ se_win_open_pri, 5 .equ se_win_open_rev, reverb_set+50 .equ se_win_open_mvl, 127 diff --git a/sound/voice_groups.inc b/sound/voice_groups.inc index 8ee57619b6..eabcc5c752 100644 --- a/sound/voice_groups.inc +++ b/sound/voice_groups.inc @@ -1,192 +1,203 @@ -.include "sound/voicegroups/voicegroup000.inc" -.include "sound/voicegroups/voicegroup001.inc" -.include "sound/voicegroups/voicegroup002.inc" -.include "sound/voicegroups/voicegroup003.inc" -.include "sound/voicegroups/voicegroup004.inc" -.include "sound/voicegroups/voicegroup005.inc" -.include "sound/voicegroups/voicegroup006.inc" -.include "sound/voicegroups/voicegroup007.inc" -.include "sound/voicegroups/voicegroup008.inc" -.include "sound/voicegroups/voicegroup009.inc" -.include "sound/voicegroups/voicegroup010.inc" -.include "sound/voicegroups/voicegroup011.inc" -.include "sound/voicegroups/voicegroup012.inc" -.include "sound/voicegroups/voicegroup013.inc" -.include "sound/voicegroups/voicegroup014.inc" -.include "sound/voicegroups/voicegroup015.inc" -.include "sound/voicegroups/voicegroup016.inc" -.include "sound/voicegroups/voicegroup017.inc" -.include "sound/voicegroups/voicegroup018.inc" -.include "sound/voicegroups/voicegroup019.inc" -.include "sound/voicegroups/voicegroup020.inc" -.include "sound/voicegroups/voicegroup021.inc" -.include "sound/voicegroups/voicegroup022.inc" -.include "sound/voicegroups/voicegroup023.inc" -.include "sound/voicegroups/voicegroup024.inc" -.include "sound/voicegroups/voicegroup025.inc" -.include "sound/voicegroups/voicegroup026.inc" -.include "sound/voicegroups/voicegroup027.inc" -.include "sound/voicegroups/voicegroup028.inc" -.include "sound/voicegroups/voicegroup029.inc" -.include "sound/voicegroups/voicegroup030.inc" -.include "sound/voicegroups/voicegroup031.inc" -.include "sound/voicegroups/voicegroup032.inc" -.include "sound/voicegroups/voicegroup033.inc" -.include "sound/voicegroups/voicegroup034.inc" -.include "sound/voicegroups/voicegroup035.inc" -.include "sound/voicegroups/voicegroup036.inc" -.include "sound/voicegroups/voicegroup037.inc" -.include "sound/voicegroups/voicegroup038.inc" -.include "sound/voicegroups/voicegroup039.inc" -.include "sound/voicegroups/voicegroup040.inc" -.include "sound/voicegroups/voicegroup041.inc" -.include "sound/voicegroups/voicegroup042.inc" -.include "sound/voicegroups/voicegroup043.inc" -.include "sound/voicegroups/voicegroup044.inc" -.include "sound/voicegroups/voicegroup045.inc" -.include "sound/voicegroups/voicegroup046.inc" -.include "sound/voicegroups/voicegroup047.inc" -.include "sound/voicegroups/voicegroup048.inc" -.include "sound/voicegroups/voicegroup049.inc" -.include "sound/voicegroups/voicegroup050.inc" -.include "sound/voicegroups/voicegroup051.inc" -.include "sound/voicegroups/voicegroup052.inc" -.include "sound/voicegroups/voicegroup053.inc" -.include "sound/voicegroups/voicegroup054.inc" -.include "sound/voicegroups/voicegroup055.inc" -.include "sound/voicegroups/voicegroup056.inc" -.include "sound/voicegroups/voicegroup057.inc" -.include "sound/voicegroups/voicegroup058.inc" -.include "sound/voicegroups/voicegroup059.inc" -.include "sound/voicegroups/voicegroup060.inc" -.include "sound/voicegroups/voicegroup061.inc" -.include "sound/voicegroups/voicegroup062.inc" -.include "sound/voicegroups/voicegroup063.inc" -.include "sound/voicegroups/voicegroup064.inc" -.include "sound/voicegroups/voicegroup065.inc" -.include "sound/voicegroups/voicegroup066.inc" -.include "sound/voicegroups/voicegroup067.inc" -.include "sound/voicegroups/voicegroup068.inc" -.include "sound/voicegroups/voicegroup069.inc" -.include "sound/voicegroups/voicegroup070.inc" -.include "sound/voicegroups/voicegroup071.inc" -.include "sound/voicegroups/voicegroup072.inc" -.include "sound/voicegroups/voicegroup073.inc" -.include "sound/voicegroups/voicegroup074.inc" -.include "sound/voicegroups/voicegroup075.inc" -.include "sound/voicegroups/voicegroup076.inc" -.include "sound/voicegroups/voicegroup077.inc" -.include "sound/voicegroups/voicegroup078.inc" -.include "sound/voicegroups/voicegroup079.inc" -.include "sound/voicegroups/voicegroup080.inc" -.include "sound/voicegroups/voicegroup081.inc" -.include "sound/voicegroups/voicegroup082.inc" -.include "sound/voicegroups/voicegroup083.inc" -.include "sound/voicegroups/voicegroup084.inc" -.include "sound/voicegroups/voicegroup085.inc" -.include "sound/voicegroups/voicegroup086.inc" -.include "sound/voicegroups/voicegroup087.inc" -.include "sound/voicegroups/voicegroup088.inc" -.include "sound/voicegroups/voicegroup089.inc" -.include "sound/voicegroups/voicegroup090.inc" -.include "sound/voicegroups/voicegroup091.inc" -.include "sound/voicegroups/voicegroup092.inc" -.include "sound/voicegroups/voicegroup093.inc" -.include "sound/voicegroups/voicegroup094.inc" -.include "sound/voicegroups/voicegroup095.inc" -.include "sound/voicegroups/voicegroup096.inc" -.include "sound/voicegroups/voicegroup097.inc" -.include "sound/voicegroups/voicegroup098.inc" -.include "sound/voicegroups/voicegroup099.inc" -.include "sound/voicegroups/voicegroup100.inc" -.include "sound/voicegroups/voicegroup101.inc" -.include "sound/voicegroups/voicegroup102.inc" -.include "sound/voicegroups/voicegroup103.inc" -.include "sound/voicegroups/voicegroup104.inc" -.include "sound/voicegroups/voicegroup105.inc" -.include "sound/voicegroups/voicegroup106.inc" -.include "sound/voicegroups/voicegroup107.inc" -.include "sound/voicegroups/voicegroup108.inc" -.include "sound/voicegroups/voicegroup109.inc" -.include "sound/voicegroups/voicegroup110.inc" -.include "sound/voicegroups/voicegroup111.inc" -.include "sound/voicegroups/voicegroup112.inc" -.include "sound/voicegroups/voicegroup113.inc" -.include "sound/voicegroups/voicegroup114.inc" -.include "sound/voicegroups/voicegroup115.inc" -.include "sound/voicegroups/voicegroup116.inc" -.include "sound/voicegroups/voicegroup117.inc" -.include "sound/voicegroups/voicegroup118.inc" -.include "sound/voicegroups/voicegroup119.inc" -.include "sound/voicegroups/voicegroup120.inc" -.include "sound/voicegroups/voicegroup121.inc" -.include "sound/voicegroups/voicegroup122.inc" -.include "sound/voicegroups/voicegroup123.inc" -.include "sound/voicegroups/voicegroup124.inc" -.include "sound/voicegroups/voicegroup125.inc" -.include "sound/voicegroups/voicegroup126.inc" -.include "sound/voicegroups/voicegroup127.inc" -.include "sound/voicegroups/voicegroup128.inc" +.include "sound/voicegroups/dummy.inc" + +@ drumsets +.include "sound/voicegroups/drumsets/rs.inc" +.include "sound/voicegroups/drumsets/frlg.inc" +.include "sound/voicegroups/drumsets/emerald_1.inc" +.include "sound/voicegroups/drumsets/emerald_2.inc" + +@ key splits +.include "sound/voicegroups/keysplits/piano.inc" +.include "sound/voicegroups/keysplits/strings.inc" +.include "sound/voicegroups/keysplits/trumpet.inc" +.include "sound/voicegroups/unused.inc" +.include "sound/voicegroups/keysplits/tuba.inc" +.include "sound/voicegroups/keysplits/french_horn.inc" + +.include "sound/voicegroups/route110.inc" +.include "sound/voicegroups/route101.inc" +.include "sound/voicegroups/fanfare.inc" +.include "sound/voicegroups/gym.inc" +.include "sound/voicegroups/route120.inc" +.include "sound/voicegroups/petalburg.inc" +.include "sound/voicegroups/drumsets/petalburg.inc" +.include "sound/voicegroups/surf.inc" +.include "sound/voicegroups/petalburg_woods.inc" +.include "sound/voicegroups/oldale.inc" +.include "sound/voicegroups/lilycove_museum.inc" +.include "sound/voicegroups/route122.inc" +.include "sound/voicegroups/drumsets/route101.inc" +.include "sound/voicegroups/oceanic_museum.inc" +.include "sound/voicegroups/victory_gym_leader.inc" +.include "sound/voicegroups/victory_wild.inc" +.include "sound/voicegroups/evolution.inc" +.include "sound/voicegroups/encounter_girl.inc" +.include "sound/voicegroups/encounter_male.inc" +.include "sound/voicegroups/victory_league.inc" +.include "sound/voicegroups/abandoned_ship.inc" +.include "sound/voicegroups/drumsets/route110.inc" +.include "sound/voicegroups/fortree.inc" +.include "sound/voicegroups/birch_lab.inc" +.include "sound/voicegroups/littleroot_test.inc" +.include "sound/voicegroups/b_tower_rs.inc" +.include "sound/voicegroups/encounter_swimmer.inc" +.include "sound/voicegroups/cave_of_origin.inc" +.include "sound/voicegroups/roulette.inc" +.include "sound/voicegroups/link_contest_p1.inc" +.include "sound/voicegroups/link_contest_p2.inc" +.include "sound/voicegroups/link_contest_p3.inc" +.include "sound/voicegroups/link_contest_p4.inc" +.include "sound/voicegroups/encounter_rich.inc" +.include "sound/voicegroups/verdanturf.inc" +.include "sound/voicegroups/rustboro.inc" +.include "sound/voicegroups/poke_center.inc" +.include "sound/voicegroups/route104.inc" +.include "sound/voicegroups/route119.inc" +.include "sound/voicegroups/cycling.inc" +.include "sound/voicegroups/poke_mart.inc" +.include "sound/voicegroups/littleroot.inc" +.include "sound/voicegroups/mt_chimney.inc" +.include "sound/voicegroups/encounter_female.inc" +.include "sound/voicegroups/lilycove.inc" +.include "sound/voicegroups/route111.inc" +.include "sound/voicegroups/help.inc" +.include "sound/voicegroups/underwater.inc" +.include "sound/voicegroups/victory_trainer.inc" +.include "sound/voicegroups/title.inc" +.include "sound/voicegroups/intro.inc" +.include "sound/voicegroups/encounter_may.inc" +.include "sound/voicegroups/encounter_intense.inc" +.include "sound/voicegroups/encounter_cool.inc" +.include "sound/voicegroups/route113.inc" +.include "sound/voicegroups/encounter_aqua.inc" +.include "sound/voicegroups/follow_me.inc" +.include "sound/voicegroups/encounter_brendan.inc" +.include "sound/voicegroups/ever_grande.inc" +.include "sound/voicegroups/encounter_suspicious.inc" +.include "sound/voicegroups/victory_aqua_magma.inc" +.include "sound/voicegroups/cable_car.inc" +.include "sound/voicegroups/game_corner.inc" +.include "sound/voicegroups/dewford.inc" +.include "sound/voicegroups/safari_zone.inc" +.include "sound/voicegroups/victory_road.inc" +.include "sound/voicegroups/aqua_magma_hideout.inc" +.include "sound/voicegroups/sailing.inc" +.include "sound/voicegroups/mt_pyre.inc" +.include "sound/voicegroups/slateport.inc" +.include "sound/voicegroups/mt_pyre_exterior.inc" +.include "sound/voicegroups/school.inc" +.include "sound/voicegroups/hall_of_fame.inc" +.include "sound/voicegroups/fallarbor.inc" +.include "sound/voicegroups/sealed_chamber.inc" +.include "sound/voicegroups/contest_winner.inc" +.include "sound/voicegroups/contest.inc" +.include "sound/voicegroups/encounter_magma.inc" +.include "sound/voicegroups/intro_battle.inc" +.include "sound/voicegroups/abnormal_weather.inc" +.include "sound/voicegroups/weather_groudon.inc" +.include "sound/voicegroups/sootopolis.inc" +.include "sound/voicegroups/contest_results.inc" +.include "sound/voicegroups/hall_of_fame_room.inc" +.include "sound/voicegroups/trick_house.inc" +.include "sound/voicegroups/encounter_twins.inc" +.include "sound/voicegroups/encounter_elite_four.inc" +.include "sound/voicegroups/encounter_hiker.inc" +.include "sound/voicegroups/contest_lobby.inc" +.include "sound/voicegroups/encounter_interviewer.inc" +.include "sound/voicegroups/encounter_champion.inc" +.include "sound/voicegroups/credits.inc" +.include "sound/voicegroups/end.inc" +.include "sound/voicegroups/b_frontier.inc" +.include "sound/voicegroups/b_arena.inc" +.include "sound/voicegroups/register_match_call.inc" +.include "sound/voicegroups/b_pyramid.inc" +.include "sound/voicegroups/b_pyramid_top.inc" +.include "sound/voicegroups/b_palace.inc" +.include "sound/voicegroups/rayquaza_appears.inc" +.include "sound/voicegroups/b_tower.inc" +.include "sound/voicegroups/b_dome.inc" +.include "sound/voicegroups/b_pike.inc" +.include "sound/voicegroups/b_factory.inc" +.include "sound/voicegroups/vs_rayquaza.inc" +.include "sound/voicegroups/vs_frontier_brain.inc" +.include "sound/voicegroups/vs_mew.inc" +.include "sound/voicegroups/vs_wild.inc" +.include "sound/voicegroups/vs_aqua_magma.inc" +.include "sound/voicegroups/vs_trainer.inc" +.include "sound/voicegroups/vs_gym_leader.inc" +.include "sound/voicegroups/vs_champion.inc" +.include "sound/voicegroups/vs_regi.inc" +.include "sound/voicegroups/vs_kyogre_groudon.inc" @ duplicate of vs_rayquaza +.include "sound/voicegroups/vs_rival.inc" +.include "sound/voicegroups/vs_elite_four.inc" +.include "sound/voicegroups/vs_aqua_magma_leader.inc" +.include "sound/voicegroups/rs_sfx_1.inc" +.include "sound/voicegroups/rs_sfx_2.inc" .include "sound/cry_tables.inc" -.include "sound/voicegroups/voicegroup129.inc" -.include "sound/voicegroups/voicegroup130.inc" -.include "sound/voicegroups/voicegroup131.inc" -.include "sound/voicegroups/voicegroup132.inc" -.include "sound/voicegroups/voicegroup133.inc" -.include "sound/voicegroups/voicegroup134.inc" -.include "sound/voicegroups/voicegroup135.inc" -.include "sound/voicegroups/voicegroup136.inc" -.include "sound/voicegroups/voicegroup137.inc" -.include "sound/voicegroups/voicegroup138.inc" -.include "sound/voicegroups/voicegroup139.inc" -.include "sound/voicegroups/voicegroup140.inc" -.include "sound/voicegroups/voicegroup141.inc" -.include "sound/voicegroups/voicegroup142.inc" -.include "sound/voicegroups/voicegroup143.inc" -.include "sound/voicegroups/voicegroup144.inc" -.include "sound/voicegroups/voicegroup145.inc" -.include "sound/voicegroups/voicegroup146.inc" -.include "sound/voicegroups/voicegroup147.inc" -.include "sound/voicegroups/voicegroup148.inc" -.include "sound/voicegroups/voicegroup149.inc" -.include "sound/voicegroups/voicegroup150.inc" -.include "sound/voicegroups/voicegroup151.inc" -.include "sound/voicegroups/voicegroup152.inc" -.include "sound/voicegroups/voicegroup153.inc" -.include "sound/voicegroups/voicegroup154.inc" -.include "sound/voicegroups/voicegroup155.inc" -.include "sound/voicegroups/voicegroup156.inc" -.include "sound/voicegroups/voicegroup157.inc" -.include "sound/voicegroups/voicegroup158.inc" -.include "sound/voicegroups/voicegroup159.inc" -.include "sound/voicegroups/voicegroup160.inc" -.include "sound/voicegroups/voicegroup161.inc" -.include "sound/voicegroups/voicegroup162.inc" -.include "sound/voicegroups/voicegroup163.inc" -.include "sound/voicegroups/voicegroup164.inc" -.include "sound/voicegroups/voicegroup165.inc" -.include "sound/voicegroups/voicegroup166.inc" -.include "sound/voicegroups/voicegroup167.inc" -.include "sound/voicegroups/voicegroup168.inc" -.include "sound/voicegroups/voicegroup169.inc" -.include "sound/voicegroups/voicegroup170.inc" -.include "sound/voicegroups/voicegroup171.inc" -.include "sound/voicegroups/voicegroup172.inc" -.include "sound/voicegroups/voicegroup173.inc" -.include "sound/voicegroups/voicegroup174.inc" -.include "sound/voicegroups/voicegroup175.inc" -.include "sound/voicegroups/voicegroup176.inc" -.include "sound/voicegroups/voicegroup177.inc" -.include "sound/voicegroups/voicegroup178.inc" -.include "sound/voicegroups/voicegroup179.inc" -.include "sound/voicegroups/voicegroup180.inc" -.include "sound/voicegroups/voicegroup181.inc" -.include "sound/voicegroups/voicegroup182.inc" -.include "sound/voicegroups/voicegroup183.inc" -.include "sound/voicegroups/voicegroup184.inc" -.include "sound/voicegroups/voicegroup185.inc" -.include "sound/voicegroups/voicegroup186.inc" -.include "sound/voicegroups/voicegroup187.inc" -.include "sound/voicegroups/voicegroup188.inc" -.include "sound/voicegroups/voicegroup189.inc" -.include "sound/voicegroups/voicegroup190.inc" +.include "sound/voicegroups/frlg_sfx.inc" +.include "sound/voicegroups/bard.inc" +.include "sound/voicegroups/unused_2.inc" @ used by unused GSC radio tower takeover test track in RS + +@ FRLG +.include "sound/voicegroups/rg_follow_me.inc" +.include "sound/voicegroups/rg_game_corner.inc" +.include "sound/voicegroups/rg_rocket_hideout.inc" +.include "sound/voicegroups/rg_gym.inc" +.include "sound/voicegroups/rg_jigglypuff.inc" +.include "sound/voicegroups/rg_intro_fight.inc" +.include "sound/voicegroups/rg_title.inc" +.include "sound/voicegroups/rg_cinnabar.inc" +.include "sound/voicegroups/rg_lavender.inc" +.include "sound/voicegroups/rg_heal.inc" +.include "sound/voicegroups/rg_cycling.inc" +.include "sound/voicegroups/rg_encounter_rocket.inc" +.include "sound/voicegroups/rg_encounter_girl.inc" +.include "sound/voicegroups/rg_encounter_boy.inc" +.include "sound/voicegroups/rg_hall_of_fame.inc" +.include "sound/voicegroups/rg_viridian_forest.inc" +.include "sound/voicegroups/rg_mt_moon.inc" +.include "sound/voicegroups/rg_poke_mansion.inc" +.include "sound/voicegroups/rg_credits.inc" +.include "sound/voicegroups/rg_route1.inc" +.include "sound/voicegroups/rg_route24.inc" +.include "sound/voicegroups/rg_route3.inc" +.include "sound/voicegroups/rg_route11.inc" +.include "sound/voicegroups/rg_victory_road.inc" +.include "sound/voicegroups/rg_vs_gym_leader.inc" +.include "sound/voicegroups/rg_vs_trainer.inc" +.include "sound/voicegroups/rg_vs_wild.inc" +.include "sound/voicegroups/rg_vs_champion.inc" +.include "sound/voicegroups/rg_pallet.inc" +.include "sound/voicegroups/rg_oak_lab.inc" +.include "sound/voicegroups/rg_oak.inc" +.include "sound/voicegroups/rg_poke_center.inc" +.include "sound/voicegroups/rg_ss_anne.inc" +.include "sound/voicegroups/rg_surf.inc" +.include "sound/voicegroups/rg_poke_tower.inc" +.include "sound/voicegroups/rg_silph.inc" +.include "sound/voicegroups/rg_fuchsia.inc" +.include "sound/voicegroups/rg_celadon.inc" +.include "sound/voicegroups/rg_victory_trainer.inc" +.include "sound/voicegroups/rg_victory_wild.inc" +.include "sound/voicegroups/rg_victory_gym_leader.inc" +.include "sound/voicegroups/rg_vermillion.inc" +.include "sound/voicegroups/rg_pewter.inc" +.include "sound/voicegroups/rg_encounter_rival.inc" +.include "sound/voicegroups/rg_unused.inc" +.include "sound/voicegroups/rg_unused_2.inc" +.include "sound/voicegroups/rg_dex_rating.inc" +.include "sound/voicegroups/drumsets/frlg_fanfare_2.inc" +.include "sound/voicegroups/drumsets/frlg_fanfare_1.inc" +.include "sound/voicegroups/rg_obtain_key_item.inc" +.include "sound/voicegroups/rg_caught_intro.inc" +.include "sound/voicegroups/rg_photo.inc" +.include "sound/voicegroups/rg_game_freak.inc" +.include "sound/voicegroups/rg_new_game.inc" +.include "sound/voicegroups/rg_mystery_gift.inc" +.include "sound/voicegroups/rg_encounter_deoxys.inc" +.include "sound/voicegroups/rg_vs_deoxys.inc" +.include "sound/voicegroups/rg_teachy_tv_menu.inc" +.include "sound/voicegroups/rg_sevii_route.inc" +.include "sound/voicegroups/rg_sevii_45.inc" +.include "sound/voicegroups/rg_sevii_67.inc" +.include "sound/voicegroups/drumsets/rg_credits.inc" diff --git a/sound/voicegroups/abandoned_ship.inc b/sound/voicegroups/abandoned_ship.inc new file mode 100644 index 0000000000..37b1e7a95e --- /dev/null +++ b/sound/voicegroups/abandoned_ship.inc @@ -0,0 +1,97 @@ +voice_group abandoned_ship + voice_keysplit_all voicegroup_route110_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2_alt 60, 0, 3, 0, 2, 4, 0 + voice_square_1_alt 60, 0, 0, 3, 0, 2, 4, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tubular_bell, 255, 216, 90, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 37, 165, 180, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_3, 0, 7, 15, 1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_trinity_big_boned, 255, 165, 154, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + diff --git a/sound/voicegroups/voicegroup089.inc b/sound/voicegroups/abnormal_weather.inc similarity index 96% rename from sound/voicegroups/voicegroup089.inc rename to sound/voicegroups/abnormal_weather.inc index 4b5e7d57bd..fc6ac4639d 100644 --- a/sound/voicegroups/voicegroup089.inc +++ b/sound/voicegroups/abnormal_weather.inc @@ -1,6 +1,6 @@ - .align 2 -voicegroup089:: - voice_keysplit_all voicegroup001 + +voice_group abnormal_weather + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +48,7 @@ voicegroup089:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +60,7 @@ voicegroup089:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup076.inc b/sound/voicegroups/aqua_magma_hideout.inc similarity index 97% rename from sound/voicegroups/voicegroup076.inc rename to sound/voicegroups/aqua_magma_hideout.inc index 378a8ff669..f9feafc9e9 100644 --- a/sound/voicegroups/voicegroup076.inc +++ b/sound/voicegroups/aqua_magma_hideout.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup076:: - voice_keysplit_all voicegroup001 +voice_group aqua_magma_hideout + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup076:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup104.inc b/sound/voicegroups/b_arena.inc similarity index 98% rename from sound/voicegroups/voicegroup104.inc rename to sound/voicegroups/b_arena.inc index c1b623918b..bb35ad718c 100644 --- a/sound/voicegroups/voicegroup104.inc +++ b/sound/voicegroups/b_arena.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup104:: - voice_keysplit_all voicegroup003 +voice_group b_arena + voice_keysplit_all voicegroup_emerald_drumset_1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_unknown_koto_high, 255, 0, 206, 242 diff --git a/sound/voicegroups/voicegroup111.inc b/sound/voicegroups/b_dome.inc similarity index 98% rename from sound/voicegroups/voicegroup111.inc rename to sound/voicegroups/b_dome.inc index 27b418f462..e54ec9d99c 100644 --- a/sound/voicegroups/voicegroup111.inc +++ b/sound/voicegroups/b_dome.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup111:: - voice_keysplit_all voicegroup002 +voice_group b_dome + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup113.inc b/sound/voicegroups/b_factory.inc similarity index 96% rename from sound/voicegroups/voicegroup113.inc rename to sound/voicegroups/b_factory.inc index 0fa279c8a6..4f6af2cd29 100644 --- a/sound/voicegroups/voicegroup113.inc +++ b/sound/voicegroups/b_factory.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup113:: - voice_keysplit_all voicegroup002 +voice_group b_factory + voice_keysplit_all voicegroup_frlg_drumset voice_programmable_wave_alt 60, 0, ProgrammableWaveData_23, 0, 7, 15, 1 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_25, 0, 7, 15, 1 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_24, 0, 7, 15, 1 @@ -56,11 +55,11 @@ voicegroup113:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup103.inc b/sound/voicegroups/b_frontier.inc similarity index 95% rename from sound/voicegroups/voicegroup103.inc rename to sound/voicegroups/b_frontier.inc index cc743edb22..50a3287746 100644 --- a/sound/voicegroups/voicegroup103.inc +++ b/sound/voicegroups/b_frontier.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup103:: +voice_group b_frontier voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit_all voicegroup002 + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup103:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup103:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup108.inc b/sound/voicegroups/b_palace.inc similarity index 97% rename from sound/voicegroups/voicegroup108.inc rename to sound/voicegroups/b_palace.inc index a92ee43c6a..6fe0cf3971 100644 --- a/sound/voicegroups/voicegroup108.inc +++ b/sound/voicegroups/b_palace.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup108:: - voice_keysplit_all voicegroup004 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group b_palace + voice_keysplit_all voicegroup_emerald_drumset_2 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup112.inc b/sound/voicegroups/b_pike.inc similarity index 95% rename from sound/voicegroups/voicegroup112.inc rename to sound/voicegroups/b_pike.inc index 9cb2f415a9..266a4be4b8 100644 --- a/sound/voicegroups/voicegroup112.inc +++ b/sound/voicegroups/b_pike.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup112:: - voice_keysplit_all voicegroup003 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group b_pike + voice_keysplit_all voicegroup_emerald_drumset_1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_21, 0, 7, 15, 1 @@ -48,7 +47,7 @@ voicegroup112:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup112:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup106.inc b/sound/voicegroups/b_pyramid.inc similarity index 94% rename from sound/voicegroups/voicegroup106.inc rename to sound/voicegroups/b_pyramid.inc index 1a1125be8a..f3016ab727 100644 --- a/sound/voicegroups/voicegroup106.inc +++ b/sound/voicegroups/b_pyramid.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup106:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group b_pyramid + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup106:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup106:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup107.inc b/sound/voicegroups/b_pyramid_top.inc similarity index 96% rename from sound/voicegroups/voicegroup107.inc rename to sound/voicegroups/b_pyramid_top.inc index c43a518ec7..1cc81ff7c2 100644 --- a/sound/voicegroups/voicegroup107.inc +++ b/sound/voicegroups/b_pyramid_top.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup107:: - voice_keysplit_all voicegroup002 +voice_group b_pyramid_top + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup107:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup107:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup110.inc b/sound/voicegroups/b_tower.inc similarity index 94% rename from sound/voicegroups/voicegroup110.inc rename to sound/voicegroups/b_tower.inc index 25b6fdaae0..4abf332680 100644 --- a/sound/voicegroups/voicegroup110.inc +++ b/sound/voicegroups/b_tower.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup110:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group b_tower + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup110:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup110:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup035.inc b/sound/voicegroups/b_tower_rs.inc similarity index 91% rename from sound/voicegroups/voicegroup035.inc rename to sound/voicegroups/b_tower_rs.inc index 2c3ac4bddd..dc06a0e462 100644 --- a/sound/voicegroups/voicegroup035.inc +++ b/sound/voicegroups/b_tower_rs.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup035:: - voice_keysplit_all voicegroup031 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group b_tower_rs + voice_keysplit_all voicegroup_route110_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 2, 0, 1, 7, 1 @@ -48,7 +47,7 @@ voicegroup035:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup035:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/bard.inc b/sound/voicegroups/bard.inc new file mode 100644 index 0000000000..57ba0bfd1c --- /dev/null +++ b/sound/voicegroups/bard.inc @@ -0,0 +1,53 @@ +voice_group bard + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_1, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_2, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_3, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_4, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_5, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_6, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_7, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_8, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_9, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_10, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_11, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_12, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_13, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_14, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_15, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_16, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_17, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_18, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_19, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_20, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_21, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_22, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_23, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_24, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_25, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_26, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_27, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_28, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_29, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_30, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_31, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_32, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_33, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_34, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_35, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_36, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_37, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_38, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_39, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_40, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_41, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_42, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_43, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_44, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_45, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_46, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_47, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_48, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_49, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_50, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_Phoneme_51, 255, 0, 255, 0 + diff --git a/sound/voicegroups/voicegroup033.inc b/sound/voicegroups/birch_lab.inc similarity index 94% rename from sound/voicegroups/voicegroup033.inc rename to sound/voicegroups/birch_lab.inc index 34e7e43b71..20e7edd4b6 100644 --- a/sound/voicegroups/voicegroup033.inc +++ b/sound/voicegroups/birch_lab.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup033:: - voice_keysplit_all voicegroup001 +voice_group birch_lab + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup033:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup033:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup071.inc b/sound/voicegroups/cable_car.inc similarity index 95% rename from sound/voicegroups/voicegroup071.inc rename to sound/voicegroups/cable_car.inc index a4cb9c721f..7cb2fb8a58 100644 --- a/sound/voicegroups/voicegroup071.inc +++ b/sound/voicegroups/cable_car.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup071:: - voice_keysplit_all voicegroup001 +voice_group cable_car + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup071:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup037.inc b/sound/voicegroups/cave_of_origin.inc similarity index 93% rename from sound/voicegroups/voicegroup037.inc rename to sound/voicegroups/cave_of_origin.inc index 057891c01b..d1bd42e395 100644 --- a/sound/voicegroups/voicegroup037.inc +++ b/sound/voicegroups/cave_of_origin.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup037:: - voice_keysplit_all voicegroup031 +voice_group cave_of_origin + voice_keysplit_all voicegroup_route110_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup037:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup037:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup086.inc b/sound/voicegroups/contest.inc similarity index 95% rename from sound/voicegroups/voicegroup086.inc rename to sound/voicegroups/contest.inc index d5298f9b03..f0c245089d 100644 --- a/sound/voicegroups/voicegroup086.inc +++ b/sound/voicegroups/contest.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup086:: - voice_keysplit_all voicegroup001 +voice_group contest + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup086:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup086:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup098.inc b/sound/voicegroups/contest_lobby.inc similarity index 96% rename from sound/voicegroups/voicegroup098.inc rename to sound/voicegroups/contest_lobby.inc index 3a927368bc..ec606540f1 100644 --- a/sound/voicegroups/voicegroup098.inc +++ b/sound/voicegroups/contest_lobby.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup098:: - voice_keysplit_all voicegroup001 +voice_group contest_lobby + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup098:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup092.inc b/sound/voicegroups/contest_results.inc similarity index 98% rename from sound/voicegroups/voicegroup092.inc rename to sound/voicegroups/contest_results.inc index 90e2858175..ba4f70b996 100644 --- a/sound/voicegroups/voicegroup092.inc +++ b/sound/voicegroups/contest_results.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup092:: - voice_keysplit_all voicegroup001 +voice_group contest_results + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup085.inc b/sound/voicegroups/contest_winner.inc similarity index 97% rename from sound/voicegroups/voicegroup085.inc rename to sound/voicegroups/contest_winner.inc index 6260fb198a..e1d55a7238 100644 --- a/sound/voicegroups/voicegroup085.inc +++ b/sound/voicegroups/contest_winner.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup085:: - voice_keysplit_all voicegroup001 +voice_group contest_winner + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup085:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup101.inc b/sound/voicegroups/credits.inc similarity index 92% rename from sound/voicegroups/voicegroup101.inc rename to sound/voicegroups/credits.inc index 768c18dea2..6234450ed2 100644 --- a/sound/voicegroups/voicegroup101.inc +++ b/sound/voicegroups/credits.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup101:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group credits + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 1, 1, 5, 2, 4 @@ -48,7 +47,7 @@ voicegroup101:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup101:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup049.inc b/sound/voicegroups/cycling.inc similarity index 94% rename from sound/voicegroups/voicegroup049.inc rename to sound/voicegroups/cycling.inc index b6b0774cf3..496c41cdd6 100644 --- a/sound/voicegroups/voicegroup049.inc +++ b/sound/voicegroups/cycling.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup049:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group cycling + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup049:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup049:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup073.inc b/sound/voicegroups/dewford.inc similarity index 94% rename from sound/voicegroups/voicegroup073.inc rename to sound/voicegroups/dewford.inc index b10ab81d1a..7de8c35be9 100644 --- a/sound/voicegroups/voicegroup073.inc +++ b/sound/voicegroups/dewford.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup073:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group dewford + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup073:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup073:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/drumsets/emerald_1.inc b/sound/voicegroups/drumsets/emerald_1.inc new file mode 100644 index 0000000000..80a9957f86 --- /dev/null +++ b/sound/voicegroups/drumsets/emerald_1.inc @@ -0,0 +1,56 @@ +voice_group emerald_drumset_1, 36 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 + voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_directsound 64, 24, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 64, 80, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_directsound 68, 34, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 + voice_directsound 72, 44, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 76, 84, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound 80, 94, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 33, 89, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_directsound 64, 104, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 235 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 63, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_directsound_no_resample 64, 24, DirectSoundWaveData_dance_drums_ride_bell, 255, 165, 103, 231 + voice_directsound_no_resample 66, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 + voice_directsound_no_resample 64, 14, DirectSoundWaveData_trinity_cymbal_crash, 255, 231, 0, 188 + voice_directsound_no_resample 64, 89, DirectSoundWaveData_sd90_cowbell, 255, 0, 255, 242 + voice_directsound_no_resample 64, 29, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 + voice_directsound_no_resample 64, 94, DirectSoundWaveData_unused_heart_of_asia_indian_drum, 255, 0, 255, 0 + voice_directsound_no_resample 64, 34, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 + voice_directsound_no_resample 64, 34, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 + voice_directsound_no_resample 64, 90, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 61, 84, DirectSoundWaveData_ethnic_flavours_hyoushigi, 255, 0, 255, 0 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_ethnic_flavours_ohtsuzumi, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 64, 39, DirectSoundWaveData_sd90_open_triangle, 255, 242, 103, 188 + voice_directsound_no_resample 64, 79, DirectSoundWaveData_sd90_open_triangle, 255, 242, 103, 188 + voice_directsound_no_resample 64, 39, DirectSoundWaveData_sd90_open_triangle, 255, 165, 103, 188 + voice_directsound_no_resample 64, 24, DirectSoundWaveData_sc88pro_jingle_bell, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 64, 104, DirectSoundWaveData_ethnic_flavours_atarigane, 255, 0, 255, 0 + voice_directsound 63, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 + voice_directsound 50, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 + voice_directsound 64, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 + diff --git a/sound/voicegroups/voicegroup004.inc b/sound/voicegroups/drumsets/emerald_2.inc similarity index 60% rename from sound/voicegroups/voicegroup004.inc rename to sound/voicegroups/drumsets/emerald_2.inc index 6aa28d6a9f..4ad57546e0 100644 --- a/sound/voicegroups/voicegroup004.inc +++ b/sound/voicegroups/drumsets/emerald_2.inc @@ -1,41 +1,4 @@ - .align 2 -voicegroup004:: - voice_directsound_no_resample 66, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 - voice_directsound_no_resample 64, 14, DirectSoundWaveData_trinity_cymbal_crash, 255, 231, 0, 188 - voice_directsound_no_resample 64, 89, DirectSoundWaveData_sd90_cowbell, 255, 0, 255, 242 - voice_directsound_no_resample 64, 29, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 - voice_directsound_no_resample 64, 94, DirectSoundWaveData_unused_heart_of_asia_indian_drum, 255, 0, 255, 0 - voice_directsound_no_resample 64, 34, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 - voice_directsound_no_resample 64, 34, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 - voice_directsound_no_resample 64, 90, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 61, 84, DirectSoundWaveData_ethnic_flavours_hyoushigi, 255, 0, 255, 0 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_ethnic_flavours_ohtsuzumi, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 64, 39, DirectSoundWaveData_sd90_open_triangle, 255, 242, 103, 188 - voice_directsound_no_resample 64, 79, DirectSoundWaveData_sd90_open_triangle, 255, 242, 103, 188 - voice_directsound_no_resample 64, 39, DirectSoundWaveData_sd90_open_triangle, 255, 165, 103, 188 - voice_directsound_no_resample 64, 24, DirectSoundWaveData_sc88pro_jingle_bell, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 64, 104, DirectSoundWaveData_ethnic_flavours_atarigane, 255, 0, 255, 0 - voice_directsound 63, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 - voice_directsound 50, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 - voice_directsound 64, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 +voice_group emerald_drumset_2, 36 voice_directsound 62, 64, DirectSoundWaveData_drum_and_percussion_kick, 255, 0, 255, 0 voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 diff --git a/sound/voicegroups/voicegroup003.inc b/sound/voicegroups/drumsets/frlg.inc similarity index 94% rename from sound/voicegroups/voicegroup003.inc rename to sound/voicegroups/drumsets/frlg.inc index d77150fc12..c0a2e59729 100644 --- a/sound/voicegroups/voicegroup003.inc +++ b/sound/voicegroups/drumsets/frlg.inc @@ -1,5 +1,22 @@ - .align 2 -voicegroup003:: +voice_group frlg_drumset, 36 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_drum_and_percussion_kick, 255, 0, 255, 0 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 + voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_directsound 64, 24, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 64, 80, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_directsound 68, 34, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 + voice_directsound 72, 44, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 + voice_directsound 76, 84, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound 80, 94, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 + voice_directsound_no_resample 33, 89, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_directsound 84, 104, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 235 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 63, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 + voice_directsound_no_resample 64, 24, DirectSoundWaveData_dance_drums_ride_bell, 255, 165, 103, 231 voice_directsound_no_resample 64, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 voice_directsound_no_resample 64, 14, DirectSoundWaveData_trinity_cymbal_crash, 255, 231, 0, 188 voice_directsound_no_resample 64, 89, DirectSoundWaveData_sd90_cowbell, 255, 0, 255, 242 @@ -36,22 +53,4 @@ voicegroup003:: voice_directsound 63, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 voice_directsound 50, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 voice_directsound 64, 84, DirectSoundWaveData_ethnic_flavours_kotsuzumi, 255, 0, 255, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 - voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_directsound 64, 24, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 64, 80, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_directsound 68, 34, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 - voice_directsound 72, 44, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 76, 84, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound 80, 94, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 33, 89, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_directsound 64, 104, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 235 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 63, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_directsound_no_resample 64, 24, DirectSoundWaveData_dance_drums_ride_bell, 255, 165, 103, 231 diff --git a/sound/voicegroups/voicegroup177.inc b/sound/voicegroups/drumsets/frlg_fanfare_1.inc similarity index 72% rename from sound/voicegroups/voicegroup177.inc rename to sound/voicegroups/drumsets/frlg_fanfare_1.inc index bd0e738fd4..0ba197265c 100644 --- a/sound/voicegroups/voicegroup177.inc +++ b/sound/voicegroups/drumsets/frlg_fanfare_1.inc @@ -1,41 +1,4 @@ - .align 2 -voicegroup177:: - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_jingle_bell, 255, 0, 255, 0 +voice_group frlg_fanfare_drumset_1, 36 voice_directsound_no_resample 64, 64, DirectSoundWaveData_drum_and_percussion_kick, 255, 0, 255, 0 voice_directsound_no_resample 67, 71, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 diff --git a/sound/voicegroups/voicegroup176.inc b/sound/voicegroups/drumsets/frlg_fanfare_2.inc similarity index 89% rename from sound/voicegroups/voicegroup176.inc rename to sound/voicegroups/drumsets/frlg_fanfare_2.inc index ee3c97e493..acc72aa3b7 100644 --- a/sound/voicegroups/voicegroup176.inc +++ b/sound/voicegroups/drumsets/frlg_fanfare_2.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup176:: +voice_group frlg_fanfare_drumset_2, 36 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -28,14 +27,11 @@ voicegroup176:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1_alt 60, 0, 0, 2, 0, 2, 7, 1 - voice_square_2_alt 60, 0, 2, 0, 2, 9, 1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_1, 0, 7, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,4 +44,7 @@ voicegroup176:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_jingle_bell, 255, 0, 255, 0 diff --git a/sound/voicegroups/voicegroup016.inc b/sound/voicegroups/drumsets/petalburg.inc similarity index 50% rename from sound/voicegroups/voicegroup016.inc rename to sound/voicegroups/drumsets/petalburg.inc index 1b17ac49c7..4008b40f7b 100644 --- a/sound/voicegroups/voicegroup016.inc +++ b/sound/voicegroups/drumsets/petalburg.inc @@ -1,41 +1,4 @@ - .align 2 -voicegroup016:: - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_noise_alt 60, 0, 0, 0, 2, 0, 2 - voice_noise_alt 60, 0, 0, 0, 1, 0, 1 +voice_group petalburg_drumset, 36 voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_kick, 255, 0, 255, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 diff --git a/sound/voicegroups/voicegroup190.inc b/sound/voicegroups/drumsets/rg_credits.inc similarity index 68% rename from sound/voicegroups/voicegroup190.inc rename to sound/voicegroups/drumsets/rg_credits.inc index 25a84e84ed..0af80106d6 100644 --- a/sound/voicegroups/voicegroup190.inc +++ b/sound/voicegroups/drumsets/rg_credits.inc @@ -1,41 +1,4 @@ - .align 2 -voicegroup190:: - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_1, 0, 7, 15, 2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_noise_alt 60, 0, 0, 0, 2, 7, 0 - voice_noise_alt 60, 0, 0, 0, 1, 9, 1 +voice_group rg_credits_drumset, 36 voice_directsound_no_resample 64, 64, DirectSoundWaveData_drum_and_percussion_kick, 255, 0, 255, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound_no_resample 64, 52, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 @@ -88,3 +51,4 @@ voicegroup190:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound_no_resample 64, 104, DirectSoundWaveData_ethnic_flavours_atarigane, 255, 0, 255, 0 voice_directsound 63, 64, DirectSoundWaveData_sc88pro_taiko, 255, 0, 255, 0 + diff --git a/sound/voicegroups/drumsets/route101.inc b/sound/voicegroups/drumsets/route101.inc new file mode 100644 index 0000000000..779831fc4e --- /dev/null +++ b/sound/voicegroups/drumsets/route101.inc @@ -0,0 +1,31 @@ +voice_group route101_drumset, 36 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_kick, 255, 0, 255, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 32, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 67, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 61, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 + diff --git a/sound/voicegroups/drumsets/route110.inc b/sound/voicegroups/drumsets/route110.inc new file mode 100644 index 0000000000..3535f62927 --- /dev/null +++ b/sound/voicegroups/drumsets/route110.inc @@ -0,0 +1,27 @@ +voice_group route110_drumset, 40 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 32, 49, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 79, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 74, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 + diff --git a/sound/voicegroups/drumsets/rs.inc b/sound/voicegroups/drumsets/rs.inc new file mode 100644 index 0000000000..f15d9a514c --- /dev/null +++ b/sound/voicegroups/drumsets/rs.inc @@ -0,0 +1,31 @@ +voice_group rs_drumset, 36 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_kick, 255, 0, 255, 242 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 + voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 + voice_directsound 48, 44, DirectSoundWaveData_unused_sc55_tom, 255, 210, 77, 204 + voice_directsound_no_resample 60, 79, DirectSoundWaveData_unknown_close_hihat, 255, 127, 0, 188 + voice_directsound 51, 54, DirectSoundWaveData_unused_sc55_tom, 255, 216, 77, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 54, 64, DirectSoundWaveData_unused_sc55_tom, 255, 216, 77, 204 + voice_directsound_no_resample 60, 79, DirectSoundWaveData_unknown_open_hihat, 255, 242, 141, 0 + voice_directsound 57, 69, DirectSoundWaveData_unused_sc55_tom, 255, 210, 77, 204 + voice_directsound 60, 79, DirectSoundWaveData_unused_sc55_tom, 255, 204, 77, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 62, 84, DirectSoundWaveData_unused_sc55_tom, 255, 204, 77, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 70, 49, DirectSoundWaveData_unknown_bell, 255, 165, 103, 231 + voice_directsound_no_resample 32, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 + voice_directsound_no_resample 60, 14, DirectSoundWaveData_trinity_cymbal_crash, 255, 235, 0, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 + voice_directsound_no_resample 30, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 104, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound_no_resample 72, 94, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 + diff --git a/sound/voicegroups/dummy.inc b/sound/voicegroups/dummy.inc new file mode 100644 index 0000000000..34b4275bc1 --- /dev/null +++ b/sound/voicegroups/dummy.inc @@ -0,0 +1,100 @@ +voice_group dummy + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2 60, 0, 2, 0, 0, 9, 2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_glockenspiel, 255, 165, 51, 235 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 255, 0, 255, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 149 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_slap_bass, 255, 235, 128, 115 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_synth_bass, 255, 252, 0, 115 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 1, 6, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave 60, 0, ProgrammableWaveData_1, 0, 7, 15, 1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2 60, 0, 2, 0, 1, 6, 0 + voice_programmable_wave 60, 0, ProgrammableWaveData_3, 0, 7, 15, 1 + voice_square_1 60, 0, 0, 2, 0, 1, 6, 0 + voice_square_2 60, 0, 3, 0, 1, 6, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 0, 0, 1, 6, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_oboe, 255, 165, 154, 127 + voice_directsound 60, 0, DirectSoundWaveData_unused_sd90_oboe, 255, 165, 154, 127 + voice_directsound 60, 0, DirectSoundWaveData_unused_guitar_separates_power_chord, 255, 165, 206, 127 + voice_directsound 60, 0, DirectSoundWaveData_unused_sc88pro_unison_slap, 255, 165, 206, 127 + voice_directsound 60, 0, DirectSoundWaveData_unknown_snare, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_ethnic_flavours_ohtsuzumi, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_ethnic_flavours_hyoushigi, 255, 0, 255, 0 + diff --git a/sound/voicegroups/voicegroup065.inc b/sound/voicegroups/encounter_aqua.inc similarity index 96% rename from sound/voicegroups/voicegroup065.inc rename to sound/voicegroups/encounter_aqua.inc index 163bce0c7e..ce60ac2653 100644 --- a/sound/voicegroups/voicegroup065.inc +++ b/sound/voicegroups/encounter_aqua.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup065:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group encounter_aqua + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup065:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup067.inc b/sound/voicegroups/encounter_brendan.inc similarity index 96% rename from sound/voicegroups/voicegroup067.inc rename to sound/voicegroups/encounter_brendan.inc index ed8ccef4f8..f6f5c3ce9b 100644 --- a/sound/voicegroups/voicegroup067.inc +++ b/sound/voicegroups/encounter_brendan.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup067:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group encounter_brendan + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup067:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup100.inc b/sound/voicegroups/encounter_champion.inc similarity index 97% rename from sound/voicegroups/voicegroup100.inc rename to sound/voicegroups/encounter_champion.inc index 577d05c354..f6f9e64b25 100644 --- a/sound/voicegroups/voicegroup100.inc +++ b/sound/voicegroups/encounter_champion.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup100:: - voice_keysplit_all voicegroup001 +voice_group encounter_champion + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup100:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup063.inc b/sound/voicegroups/encounter_cool.inc similarity index 97% rename from sound/voicegroups/voicegroup063.inc rename to sound/voicegroups/encounter_cool.inc index 966ae20809..6dbf63464a 100644 --- a/sound/voicegroups/voicegroup063.inc +++ b/sound/voicegroups/encounter_cool.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup063:: - voice_keysplit_all voicegroup001 +voice_group encounter_cool + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup063:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup096.inc b/sound/voicegroups/encounter_elite_four.inc similarity index 97% rename from sound/voicegroups/voicegroup096.inc rename to sound/voicegroups/encounter_elite_four.inc index b0cb653caf..131a04ece7 100644 --- a/sound/voicegroups/voicegroup096.inc +++ b/sound/voicegroups/encounter_elite_four.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup096:: - voice_keysplit_all voicegroup001 +voice_group encounter_elite_four + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup096:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup053.inc b/sound/voicegroups/encounter_female.inc similarity index 96% rename from sound/voicegroups/voicegroup053.inc rename to sound/voicegroups/encounter_female.inc index e5f1a4d7e8..cae41b553a 100644 --- a/sound/voicegroups/voicegroup053.inc +++ b/sound/voicegroups/encounter_female.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup053:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group encounter_female + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup053:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup027.inc b/sound/voicegroups/encounter_girl.inc similarity index 97% rename from sound/voicegroups/voicegroup027.inc rename to sound/voicegroups/encounter_girl.inc index 517ee87d43..850b020bc7 100644 --- a/sound/voicegroups/voicegroup027.inc +++ b/sound/voicegroups/encounter_girl.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup027:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group encounter_girl + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup097.inc b/sound/voicegroups/encounter_hiker.inc similarity index 95% rename from sound/voicegroups/voicegroup097.inc rename to sound/voicegroups/encounter_hiker.inc index fb0542dac6..5c799ecacc 100644 --- a/sound/voicegroups/voicegroup097.inc +++ b/sound/voicegroups/encounter_hiker.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup097:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group encounter_hiker + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup097:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup062.inc b/sound/voicegroups/encounter_intense.inc similarity index 97% rename from sound/voicegroups/voicegroup062.inc rename to sound/voicegroups/encounter_intense.inc index ad2e6cad7f..3ac97d2b21 100644 --- a/sound/voicegroups/voicegroup062.inc +++ b/sound/voicegroups/encounter_intense.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup062:: - voice_keysplit_all voicegroup001 +voice_group encounter_intense + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup062:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup099.inc b/sound/voicegroups/encounter_interviewer.inc similarity index 97% rename from sound/voicegroups/voicegroup099.inc rename to sound/voicegroups/encounter_interviewer.inc index e750f95831..0a6d62e3b9 100644 --- a/sound/voicegroups/voicegroup099.inc +++ b/sound/voicegroups/encounter_interviewer.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup099:: - voice_keysplit_all voicegroup001 +voice_group encounter_interviewer + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup099:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup087.inc b/sound/voicegroups/encounter_magma.inc similarity index 96% rename from sound/voicegroups/voicegroup087.inc rename to sound/voicegroups/encounter_magma.inc index 1ccb69ea55..fa77bd2ebd 100644 --- a/sound/voicegroups/voicegroup087.inc +++ b/sound/voicegroups/encounter_magma.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup087:: - voice_keysplit_all voicegroup001 +voice_group encounter_magma + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup087:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup028.inc b/sound/voicegroups/encounter_male.inc similarity index 96% rename from sound/voicegroups/voicegroup028.inc rename to sound/voicegroups/encounter_male.inc index 9af19f1879..fd2da689e6 100644 --- a/sound/voicegroups/voicegroup028.inc +++ b/sound/voicegroups/encounter_male.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup028:: - voice_keysplit_all voicegroup001 +voice_group encounter_male + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 3, 0, 1, 0, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup028:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup061.inc b/sound/voicegroups/encounter_may.inc similarity index 97% rename from sound/voicegroups/voicegroup061.inc rename to sound/voicegroups/encounter_may.inc index d73730ecbc..cf909245e2 100644 --- a/sound/voicegroups/voicegroup061.inc +++ b/sound/voicegroups/encounter_may.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup061:: - voice_keysplit_all voicegroup001 +voice_group encounter_may + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup061:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup043.inc b/sound/voicegroups/encounter_rich.inc similarity index 94% rename from sound/voicegroups/voicegroup043.inc rename to sound/voicegroups/encounter_rich.inc index d6bd30bcba..7ae524d2bb 100644 --- a/sound/voicegroups/voicegroup043.inc +++ b/sound/voicegroups/encounter_rich.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup043:: +voice_group encounter_rich voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup043:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,7 +57,7 @@ voicegroup043:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup069.inc b/sound/voicegroups/encounter_suspicious.inc similarity index 96% rename from sound/voicegroups/voicegroup069.inc rename to sound/voicegroups/encounter_suspicious.inc index 26ea294051..4722f618d3 100644 --- a/sound/voicegroups/voicegroup069.inc +++ b/sound/voicegroups/encounter_suspicious.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup069:: - voice_keysplit_all voicegroup001 +voice_group encounter_suspicious + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup069:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,7 +57,7 @@ voicegroup069:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup036.inc b/sound/voicegroups/encounter_swimmer.inc similarity index 96% rename from sound/voicegroups/voicegroup036.inc rename to sound/voicegroups/encounter_swimmer.inc index c3d2df146c..de50110ac1 100644 --- a/sound/voicegroups/voicegroup036.inc +++ b/sound/voicegroups/encounter_swimmer.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup036:: - voice_keysplit_all voicegroup001 +voice_group encounter_swimmer + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup036:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup036:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup095.inc b/sound/voicegroups/encounter_twins.inc similarity index 98% rename from sound/voicegroups/voicegroup095.inc rename to sound/voicegroups/encounter_twins.inc index 96b531f8ed..be0a7d70e9 100644 --- a/sound/voicegroups/voicegroup095.inc +++ b/sound/voicegroups/encounter_twins.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup095:: - voice_keysplit_all voicegroup001 +voice_group encounter_twins + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup102.inc b/sound/voicegroups/end.inc similarity index 99% rename from sound/voicegroups/voicegroup102.inc rename to sound/voicegroups/end.inc index 197ed891be..07da4dfad0 100644 --- a/sound/voicegroups/voicegroup102.inc +++ b/sound/voicegroups/end.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup102:: +voice_group end voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup068.inc b/sound/voicegroups/ever_grande.inc similarity index 96% rename from sound/voicegroups/voicegroup068.inc rename to sound/voicegroups/ever_grande.inc index 787ce997b7..1fe7110529 100644 --- a/sound/voicegroups/voicegroup068.inc +++ b/sound/voicegroups/ever_grande.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup068:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group ever_grande + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup068:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup026.inc b/sound/voicegroups/evolution.inc similarity index 96% rename from sound/voicegroups/voicegroup026.inc rename to sound/voicegroups/evolution.inc index d18047d582..5ccefa3dbe 100644 --- a/sound/voicegroups/voicegroup026.inc +++ b/sound/voicegroups/evolution.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup026:: - voice_keysplit_all voicegroup001 +voice_group evolution + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup026:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup083.inc b/sound/voicegroups/fallarbor.inc similarity index 92% rename from sound/voicegroups/voicegroup083.inc rename to sound/voicegroups/fallarbor.inc index 4f2fcd809f..f129e5094a 100644 --- a/sound/voicegroups/voicegroup083.inc +++ b/sound/voicegroups/fallarbor.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup083:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group fallarbor + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup083:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup083:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup012.inc b/sound/voicegroups/fanfare.inc similarity index 92% rename from sound/voicegroups/voicegroup012.inc rename to sound/voicegroups/fanfare.inc index 2fe7cf8180..caaeaf40e5 100644 --- a/sound/voicegroups/voicegroup012.inc +++ b/sound/voicegroups/fanfare.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup012:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group fanfare + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_directsound 60, 0, DirectSoundWaveData_trinity_30303_mega_bass, 255, 178, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup012:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup012:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup066.inc b/sound/voicegroups/follow_me.inc similarity index 98% rename from sound/voicegroups/voicegroup066.inc rename to sound/voicegroups/follow_me.inc index af4a7f8410..d1b4297392 100644 --- a/sound/voicegroups/voicegroup066.inc +++ b/sound/voicegroups/follow_me.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup066:: - voice_keysplit_all voicegroup001 +voice_group follow_me + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup032.inc b/sound/voicegroups/fortree.inc similarity index 97% rename from sound/voicegroups/voicegroup032.inc rename to sound/voicegroups/fortree.inc index dc60bbdf3b..0c4d0281d3 100644 --- a/sound/voicegroups/voicegroup032.inc +++ b/sound/voicegroups/fortree.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup032:: - voice_keysplit_all voicegroup016 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group fortree + voice_keysplit_all voicegroup_petalburg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup129.inc b/sound/voicegroups/frlg_sfx.inc similarity index 98% rename from sound/voicegroups/voicegroup129.inc rename to sound/voicegroups/frlg_sfx.inc index 8e136bdf48..44a933ac1c 100644 --- a/sound/voicegroups/voicegroup129.inc +++ b/sound/voicegroups/frlg_sfx.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup129:: +voice_group frlg_sfx voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 @@ -58,7 +57,7 @@ voicegroup129:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup072.inc b/sound/voicegroups/game_corner.inc similarity index 94% rename from sound/voicegroups/voicegroup072.inc rename to sound/voicegroups/game_corner.inc index 50fa4e4cfa..9a06e577f4 100644 --- a/sound/voicegroups/voicegroup072.inc +++ b/sound/voicegroups/game_corner.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup072:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group game_corner + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup072:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup072:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup013.inc b/sound/voicegroups/gym.inc similarity index 93% rename from sound/voicegroups/voicegroup013.inc rename to sound/voicegroups/gym.inc index f99c6f3cdc..715abccf18 100644 --- a/sound/voicegroups/voicegroup013.inc +++ b/sound/voicegroups/gym.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup013:: - voice_keysplit_all voicegroup001 +voice_group gym + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup013:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup013:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup082.inc b/sound/voicegroups/hall_of_fame.inc similarity index 94% rename from sound/voicegroups/voicegroup082.inc rename to sound/voicegroups/hall_of_fame.inc index b6b5506f1a..6e831e4c2b 100644 --- a/sound/voicegroups/voicegroup082.inc +++ b/sound/voicegroups/hall_of_fame.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup082:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group hall_of_fame + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup082:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup082:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup093.inc b/sound/voicegroups/hall_of_fame_room.inc similarity index 95% rename from sound/voicegroups/voicegroup093.inc rename to sound/voicegroups/hall_of_fame_room.inc index 8cea357335..efbc1a4f33 100644 --- a/sound/voicegroups/voicegroup093.inc +++ b/sound/voicegroups/hall_of_fame_room.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup093:: - voice_keysplit_all voicegroup001 +voice_group hall_of_fame_room + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup093:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup093:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup056.inc b/sound/voicegroups/help.inc similarity index 96% rename from sound/voicegroups/voicegroup056.inc rename to sound/voicegroups/help.inc index ec543b9b33..d7530853c5 100644 --- a/sound/voicegroups/voicegroup056.inc +++ b/sound/voicegroups/help.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup056:: - voice_keysplit_all voicegroup001 +voice_group help + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup056:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup056:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup060.inc b/sound/voicegroups/intro.inc similarity index 93% rename from sound/voicegroups/voicegroup060.inc rename to sound/voicegroups/intro.inc index 448841e625..3a1a123cc4 100644 --- a/sound/voicegroups/voicegroup060.inc +++ b/sound/voicegroups/intro.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup060:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group intro + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup060:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 128, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup060:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup088.inc b/sound/voicegroups/intro_battle.inc similarity index 93% rename from sound/voicegroups/voicegroup088.inc rename to sound/voicegroups/intro_battle.inc index 8f6f216884..a01918d871 100644 --- a/sound/voicegroups/voicegroup088.inc +++ b/sound/voicegroups/intro_battle.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup088:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group intro_battle + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 1, 1, 1, 6, 2 @@ -48,7 +47,7 @@ voicegroup088:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup088:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup009.inc b/sound/voicegroups/keysplits/french_horn.inc similarity index 84% rename from sound/voicegroups/voicegroup009.inc rename to sound/voicegroups/keysplits/french_horn.inc index 4a51a02ca3..193fa3957c 100644 --- a/sound/voicegroups/voicegroup009.inc +++ b/sound/voicegroups/keysplits/french_horn.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup009:: +voice_group french_horn_keysplit voice_directsound 60, 0, DirectSoundWaveData_sc88pro_french_horn_60, 255, 0, 224, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_french_horn_72, 255, 0, 218, 165 diff --git a/sound/voicegroups/voicegroup005.inc b/sound/voicegroups/keysplits/piano.inc similarity index 92% rename from sound/voicegroups/voicegroup005.inc rename to sound/voicegroups/keysplits/piano.inc index 584451a62f..93484ea8b2 100644 --- a/sound/voicegroups/voicegroup005.inc +++ b/sound/voicegroups/keysplits/piano.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup005:: +voice_group piano_keysplit voice_directsound 60, 0, DirectSoundWaveData_sc88pro_piano1_48, 255, 252, 0, 239 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_piano1_60, 255, 250, 0, 221 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_piano1_72, 255, 250, 0, 221 diff --git a/sound/voicegroups/voicegroup006.inc b/sound/voicegroups/keysplits/strings.inc similarity index 90% rename from sound/voicegroups/voicegroup006.inc rename to sound/voicegroups/keysplits/strings.inc index 52b2b335f2..27e445e359 100644 --- a/sound/voicegroups/voicegroup006.inc +++ b/sound/voicegroups/keysplits/strings.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup006:: +voice_group strings_keysplit voice_directsound 60, 0, DirectSoundWaveData_sc88pro_string_ensemble_60, 255, 0, 255, 196 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_string_ensemble_72, 255, 0, 255, 196 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_string_ensemble_84, 255, 0, 255, 196 diff --git a/sound/voicegroups/keysplits/trumpet.inc b/sound/voicegroups/keysplits/trumpet.inc new file mode 100644 index 0000000000..eb38b7de74 --- /dev/null +++ b/sound/voicegroups/keysplits/trumpet.inc @@ -0,0 +1,5 @@ +voice_group trumpet_keysplit + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_60, 255, 0, 193, 127 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_72, 255, 0, 193, 127 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_84, 255, 0, 193, 127 + diff --git a/sound/voicegroups/voicegroup008.inc b/sound/voicegroups/keysplits/tuba.inc similarity index 86% rename from sound/voicegroups/voicegroup008.inc rename to sound/voicegroups/keysplits/tuba.inc index 7fc874e87a..5d00a8000a 100644 --- a/sound/voicegroups/voicegroup008.inc +++ b/sound/voicegroups/keysplits/tuba.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup008:: +voice_group tuba_keysplit voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tuba_39, 255, 0, 255, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tuba_51, 255, 0, 255, 165 diff --git a/sound/voicegroups/voicegroup054.inc b/sound/voicegroups/lilycove.inc similarity index 95% rename from sound/voicegroups/voicegroup054.inc rename to sound/voicegroups/lilycove.inc index ddd17ed995..d016db496f 100644 --- a/sound/voicegroups/voicegroup054.inc +++ b/sound/voicegroups/lilycove.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup054:: - voice_keysplit_all voicegroup001 +voice_group lilycove + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup054:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup054:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup020.inc b/sound/voicegroups/lilycove_museum.inc similarity index 94% rename from sound/voicegroups/voicegroup020.inc rename to sound/voicegroups/lilycove_museum.inc index 8449fbdd60..ab9c5d3bd5 100644 --- a/sound/voicegroups/voicegroup020.inc +++ b/sound/voicegroups/lilycove_museum.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup020:: - voice_keysplit voicegroup005, KeySplitTable1 +voice_group lilycove_museum + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup020:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,7 +57,7 @@ voicegroup020:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup041.inc b/sound/voicegroups/link_contest_p1.inc similarity index 95% rename from sound/voicegroups/voicegroup041.inc rename to sound/voicegroups/link_contest_p1.inc index def4e46b00..aae277742f 100644 --- a/sound/voicegroups/voicegroup041.inc +++ b/sound/voicegroups/link_contest_p1.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup041:: - voice_keysplit_all voicegroup001 +voice_group link_contest_p1 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup041:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup041:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup040.inc b/sound/voicegroups/link_contest_p2.inc similarity index 95% rename from sound/voicegroups/voicegroup040.inc rename to sound/voicegroups/link_contest_p2.inc index f390cb3d85..bfbfcb9090 100644 --- a/sound/voicegroups/voicegroup040.inc +++ b/sound/voicegroups/link_contest_p2.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup040:: - voice_keysplit_all voicegroup001 +voice_group link_contest_p2 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup040:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup040:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup042.inc b/sound/voicegroups/link_contest_p3.inc similarity index 95% rename from sound/voicegroups/voicegroup042.inc rename to sound/voicegroups/link_contest_p3.inc index 1298ddbd52..ef038d5dd6 100644 --- a/sound/voicegroups/voicegroup042.inc +++ b/sound/voicegroups/link_contest_p3.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup042:: - voice_keysplit_all voicegroup001 +voice_group link_contest_p3 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup042:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup042:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup039.inc b/sound/voicegroups/link_contest_p4.inc similarity index 95% rename from sound/voicegroups/voicegroup039.inc rename to sound/voicegroups/link_contest_p4.inc index 9e8d16df0b..235ebb1d9a 100644 --- a/sound/voicegroups/voicegroup039.inc +++ b/sound/voicegroups/link_contest_p4.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup039:: - voice_keysplit_all voicegroup001 +voice_group link_contest_p4 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup039:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup039:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup051.inc b/sound/voicegroups/littleroot.inc similarity index 94% rename from sound/voicegroups/voicegroup051.inc rename to sound/voicegroups/littleroot.inc index d3a144622a..594f7202f3 100644 --- a/sound/voicegroups/voicegroup051.inc +++ b/sound/voicegroups/littleroot.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup051:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group littleroot + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 2, 1, 4, 4, 2 @@ -48,7 +47,7 @@ voicegroup051:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 99 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup034.inc b/sound/voicegroups/littleroot_test.inc similarity index 94% rename from sound/voicegroups/voicegroup034.inc rename to sound/voicegroups/littleroot_test.inc index fe973b84c3..e094ed33fa 100644 --- a/sound/voicegroups/voicegroup034.inc +++ b/sound/voicegroups/littleroot_test.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup034:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group littleroot_test + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 1, 4, 2 @@ -48,7 +47,7 @@ voicegroup034:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup052.inc b/sound/voicegroups/mt_chimney.inc similarity index 94% rename from sound/voicegroups/voicegroup052.inc rename to sound/voicegroups/mt_chimney.inc index 438e2d5f17..b4de7d7ac6 100644 --- a/sound/voicegroups/voicegroup052.inc +++ b/sound/voicegroups/mt_chimney.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup052:: - voice_keysplit_all voicegroup001 +voice_group mt_chimney + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 3, 1, 2, 6, 0 voice_square_2 60, 0, 3, 1, 2, 6, 0 @@ -48,7 +47,7 @@ voicegroup052:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup052:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup078.inc b/sound/voicegroups/mt_pyre.inc similarity index 96% rename from sound/voicegroups/voicegroup078.inc rename to sound/voicegroups/mt_pyre.inc index e3ef10feb7..402b222ccd 100644 --- a/sound/voicegroups/voicegroup078.inc +++ b/sound/voicegroups/mt_pyre.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup078:: - voice_keysplit_all voicegroup001 +voice_group mt_pyre + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup078:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup078:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup080.inc b/sound/voicegroups/mt_pyre_exterior.inc similarity index 96% rename from sound/voicegroups/voicegroup080.inc rename to sound/voicegroups/mt_pyre_exterior.inc index 6d627ad92e..e7336bf2c6 100644 --- a/sound/voicegroups/voicegroup080.inc +++ b/sound/voicegroups/mt_pyre_exterior.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup080:: - voice_keysplit_all voicegroup001 +voice_group mt_pyre_exterior + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup080:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup080:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup023.inc b/sound/voicegroups/oceanic_museum.inc similarity index 93% rename from sound/voicegroups/voicegroup023.inc rename to sound/voicegroups/oceanic_museum.inc index eede8dc019..422bc6d776 100644 --- a/sound/voicegroups/voicegroup023.inc +++ b/sound/voicegroups/oceanic_museum.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup023:: - voice_keysplit voicegroup005, KeySplitTable1 - voice_keysplit_all voicegroup001 +voice_group oceanic_museum + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup023:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup023:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup019.inc b/sound/voicegroups/oldale.inc similarity index 94% rename from sound/voicegroups/voicegroup019.inc rename to sound/voicegroups/oldale.inc index a983659c39..0ecc1f9d2b 100644 --- a/sound/voicegroups/voicegroup019.inc +++ b/sound/voicegroups/oldale.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup019:: +voice_group oldale voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup019:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup019:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/petalburg.inc b/sound/voicegroups/petalburg.inc new file mode 100644 index 0000000000..16abe3f128 --- /dev/null +++ b/sound/voicegroups/petalburg.inc @@ -0,0 +1,130 @@ +voice_group petalburg + voice_keysplit_all voicegroup_petalburg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2 60, 0, 3, 0, 2, 0, 0 + voice_square_1 60, 0, 0, 3, 0, 2, 0, 0 + voice_square_2 60, 0, 3, 0, 6, 0, 0 + voice_square_1 60, 0, 0, 3, 0, 6, 0, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 149 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion, 255, 0, 255, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 + voice_programmable_wave 60, 0, ProgrammableWaveData_1, 0, 7, 15, 1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_3, 0, 7, 15, 2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_noise_alt 60, 0, 0, 0, 2, 0, 2 + voice_noise_alt 60, 0, 0, 0, 1, 0, 1 + diff --git a/sound/voicegroups/voicegroup018.inc b/sound/voicegroups/petalburg_woods.inc similarity index 96% rename from sound/voicegroups/voicegroup018.inc rename to sound/voicegroups/petalburg_woods.inc index 30b63bb26e..5cf1de28c8 100644 --- a/sound/voicegroups/voicegroup018.inc +++ b/sound/voicegroups/petalburg_woods.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup018:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group petalburg_woods + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 0, 0, 1, 7, 1 @@ -48,7 +47,7 @@ voicegroup018:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup046.inc b/sound/voicegroups/poke_center.inc similarity index 97% rename from sound/voicegroups/voicegroup046.inc rename to sound/voicegroups/poke_center.inc index f653241e35..6b14b67e7f 100644 --- a/sound/voicegroups/voicegroup046.inc +++ b/sound/voicegroups/poke_center.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup046:: - voice_keysplit voicegroup005, KeySplitTable1 +voice_group poke_center + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_14, 0, 1, 12, 0 voice_square_1_alt 60, 0, 0, 0, 1, 1, 9, 0 voice_square_2_alt 60, 0, 2, 0, 2, 6, 3 @@ -48,7 +47,7 @@ voicegroup046:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup050.inc b/sound/voicegroups/poke_mart.inc similarity index 97% rename from sound/voicegroups/voicegroup050.inc rename to sound/voicegroups/poke_mart.inc index 6b45664eb0..aaf53d83ad 100644 --- a/sound/voicegroups/voicegroup050.inc +++ b/sound/voicegroups/poke_mart.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup050:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group poke_mart + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup109.inc b/sound/voicegroups/rayquaza_appears.inc similarity index 97% rename from sound/voicegroups/voicegroup109.inc rename to sound/voicegroups/rayquaza_appears.inc index a999143737..f7cddd3881 100644 --- a/sound/voicegroups/voicegroup109.inc +++ b/sound/voicegroups/rayquaza_appears.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup109:: - voice_keysplit_all voicegroup004 +voice_group rayquaza_appears + voice_keysplit_all voicegroup_emerald_drumset_2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup105.inc b/sound/voicegroups/register_match_call.inc similarity index 97% rename from sound/voicegroups/voicegroup105.inc rename to sound/voicegroups/register_match_call.inc index a1a1bc2d61..b35b30fb36 100644 --- a/sound/voicegroups/voicegroup105.inc +++ b/sound/voicegroups/register_match_call.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup105:: - voice_keysplit_all voicegroup002 +voice_group register_match_call + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup179.inc b/sound/voicegroups/rg_caught_intro.inc similarity index 88% rename from sound/voicegroups/voicegroup179.inc rename to sound/voicegroups/rg_caught_intro.inc index e69cace5b8..c3719d9c02 100644 --- a/sound/voicegroups/voicegroup179.inc +++ b/sound/voicegroups/rg_caught_intro.inc @@ -1,8 +1,7 @@ - .align 2 -voicegroup179:: - voice_keysplit_all voicegroup177 - voice_keysplit_all voicegroup176 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_caught_intro + voice_keysplit_all voicegroup_frlg_fanfare_drumset_1 + voice_keysplit_all voicegroup_frlg_fanfare_drumset_2 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup179:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup179:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup168.inc b/sound/voicegroups/rg_celadon.inc similarity index 95% rename from sound/voicegroups/voicegroup168.inc rename to sound/voicegroups/rg_celadon.inc index ea6b59d2ef..91efdad253 100644 --- a/sound/voicegroups/voicegroup168.inc +++ b/sound/voicegroups/rg_celadon.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup168:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_celadon + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup168:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup168:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup138.inc b/sound/voicegroups/rg_cinnabar.inc similarity index 95% rename from sound/voicegroups/voicegroup138.inc rename to sound/voicegroups/rg_cinnabar.inc index 227538f5dc..c527c0bf6c 100644 --- a/sound/voicegroups/voicegroup138.inc +++ b/sound/voicegroups/rg_cinnabar.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup138:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_cinnabar + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup138:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup138:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup149.inc b/sound/voicegroups/rg_credits.inc similarity index 91% rename from sound/voicegroups/voicegroup149.inc rename to sound/voicegroups/rg_credits.inc index c0239fef95..6d16fee802 100644 --- a/sound/voicegroups/voicegroup149.inc +++ b/sound/voicegroups/rg_credits.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup149:: - voice_keysplit_all voicegroup190 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_credits + voice_keysplit_all voicegroup_rg_credits_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1_alt 60, 0, 0, 2, 0, 0, 12, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup149:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 165, 154, 153 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup149:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup141.inc b/sound/voicegroups/rg_cycling.inc similarity index 95% rename from sound/voicegroups/voicegroup141.inc rename to sound/voicegroups/rg_cycling.inc index 1e556a21b6..a693dd36f6 100644 --- a/sound/voicegroups/voicegroup141.inc +++ b/sound/voicegroups/rg_cycling.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup141:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_cycling + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup141:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup141:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_dex_rating.inc b/sound/voicegroups/rg_dex_rating.inc new file mode 100644 index 0000000000..b349e6a132 --- /dev/null +++ b/sound/voicegroups/rg_dex_rating.inc @@ -0,0 +1,90 @@ +voice_group rg_dex_rating + voice_keysplit_all voicegroup_frlg_fanfare_drumset_1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_xylophone, 255, 235, 0, 204 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 85, 165, 154, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1_alt 60, 0, 0, 2, 0, 2, 7, 1 + voice_square_2_alt 60, 0, 2, 0, 2, 9, 1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_1, 0, 7, 15, 0 + diff --git a/sound/voicegroups/voicegroup144.inc b/sound/voicegroups/rg_encounter_boy.inc similarity index 96% rename from sound/voicegroups/voicegroup144.inc rename to sound/voicegroups/rg_encounter_boy.inc index 87830a387b..34447dc15e 100644 --- a/sound/voicegroups/voicegroup144.inc +++ b/sound/voicegroups/rg_encounter_boy.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup144:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_encounter_boy + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup144:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup184.inc b/sound/voicegroups/rg_encounter_deoxys.inc similarity index 99% rename from sound/voicegroups/voicegroup184.inc rename to sound/voicegroups/rg_encounter_deoxys.inc index 86f392e65c..7b7fd5bd98 100644 --- a/sound/voicegroups/voicegroup184.inc +++ b/sound/voicegroups/rg_encounter_deoxys.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup184:: +voice_group rg_encounter_deoxys voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup143.inc b/sound/voicegroups/rg_encounter_girl.inc similarity index 96% rename from sound/voicegroups/voicegroup143.inc rename to sound/voicegroups/rg_encounter_girl.inc index 9cb286ac13..101e2d3641 100644 --- a/sound/voicegroups/voicegroup143.inc +++ b/sound/voicegroups/rg_encounter_girl.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup143:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_encounter_girl + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup143:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_encounter_rival.inc b/sound/voicegroups/rg_encounter_rival.inc new file mode 100644 index 0000000000..3b918569e2 --- /dev/null +++ b/sound/voicegroups/rg_encounter_rival.inc @@ -0,0 +1,130 @@ +voice_group rg_encounter_rival + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 255, 0, 255, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion, 255, 0, 255, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_overdrive_guitar, 128, 0, 255, 214 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_high, 128, 0, 255, 206 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_synth_bass, 255, 252, 0, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 209 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1_alt 60, 0, 0, 3, 0, 2, 3, 4 + voice_square_2_alt 60, 0, 3, 0, 2, 3, 4 + voice_square_1_alt 60, 0, 0, 3, 0, 2, 3, 4 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_2, 0, 7, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_special_scream_drive, 255, 0, 255, 165 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_noise_alt 60, 0, 0, 0, 2, 6, 0 + voice_noise_alt 60, 0, 0, 0, 1, 3, 1 + diff --git a/sound/voicegroups/voicegroup142.inc b/sound/voicegroups/rg_encounter_rocket.inc similarity index 98% rename from sound/voicegroups/voicegroup142.inc rename to sound/voicegroups/rg_encounter_rocket.inc index af5b809bf8..69fd532a0e 100644 --- a/sound/voicegroups/voicegroup142.inc +++ b/sound/voicegroups/rg_encounter_rocket.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup142:: - voice_keysplit_all voicegroup002 +voice_group rg_encounter_rocket + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup131.inc b/sound/voicegroups/rg_follow_me.inc similarity index 97% rename from sound/voicegroups/voicegroup131.inc rename to sound/voicegroups/rg_follow_me.inc index 029afa5be5..198cef9680 100644 --- a/sound/voicegroups/voicegroup131.inc +++ b/sound/voicegroups/rg_follow_me.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup131:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_follow_me + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_directsound 60, 0, DirectSoundWaveData_steinway_b_piano, 128, 204, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup167.inc b/sound/voicegroups/rg_fuchsia.inc similarity index 97% rename from sound/voicegroups/voicegroup167.inc rename to sound/voicegroups/rg_fuchsia.inc index 0213b7aec0..fd41166c1d 100644 --- a/sound/voicegroups/voicegroup167.inc +++ b/sound/voicegroups/rg_fuchsia.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup167:: - voice_keysplit_all voicegroup002 +voice_group rg_fuchsia + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup167:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup132.inc b/sound/voicegroups/rg_game_corner.inc similarity index 94% rename from sound/voicegroups/voicegroup132.inc rename to sound/voicegroups/rg_game_corner.inc index 2806916bca..aee7c99a15 100644 --- a/sound/voicegroups/voicegroup132.inc +++ b/sound/voicegroups/rg_game_corner.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup132:: - voice_keysplit_all voicegroup002 +voice_group rg_game_corner + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup132:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 165, 154, 235 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup132:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup181.inc b/sound/voicegroups/rg_game_freak.inc similarity index 95% rename from sound/voicegroups/voicegroup181.inc rename to sound/voicegroups/rg_game_freak.inc index 92df8710a8..98e0cad897 100644 --- a/sound/voicegroups/voicegroup181.inc +++ b/sound/voicegroups/rg_game_freak.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup181:: +voice_group rg_game_freak voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup134.inc b/sound/voicegroups/rg_gym.inc similarity index 93% rename from sound/voicegroups/voicegroup134.inc rename to sound/voicegroups/rg_gym.inc index 1bc01fed07..cc85606a66 100644 --- a/sound/voicegroups/voicegroup134.inc +++ b/sound/voicegroups/rg_gym.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup134:: - voice_keysplit_all voicegroup001 +voice_group rg_gym + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup134:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup134:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup145.inc b/sound/voicegroups/rg_hall_of_fame.inc similarity index 95% rename from sound/voicegroups/voicegroup145.inc rename to sound/voicegroups/rg_hall_of_fame.inc index 96cda70e48..e9539c8fa9 100644 --- a/sound/voicegroups/voicegroup145.inc +++ b/sound/voicegroups/rg_hall_of_fame.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup145:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_hall_of_fame + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup145:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup145:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup140.inc b/sound/voicegroups/rg_heal.inc similarity index 71% rename from sound/voicegroups/voicegroup140.inc rename to sound/voicegroups/rg_heal.inc index 8206cca1d2..01efe859ed 100644 --- a/sound/voicegroups/voicegroup140.inc +++ b/sound/voicegroups/rg_heal.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup140:: - voice_keysplit_all voicegroup001 +voice_group rg_heal + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 2, 3, 1 voice_square_2_alt 60, 0, 2, 0, 2, 3, 1 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 diff --git a/sound/voicegroups/voicegroup136.inc b/sound/voicegroups/rg_intro_fight.inc similarity index 96% rename from sound/voicegroups/voicegroup136.inc rename to sound/voicegroups/rg_intro_fight.inc index 0428c8c004..5476348ca2 100644 --- a/sound/voicegroups/voicegroup136.inc +++ b/sound/voicegroups/rg_intro_fight.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup136:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_intro_fight + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup136:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup135.inc b/sound/voicegroups/rg_jigglypuff.inc similarity index 97% rename from sound/voicegroups/voicegroup135.inc rename to sound/voicegroups/rg_jigglypuff.inc index 2ea22bf969..8c0abfcb10 100644 --- a/sound/voicegroups/voicegroup135.inc +++ b/sound/voicegroups/rg_jigglypuff.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup135:: - voice_keysplit_all voicegroup002 +voice_group rg_jigglypuff + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup139.inc b/sound/voicegroups/rg_lavender.inc similarity index 94% rename from sound/voicegroups/voicegroup139.inc rename to sound/voicegroups/rg_lavender.inc index e8969de570..f5707972cd 100644 --- a/sound/voicegroups/voicegroup139.inc +++ b/sound/voicegroups/rg_lavender.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup139:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_lavender + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup139:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 226 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 2, 0, 2, 3, 1 voice_square_2_alt 60, 0, 3, 0, 2, 7, 2 @@ -58,9 +57,9 @@ voicegroup139:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup147.inc b/sound/voicegroups/rg_mt_moon.inc similarity index 94% rename from sound/voicegroups/voicegroup147.inc rename to sound/voicegroups/rg_mt_moon.inc index 4767815824..bb575cf50f 100644 --- a/sound/voicegroups/voicegroup147.inc +++ b/sound/voicegroups/rg_mt_moon.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup147:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_mt_moon + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup147:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup183.inc b/sound/voicegroups/rg_mystery_gift.inc similarity index 98% rename from sound/voicegroups/voicegroup183.inc rename to sound/voicegroups/rg_mystery_gift.inc index ff49e3763b..8f26abe0e0 100644 --- a/sound/voicegroups/voicegroup183.inc +++ b/sound/voicegroups/rg_mystery_gift.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup183:: - voice_keysplit_all voicegroup002 +voice_group rg_mystery_gift + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup182.inc b/sound/voicegroups/rg_new_game.inc similarity index 91% rename from sound/voicegroups/voicegroup182.inc rename to sound/voicegroups/rg_new_game.inc index ec39554958..3206ae717d 100644 --- a/sound/voicegroups/voicegroup182.inc +++ b/sound/voicegroups/rg_new_game.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup182:: - voice_keysplit_all voicegroup002 +voice_group rg_new_game + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup182:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 76 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup182:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup161.inc b/sound/voicegroups/rg_oak.inc similarity index 94% rename from sound/voicegroups/voicegroup161.inc rename to sound/voicegroups/rg_oak.inc index c334fa2647..5965bc59fb 100644 --- a/sound/voicegroups/voicegroup161.inc +++ b/sound/voicegroups/rg_oak.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup161:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_oak + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup161:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup161:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup160.inc b/sound/voicegroups/rg_oak_lab.inc similarity index 96% rename from sound/voicegroups/voicegroup160.inc rename to sound/voicegroups/rg_oak_lab.inc index 160d0cad8f..40352f6060 100644 --- a/sound/voicegroups/voicegroup160.inc +++ b/sound/voicegroups/rg_oak_lab.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup160:: - voice_keysplit_all voicegroup001 +voice_group rg_oak_lab + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup160:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup178.inc b/sound/voicegroups/rg_obtain_key_item.inc similarity index 97% rename from sound/voicegroups/voicegroup178.inc rename to sound/voicegroups/rg_obtain_key_item.inc index 026d7bb3d8..e9f2bc0078 100644 --- a/sound/voicegroups/voicegroup178.inc +++ b/sound/voicegroups/rg_obtain_key_item.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup178:: - voice_keysplit_all voicegroup177 +voice_group rg_obtain_key_item + voice_keysplit_all voicegroup_frlg_fanfare_drumset_1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup159.inc b/sound/voicegroups/rg_pallet.inc similarity index 98% rename from sound/voicegroups/voicegroup159.inc rename to sound/voicegroups/rg_pallet.inc index f1d2046560..ccd491e720 100644 --- a/sound/voicegroups/voicegroup159.inc +++ b/sound/voicegroups/rg_pallet.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup159:: +voice_group rg_pallet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup159:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup173.inc b/sound/voicegroups/rg_pewter.inc similarity index 96% rename from sound/voicegroups/voicegroup173.inc rename to sound/voicegroups/rg_pewter.inc index 46979c6258..e986eafa65 100644 --- a/sound/voicegroups/voicegroup173.inc +++ b/sound/voicegroups/rg_pewter.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup173:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_pewter + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup173:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup180.inc b/sound/voicegroups/rg_photo.inc similarity index 98% rename from sound/voicegroups/voicegroup180.inc rename to sound/voicegroups/rg_photo.inc index ea182d38e5..88177033bb 100644 --- a/sound/voicegroups/voicegroup180.inc +++ b/sound/voicegroups/rg_photo.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup180:: +voice_group rg_photo voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 64, 249, 0, 188 diff --git a/sound/voicegroups/voicegroup162.inc b/sound/voicegroups/rg_poke_center.inc similarity index 96% rename from sound/voicegroups/voicegroup162.inc rename to sound/voicegroups/rg_poke_center.inc index 3a532b23ee..a66f7b2bb4 100644 --- a/sound/voicegroups/voicegroup162.inc +++ b/sound/voicegroups/rg_poke_center.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup162:: - voice_keysplit_all voicegroup002 +voice_group rg_poke_center + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup162:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup148.inc b/sound/voicegroups/rg_poke_mansion.inc similarity index 96% rename from sound/voicegroups/voicegroup148.inc rename to sound/voicegroups/rg_poke_mansion.inc index 4fc324df88..6e2ca3c56e 100644 --- a/sound/voicegroups/voicegroup148.inc +++ b/sound/voicegroups/rg_poke_mansion.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup148:: - voice_keysplit_all voicegroup002 +voice_group rg_poke_mansion + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup148:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,7 +57,7 @@ voicegroup148:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup165.inc b/sound/voicegroups/rg_poke_tower.inc similarity index 94% rename from sound/voicegroups/voicegroup165.inc rename to sound/voicegroups/rg_poke_tower.inc index c3262766cb..e815316240 100644 --- a/sound/voicegroups/voicegroup165.inc +++ b/sound/voicegroups/rg_poke_tower.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup165:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_poke_tower + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup165:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 226 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 2, 0, 2, 10, 1 voice_square_2_alt 60, 0, 2, 0, 2, 6, 6 @@ -58,9 +57,9 @@ voicegroup165:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup133.inc b/sound/voicegroups/rg_rocket_hideout.inc similarity index 94% rename from sound/voicegroups/voicegroup133.inc rename to sound/voicegroups/rg_rocket_hideout.inc index be70f6ae33..b84e5ee17a 100644 --- a/sound/voicegroups/voicegroup133.inc +++ b/sound/voicegroups/rg_rocket_hideout.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup133:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_rocket_hideout + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup133:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup133:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup150.inc b/sound/voicegroups/rg_route1.inc similarity index 98% rename from sound/voicegroups/voicegroup150.inc rename to sound/voicegroups/rg_route1.inc index c51150d782..237e091282 100644 --- a/sound/voicegroups/voicegroup150.inc +++ b/sound/voicegroups/rg_route1.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup150:: - voice_keysplit_all voicegroup002 +voice_group rg_route1 + voice_keysplit_all voicegroup_frlg_drumset voice_directsound 60, 0, DirectSoundWaveData_steinway_b_piano, 255, 165, 103, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup153.inc b/sound/voicegroups/rg_route11.inc similarity index 93% rename from sound/voicegroups/voicegroup153.inc rename to sound/voicegroups/rg_route11.inc index 7206c7ba3d..c166b346ba 100644 --- a/sound/voicegroups/voicegroup153.inc +++ b/sound/voicegroups/rg_route11.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup153:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_route11 + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup153:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup153:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup151.inc b/sound/voicegroups/rg_route24.inc similarity index 91% rename from sound/voicegroups/voicegroup151.inc rename to sound/voicegroups/rg_route24.inc index 29571169d6..e9e89db09e 100644 --- a/sound/voicegroups/voicegroup151.inc +++ b/sound/voicegroups/rg_route24.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup151:: - voice_keysplit_all voicegroup002 +voice_group rg_route24 + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup151:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 127 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup151:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup152.inc b/sound/voicegroups/rg_route3.inc similarity index 94% rename from sound/voicegroups/voicegroup152.inc rename to sound/voicegroups/rg_route3.inc index 06ccc3ae9d..0b49ff7fe2 100644 --- a/sound/voicegroups/voicegroup152.inc +++ b/sound/voicegroups/rg_route3.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup152:: - voice_keysplit_all voicegroup002 +voice_group rg_route3 + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup152:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup152:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup188.inc b/sound/voicegroups/rg_sevii_45.inc similarity index 96% rename from sound/voicegroups/voicegroup188.inc rename to sound/voicegroups/rg_sevii_45.inc index 8556bcd4d2..13b33f4af0 100644 --- a/sound/voicegroups/voicegroup188.inc +++ b/sound/voicegroups/rg_sevii_45.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup188:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_sevii_45 + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup188:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_sevii_67.inc b/sound/voicegroups/rg_sevii_67.inc new file mode 100644 index 0000000000..0804e0fc9c --- /dev/null +++ b/sound/voicegroups/rg_sevii_67.inc @@ -0,0 +1,130 @@ +voice_group rg_sevii_67 + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 + voice_directsound 60, 65, DirectSoundWaveData_sd90_classical_detuned_ep1_high, 128, 204, 77, 246 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tubular_bell, 255, 165, 90, 216 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 51, 0, 203, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 128, 249, 25, 127 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 64, 216, 51, 224 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 188 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1_alt 60, 0, 0, 2, 0, 2, 6, 3 + voice_square_2_alt 60, 0, 3, 0, 2, 7, 2 + voice_square_1_alt 60, 0, 0, 1, 0, 2, 6, 2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_1, 0, 7, 15, 2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_noise_alt 60, 0, 0, 0, 2, 7, 0 + voice_noise_alt 60, 0, 0, 0, 1, 9, 1 + diff --git a/sound/voicegroups/voicegroup187.inc b/sound/voicegroups/rg_sevii_route.inc similarity index 94% rename from sound/voicegroups/voicegroup187.inc rename to sound/voicegroups/rg_sevii_route.inc index 640912505a..48724cbe82 100644 --- a/sound/voicegroups/voicegroup187.inc +++ b/sound/voicegroups/rg_sevii_route.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup187:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_sevii_route + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup187:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup187:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup166.inc b/sound/voicegroups/rg_silph.inc similarity index 94% rename from sound/voicegroups/voicegroup166.inc rename to sound/voicegroups/rg_silph.inc index edd94624c0..20e2288942 100644 --- a/sound/voicegroups/voicegroup166.inc +++ b/sound/voicegroups/rg_silph.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup166:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_silph + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup166:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup166:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 236, 188 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup163.inc b/sound/voicegroups/rg_ss_anne.inc similarity index 95% rename from sound/voicegroups/voicegroup163.inc rename to sound/voicegroups/rg_ss_anne.inc index cd7c6ebef2..e69ac24ce2 100644 --- a/sound/voicegroups/voicegroup163.inc +++ b/sound/voicegroups/rg_ss_anne.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup163:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_ss_anne + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup163:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup163:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_unknown_18, 255, 0, 206, 204 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup164.inc b/sound/voicegroups/rg_surf.inc similarity index 96% rename from sound/voicegroups/voicegroup164.inc rename to sound/voicegroups/rg_surf.inc index d64cfd33ad..a8e63e46b0 100644 --- a/sound/voicegroups/voicegroup164.inc +++ b/sound/voicegroups/rg_surf.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup164:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_surf + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 128, 180, 108, 209 @@ -48,7 +47,7 @@ voicegroup164:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup186.inc b/sound/voicegroups/rg_teachy_tv_menu.inc similarity index 98% rename from sound/voicegroups/voicegroup186.inc rename to sound/voicegroups/rg_teachy_tv_menu.inc index 18dc71d70d..1d51f7692e 100644 --- a/sound/voicegroups/voicegroup186.inc +++ b/sound/voicegroups/rg_teachy_tv_menu.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup186:: +voice_group rg_teachy_tv_menu voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup137.inc b/sound/voicegroups/rg_title.inc similarity index 94% rename from sound/voicegroups/voicegroup137.inc rename to sound/voicegroups/rg_title.inc index cf7422cd23..425bcb7f62 100644 --- a/sound/voicegroups/voicegroup137.inc +++ b/sound/voicegroups/rg_title.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup137:: - voice_keysplit_all voicegroup002 +voice_group rg_title + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup137:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup137:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup001.inc b/sound/voicegroups/rg_unused.inc similarity index 62% rename from sound/voicegroups/voicegroup001.inc rename to sound/voicegroups/rg_unused.inc index 20a2795dc1..8dac5129ad 100644 --- a/sound/voicegroups/voicegroup001.inc +++ b/sound/voicegroups/rg_unused.inc @@ -1,5 +1,8 @@ - .align 2 -voicegroup001:: +voice_group rg_unused + voice_keysplit_all voicegroup_frlg_fanfare_drumset_1 + voice_square_1_alt 60, 0, 0, 2, 0, 2, 9, 1 + voice_square_2_alt 60, 0, 2, 0, 2, 9, 1 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -8,25 +11,17 @@ voicegroup001:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 1, 6, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_programmable_wave 60, 0, ProgrammableWaveData_1, 0, 7, 15, 1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2 60, 0, 2, 0, 1, 6, 0 - voice_programmable_wave 60, 0, ProgrammableWaveData_3, 0, 7, 15, 1 - voice_square_1 60, 0, 0, 2, 0, 1, 6, 0 - voice_square_2 60, 0, 3, 0, 1, 6, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 0, 0, 1, 6, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 255, 0, 255, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 255, 165, 154, 127 diff --git a/sound/voicegroups/rg_unused_2.inc b/sound/voicegroups/rg_unused_2.inc new file mode 100644 index 0000000000..3b46ec9777 --- /dev/null +++ b/sound/voicegroups/rg_unused_2.inc @@ -0,0 +1,6 @@ +voice_group rg_unused_2 + voice_keysplit_all voicegroup_frlg_drumset + voice_square_1_alt 60, 0, 0, 2, 0, 2, 3, 1 + voice_square_2_alt 60, 0, 2, 0, 2, 3, 1 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 + diff --git a/sound/voicegroups/voicegroup172.inc b/sound/voicegroups/rg_vermillion.inc similarity index 95% rename from sound/voicegroups/voicegroup172.inc rename to sound/voicegroups/rg_vermillion.inc index ffd981c830..c6c475aef4 100644 --- a/sound/voicegroups/voicegroup172.inc +++ b/sound/voicegroups/rg_vermillion.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup172:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_vermillion + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -48,7 +47,7 @@ voicegroup172:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup172:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup171.inc b/sound/voicegroups/rg_victory_gym_leader.inc similarity index 93% rename from sound/voicegroups/voicegroup171.inc rename to sound/voicegroups/rg_victory_gym_leader.inc index f4ae315ce5..f3753388d2 100644 --- a/sound/voicegroups/voicegroup171.inc +++ b/sound/voicegroups/rg_victory_gym_leader.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup171:: - voice_keysplit_all voicegroup001 +voice_group rg_victory_gym_leader + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup171:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup171:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup154.inc b/sound/voicegroups/rg_victory_road.inc similarity index 92% rename from sound/voicegroups/voicegroup154.inc rename to sound/voicegroups/rg_victory_road.inc index ce70e65d57..ff703c4ab5 100644 --- a/sound/voicegroups/voicegroup154.inc +++ b/sound/voicegroups/rg_victory_road.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup154:: - voice_keysplit_all voicegroup002 +voice_group rg_victory_road + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup154:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup154:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup169.inc b/sound/voicegroups/rg_victory_trainer.inc similarity index 96% rename from sound/voicegroups/voicegroup169.inc rename to sound/voicegroups/rg_victory_trainer.inc index 77ee6ffee4..9cb14bb46e 100644 --- a/sound/voicegroups/voicegroup169.inc +++ b/sound/voicegroups/rg_victory_trainer.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup169:: - voice_keysplit_all voicegroup001 +voice_group rg_victory_trainer + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup169:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup025.inc b/sound/voicegroups/rg_victory_wild.inc similarity index 94% rename from sound/voicegroups/voicegroup025.inc rename to sound/voicegroups/rg_victory_wild.inc index 3449629469..c19ee7b264 100644 --- a/sound/voicegroups/voicegroup025.inc +++ b/sound/voicegroups/rg_victory_wild.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup025:: - voice_keysplit_all voicegroup001 +voice_group rg_victory_wild + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup025:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup146.inc b/sound/voicegroups/rg_viridian_forest.inc similarity index 97% rename from sound/voicegroups/voicegroup146.inc rename to sound/voicegroups/rg_viridian_forest.inc index b0f1b92d6f..d171e3cb67 100644 --- a/sound/voicegroups/voicegroup146.inc +++ b/sound/voicegroups/rg_viridian_forest.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup146:: - voice_keysplit_all voicegroup002 +voice_group rg_viridian_forest + voice_keysplit_all voicegroup_frlg_drumset voice_directsound 60, 0, DirectSoundWaveData_steinway_b_piano, 255, 165, 103, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup146:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup158.inc b/sound/voicegroups/rg_vs_champion.inc similarity index 94% rename from sound/voicegroups/voicegroup158.inc rename to sound/voicegroups/rg_vs_champion.inc index 50fa566068..3f7f59ed76 100644 --- a/sound/voicegroups/voicegroup158.inc +++ b/sound/voicegroups/rg_vs_champion.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup158:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_vs_champion + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 @@ -48,7 +47,7 @@ voicegroup158:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup158:: voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 255, 0, 255, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 236, 188 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup185.inc b/sound/voicegroups/rg_vs_deoxys.inc similarity index 95% rename from sound/voicegroups/voicegroup185.inc rename to sound/voicegroups/rg_vs_deoxys.inc index 879a4e8883..35d2b6f591 100644 --- a/sound/voicegroups/voicegroup185.inc +++ b/sound/voicegroups/rg_vs_deoxys.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup185:: - voice_keysplit_all voicegroup002 +voice_group rg_vs_deoxys + voice_keysplit_all voicegroup_frlg_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup185:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup185:: voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 85, 0, 154, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 209 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup155.inc b/sound/voicegroups/rg_vs_gym_leader.inc similarity index 94% rename from sound/voicegroups/voicegroup155.inc rename to sound/voicegroups/rg_vs_gym_leader.inc index 8150754aab..75341ae46a 100644 --- a/sound/voicegroups/voicegroup155.inc +++ b/sound/voicegroups/rg_vs_gym_leader.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup155:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_vs_gym_leader + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 @@ -48,7 +47,7 @@ voicegroup155:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup155:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 165, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup156.inc b/sound/voicegroups/rg_vs_trainer.inc similarity index 94% rename from sound/voicegroups/voicegroup156.inc rename to sound/voicegroups/rg_vs_trainer.inc index 374464fff9..5808a9b15c 100644 --- a/sound/voicegroups/voicegroup156.inc +++ b/sound/voicegroups/rg_vs_trainer.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup156:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_vs_trainer + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup156:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup156:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup157.inc b/sound/voicegroups/rg_vs_wild.inc similarity index 94% rename from sound/voicegroups/voicegroup157.inc rename to sound/voicegroups/rg_vs_wild.inc index 7dd93abd0a..d07bc73771 100644 --- a/sound/voicegroups/voicegroup157.inc +++ b/sound/voicegroups/rg_vs_wild.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup157:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group rg_vs_wild + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 2, 6, 5 @@ -48,7 +47,7 @@ voicegroup157:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup157:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup038.inc b/sound/voicegroups/roulette.inc similarity index 98% rename from sound/voicegroups/voicegroup038.inc rename to sound/voicegroups/roulette.inc index bcb211d6f5..351d232173 100644 --- a/sound/voicegroups/voicegroup038.inc +++ b/sound/voicegroups/roulette.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup038:: - voice_keysplit_all voicegroup001 +voice_group roulette + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup011.inc b/sound/voicegroups/route101.inc similarity index 97% rename from sound/voicegroups/voicegroup011.inc rename to sound/voicegroups/route101.inc index 5527cc3698..223763608d 100644 --- a/sound/voicegroups/voicegroup011.inc +++ b/sound/voicegroups/route101.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup011:: - voice_keysplit_all voicegroup022 +voice_group route101 + voice_keysplit_all voicegroup_route101_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup011:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup047.inc b/sound/voicegroups/route104.inc similarity index 94% rename from sound/voicegroups/voicegroup047.inc rename to sound/voicegroups/route104.inc index 84fa9335a8..59b47960cd 100644 --- a/sound/voicegroups/voicegroup047.inc +++ b/sound/voicegroups/route104.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup047:: - voice_keysplit_all voicegroup001 +voice_group route104 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup047:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup047:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup010.inc b/sound/voicegroups/route110.inc similarity index 91% rename from sound/voicegroups/voicegroup010.inc rename to sound/voicegroups/route110.inc index 8d0f7a56dd..f26f1ad74b 100644 --- a/sound/voicegroups/voicegroup010.inc +++ b/sound/voicegroups/route110.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup010:: - voice_keysplit_all voicegroup031 +voice_group route110 + voice_keysplit_all voicegroup_route110_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup010:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup010:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup055.inc b/sound/voicegroups/route111.inc similarity index 94% rename from sound/voicegroups/voicegroup055.inc rename to sound/voicegroups/route111.inc index 9157030e83..f253a4051c 100644 --- a/sound/voicegroups/voicegroup055.inc +++ b/sound/voicegroups/route111.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup055:: - voice_keysplit_all voicegroup001 +voice_group route111 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup055:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup055:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup064.inc b/sound/voicegroups/route113.inc similarity index 96% rename from sound/voicegroups/voicegroup064.inc rename to sound/voicegroups/route113.inc index fa56af03ea..e21c37f002 100644 --- a/sound/voicegroups/voicegroup064.inc +++ b/sound/voicegroups/route113.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup064:: - voice_keysplit_all voicegroup001 +voice_group route113 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup064:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup064:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup048.inc b/sound/voicegroups/route119.inc similarity index 92% rename from sound/voicegroups/voicegroup048.inc rename to sound/voicegroups/route119.inc index eeb5b682a3..c18dbd1da0 100644 --- a/sound/voicegroups/voicegroup048.inc +++ b/sound/voicegroups/route119.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup048:: - voice_keysplit_all voicegroup001 +voice_group route119 + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup048:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup048:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup014.inc b/sound/voicegroups/route120.inc similarity index 92% rename from sound/voicegroups/voicegroup014.inc rename to sound/voicegroups/route120.inc index 6ce0897d10..8badc8b531 100644 --- a/sound/voicegroups/voicegroup014.inc +++ b/sound/voicegroups/route120.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup014:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group route120 + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 1, 6, 1 @@ -48,7 +47,7 @@ voicegroup014:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup014:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route122.inc b/sound/voicegroups/route122.inc new file mode 100644 index 0000000000..b81d75d7b3 --- /dev/null +++ b/sound/voicegroups/route122.inc @@ -0,0 +1,89 @@ +voice_group route122 + voice_keysplit_all voicegroup_rs_drumset + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2_alt 60, 0, 3, 0, 2, 0, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2_alt 60, 0, 3, 0, 1, 6, 0 + voice_square_1_alt 60, 0, 0, 3, 0, 1, 6, 0 + voice_square_1_alt 60, 0, 0, 3, 0, 0, 6, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_2_alt 60, 0, 0, 0, 1, 7, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_7, 0, 7, 15, 1 + voice_square_1_alt 60, 0, 0, 0, 0, 1, 7, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_7, 0, 7, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 + voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 1 + voice_square_1_alt 60, 0, 0, 0, 0, 0, 7, 0 + diff --git a/sound/voicegroups/voicegroup127.inc b/sound/voicegroups/rs_sfx_1.inc similarity index 98% rename from sound/voicegroups/voicegroup127.inc rename to sound/voicegroups/rs_sfx_1.inc index 476d3f48f6..31d514a328 100644 --- a/sound/voicegroups/voicegroup127.inc +++ b/sound/voicegroups/rs_sfx_1.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup127:: +voice_group rs_sfx_1 voice_directsound 60, 0, DirectSoundWaveData_unknown_synth_snare, 255, 249, 103, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup127:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup128.inc b/sound/voicegroups/rs_sfx_2.inc similarity index 99% rename from sound/voicegroups/voicegroup128.inc rename to sound/voicegroups/rs_sfx_2.inc index 69b52d29d6..b93f29b0ff 100644 --- a/sound/voicegroups/voicegroup128.inc +++ b/sound/voicegroups/rs_sfx_2.inc @@ -1,5 +1,4 @@ - .align 2 -voicegroup128:: +voice_group rs_sfx_2 voice_directsound_no_resample 60, 0, DirectSoundWaveData_bicycle_bell, 255, 249, 0, 165 voice_directsound_alt 60, 0, DirectSoundWaveData_bicycle_bell, 255, 0, 255, 165 voice_directsound 60, 0, DirectSoundWaveData_unknown_synth_snare, 255, 0, 255, 165 diff --git a/sound/voicegroups/voicegroup045.inc b/sound/voicegroups/rustboro.inc similarity index 96% rename from sound/voicegroups/voicegroup045.inc rename to sound/voicegroups/rustboro.inc index 2e2016e439..a0292d77a8 100644 --- a/sound/voicegroups/voicegroup045.inc +++ b/sound/voicegroups/rustboro.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup045:: - voice_keysplit_all voicegroup001 +voice_group rustboro + voice_keysplit_all voicegroup_rs_drumset voice_square_1_alt 60, 0, 0, 1, 0, 2, 0, 1 voice_square_1_alt 60, 0, 0, 3, 1, 2, 6, 0 voice_square_2_alt 60, 0, 3, 1, 2, 6, 0 @@ -10,7 +9,7 @@ voicegroup045:: voice_programmable_wave_alt 60, 0, ProgrammableWaveData_4, 1, 7, 15, 1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup045:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup074.inc b/sound/voicegroups/safari_zone.inc similarity index 98% rename from sound/voicegroups/voicegroup074.inc rename to sound/voicegroups/safari_zone.inc index 1c3c67f8dc..29eb4db861 100644 --- a/sound/voicegroups/voicegroup074.inc +++ b/sound/voicegroups/safari_zone.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup074:: - voice_keysplit_all voicegroup001 +voice_group safari_zone + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup077.inc b/sound/voicegroups/sailing.inc similarity index 97% rename from sound/voicegroups/voicegroup077.inc rename to sound/voicegroups/sailing.inc index 994d9f411d..3c2e1885c2 100644 --- a/sound/voicegroups/voicegroup077.inc +++ b/sound/voicegroups/sailing.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup077:: - voice_keysplit_all voicegroup001 +voice_group sailing + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup077:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/school.inc b/sound/voicegroups/school.inc new file mode 100644 index 0000000000..b7eb6deb30 --- /dev/null +++ b/sound/voicegroups/school.inc @@ -0,0 +1,4 @@ +voice_group school + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + diff --git a/sound/voicegroups/voicegroup084.inc b/sound/voicegroups/sealed_chamber.inc similarity index 96% rename from sound/voicegroups/voicegroup084.inc rename to sound/voicegroups/sealed_chamber.inc index 510b37c23a..9ab3a67924 100644 --- a/sound/voicegroups/voicegroup084.inc +++ b/sound/voicegroups/sealed_chamber.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup084:: - voice_keysplit_all voicegroup001 +voice_group sealed_chamber + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup084:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup084:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup079.inc b/sound/voicegroups/slateport.inc similarity index 96% rename from sound/voicegroups/voicegroup079.inc rename to sound/voicegroups/slateport.inc index 42b51faea4..669b089855 100644 --- a/sound/voicegroups/voicegroup079.inc +++ b/sound/voicegroups/slateport.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup079:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group slateport + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup079:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup091.inc b/sound/voicegroups/sootopolis.inc similarity index 94% rename from sound/voicegroups/voicegroup091.inc rename to sound/voicegroups/sootopolis.inc index 28a64ab488..fdd0ed9d4a 100644 --- a/sound/voicegroups/voicegroup091.inc +++ b/sound/voicegroups/sootopolis.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup091:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group sootopolis + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup091:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup091:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup017.inc b/sound/voicegroups/surf.inc similarity index 94% rename from sound/voicegroups/voicegroup017.inc rename to sound/voicegroups/surf.inc index 06738d297b..cadc04e077 100644 --- a/sound/voicegroups/voicegroup017.inc +++ b/sound/voicegroups/surf.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup017:: - voice_keysplit_all voicegroup001 +voice_group surf + voice_keysplit_all voicegroup_rs_drumset voice_square_2_alt 60, 0, 2, 0, 3, 3, 1 voice_square_1_alt 60, 0, 0, 2, 0, 3, 3, 1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup017:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup017:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup059.inc b/sound/voicegroups/title.inc similarity index 91% rename from sound/voicegroups/voicegroup059.inc rename to sound/voicegroups/title.inc index 5a45d437d3..abb6d853a9 100644 --- a/sound/voicegroups/voicegroup059.inc +++ b/sound/voicegroups/title.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup059:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group title + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 1, 1, 1, 6, 2 @@ -48,7 +47,7 @@ voicegroup059:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup059:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup094.inc b/sound/voicegroups/trick_house.inc similarity index 95% rename from sound/voicegroups/voicegroup094.inc rename to sound/voicegroups/trick_house.inc index b52e958926..f0c2e1f6ca 100644 --- a/sound/voicegroups/voicegroup094.inc +++ b/sound/voicegroups/trick_house.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup094:: - voice_keysplit_all voicegroup001 +voice_group trick_house + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup094:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup094:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup057.inc b/sound/voicegroups/underwater.inc similarity index 97% rename from sound/voicegroups/voicegroup057.inc rename to sound/voicegroups/underwater.inc index 391b7cf8bc..03526599ad 100644 --- a/sound/voicegroups/voicegroup057.inc +++ b/sound/voicegroups/underwater.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup057:: - voice_keysplit_all voicegroup001 +voice_group underwater + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup057:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup007.inc b/sound/voicegroups/unused.inc similarity index 95% rename from sound/voicegroups/voicegroup007.inc rename to sound/voicegroups/unused.inc index 66bcd3fa6c..ee5a89b715 100644 --- a/sound/voicegroups/voicegroup007.inc +++ b/sound/voicegroups/unused.inc @@ -1,8 +1,4 @@ - .align 2 -voicegroup007:: - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_60, 255, 0, 193, 127 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_72, 255, 0, 193, 127 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_trumpet_84, 255, 0, 193, 127 +voice_group unused voice_square_1_alt 60, 0, 38, 2, 1, 0, 0, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/unused_2.inc b/sound/voicegroups/unused_2.inc new file mode 100644 index 0000000000..d2e1a4cf04 --- /dev/null +++ b/sound/voicegroups/unused_2.inc @@ -0,0 +1,130 @@ +voice_group unused_2 + voice_keysplit_all voicegroup_rs_drumset + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion_duplicate, 255, 249, 25, 248 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 + voice_noise_alt 60, 0, 0, 0, 1, 7, 1 + diff --git a/sound/voicegroups/voicegroup044.inc b/sound/voicegroups/verdanturf.inc similarity index 96% rename from sound/voicegroups/voicegroup044.inc rename to sound/voicegroups/verdanturf.inc index 9a057754b3..f58ffed848 100644 --- a/sound/voicegroups/voicegroup044.inc +++ b/sound/voicegroups/verdanturf.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup044:: - voice_keysplit voicegroup005, KeySplitTable1 +voice_group verdanturf + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup044:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup070.inc b/sound/voicegroups/victory_aqua_magma.inc similarity index 96% rename from sound/voicegroups/voicegroup070.inc rename to sound/voicegroups/victory_aqua_magma.inc index 59a43180df..cd9a7645a6 100644 --- a/sound/voicegroups/voicegroup070.inc +++ b/sound/voicegroups/victory_aqua_magma.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup070:: - voice_keysplit_all voicegroup001 +voice_group victory_aqua_magma + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup070:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,7 +55,7 @@ voicegroup070:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup024.inc b/sound/voicegroups/victory_gym_leader.inc similarity index 93% rename from sound/voicegroups/voicegroup024.inc rename to sound/voicegroups/victory_gym_leader.inc index 3806b462d6..8e91c799a0 100644 --- a/sound/voicegroups/voicegroup024.inc +++ b/sound/voicegroups/victory_gym_leader.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup024:: - voice_keysplit_all voicegroup001 +voice_group victory_gym_leader + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup024:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup024:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup029.inc b/sound/voicegroups/victory_league.inc similarity index 93% rename from sound/voicegroups/voicegroup029.inc rename to sound/voicegroups/victory_league.inc index 7c801afcb3..7d4d669662 100644 --- a/sound/voicegroups/voicegroup029.inc +++ b/sound/voicegroups/victory_league.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup029:: - voice_keysplit_all voicegroup001 +voice_group victory_league + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup029:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup029:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup075.inc b/sound/voicegroups/victory_road.inc similarity index 93% rename from sound/voicegroups/voicegroup075.inc rename to sound/voicegroups/victory_road.inc index 86af71af4b..043789e6c5 100644 --- a/sound/voicegroups/voicegroup075.inc +++ b/sound/voicegroups/victory_road.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup075:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group victory_road + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup075:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup075:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup058.inc b/sound/voicegroups/victory_trainer.inc similarity index 96% rename from sound/voicegroups/voicegroup058.inc rename to sound/voicegroups/victory_trainer.inc index 56dff5f5bb..cfa101e98e 100644 --- a/sound/voicegroups/voicegroup058.inc +++ b/sound/voicegroups/victory_trainer.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup058:: - voice_keysplit_all voicegroup001 +voice_group victory_trainer + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup058:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup170.inc b/sound/voicegroups/victory_wild.inc similarity index 94% rename from sound/voicegroups/voicegroup170.inc rename to sound/voicegroups/victory_wild.inc index 43c8ae6df7..f250bf92e2 100644 --- a/sound/voicegroups/voicegroup170.inc +++ b/sound/voicegroups/victory_wild.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup170:: - voice_keysplit_all voicegroup001 +voice_group victory_wild + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,9 +55,9 @@ voicegroup170:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup000.inc b/sound/voicegroups/voicegroup000.inc deleted file mode 100644 index 7a2c5772f9..0000000000 --- a/sound/voicegroups/voicegroup000.inc +++ /dev/null @@ -1,65 +0,0 @@ - .align 2 -voicegroup000:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2 60, 0, 2, 0, 0, 9, 2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_glockenspiel, 255, 165, 51, 235 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 255, 0, 255, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 149 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_slap_bass, 255, 235, 128, 115 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_synth_bass, 255, 252, 0, 115 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup006, KeySplitTable2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup002.inc b/sound/voicegroups/voicegroup002.inc deleted file mode 100644 index bd6f080aa4..0000000000 --- a/sound/voicegroups/voicegroup002.inc +++ /dev/null @@ -1,57 +0,0 @@ - .align 2 -voicegroup002:: - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_oboe, 255, 165, 154, 127 - voice_directsound 60, 0, DirectSoundWaveData_unused_sd90_oboe, 255, 165, 154, 127 - voice_directsound 60, 0, DirectSoundWaveData_unused_guitar_separates_power_chord, 255, 165, 206, 127 - voice_directsound 60, 0, DirectSoundWaveData_unused_sc88pro_unison_slap, 255, 165, 206, 127 - voice_directsound 60, 0, DirectSoundWaveData_unknown_snare, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_ethnic_flavours_ohtsuzumi, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_ethnic_flavours_hyoushigi, 255, 0, 255, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_kick, 255, 0, 255, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_directsound 48, 44, DirectSoundWaveData_unused_sc55_tom, 255, 210, 77, 204 - voice_directsound_no_resample 60, 79, DirectSoundWaveData_unknown_close_hihat, 255, 127, 0, 188 - voice_directsound 51, 54, DirectSoundWaveData_unused_sc55_tom, 255, 216, 77, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 54, 64, DirectSoundWaveData_unused_sc55_tom, 255, 216, 77, 204 - voice_directsound_no_resample 60, 79, DirectSoundWaveData_unknown_open_hihat, 255, 242, 141, 0 - voice_directsound 57, 69, DirectSoundWaveData_unused_sc55_tom, 255, 210, 77, 204 - voice_directsound 60, 79, DirectSoundWaveData_unused_sc55_tom, 255, 204, 77, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 62, 84, DirectSoundWaveData_unused_sc55_tom, 255, 204, 77, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 70, 49, DirectSoundWaveData_unknown_bell, 255, 165, 103, 231 - voice_directsound_no_resample 32, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 - voice_directsound_no_resample 60, 14, DirectSoundWaveData_trinity_cymbal_crash, 255, 235, 0, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 - voice_directsound_no_resample 30, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 104, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 94, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_drum_and_percussion_kick, 255, 0, 255, 0 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 180, 175, 228 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sd90_solo_snare, 255, 0, 255, 242 - voice_directsound_no_resample 64, 54, DirectSoundWaveData_sc88pro_tr909_hand_clap, 255, 255, 255, 127 - voice_directsound_no_resample 64, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_directsound 64, 24, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 64, 80, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_directsound 68, 34, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 - voice_directsound 72, 44, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 - voice_directsound 76, 84, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound 80, 94, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 226 - voice_directsound_no_resample 33, 89, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_directsound 84, 104, DirectSoundWaveData_sd90_ambient_tom, 255, 0, 255, 235 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 63, 64, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 235, 0, 231 - voice_directsound_no_resample 64, 24, DirectSoundWaveData_dance_drums_ride_bell, 255, 165, 103, 231 - diff --git a/sound/voicegroups/voicegroup015.inc b/sound/voicegroups/voicegroup015.inc deleted file mode 100644 index a528476356..0000000000 --- a/sound/voicegroups/voicegroup015.inc +++ /dev/null @@ -1,95 +0,0 @@ - .align 2 -voicegroup015:: - voice_keysplit_all voicegroup016 - voice_keysplit voicegroup005, KeySplitTable1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2 60, 0, 3, 0, 2, 0, 0 - voice_square_1 60, 0, 0, 3, 0, 2, 0, 0 - voice_square_2 60, 0, 3, 0, 6, 0, 0 - voice_square_1 60, 0, 0, 3, 0, 6, 0, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 149 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion, 255, 0, 255, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 - voice_programmable_wave 60, 0, ProgrammableWaveData_1, 0, 7, 15, 1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_3, 0, 7, 15, 2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup021.inc b/sound/voicegroups/voicegroup021.inc deleted file mode 100644 index 43aa9150ee..0000000000 --- a/sound/voicegroups/voicegroup021.inc +++ /dev/null @@ -1,54 +0,0 @@ - .align 2 -voicegroup021:: - voice_keysplit_all voicegroup001 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2_alt 60, 0, 3, 0, 2, 0, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2_alt 60, 0, 3, 0, 1, 6, 0 - voice_square_1_alt 60, 0, 0, 3, 0, 1, 6, 0 - voice_square_1_alt 60, 0, 0, 3, 0, 0, 6, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup022.inc b/sound/voicegroups/voicegroup022.inc deleted file mode 100644 index 877f57d6ce..0000000000 --- a/sound/voicegroups/voicegroup022.inc +++ /dev/null @@ -1,68 +0,0 @@ - .align 2 -voicegroup022:: - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2_alt 60, 0, 0, 0, 1, 7, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_7, 0, 7, 15, 1 - voice_square_1_alt 60, 0, 0, 0, 0, 1, 7, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_7, 0, 7, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 1 - voice_square_1_alt 60, 0, 0, 0, 0, 0, 7, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_kick, 255, 0, 255, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_rnd_snare, 255, 0, 255, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 32, 34, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 67, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 61, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 - diff --git a/sound/voicegroups/voicegroup030.inc b/sound/voicegroups/voicegroup030.inc deleted file mode 100644 index 1e1b5088dd..0000000000 --- a/sound/voicegroups/voicegroup030.inc +++ /dev/null @@ -1,58 +0,0 @@ - .align 2 -voicegroup030:: - voice_keysplit_all voicegroup031 - voice_keysplit voicegroup005, KeySplitTable1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_2_alt 60, 0, 3, 0, 2, 4, 0 - voice_square_1_alt 60, 0, 0, 3, 0, 2, 4, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tubular_bell, 255, 216, 90, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 37, 165, 180, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup031.inc b/sound/voicegroups/voicegroup031.inc deleted file mode 100644 index 178d7ec63d..0000000000 --- a/sound/voicegroups/voicegroup031.inc +++ /dev/null @@ -1,68 +0,0 @@ - .align 2 -voicegroup031:: - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_3, 0, 7, 15, 1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_trinity_big_boned, 255, 165, 154, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 60, 64, DirectSoundWaveData_sc88pro_orchestra_snare, 255, 0, 255, 242 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 32, 49, DirectSoundWaveData_sc88pro_tambourine, 255, 127, 77, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 8, 0, 255, 216 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 30, 54, DirectSoundWaveData_sc88pro_orchestra_cymbal_crash, 255, 246, 0, 216 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 79, DirectSoundWaveData_sc88pro_mute_high_conga, 255, 0, 255, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound_no_resample 72, 74, DirectSoundWaveData_sc88pro_open_low_conga, 255, 0, 255, 0 - diff --git a/sound/voicegroups/voicegroup081.inc b/sound/voicegroups/voicegroup081.inc deleted file mode 100644 index e9c2011e40..0000000000 --- a/sound/voicegroups/voicegroup081.inc +++ /dev/null @@ -1,5 +0,0 @@ - .align 2 -voicegroup081:: - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup005, KeySplitTable1 - diff --git a/sound/voicegroups/voicegroup130.inc b/sound/voicegroups/voicegroup130.inc deleted file mode 100644 index 7044bb38e4..0000000000 --- a/sound/voicegroups/voicegroup130.inc +++ /dev/null @@ -1,182 +0,0 @@ - .align 2 -voicegroup130:: - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_1, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_2, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_3, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_4, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_5, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_6, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_7, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_8, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_9, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_10, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_11, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_12, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_13, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_14, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_15, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_16, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_17, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_18, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_19, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_20, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_21, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_22, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_23, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_24, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_25, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_26, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_27, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_28, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_29, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_30, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_31, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_32, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_33, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_34, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_35, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_36, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_37, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_38, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_39, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_40, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_41, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_42, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_43, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_44, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_45, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_46, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_47, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_48, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_49, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_50, 255, 0, 255, 0 - voice_directsound 60, 0, DirectSoundWaveData_Phoneme_51, 255, 0, 255, 0 - voice_keysplit_all voicegroup001 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion_duplicate, 255, 249, 25, 248 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_noise_alt 60, 0, 0, 0, 1, 7, 1 - diff --git a/sound/voicegroups/voicegroup174.inc b/sound/voicegroups/voicegroup174.inc deleted file mode 100644 index ab7d43fc72..0000000000 --- a/sound/voicegroups/voicegroup174.inc +++ /dev/null @@ -1,160 +0,0 @@ - .align 2 -voicegroup174:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 255, 0, 255, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_accordion, 255, 0, 255, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_overdrive_guitar, 128, 0, 255, 214 - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_high, 128, 0, 255, 206 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_synth_bass, 255, 252, 0, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 209 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1_alt 60, 0, 0, 3, 0, 2, 3, 4 - voice_square_2_alt 60, 0, 3, 0, 2, 3, 4 - voice_square_1_alt 60, 0, 0, 3, 0, 2, 3, 4 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_2, 0, 7, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sd90_special_scream_drive, 255, 0, 255, 165 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_noise_alt 60, 0, 0, 0, 2, 6, 0 - voice_noise_alt 60, 0, 0, 0, 1, 3, 1 - voice_keysplit_all voicegroup177 - voice_square_1_alt 60, 0, 0, 2, 0, 2, 9, 1 - voice_square_2_alt 60, 0, 2, 0, 2, 9, 1 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 255, 165, 154, 127 - voice_keysplit_all voicegroup002 - voice_square_1_alt 60, 0, 0, 2, 0, 2, 3, 1 - voice_square_2_alt 60, 0, 2, 0, 2, 3, 1 - voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 - diff --git a/sound/voicegroups/voicegroup175.inc b/sound/voicegroups/voicegroup175.inc deleted file mode 100644 index a074f216dd..0000000000 --- a/sound/voicegroups/voicegroup175.inc +++ /dev/null @@ -1,55 +0,0 @@ - .align 2 -voicegroup175:: - voice_keysplit_all voicegroup177 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_xylophone, 255, 235, 0, 204 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 85, 165, 154, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup189.inc b/sound/voicegroups/voicegroup189.inc deleted file mode 100644 index 6c04cd8320..0000000000 --- a/sound/voicegroups/voicegroup189.inc +++ /dev/null @@ -1,95 +0,0 @@ - .align 2 -voicegroup189:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 - voice_directsound 60, 65, DirectSoundWaveData_sd90_classical_detuned_ep1_high, 128, 204, 77, 246 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_tubular_bell, 255, 165, 90, 216 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_organ2, 51, 0, 203, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 128, 249, 25, 127 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_nylon_str_guitar, 64, 216, 51, 224 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_fretless_bass, 255, 253, 0, 188 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_directsound 60, 0, DirectSoundWaveData_sc88pro_flute, 255, 127, 231, 127 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1_alt 60, 0, 0, 2, 0, 2, 6, 3 - voice_square_2_alt 60, 0, 3, 0, 2, 7, 2 - voice_square_1_alt 60, 0, 0, 1, 0, 2, 6, 2 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - diff --git a/sound/voicegroups/voicegroup118.inc b/sound/voicegroups/vs_aqua_magma.inc similarity index 94% rename from sound/voicegroups/voicegroup118.inc rename to sound/voicegroups/vs_aqua_magma.inc index 89e66b21d2..a83533f90c 100644 --- a/sound/voicegroups/voicegroup118.inc +++ b/sound/voicegroups/vs_aqua_magma.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup118:: - voice_keysplit_all voicegroup001 +voice_group vs_aqua_magma + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup118:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -58,9 +57,9 @@ voicegroup118:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup126.inc b/sound/voicegroups/vs_aqua_magma_leader.inc similarity index 95% rename from sound/voicegroups/voicegroup126.inc rename to sound/voicegroups/vs_aqua_magma_leader.inc index 51959b4f1e..78c23d136a 100644 --- a/sound/voicegroups/voicegroup126.inc +++ b/sound/voicegroups/vs_aqua_magma_leader.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup126:: - voice_keysplit_all voicegroup001 +voice_group vs_aqua_magma_leader + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup126:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup126:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup121.inc b/sound/voicegroups/vs_champion.inc similarity index 91% rename from sound/voicegroups/voicegroup121.inc rename to sound/voicegroups/vs_champion.inc index f09ddd7741..f18c9182d7 100644 --- a/sound/voicegroups/voicegroup121.inc +++ b/sound/voicegroups/vs_champion.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup121:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_champion + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup121:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup121:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup125.inc b/sound/voicegroups/vs_elite_four.inc similarity index 93% rename from sound/voicegroups/voicegroup125.inc rename to sound/voicegroups/vs_elite_four.inc index 644002abf7..551e34e36e 100644 --- a/sound/voicegroups/voicegroup125.inc +++ b/sound/voicegroups/vs_elite_four.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup125:: - voice_keysplit_all voicegroup001 +voice_group vs_elite_four + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup125:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup125:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup115.inc b/sound/voicegroups/vs_frontier_brain.inc similarity index 94% rename from sound/voicegroups/voicegroup115.inc rename to sound/voicegroups/vs_frontier_brain.inc index eb4f52b878..c544475e77 100644 --- a/sound/voicegroups/voicegroup115.inc +++ b/sound/voicegroups/vs_frontier_brain.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup115:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_frontier_brain + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 128, 249, 0, 188 @@ -48,7 +47,7 @@ voicegroup115:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup115:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 165, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup120.inc b/sound/voicegroups/vs_gym_leader.inc similarity index 92% rename from sound/voicegroups/voicegroup120.inc rename to sound/voicegroups/vs_gym_leader.inc index 2c104fb10b..058b180e67 100644 --- a/sound/voicegroups/voicegroup120.inc +++ b/sound/voicegroups/vs_gym_leader.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup120:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_gym_leader + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 2, 6, 1 @@ -48,7 +47,7 @@ voicegroup120:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup120:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup123.inc b/sound/voicegroups/vs_kyogre_groudon.inc similarity index 95% rename from sound/voicegroups/voicegroup123.inc rename to sound/voicegroups/vs_kyogre_groudon.inc index 6178994cca..4ece3f9e26 100644 --- a/sound/voicegroups/voicegroup123.inc +++ b/sound/voicegroups/vs_kyogre_groudon.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup123:: - voice_keysplit_all voicegroup001 +voice_group vs_kyogre_groudon + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup123:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup123:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup116.inc b/sound/voicegroups/vs_mew.inc similarity index 94% rename from sound/voicegroups/voicegroup116.inc rename to sound/voicegroups/vs_mew.inc index a86a87f5d1..14f3c536f7 100644 --- a/sound/voicegroups/voicegroup116.inc +++ b/sound/voicegroups/vs_mew.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup116:: - voice_keysplit_all voicegroup002 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_mew + voice_keysplit_all voicegroup_frlg_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 2, 6, 5 @@ -48,7 +47,7 @@ voicegroup116:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup116:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup114.inc b/sound/voicegroups/vs_rayquaza.inc similarity index 95% rename from sound/voicegroups/voicegroup114.inc rename to sound/voicegroups/vs_rayquaza.inc index cb078d24c3..8199a8a4a0 100644 --- a/sound/voicegroups/voicegroup114.inc +++ b/sound/voicegroups/vs_rayquaza.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup114:: - voice_keysplit_all voicegroup001 +voice_group vs_rayquaza + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup114:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup114:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup122.inc b/sound/voicegroups/vs_regi.inc similarity index 94% rename from sound/voicegroups/voicegroup122.inc rename to sound/voicegroups/vs_regi.inc index 65356a3d17..be785e62e8 100644 --- a/sound/voicegroups/voicegroup122.inc +++ b/sound/voicegroups/vs_regi.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup122:: - voice_keysplit_all voicegroup001 +voice_group vs_regi + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup122:: voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +59,7 @@ voicegroup122:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup124.inc b/sound/voicegroups/vs_rival.inc similarity index 91% rename from sound/voicegroups/voicegroup124.inc rename to sound/voicegroups/vs_rival.inc index 274d76dcd1..e3d07742c0 100644 --- a/sound/voicegroups/voicegroup124.inc +++ b/sound/voicegroups/vs_rival.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup124:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_rival + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 2, 3, 1 @@ -48,7 +47,7 @@ voicegroup124:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup124:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup119.inc b/sound/voicegroups/vs_trainer.inc similarity index 92% rename from sound/voicegroups/voicegroup119.inc rename to sound/voicegroups/vs_trainer.inc index 8b7fe24c79..1470990f55 100644 --- a/sound/voicegroups/voicegroup119.inc +++ b/sound/voicegroups/vs_trainer.inc @@ -1,7 +1,6 @@ - .align 2 -voicegroup119:: - voice_keysplit_all voicegroup001 - voice_keysplit voicegroup005, KeySplitTable1 +voice_group vs_trainer + voice_keysplit_all voicegroup_rs_drumset + voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 0, 0, 2, 4, 1 @@ -48,7 +47,7 @@ voicegroup119:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound_no_resample 60, 0, DirectSoundWaveData_sc88pro_timpani_with_snare, 255, 246, 0, 226 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup119:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup117.inc b/sound/voicegroups/vs_wild.inc similarity index 91% rename from sound/voicegroups/voicegroup117.inc rename to sound/voicegroups/vs_wild.inc index 3a86ec4f58..c3944d50a7 100644 --- a/sound/voicegroups/voicegroup117.inc +++ b/sound/voicegroups/vs_wild.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup117:: - voice_keysplit_all voicegroup001 +voice_group vs_wild + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -48,7 +47,7 @@ voicegroup117:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup006, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -56,11 +55,11 @@ voicegroup117:: voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup007, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup008, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup009, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/voicegroup090.inc b/sound/voicegroups/weather_groudon.inc similarity index 98% rename from sound/voicegroups/voicegroup090.inc rename to sound/voicegroups/weather_groudon.inc index 4039ad8d14..dde2a4637b 100644 --- a/sound/voicegroups/voicegroup090.inc +++ b/sound/voicegroups/weather_groudon.inc @@ -1,6 +1,5 @@ - .align 2 -voicegroup090:: - voice_keysplit_all voicegroup001 +voice_group weather_groudon + voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/src/m4a_tables.c b/src/m4a_tables.c index 6fb3b273a3..5bc1075494 100644 --- a/src/m4a_tables.c +++ b/src/m4a_tables.c @@ -261,7 +261,7 @@ const struct PokemonCrySong gPokemonCrySongTemplate = .blockCount = 0, .priority = 255, .reverb = 0, - .tone = (struct ToneData *)&voicegroup000, + .tone = (struct ToneData *)&voicegroup_dummy, .part = {NULL, NULL}, .gap = 0, .part0 = TUNE, diff --git a/tools/mid2agb/agb.cpp b/tools/mid2agb/agb.cpp index caa6f0ecd9..76f6aae028 100644 --- a/tools/mid2agb/agb.cpp +++ b/tools/mid2agb/agb.cpp @@ -46,7 +46,7 @@ static int s_memaccParam2; void PrintAgbHeader() { std::fprintf(g_outputFile, "\t.include \"MPlayDef.s\"\n\n"); - std::fprintf(g_outputFile, "\t.equ\t%s_grp, voicegroup%03u\n", g_asmLabel.c_str(), g_voiceGroup); + std::fprintf(g_outputFile, "\t.equ\t%s_grp, voicegroup%s\n", g_asmLabel.c_str(), g_voiceGroup.c_str()); std::fprintf(g_outputFile, "\t.equ\t%s_pri, %u\n", g_asmLabel.c_str(), g_priority); if (g_reverb >= 0) diff --git a/tools/mid2agb/main.cpp b/tools/mid2agb/main.cpp index ea2b294ac8..ca5a3da8a7 100644 --- a/tools/mid2agb/main.cpp +++ b/tools/mid2agb/main.cpp @@ -35,7 +35,7 @@ FILE* g_outputFile = nullptr; std::string g_asmLabel; int g_masterVolume = 127; -int g_voiceGroup = 0; +std::string g_voiceGroup = "_dummy"; int g_priority = 0; int g_reverb = -1; int g_clocksPerBeat = 1; @@ -52,7 +52,7 @@ bool g_compressionEnabled = true; "\n" "options -L??? label for assembler (default:output_file)\n" " -V??? master volume (default:127)\n" - " -G??? voice group number (default:0)\n" + " -G??? voice group label (default:_dummy)\n" " -P??? priority (default:0)\n" " -R??? reverb (default:off)\n" " -X 48 clocks/beat (default:24 clocks/beat)\n" @@ -149,7 +149,7 @@ int main(int argc, char** argv) arg = GetArgument(argc, argv, i); if (arg == nullptr) PrintUsage(); - g_voiceGroup = std::stoi(arg); + g_voiceGroup = arg; break; case 'L': arg = GetArgument(argc, argv, i); diff --git a/tools/mid2agb/main.h b/tools/mid2agb/main.h index 6e71e73fd4..76443e5db9 100644 --- a/tools/mid2agb/main.h +++ b/tools/mid2agb/main.h @@ -29,7 +29,7 @@ extern FILE* g_outputFile; extern std::string g_asmLabel; extern int g_masterVolume; -extern int g_voiceGroup; +extern std::string g_voiceGroup; extern int g_priority; extern int g_reverb; extern int g_clocksPerBeat; From 48c850c60b533ce73a33b93002175e08bb01de07 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:32:16 -0700 Subject: [PATCH 151/283] add tustin2121 as a contributor for doc, and code (#7445) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ CREDITS.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index c8b79ba30e..c4ed2ea558 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -338,6 +338,16 @@ "contributions": [ "code" ] + }, + { + "login": "tustin2121", + "name": "tustin2121", + "avatar_url": "https://avatars.githubusercontent.com/u/794812?v=4", + "profile": "https://tustin2121.github.io/", + "contributions": [ + "doc", + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index ab5c596248..17809a3c3f 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -58,7 +58,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Zatsu
Zatsu

💻 poetahto
poetahto

💻 lordraindance2
lordraindance2

💻 - Pablo Pena
Pablo Pena

💻 + Pablo Pena
Pablo Pena

💻 + tustin2121
tustin2121

📖 💻 From 01105171a3701384d156499fc8329c4cd6b403ea Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:30:50 +0100 Subject: [PATCH 152/283] Fixes Magnet Rise when user is Rooted/Smacked Down (#7449) --- data/battle_scripts_1.s | 2 + test/battle/move_effect/magic_room.c | 2 + test/battle/move_effect/magnet_rise.c | 55 ++++++++++++++++++- .../move_effect_secondary/will_o_wisp.c | 4 -- 4 files changed, 58 insertions(+), 5 deletions(-) delete mode 100644 test/battle/move_effect_secondary/will_o_wisp.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 31835383dd..13d3c09012 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2601,6 +2601,8 @@ BattleScript_EffectMagnetRise:: attackcanceler attackstring ppreduce + jumpifstatus3 BS_ATTACKER, STATUS3_ROOTED, BattleScript_ButItFailed + jumpifstatus3 BS_ATTACKER, STATUS3_SMACKED_DOWN, BattleScript_ButItFailed setuserstatus3 STATUS3_MAGNET_RISE, BattleScript_ButItFailed attackanimation waitanimation diff --git a/test/battle/move_effect/magic_room.c b/test/battle/move_effect/magic_room.c index b1be6ac5bc..98d55cfd57 100644 --- a/test/battle/move_effect/magic_room.c +++ b/test/battle/move_effect/magic_room.c @@ -35,3 +35,5 @@ DOUBLE_BATTLE_TEST("Magic Room prevents item hold effects") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); } } + +TO_DO_BATTLE_TEST("TODO: Write Magic Room (Move Effect) test titles") diff --git a/test/battle/move_effect/magnet_rise.c b/test/battle/move_effect/magnet_rise.c index 9fde0046fd..7e50bb24cb 100644 --- a/test/battle/move_effect/magnet_rise.c +++ b/test/battle/move_effect/magnet_rise.c @@ -1,4 +1,57 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Magic Room (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_MAGNET_RISE) == EFFECT_MAGNET_RISE); +} + +SINGLE_BATTLE_TEST("Magnet Rise rises the user into the air, avoiding Ground-type attacks") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_MAGNET_RISE); MOVE(opponent, MOVE_EARTHQUAKE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Magnet Rise fails if the user is Rooted") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_INGRAIN) == EFFECT_INGRAIN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_INGRAIN); } + TURN { MOVE(player, MOVE_MAGNET_RISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_INGRAIN, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + } +} + +SINGLE_BATTLE_TEST("Magnet Rise fails if the user is Grounded by Smack Down") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_SMACK_DOWN) == EFFECT_SMACK_DOWN); + ASSUME(gSpeciesInfo[SPECIES_XATU].types[0] == TYPE_FLYING || gSpeciesInfo[SPECIES_XATU].types[1] == TYPE_FLYING); + PLAYER(SPECIES_XATU); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_SMACK_DOWN); MOVE(player, MOVE_MAGNET_RISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SMACK_DOWN, opponent); + MESSAGE("Xatu fell straight down!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + } +} + +TO_DO_BATTLE_TEST("TODO: Write Magnet Rise (Move Effect) test titles") diff --git a/test/battle/move_effect_secondary/will_o_wisp.c b/test/battle/move_effect_secondary/will_o_wisp.c deleted file mode 100644 index 08b1bd6c69..0000000000 --- a/test/battle/move_effect_secondary/will_o_wisp.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Will-O-Wisp (Move Effect) test titles") From a16d6e3bfe64c0e13415edf3657cf14abd4b12b6 Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 1 Aug 2025 12:10:44 -0400 Subject: [PATCH 153/283] Avoid doubling up on status moves in double battles. (#7452) --- src/battle_ai_main.c | 21 ++++++++++++--- test/battle/ai/ai_doubles.c | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d29becb2ea..fc2ac90b1d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1720,7 +1720,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gBattleMons[battlerAtk].volatiles.dragonCheer || gBattleMons[battlerAtk].volatiles.focusEnergy) ADJUST_SCORE(-10); break; + case EFFECT_NON_VOLATILE_STATUS: + if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY + && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; case EFFECT_CONFUSE: + if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY + && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); case EFFECT_SWAGGER: case EFFECT_FLATTER: if (!AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) @@ -1853,7 +1863,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_STICKY_WEB: if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); - else if (PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) && IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) + if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: @@ -1881,7 +1891,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(-10); //Both enemies are perish songed } - else if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + else if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); } @@ -2547,7 +2557,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // This only happens if the ally already rolled on double trick room on final turn. // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. - if (gFieldTimers.trickRoomTimer == gBattleTurnCounter) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter) ADJUST_SCORE(PERFECT_EFFECT); else ADJUST_SCORE(-10); @@ -2854,6 +2864,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); } break; + case EFFECT_COURT_CHANGE: + case EFFECT_TEATIME: + if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index e4ab8610ab..60dce82801 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -85,6 +85,59 @@ AI_DOUBLE_BATTLE_TEST("AI will not use a status move if partner already chose He } } +TO_DO_BATTLE_TEST("AI understands Instruct") + +TO_DO_BATTLE_TEST("AI understands Quick Guard") +TO_DO_BATTLE_TEST("AI understands Wide Guard") + +AI_DOUBLE_BATTLE_TEST("AI will not use the same nondamaging move as its partner for no reason") +{ + u32 move; + PARAMETRIZE { move = MOVE_AROMATHERAPY; } + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } + PARAMETRIZE { move = MOVE_FOLLOW_ME; } + PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; } + PARAMETRIZE { move = MOVE_GRAVITY; } + PARAMETRIZE { move = MOVE_HAIL; } + PARAMETRIZE { move = MOVE_HEAL_BELL; } + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_LUCKY_CHANT; } + PARAMETRIZE { move = MOVE_MAGIC_ROOM; } + PARAMETRIZE { move = MOVE_MISTY_TERRAIN; } + PARAMETRIZE { move = MOVE_MUD_SPORT; } + PARAMETRIZE { move = MOVE_PSYCHIC_TERRAIN; } + PARAMETRIZE { move = MOVE_RAIN_DANCE; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_SAFEGUARD; } + PARAMETRIZE { move = MOVE_SANDSTORM; } + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + PARAMETRIZE { move = MOVE_SPOTLIGHT; } + PARAMETRIZE { move = MOVE_STEALTH_ROCK; } + PARAMETRIZE { move = MOVE_SUNNY_DAY; } + PARAMETRIZE { move = MOVE_TAILWIND; } + PARAMETRIZE { move = MOVE_TEETER_DANCE; } + PARAMETRIZE { move = MOVE_TRICK_ROOM; } + PARAMETRIZE { move = MOVE_WATER_SPORT; } + PARAMETRIZE { move = MOVE_COURT_CHANGE; } + PARAMETRIZE { move = MOVE_PERISH_SONG; } + PARAMETRIZE { move = MOVE_STICKY_WEB; } + PARAMETRIZE { move = MOVE_TEATIME; } + PARAMETRIZE { move = MOVE_WONDER_ROOM; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); EXPECT_MOVE(opponentRight, MOVE_TACKLE); } + } +} + AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner without a positive effect") { ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); From 0b44093a8e946a0b808888594e49545c0866f592 Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 1 Aug 2025 12:11:34 -0400 Subject: [PATCH 154/283] Adds AI_FLAG_ASSUMPTIONS as a constant for semi-omniscience (#7435) --- include/constants/battle_ai.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index db386be4b0..8781640d60 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -45,6 +45,7 @@ #define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY) #define AI_FLAG_SMART_TRAINER (AI_FLAG_BASIC_TRAINER | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION | AI_FLAG_SMART_TERA) #define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON | AI_FLAG_PREDICT_MOVE) +#define AI_FLAG_ASSUMPTIONS (AI_FLAG_ASSUME_STAB | AI_FLAG_ASSUME_STATUS_MOVES | AI_FLAG_WEIGH_ABILITY_PREDICTION) // 'other' ai logic flags #define AI_FLAG_DYNAMIC_FUNC ((u64)1 << 60) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd From 73fd5675201f8cbbd515289d48a1c1000a7e4a0d Mon Sep 17 00:00:00 2001 From: Nephrite Date: Fri, 1 Aug 2025 19:13:23 +0300 Subject: [PATCH 155/283] Additional effects tweak (#7392) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- docs/tutorials/how_to_new_move.md | 21 ++++++++++++--------- include/battle_ai_util.h | 4 ++-- include/battle_util.h | 2 +- include/constants/battle.h | 2 +- include/constants/battle_string_ids.h | 3 +-- include/move.h | 17 +++++++---------- src/battle_ai_util.c | 4 ++-- src/battle_script_commands.c | 23 ++--------------------- src/battle_tv.c | 2 +- src/battle_util.c | 9 ++------- src/data/moves_info.h | 21 +++++++++++++++------ 11 files changed, 46 insertions(+), 62 deletions(-) diff --git a/docs/tutorials/how_to_new_move.md b/docs/tutorials/how_to_new_move.md index e4289f4c58..442e2b28c9 100644 --- a/docs/tutorials/how_to_new_move.md +++ b/docs/tutorials/how_to_new_move.md @@ -40,7 +40,6 @@ Let's look at an example: .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .sheerForceBoost = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 10, @@ -140,7 +139,18 @@ If you look at the example [here](#srcdatamoves_infoh), you can see that Thunder All additional effects with a defined chance (even 100%) are treated as "secondary effects". This means that they are nullified by Sheer Force, blocked by Shield Dust or the Covert Cloak, and have their chance modified by Serene Grace. Additional effects without a chance field (effectively setting it to 0) are treated as "primary effects", which means that they cannot be blocked by the aforementioned items and abilities and their chance to occur cannot be modified; they will *always* happen. -Each move can have up to 15 additional effects, allowing you to construct monstrosities like this: +Depending on the move effect, it is possible to also set a `multistring` value. For example: + +``` +.additionalEffects = ADDITIONAL_EFFECTS({ + .moveEffect = MOVE_EFFECT_WRAP, + .multistring = B_MSG_WRAPPED_MAGMA_STORM, +}), +``` + +For Magma Storm, we not only want the wrapping move effect, we want to give it a unique string when it activates. The index is an enum defined in `battle_string_ids.h` and it corresponds to an entry (for this move effect) in the `gWrappedStringIds` list in battle_message.c. For custom strings, you need to add an enum and an entry respectively. For new custom move effects, you will have to add a new set of enums and a new table of strings. + +Each move can have up to 3 additional effects, allowing you to construct monstrosities like this: ``` [MOVE_POUND] = { @@ -165,13 +175,6 @@ Each move can have up to 15 additional effects, allowing you to construct monstr },{ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, - },{ - .moveEffect = MOVE_EFFECT_ALL_STATS_UP, - .chance = 40, - .self = TRUE, - },{ - .moveEffect = MOVE_EFFECT_DEF_MINUS_2, - .chance = 50, }), .makesContact = TRUE, .ignoresKingsRock = B_UPDATED_MOVE_FLAGS == GEN_4, diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index ec8c250fd2..f5af4acb33 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -202,8 +202,8 @@ bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move); bool32 HasThawingMove(u32 battler); bool32 IsStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsStatLoweringEffect(enum BattleMoveEffects effect); -bool32 IsSelfStatLoweringEffect(enum MoveEffects effect); -bool32 IsSelfStatRaisingEffect(enum MoveEffects effect); +bool32 IsSelfStatLoweringEffect(enum MoveEffect effect); +bool32 IsSelfStatRaisingEffect(enum MoveEffect effect); bool32 IsSwitchOutEffect(enum BattleMoveEffects effect); bool32 IsChaseEffect(enum BattleMoveEffects effect); bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect); diff --git a/include/battle_util.h b/include/battle_util.h index 272ccf3d1e..95efdd9922 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -357,7 +357,7 @@ bool32 CanBeBurned(u32 battlerAtk, u32 battlerDef, u32 ability); bool32 CanBeParalyzed(u32 battlerAtk, u32 battlerDef, u32 abilityDef); bool32 CanBeFrozen(u32 battlerAtk, u32 battlerDef, u32 abilityDef); bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef); -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects secondaryMoveEffect, enum FunctionCallOption option); +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffect secondaryMoveEffect, enum FunctionCallOption option); bool32 CanBeConfused(u32 battler); bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag); u32 GetBattlerAffectionHearts(u32 battler); diff --git a/include/constants/battle.h b/include/constants/battle.h index de4b3f40ba..5faa91ad7e 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -392,7 +392,7 @@ enum BattleWeather #define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) -enum __attribute__((packed)) MoveEffects +enum __attribute__((packed)) MoveEffect { MOVE_EFFECT_NONE, MOVE_EFFECT_SLEEP, diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 57cf6f7021..df7b5e6232 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -1167,8 +1167,7 @@ enum StartingStatusStringID }; // gWrappedStringIds -// These correspond in order to sTrappingMoves! -enum WrappedStringID +enum __attribute__((packed)) WrappedStringID { B_MSG_WRAPPED_BIND, B_MSG_WRAPPED_WRAP, diff --git a/include/move.h b/include/move.h index fa89ec3cf3..61483e402e 100644 --- a/include/move.h +++ b/include/move.h @@ -4,6 +4,7 @@ #include "contest_effect.h" #include "constants/battle.h" #include "constants/battle_move_effects.h" +#include "constants/battle_string_ids.h" #include "constants/moves.h" // For defining EFFECT_HIT etc. with battle TV scores and flags etc. @@ -21,21 +22,17 @@ struct __attribute__((packed, aligned(2))) BattleMoveEffect #define EFFECTS_ARR(...) (const struct AdditionalEffect[]) {__VA_ARGS__} #define ADDITIONAL_EFFECTS(...) EFFECTS_ARR( __VA_ARGS__ ), .numAdditionalEffects = ARRAY_COUNT(EFFECTS_ARR( __VA_ARGS__ )) -enum SheerForceBoost -{ - SHEER_FORCE_AUTO_BOOST, // This is the default state when a move has a move effect with a chance - SHEER_FORCE_BOOST, // If a move effect doesn't have an effect with a chance this can force a boost - SHEER_FORCE_NO_BOOST, // Prevents a Sheer Force boost -}; - struct AdditionalEffect { - enum MoveEffects moveEffect; + enum MoveEffect moveEffect; u8 self:1; u8 onlyIfTargetRaisedStats:1; u8 onChargeTurnOnly:1; - u8 sheerForceBoost:2; // Handles edge cases for Sheer Force - u8 padding:3; + u8 sheerForceOverride:1; // Handles edge cases for Sheer Force - if TRUE, boosts when it shouldn't, or doesn't boost when it should + u8 padding:4; + union PACKED { + enum WrappedStringID wrapped; + } multistring; u8 chance; // 0% = effect certain, primary effect }; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index dc766c9ee8..b4e0cbaaf4 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2673,7 +2673,7 @@ bool32 IsStatLoweringEffect(enum BattleMoveEffects effect) } } -bool32 IsSelfStatLoweringEffect(enum MoveEffects effect) +bool32 IsSelfStatLoweringEffect(enum MoveEffect effect) { // Self stat lowering moves like Overheart, Superpower etc. switch (effect) @@ -2701,7 +2701,7 @@ bool32 IsSelfStatLoweringEffect(enum MoveEffects effect) } } -bool32 IsSelfStatRaisingEffect(enum MoveEffects effect) +bool32 IsSelfStatRaisingEffect(enum MoveEffect effect) { // Self stat lowering moves like Power Up Punch or Charge Beam switch (effect) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d7ccf40f53..e615c9d2d1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -288,20 +288,6 @@ static const s32 sExperienceScalingFactors[] = 159767, }; -static const u16 sTrappingMoves[NUM_TRAPPING_MOVES] = -{ - MOVE_BIND, - MOVE_WRAP, - MOVE_FIRE_SPIN, - MOVE_CLAMP, - MOVE_WHIRLPOOL, - MOVE_SAND_TOMB, - MOVE_MAGMA_STORM, - MOVE_INFESTATION, - MOVE_SNAP_TRAP, - MOVE_THUNDER_CAGE -}; - static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120 }; enum GiveCaughtMonStates @@ -2900,7 +2886,7 @@ static inline bool32 TrySetLightScreen(u32 battler) return FALSE; } -static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffects effect, enum StatusTrigger trigger) +static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger) { gEffectBattler = effectBattler; @@ -3187,12 +3173,6 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectWrap; - - for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattleCommunication[MULTISTRING_CHOOSER] < NUM_TRAPPING_MOVES; gBattleCommunication[MULTISTRING_CHOOSER]++) - { - if (sTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove) - break; - } } break; case MOVE_EFFECT_ATK_PLUS_1: @@ -4123,6 +4103,7 @@ static void Cmd_setadditionaleffects(void) if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance)) { gBattleScripting.moveEffect = additionalEffect->moveEffect; + gBattleCommunication[MULTISTRING_CHOOSER] = *((u8 *) &additionalEffect->multistring); SetMoveEffect( gBattlerAttacker, diff --git a/src/battle_tv.c b/src/battle_tv.c index dbcb9fb101..e23712beab 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -768,7 +768,7 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3) for (i = 0; i < GetMoveAdditionalEffectCount(move); i++) { const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - switch ((enum MoveEffects)additionalEffect->moveEffect) + switch ((enum MoveEffect)additionalEffect->moveEffect) { case MOVE_EFFECT_ATK_PLUS_1: case MOVE_EFFECT_DEF_PLUS_1: diff --git a/src/battle_util.c b/src/battle_util.c index cd33223a6e..ce82a997cc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5625,7 +5625,7 @@ bool32 CanGetFrostbite(u32 battlerAtk, u32 battlerDef, u32 abilityDef) return FALSE; } -bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffects effect, enum FunctionCallOption option) +bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, enum MoveEffect effect, enum FunctionCallOption option) { const u8 *battleScript = NULL; u32 sideBattler = ABILITY_NONE; @@ -11044,12 +11044,7 @@ bool32 MoveIsAffectedBySheerForce(u32 move) for (i = 0; i < numAdditionalEffects; i++) { const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - if (additionalEffect->sheerForceBoost == SHEER_FORCE_NO_BOOST) - continue; - - if (additionalEffect->chance > 0) - return TRUE; - if (additionalEffect->sheerForceBoost == SHEER_FORCE_BOOST) + if ((additionalEffect->chance > 0) != additionalEffect->sheerForceOverride) return TRUE; } return FALSE; diff --git a/src/data/moves_info.h b/src/data/moves_info.h index adab4af3cc..4edf88f17a 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -631,6 +631,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_BIND, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -1018,6 +1019,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_WRAP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -2255,6 +2257,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_FIRE_SPIN, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -3428,6 +3431,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_CLAMP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -6639,6 +6643,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .damagesUnderwater = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_WHIRLPOOL, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -8670,6 +8675,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_PHYSICAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_SAND_TOMB, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, @@ -11990,6 +11996,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .category = DAMAGE_CATEGORY_SPECIAL, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_MAGMA_STORM, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -15612,6 +15619,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_INFESTATION, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_SMART, @@ -16003,7 +16011,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .soundMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_REMOVE_STATUS, - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .contestEffect = CONTEST_EFFECT_HIGHLY_APPEALING, .contestCategory = CONTEST_CATEGORY_BEAUTY, @@ -17270,7 +17278,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FLINCH, .chance = 30, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_FloatyFall, }, @@ -17953,6 +17961,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_SNAP_TRAP, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -18935,6 +18944,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .metronomeBanned = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_WRAP, + .multistring.wrapped = B_MSG_WRAPPED_THUNDER_CAGE, }), .contestEffect = CONTEST_EFFECT_DONT_EXCITE_AUDIENCE, .contestCategory = CONTEST_CATEGORY_COOL, @@ -19202,7 +19212,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_StoneAxe, }, @@ -19527,7 +19537,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .makesContact = TRUE, .slicingMove = TRUE, .additionalEffects = ADDITIONAL_EFFECTS({ - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_CeaselessEdge, }, @@ -20837,7 +20847,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SP_ATK_PLUS_1, .self = TRUE, .onChargeTurnOnly = TRUE, - .sheerForceBoost = SHEER_FORCE_BOOST, + .sheerForceOverride = TRUE, }), .battleAnimScript = gBattleAnimMove_ElectroShot, }, @@ -21113,7 +21123,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_TOXIC, .chance = 50, - .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_MalignantChain, }, From 9faa5294ced5dc6684bfe2138caf75faf280f777 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:14:42 -0400 Subject: [PATCH 156/283] =?UTF-8?q?Wild=20Pok=C3=A9mon=20animate=20after?= =?UTF-8?q?=20breaking=20out=20of=20Pok=C3=A9=20Ball=20(#7339)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- asm/macros/battle_script.inc | 3 ++- data/battle_scripts_2.s | 3 +++ include/battle_controllers.h | 1 + include/config/battle.h | 31 ++++++++++++++++--------------- src/battle_controllers.c | 9 +++++++++ src/battle_script_commands.c | 10 +++++++--- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index c906938b93..c2a10b175c 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -842,8 +842,9 @@ .byte 0x95 .endm - .macro unused_96 + .macro animatewildpokemonafterfailedpokeball battler:req .byte 0x96 + .byte \battler .endm .macro tryinfatuating failInstr:req diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index 0e0f43893e..b46b30a443 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -211,6 +211,9 @@ BattleScript_WallyBallThrow:: finishturn BattleScript_ShakeBallThrow:: + animatewildpokemonafterfailedpokeball BS_TARGET + waitstate + waitmessage B_WAIT_TIME_LONG printfromtable gBallEscapeStringIds waitmessage B_WAIT_TIME_LONG jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_SAFARI, BattleScript_ShakeBallThrowEnd diff --git a/include/battle_controllers.h b/include/battle_controllers.h index d5166ce6f8..4db4aea969 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -426,6 +426,7 @@ void LinkPartnerBufferExecCompleted(u32 battler); void TrySetBattlerShadowSpriteCallback(u32 battler); +void AnimateMonAfterPokeBallFail(u32 battler); void TryShinyAnimAfterMonAnim(u32 battler); void WaitForMonAnimAfterLoad(u32 battler); void BtlController_HandleSwitchInWaitAndEnd(u32 battler); diff --git a/include/config/battle.h b/include/config/battle.h index a58b174b46..d09698c634 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -267,21 +267,22 @@ #define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain. // Interface settings -#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. -#define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. -#define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped. -#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster. -#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster. -#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move. -#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary and move relearner showing the move's category. -#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations. -#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles. -#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option -#define B_RUN_TRAINER_BATTLE TRUE // If set to TRUE, players can run from Trainer battles. This is treated as a whiteout. -#define B_MOVE_DESCRIPTION_BUTTON L_BUTTON // If set to a button other than B_LAST_USED_BALL_BUTTON, pressing this button will open the move description menu -#define B_SHOW_USELESS_Z_MOVE_INFO FALSE // If set to TRUE, Z-moves without additional effects like newer gen status moves will say "no additional effect" -#define B_ANIMATE_MON_AFTER_KO TRUE // If set to TRUE, if a Pokémon on the opposite site faints, the non-fainted Pokemon will display a victory animation. -#define B_SHOW_DYNAMAX_MESSAGE FALSE // If set to TRUE, an additional battle message is shown after completing Dynamaxing/Gigantamaxing. +#define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. +#define B_FAST_INTRO_PKMN_TEXT TRUE // If set to TRUE, battle intro texts print at the same time as animation of a Pokémon, as opposing to waiting for the animation to end. +#define B_FAST_INTRO_NO_SLIDE FALSE // If set to TRUE, the slide animation that happens at the beginning of the battle is skipped. +#define B_FAST_HP_DRAIN TRUE // If set to TRUE, HP bars will move faster. +#define B_FAST_EXP_GROW TRUE // If set to TRUE, EXP bars will move faster. +#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move. +#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary and move relearner showing the move's category. +#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations. +#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles. +#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option +#define B_RUN_TRAINER_BATTLE TRUE // If set to TRUE, players can run from Trainer battles. This is treated as a whiteout. +#define B_MOVE_DESCRIPTION_BUTTON L_BUTTON // If set to a button other than B_LAST_USED_BALL_BUTTON, pressing this button will open the move description menu +#define B_SHOW_USELESS_Z_MOVE_INFO FALSE // If set to TRUE, Z-moves without additional effects like newer gen status moves will say "no additional effect" +#define B_ANIMATE_MON_AFTER_KO TRUE // If set to TRUE, if a Pokémon on the opposite site faints, the non-fainted Pokemon will display a victory animation. +#define B_ANIMATE_MON_AFTER_FAILED_POKEBALL TRUE // If set to TRUE, if a Pokémon on the opposite side breaks out of a thrown Poké Ball, the wild Pokémon will display its animation. +#define B_SHOW_DYNAMAX_MESSAGE FALSE // If set to TRUE, an additional battle message is shown after completing Dynamaxing/Gigantamaxing. // Catching settings #define B_SEMI_INVULNERABLE_CATCH GEN_LATEST // In Gen4+, you cannot throw a ball against a Pokemon that is in a semi-invulnerable state (dig/fly/etc) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 193248ce27..d0e6117433 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -2860,6 +2860,15 @@ void BtlController_HandleBattleAnimation(u32 battler) } } +void AnimateMonAfterPokeBallFail(u32 battler) +{ + if (B_ANIMATE_MON_AFTER_FAILED_POKEBALL == FALSE) + return; + + LaunchKOAnimation(battler, ReturnAnimIdForBattler(TRUE, battler), TRUE); + TryShinyAnimation(gBattlerTarget, GetBattlerMon(gBattlerTarget)); +} + static void AnimateMonAfterKnockout(u32 battler) { if (B_ANIMATE_MON_AFTER_KO == FALSE) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e615c9d2d1..9c4da75feb 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -486,7 +486,7 @@ static void Cmd_setlightscreen(void); static void Cmd_tryKO(void); static void Cmd_checknonvolatiletrigger(void); static void Cmd_copybidedmg(void); -static void Cmd_unused_96(void); +static void Cmd_animatewildpokemonafterfailedpokeball(void); static void Cmd_tryinfatuating(void); static void Cmd_updatestatusicon(void); static void Cmd_setmist(void); @@ -745,7 +745,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_tryKO, //0x93 Cmd_checknonvolatiletrigger, //0x94 Cmd_copybidedmg, //0x95 - Cmd_unused_96, //0x96 + Cmd_animatewildpokemonafterfailedpokeball, //0x96 Cmd_tryinfatuating, //0x97 Cmd_updatestatusicon, //0x98 Cmd_setmist, //0x99 @@ -11016,8 +11016,12 @@ static void Cmd_copybidedmg(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_unused_96(void) +static void Cmd_animatewildpokemonafterfailedpokeball(void) { + CMD_ARGS(u8 battler); + u8 battler = GetBattlerForBattleScript(cmd->battler); + AnimateMonAfterPokeBallFail(battler); + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_tryinfatuating(void) From 65f9c0475768c6acdfd201c140ddbf861f8ebd12 Mon Sep 17 00:00:00 2001 From: Josh <32826900+ShinyDragonHunter@users.noreply.github.com> Date: Sat, 2 Aug 2025 02:11:50 +0100 Subject: [PATCH 157/283] Key split restructure (#2168) Key split tables have been given names based on usage (KeySplitTable1 -> keysplit_piano etc) and a new macro has been set up to better represent the individual bytes for key splits with it being more obvious to how said bytes are used for the respective voice in the voicegroup. --------- Co-authored-by: Martin Griffin --- asm/macros/m4a.inc | 28 ++ sound/keysplit_tables.inc | 398 +------------------- sound/voicegroups/abandoned_ship.inc | 4 +- sound/voicegroups/abnormal_weather.inc | 4 +- sound/voicegroups/aqua_magma_hideout.inc | 2 +- sound/voicegroups/b_factory.inc | 4 +- sound/voicegroups/b_frontier.inc | 6 +- sound/voicegroups/b_palace.inc | 2 +- sound/voicegroups/b_pike.inc | 6 +- sound/voicegroups/b_pyramid.inc | 8 +- sound/voicegroups/b_pyramid_top.inc | 4 +- sound/voicegroups/b_tower.inc | 8 +- sound/voicegroups/b_tower_rs.inc | 8 +- sound/voicegroups/birch_lab.inc | 4 +- sound/voicegroups/cable_car.inc | 6 +- sound/voicegroups/cave_of_origin.inc | 6 +- sound/voicegroups/contest.inc | 6 +- sound/voicegroups/contest_lobby.inc | 4 +- sound/voicegroups/contest_winner.inc | 2 +- sound/voicegroups/credits.inc | 10 +- sound/voicegroups/cycling.inc | 8 +- sound/voicegroups/dewford.inc | 8 +- sound/voicegroups/dummy.inc | 6 +- sound/voicegroups/encounter_aqua.inc | 4 +- sound/voicegroups/encounter_brendan.inc | 4 +- sound/voicegroups/encounter_champion.inc | 2 +- sound/voicegroups/encounter_cool.inc | 2 +- sound/voicegroups/encounter_elite_four.inc | 2 +- sound/voicegroups/encounter_female.inc | 4 +- sound/voicegroups/encounter_girl.inc | 2 +- sound/voicegroups/encounter_hiker.inc | 6 +- sound/voicegroups/encounter_intense.inc | 2 +- sound/voicegroups/encounter_interviewer.inc | 2 +- sound/voicegroups/encounter_magma.inc | 4 +- sound/voicegroups/encounter_male.inc | 2 +- sound/voicegroups/encounter_may.inc | 2 +- sound/voicegroups/encounter_rich.inc | 6 +- sound/voicegroups/encounter_suspicious.inc | 4 +- sound/voicegroups/encounter_swimmer.inc | 4 +- sound/voicegroups/ever_grande.inc | 4 +- sound/voicegroups/evolution.inc | 2 +- sound/voicegroups/fallarbor.inc | 8 +- sound/voicegroups/fanfare.inc | 10 +- sound/voicegroups/fortree.inc | 2 +- sound/voicegroups/frlg_sfx.inc | 2 +- sound/voicegroups/game_corner.inc | 8 +- sound/voicegroups/gym.inc | 6 +- sound/voicegroups/hall_of_fame.inc | 8 +- sound/voicegroups/hall_of_fame_room.inc | 6 +- sound/voicegroups/help.inc | 4 +- sound/voicegroups/intro.inc | 10 +- sound/voicegroups/intro_battle.inc | 10 +- sound/voicegroups/lilycove.inc | 6 +- sound/voicegroups/lilycove_museum.inc | 6 +- sound/voicegroups/link_contest_p1.inc | 6 +- sound/voicegroups/link_contest_p2.inc | 6 +- sound/voicegroups/link_contest_p3.inc | 6 +- sound/voicegroups/link_contest_p4.inc | 6 +- sound/voicegroups/littleroot.inc | 4 +- sound/voicegroups/littleroot_test.inc | 4 +- sound/voicegroups/mt_chimney.inc | 8 +- sound/voicegroups/mt_pyre.inc | 4 +- sound/voicegroups/mt_pyre_exterior.inc | 4 +- sound/voicegroups/oceanic_museum.inc | 6 +- sound/voicegroups/oldale.inc | 6 +- sound/voicegroups/petalburg.inc | 4 +- sound/voicegroups/petalburg_woods.inc | 4 +- sound/voicegroups/poke_center.inc | 4 +- sound/voicegroups/poke_mart.inc | 2 +- sound/voicegroups/rg_caught_intro.inc | 10 +- sound/voicegroups/rg_celadon.inc | 6 +- sound/voicegroups/rg_cinnabar.inc | 6 +- sound/voicegroups/rg_credits.inc | 10 +- sound/voicegroups/rg_cycling.inc | 6 +- sound/voicegroups/rg_encounter_boy.inc | 4 +- sound/voicegroups/rg_encounter_girl.inc | 4 +- sound/voicegroups/rg_encounter_rival.inc | 8 +- sound/voicegroups/rg_follow_me.inc | 2 +- sound/voicegroups/rg_fuchsia.inc | 2 +- sound/voicegroups/rg_game_corner.inc | 8 +- sound/voicegroups/rg_game_freak.inc | 2 +- sound/voicegroups/rg_gym.inc | 6 +- sound/voicegroups/rg_hall_of_fame.inc | 6 +- sound/voicegroups/rg_intro_fight.inc | 4 +- sound/voicegroups/rg_lavender.inc | 8 +- sound/voicegroups/rg_mt_moon.inc | 4 +- sound/voicegroups/rg_new_game.inc | 8 +- sound/voicegroups/rg_oak.inc | 8 +- sound/voicegroups/rg_oak_lab.inc | 2 +- sound/voicegroups/rg_pallet.inc | 2 +- sound/voicegroups/rg_pewter.inc | 4 +- sound/voicegroups/rg_photo.inc | 2 +- sound/voicegroups/rg_poke_center.inc | 2 +- sound/voicegroups/rg_poke_mansion.inc | 4 +- sound/voicegroups/rg_poke_tower.inc | 8 +- sound/voicegroups/rg_rocket_hideout.inc | 8 +- sound/voicegroups/rg_route11.inc | 10 +- sound/voicegroups/rg_route24.inc | 8 +- sound/voicegroups/rg_route3.inc | 8 +- sound/voicegroups/rg_sevii_45.inc | 4 +- sound/voicegroups/rg_sevii_67.inc | 4 +- sound/voicegroups/rg_sevii_route.inc | 8 +- sound/voicegroups/rg_silph.inc | 8 +- sound/voicegroups/rg_ss_anne.inc | 6 +- sound/voicegroups/rg_surf.inc | 4 +- sound/voicegroups/rg_teachy_tv_menu.inc | 2 +- sound/voicegroups/rg_title.inc | 8 +- sound/voicegroups/rg_vermillion.inc | 6 +- sound/voicegroups/rg_victory_gym_leader.inc | 6 +- sound/voicegroups/rg_victory_road.inc | 8 +- sound/voicegroups/rg_victory_trainer.inc | 4 +- sound/voicegroups/rg_victory_wild.inc | 4 +- sound/voicegroups/rg_viridian_forest.inc | 2 +- sound/voicegroups/rg_vs_champion.inc | 8 +- sound/voicegroups/rg_vs_deoxys.inc | 6 +- sound/voicegroups/rg_vs_gym_leader.inc | 8 +- sound/voicegroups/rg_vs_trainer.inc | 8 +- sound/voicegroups/rg_vs_wild.inc | 8 +- sound/voicegroups/route101.inc | 2 +- sound/voicegroups/route104.inc | 8 +- sound/voicegroups/route110.inc | 8 +- sound/voicegroups/route111.inc | 8 +- sound/voicegroups/route113.inc | 4 +- sound/voicegroups/route119.inc | 8 +- sound/voicegroups/route120.inc | 8 +- sound/voicegroups/route122.inc | 8 +- sound/voicegroups/rs_sfx_1.inc | 2 +- sound/voicegroups/rustboro.inc | 4 +- sound/voicegroups/sailing.inc | 2 +- sound/voicegroups/school.inc | 2 +- sound/voicegroups/sealed_chamber.inc | 4 +- sound/voicegroups/slateport.inc | 4 +- sound/voicegroups/sootopolis.inc | 8 +- sound/voicegroups/surf.inc | 6 +- sound/voicegroups/title.inc | 10 +- sound/voicegroups/trick_house.inc | 6 +- sound/voicegroups/underwater.inc | 2 +- sound/voicegroups/verdanturf.inc | 4 +- sound/voicegroups/victory_aqua_magma.inc | 4 +- sound/voicegroups/victory_gym_leader.inc | 6 +- sound/voicegroups/victory_league.inc | 6 +- sound/voicegroups/victory_road.inc | 10 +- sound/voicegroups/victory_trainer.inc | 4 +- sound/voicegroups/victory_wild.inc | 4 +- sound/voicegroups/vs_aqua_magma.inc | 6 +- sound/voicegroups/vs_aqua_magma_leader.inc | 6 +- sound/voicegroups/vs_champion.inc | 8 +- sound/voicegroups/vs_elite_four.inc | 6 +- sound/voicegroups/vs_frontier_brain.inc | 8 +- sound/voicegroups/vs_gym_leader.inc | 8 +- sound/voicegroups/vs_kyogre_groudon.inc | 6 +- sound/voicegroups/vs_mew.inc | 8 +- sound/voicegroups/vs_rayquaza.inc | 6 +- sound/voicegroups/vs_regi.inc | 4 +- sound/voicegroups/vs_rival.inc | 8 +- sound/voicegroups/vs_trainer.inc | 8 +- sound/voicegroups/vs_wild.inc | 8 +- 157 files changed, 472 insertions(+), 802 deletions(-) diff --git a/asm/macros/m4a.inc b/asm/macros/m4a.inc index 57853c9abd..0169a3c033 100644 --- a/asm/macros/m4a.inc +++ b/asm/macros/m4a.inc @@ -21,3 +21,31 @@ .set voicegroup_\label, . - \starting_note * 0xC .endif .endm + + .macro keysplit label:req, starting_note + .ifb \starting_note + .global keysplit_\label + keysplit_\label: + .set _last_note, 0 + .else + .set keysplit_\label, . - \starting_note + .set _last_note, \starting_note + .endif + .set _last_split, 0 + .endm + + .macro split index:req, ending_note:req + .if \ending_note < _last_note + .if _last_split == 0 + .error "split's ending_note earlier than previous keysplit's starting_note" + .else + .error "split's ending_note earlier than previous split's ending_note" + .endif + .else + .rept \ending_note - _last_note + .byte \index + .endr + .endif + .set _last_note, \ending_note + .set _last_split, 1 + .endm diff --git a/sound/keysplit_tables.inc b/sound/keysplit_tables.inc index 81301ef62b..a3145e64d2 100644 --- a/sound/keysplit_tables.inc +++ b/sound/keysplit_tables.inc @@ -1,6 +1,6 @@ @ Due to the way mks4agb (Nintendo's tool) works, key split table labels can @ appear before the actual start of the key split table data. If you look at -@ the first keysplit table (KeySplitTable1), you'll notice it's offset backwards +@ the first keysplit table (keysplit_piano), you'll notice it's offset backwards @ by 36 bytes. This is because the key split tables don't map instruments @ for the entire note range (0-127)--they only map subsets, and the upper @ and lower ranges aren't necessarily 0 or 127. @@ -10,384 +10,26 @@ @ begins. Therefore, the notes naturally map to the key split table without @ any extra offset calculation. -.set KeySplitTable1, . - 36 - .byte 0 @ 36 - .byte 0 @ 37 - .byte 0 @ 38 - .byte 0 @ 39 - .byte 0 @ 40 - .byte 0 @ 41 - .byte 0 @ 42 - .byte 0 @ 43 - .byte 0 @ 44 - .byte 0 @ 45 - .byte 0 @ 46 - .byte 0 @ 47 - .byte 0 @ 48 - .byte 0 @ 49 - .byte 0 @ 50 - .byte 0 @ 51 - .byte 0 @ 52 - .byte 0 @ 53 - .byte 0 @ 54 - .byte 1 @ 55 - .byte 1 @ 56 - .byte 1 @ 57 - .byte 1 @ 58 - .byte 1 @ 59 - .byte 1 @ 60 - .byte 1 @ 61 - .byte 1 @ 62 - .byte 1 @ 63 - .byte 1 @ 64 - .byte 1 @ 65 - .byte 1 @ 66 - .byte 1 @ 67 - .byte 1 @ 68 - .byte 1 @ 69 - .byte 2 @ 70 - .byte 2 @ 71 - .byte 2 @ 72 - .byte 2 @ 73 - .byte 2 @ 74 - .byte 2 @ 75 - .byte 2 @ 76 - .byte 2 @ 77 - .byte 2 @ 78 - .byte 2 @ 79 - .byte 2 @ 80 - .byte 2 @ 81 - .byte 2 @ 82 - .byte 2 @ 83 - .byte 2 @ 84 - .byte 2 @ 85 - .byte 2 @ 86 - .byte 2 @ 87 - .byte 2 @ 88 - .byte 2 @ 89 - .byte 2 @ 90 - .byte 3 @ 91 - .byte 3 @ 92 - .byte 3 @ 93 - .byte 3 @ 94 - .byte 3 @ 95 - .byte 3 @ 96 - .byte 3 @ 97 - .byte 3 @ 98 - .byte 3 @ 99 - .byte 3 @ 100 - .byte 3 @ 101 - .byte 3 @ 102 - .byte 3 @ 103 - .byte 3 @ 104 - .byte 3 @ 105 - .byte 3 @ 106 - .byte 3 @ 107 +keysplit piano, 36 + split 0, 55 + split 1, 70 + split 2, 91 + split 3, 108 -.set KeySplitTable2, . - 36 - .byte 0 @ 36 - .byte 0 @ 37 - .byte 0 @ 38 - .byte 0 @ 39 - .byte 0 @ 40 - .byte 0 @ 41 - .byte 0 @ 42 - .byte 0 @ 43 - .byte 0 @ 44 - .byte 0 @ 45 - .byte 0 @ 46 - .byte 0 @ 47 - .byte 0 @ 48 - .byte 0 @ 49 - .byte 0 @ 50 - .byte 0 @ 51 - .byte 0 @ 52 - .byte 0 @ 53 - .byte 0 @ 54 - .byte 0 @ 55 - .byte 0 @ 56 - .byte 0 @ 57 - .byte 0 @ 58 - .byte 0 @ 59 - .byte 0 @ 60 - .byte 0 @ 61 - .byte 0 @ 62 - .byte 0 @ 63 - .byte 0 @ 64 - .byte 0 @ 65 - .byte 0 @ 66 - .byte 0 @ 67 - .byte 0 @ 68 - .byte 1 @ 69 - .byte 1 @ 70 - .byte 1 @ 71 - .byte 1 @ 72 - .byte 1 @ 73 - .byte 1 @ 74 - .byte 1 @ 75 - .byte 1 @ 76 - .byte 1 @ 77 - .byte 1 @ 78 - .byte 1 @ 79 - .byte 1 @ 80 - .byte 2 @ 81 - .byte 2 @ 82 - .byte 2 @ 83 - .byte 2 @ 84 - .byte 2 @ 85 - .byte 2 @ 86 - .byte 2 @ 87 - .byte 2 @ 88 - .byte 2 @ 89 - .byte 2 @ 90 - .byte 2 @ 91 - .byte 2 @ 92 - .byte 2 @ 93 - .byte 2 @ 94 - .byte 2 @ 95 - .byte 2 @ 96 - .byte 2 @ 97 - .byte 2 @ 98 - .byte 2 @ 99 - .byte 2 @ 100 - .byte 2 @ 101 - .byte 2 @ 102 - .byte 2 @ 103 - .byte 2 @ 104 - .byte 2 @ 105 - .byte 2 @ 106 - .byte 2 @ 107 +keysplit strings, 36 + split 0, 69 + split 1, 81 + split 2, 108 -.set KeySplitTable3, . - 36 - .byte 0 @ 36 - .byte 0 @ 37 - .byte 0 @ 38 - .byte 0 @ 39 - .byte 0 @ 40 - .byte 0 @ 41 - .byte 0 @ 42 - .byte 0 @ 43 - .byte 0 @ 44 - .byte 0 @ 45 - .byte 0 @ 46 - .byte 0 @ 47 - .byte 0 @ 48 - .byte 0 @ 49 - .byte 0 @ 50 - .byte 0 @ 51 - .byte 0 @ 52 - .byte 0 @ 53 - .byte 0 @ 54 - .byte 0 @ 55 - .byte 0 @ 56 - .byte 0 @ 57 - .byte 0 @ 58 - .byte 0 @ 59 - .byte 0 @ 60 - .byte 0 @ 61 - .byte 0 @ 62 - .byte 0 @ 63 - .byte 0 @ 64 - .byte 0 @ 65 - .byte 1 @ 66 - .byte 1 @ 67 - .byte 1 @ 68 - .byte 1 @ 69 - .byte 1 @ 70 - .byte 1 @ 71 - .byte 1 @ 72 - .byte 1 @ 73 - .byte 1 @ 74 - .byte 1 @ 75 - .byte 1 @ 76 - .byte 1 @ 77 - .byte 1 @ 78 - .byte 1 @ 79 - .byte 1 @ 80 - .byte 1 @ 81 - .byte 1 @ 82 - .byte 1 @ 83 - .byte 2 @ 84 - .byte 2 @ 85 - .byte 2 @ 86 - .byte 2 @ 87 - .byte 2 @ 88 - .byte 2 @ 89 - .byte 2 @ 90 - .byte 2 @ 91 - .byte 2 @ 92 - .byte 2 @ 93 - .byte 2 @ 94 - .byte 2 @ 95 - .byte 2 @ 96 - .byte 2 @ 97 - .byte 2 @ 98 - .byte 2 @ 99 - .byte 2 @ 100 - .byte 2 @ 101 - .byte 2 @ 102 - .byte 2 @ 103 - .byte 2 @ 104 - .byte 2 @ 105 - .byte 2 @ 106 - .byte 2 @ 107 +keysplit trumpet, 36 + split 0, 66 + split 1, 84 + split 2, 108 -.set KeySplitTable4, . - 24 - .byte 0 @ 24 - .byte 0 @ 25 - .byte 0 @ 26 - .byte 0 @ 27 - .byte 0 @ 28 - .byte 0 @ 29 - .byte 0 @ 30 - .byte 0 @ 31 - .byte 0 @ 32 - .byte 0 @ 33 - .byte 0 @ 34 - .byte 0 @ 35 - .byte 0 @ 36 - .byte 0 @ 37 - .byte 0 @ 38 - .byte 0 @ 39 - .byte 0 @ 40 - .byte 0 @ 41 - .byte 1 @ 42 - .byte 1 @ 43 - .byte 1 @ 44 - .byte 1 @ 45 - .byte 1 @ 46 - .byte 1 @ 47 - .byte 1 @ 48 - .byte 1 @ 49 - .byte 1 @ 50 - .byte 1 @ 51 - .byte 1 @ 52 - .byte 1 @ 53 - .byte 1 @ 54 - .byte 1 @ 55 - .byte 1 @ 56 - .byte 1 @ 57 - .byte 1 @ 58 - .byte 1 @ 59 - .byte 1 @ 60 - .byte 1 @ 61 - .byte 1 @ 62 - .byte 1 @ 63 - .byte 1 @ 64 - .byte 1 @ 65 - .byte 1 @ 66 - .byte 1 @ 67 - .byte 1 @ 68 - .byte 1 @ 69 - .byte 1 @ 70 - .byte 1 @ 71 - .byte 1 @ 72 - .byte 1 @ 73 - .byte 1 @ 74 - .byte 1 @ 75 - .byte 1 @ 76 - .byte 1 @ 77 - .byte 1 @ 78 - .byte 1 @ 79 - .byte 1 @ 80 - .byte 1 @ 81 - .byte 1 @ 82 - .byte 1 @ 83 - .byte 1 @ 84 - .byte 1 @ 85 - .byte 1 @ 86 - .byte 1 @ 87 - .byte 1 @ 88 - .byte 1 @ 89 - .byte 1 @ 90 - .byte 1 @ 91 - .byte 1 @ 92 - .byte 1 @ 93 - .byte 1 @ 94 - .byte 1 @ 95 - .byte 1 @ 96 - .byte 1 @ 97 - .byte 1 @ 98 - .byte 1 @ 99 - .byte 1 @ 100 - .byte 1 @ 101 - .byte 1 @ 102 - .byte 1 @ 103 - .byte 1 @ 104 - .byte 1 @ 105 - .byte 1 @ 106 - .byte 1 @ 107 +keysplit tuba, 24 + split 0, 42 + split 1, 108 -.set KeySplitTable5, . - 36 - .byte 0 @ 36 - .byte 0 @ 37 - .byte 0 @ 38 - .byte 0 @ 39 - .byte 0 @ 40 - .byte 0 @ 41 - .byte 0 @ 42 - .byte 0 @ 43 - .byte 0 @ 44 - .byte 0 @ 45 - .byte 0 @ 46 - .byte 0 @ 47 - .byte 0 @ 48 - .byte 0 @ 49 - .byte 0 @ 50 - .byte 0 @ 51 - .byte 0 @ 52 - .byte 0 @ 53 - .byte 0 @ 54 - .byte 0 @ 55 - .byte 0 @ 56 - .byte 0 @ 57 - .byte 0 @ 58 - .byte 0 @ 59 - .byte 0 @ 60 - .byte 0 @ 61 - .byte 0 @ 62 - .byte 0 @ 63 - .byte 0 @ 64 - .byte 0 @ 65 - .byte 1 @ 66 - .byte 1 @ 67 - .byte 1 @ 68 - .byte 1 @ 69 - .byte 1 @ 70 - .byte 1 @ 71 - .byte 1 @ 72 - .byte 1 @ 73 - .byte 1 @ 74 - .byte 1 @ 75 - .byte 1 @ 76 - .byte 1 @ 77 - .byte 1 @ 78 - .byte 1 @ 79 - .byte 1 @ 80 - .byte 1 @ 81 - .byte 1 @ 82 - .byte 1 @ 83 - .byte 1 @ 84 - .byte 1 @ 85 - .byte 1 @ 86 - .byte 1 @ 87 - .byte 1 @ 88 - .byte 1 @ 89 - .byte 1 @ 90 - .byte 1 @ 91 - .byte 1 @ 92 - .byte 1 @ 93 - .byte 1 @ 94 - .byte 1 @ 95 - .byte 1 @ 96 - .byte 1 @ 97 - .byte 1 @ 98 - .byte 1 @ 99 - .byte 1 @ 100 - .byte 1 @ 101 - .byte 1 @ 102 - .byte 1 @ 103 - .byte 1 @ 104 - .byte 1 @ 105 - .byte 1 @ 106 - .byte 1 @ 107 +keysplit french_horn, 36 + split 0, 66 + split 1, 108 diff --git a/sound/voicegroups/abandoned_ship.inc b/sound/voicegroups/abandoned_ship.inc index 37b1e7a95e..dd4ab482fd 100644 --- a/sound/voicegroups/abandoned_ship.inc +++ b/sound/voicegroups/abandoned_ship.inc @@ -1,6 +1,6 @@ voice_group abandoned_ship voice_keysplit_all voicegroup_route110_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group abandoned_ship voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/abnormal_weather.inc b/sound/voicegroups/abnormal_weather.inc index fc6ac4639d..36547c4957 100644 --- a/sound/voicegroups/abnormal_weather.inc +++ b/sound/voicegroups/abnormal_weather.inc @@ -48,7 +48,7 @@ voice_group abnormal_weather voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -60,7 +60,7 @@ voice_group abnormal_weather voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/aqua_magma_hideout.inc b/sound/voicegroups/aqua_magma_hideout.inc index f9feafc9e9..5790be7e96 100644 --- a/sound/voicegroups/aqua_magma_hideout.inc +++ b/sound/voicegroups/aqua_magma_hideout.inc @@ -55,7 +55,7 @@ voice_group aqua_magma_hideout voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_factory.inc b/sound/voicegroups/b_factory.inc index 4f6af2cd29..329741050d 100644 --- a/sound/voicegroups/b_factory.inc +++ b/sound/voicegroups/b_factory.inc @@ -55,11 +55,11 @@ voice_group b_factory voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_frontier.inc b/sound/voicegroups/b_frontier.inc index 50a3287746..bcdcfded3d 100644 --- a/sound/voicegroups/b_frontier.inc +++ b/sound/voicegroups/b_frontier.inc @@ -47,7 +47,7 @@ voice_group b_frontier voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group b_frontier voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_palace.inc b/sound/voicegroups/b_palace.inc index 6fe0cf3971..1e0db2616d 100644 --- a/sound/voicegroups/b_palace.inc +++ b/sound/voicegroups/b_palace.inc @@ -1,6 +1,6 @@ voice_group b_palace voice_keysplit_all voicegroup_emerald_drumset_2 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_pike.inc b/sound/voicegroups/b_pike.inc index 266a4be4b8..deb900a599 100644 --- a/sound/voicegroups/b_pike.inc +++ b/sound/voicegroups/b_pike.inc @@ -1,6 +1,6 @@ voice_group b_pike voice_keysplit_all voicegroup_emerald_drumset_1 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_21, 0, 7, 15, 1 @@ -47,7 +47,7 @@ voice_group b_pike voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group b_pike voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_pyramid.inc b/sound/voicegroups/b_pyramid.inc index f3016ab727..855088884f 100644 --- a/sound/voicegroups/b_pyramid.inc +++ b/sound/voicegroups/b_pyramid.inc @@ -1,6 +1,6 @@ voice_group b_pyramid voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group b_pyramid voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group b_pyramid voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_pyramid_top.inc b/sound/voicegroups/b_pyramid_top.inc index 1cc81ff7c2..95707f5920 100644 --- a/sound/voicegroups/b_pyramid_top.inc +++ b/sound/voicegroups/b_pyramid_top.inc @@ -47,7 +47,7 @@ voice_group b_pyramid_top voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group b_pyramid_top voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_tower.inc b/sound/voicegroups/b_tower.inc index 4abf332680..d8fd60920b 100644 --- a/sound/voicegroups/b_tower.inc +++ b/sound/voicegroups/b_tower.inc @@ -1,6 +1,6 @@ voice_group b_tower voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group b_tower voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group b_tower voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/b_tower_rs.inc b/sound/voicegroups/b_tower_rs.inc index dc06a0e462..777e1b3a7c 100644 --- a/sound/voicegroups/b_tower_rs.inc +++ b/sound/voicegroups/b_tower_rs.inc @@ -1,6 +1,6 @@ voice_group b_tower_rs voice_keysplit_all voicegroup_route110_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 2, 0, 1, 7, 1 @@ -47,7 +47,7 @@ voice_group b_tower_rs voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group b_tower_rs voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/birch_lab.inc b/sound/voicegroups/birch_lab.inc index 20e7edd4b6..2b10e4f1e2 100644 --- a/sound/voicegroups/birch_lab.inc +++ b/sound/voicegroups/birch_lab.inc @@ -47,7 +47,7 @@ voice_group birch_lab voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group birch_lab voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/cable_car.inc b/sound/voicegroups/cable_car.inc index 7cb2fb8a58..85d324b02d 100644 --- a/sound/voicegroups/cable_car.inc +++ b/sound/voicegroups/cable_car.inc @@ -55,11 +55,11 @@ voice_group cable_car voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/cave_of_origin.inc b/sound/voicegroups/cave_of_origin.inc index d1bd42e395..36ded3d35f 100644 --- a/sound/voicegroups/cave_of_origin.inc +++ b/sound/voicegroups/cave_of_origin.inc @@ -47,7 +47,7 @@ voice_group cave_of_origin voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group cave_of_origin voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/contest.inc b/sound/voicegroups/contest.inc index f0c245089d..24ff586dfc 100644 --- a/sound/voicegroups/contest.inc +++ b/sound/voicegroups/contest.inc @@ -47,7 +47,7 @@ voice_group contest voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group contest voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/contest_lobby.inc b/sound/voicegroups/contest_lobby.inc index ec606540f1..88b1402b39 100644 --- a/sound/voicegroups/contest_lobby.inc +++ b/sound/voicegroups/contest_lobby.inc @@ -55,9 +55,9 @@ voice_group contest_lobby voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/contest_winner.inc b/sound/voicegroups/contest_winner.inc index e1d55a7238..df323c002f 100644 --- a/sound/voicegroups/contest_winner.inc +++ b/sound/voicegroups/contest_winner.inc @@ -55,7 +55,7 @@ voice_group contest_winner voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/credits.inc b/sound/voicegroups/credits.inc index 6234450ed2..d05ac8025c 100644 --- a/sound/voicegroups/credits.inc +++ b/sound/voicegroups/credits.inc @@ -1,6 +1,6 @@ voice_group credits voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 1, 1, 5, 2, 4 @@ -47,7 +47,7 @@ voice_group credits voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group credits voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/cycling.inc b/sound/voicegroups/cycling.inc index 496c41cdd6..a734c5fe60 100644 --- a/sound/voicegroups/cycling.inc +++ b/sound/voicegroups/cycling.inc @@ -1,6 +1,6 @@ voice_group cycling voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group cycling voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group cycling voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/dewford.inc b/sound/voicegroups/dewford.inc index 7de8c35be9..e0fc659a9b 100644 --- a/sound/voicegroups/dewford.inc +++ b/sound/voicegroups/dewford.inc @@ -1,6 +1,6 @@ voice_group dewford voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group dewford voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group dewford voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/dummy.inc b/sound/voicegroups/dummy.inc index 34b4275bc1..43b431f856 100644 --- a/sound/voicegroups/dummy.inc +++ b/sound/voicegroups/dummy.inc @@ -1,6 +1,6 @@ voice_group dummy voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group dummy voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group dummy voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_aqua.inc b/sound/voicegroups/encounter_aqua.inc index ce60ac2653..f45e9843c4 100644 --- a/sound/voicegroups/encounter_aqua.inc +++ b/sound/voicegroups/encounter_aqua.inc @@ -1,6 +1,6 @@ voice_group encounter_aqua voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group encounter_aqua voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_brendan.inc b/sound/voicegroups/encounter_brendan.inc index f6f5c3ce9b..3e0f96b624 100644 --- a/sound/voicegroups/encounter_brendan.inc +++ b/sound/voicegroups/encounter_brendan.inc @@ -1,6 +1,6 @@ voice_group encounter_brendan voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group encounter_brendan voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_champion.inc b/sound/voicegroups/encounter_champion.inc index f6f9e64b25..fde001b902 100644 --- a/sound/voicegroups/encounter_champion.inc +++ b/sound/voicegroups/encounter_champion.inc @@ -55,7 +55,7 @@ voice_group encounter_champion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_cool.inc b/sound/voicegroups/encounter_cool.inc index 6dbf63464a..b0e0b9b454 100644 --- a/sound/voicegroups/encounter_cool.inc +++ b/sound/voicegroups/encounter_cool.inc @@ -55,7 +55,7 @@ voice_group encounter_cool voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_elite_four.inc b/sound/voicegroups/encounter_elite_four.inc index 131a04ece7..b7842d6d03 100644 --- a/sound/voicegroups/encounter_elite_four.inc +++ b/sound/voicegroups/encounter_elite_four.inc @@ -55,7 +55,7 @@ voice_group encounter_elite_four voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_female.inc b/sound/voicegroups/encounter_female.inc index cae41b553a..e98854b173 100644 --- a/sound/voicegroups/encounter_female.inc +++ b/sound/voicegroups/encounter_female.inc @@ -1,6 +1,6 @@ voice_group encounter_female voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group encounter_female voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_girl.inc b/sound/voicegroups/encounter_girl.inc index 850b020bc7..47426833b9 100644 --- a/sound/voicegroups/encounter_girl.inc +++ b/sound/voicegroups/encounter_girl.inc @@ -1,6 +1,6 @@ voice_group encounter_girl voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_hiker.inc b/sound/voicegroups/encounter_hiker.inc index 5c799ecacc..826fe14025 100644 --- a/sound/voicegroups/encounter_hiker.inc +++ b/sound/voicegroups/encounter_hiker.inc @@ -1,6 +1,6 @@ voice_group encounter_hiker voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group encounter_hiker voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_intense.inc b/sound/voicegroups/encounter_intense.inc index 3ac97d2b21..650fb2a8a3 100644 --- a/sound/voicegroups/encounter_intense.inc +++ b/sound/voicegroups/encounter_intense.inc @@ -55,7 +55,7 @@ voice_group encounter_intense voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_interviewer.inc b/sound/voicegroups/encounter_interviewer.inc index 0a6d62e3b9..1f3f5248a7 100644 --- a/sound/voicegroups/encounter_interviewer.inc +++ b/sound/voicegroups/encounter_interviewer.inc @@ -55,7 +55,7 @@ voice_group encounter_interviewer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_magma.inc b/sound/voicegroups/encounter_magma.inc index fa77bd2ebd..f41d1f5ad2 100644 --- a/sound/voicegroups/encounter_magma.inc +++ b/sound/voicegroups/encounter_magma.inc @@ -55,11 +55,11 @@ voice_group encounter_magma voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_male.inc b/sound/voicegroups/encounter_male.inc index fd2da689e6..80cc90476c 100644 --- a/sound/voicegroups/encounter_male.inc +++ b/sound/voicegroups/encounter_male.inc @@ -55,7 +55,7 @@ voice_group encounter_male voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_may.inc b/sound/voicegroups/encounter_may.inc index cf909245e2..d4915bb36e 100644 --- a/sound/voicegroups/encounter_may.inc +++ b/sound/voicegroups/encounter_may.inc @@ -55,7 +55,7 @@ voice_group encounter_may voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_rich.inc b/sound/voicegroups/encounter_rich.inc index 7ae524d2bb..d5ed5ddcc0 100644 --- a/sound/voicegroups/encounter_rich.inc +++ b/sound/voicegroups/encounter_rich.inc @@ -1,6 +1,6 @@ voice_group encounter_rich voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group encounter_rich voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,7 +57,7 @@ voice_group encounter_rich voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_suspicious.inc b/sound/voicegroups/encounter_suspicious.inc index 4722f618d3..41f59bc128 100644 --- a/sound/voicegroups/encounter_suspicious.inc +++ b/sound/voicegroups/encounter_suspicious.inc @@ -47,7 +47,7 @@ voice_group encounter_suspicious voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,7 +57,7 @@ voice_group encounter_suspicious voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/encounter_swimmer.inc b/sound/voicegroups/encounter_swimmer.inc index de50110ac1..eaafd5e332 100644 --- a/sound/voicegroups/encounter_swimmer.inc +++ b/sound/voicegroups/encounter_swimmer.inc @@ -47,7 +47,7 @@ voice_group encounter_swimmer voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group encounter_swimmer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/ever_grande.inc b/sound/voicegroups/ever_grande.inc index 1fe7110529..bd8acc879e 100644 --- a/sound/voicegroups/ever_grande.inc +++ b/sound/voicegroups/ever_grande.inc @@ -1,6 +1,6 @@ voice_group ever_grande voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group ever_grande voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/evolution.inc b/sound/voicegroups/evolution.inc index 5ccefa3dbe..b3513a15e7 100644 --- a/sound/voicegroups/evolution.inc +++ b/sound/voicegroups/evolution.inc @@ -59,7 +59,7 @@ voice_group evolution voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/fallarbor.inc b/sound/voicegroups/fallarbor.inc index f129e5094a..3cc2ba6bbe 100644 --- a/sound/voicegroups/fallarbor.inc +++ b/sound/voicegroups/fallarbor.inc @@ -1,6 +1,6 @@ voice_group fallarbor voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group fallarbor voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group fallarbor voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/fanfare.inc b/sound/voicegroups/fanfare.inc index caaeaf40e5..671564a9bc 100644 --- a/sound/voicegroups/fanfare.inc +++ b/sound/voicegroups/fanfare.inc @@ -1,6 +1,6 @@ voice_group fanfare voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_directsound 60, 0, DirectSoundWaveData_trinity_30303_mega_bass, 255, 178, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group fanfare voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group fanfare voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/fortree.inc b/sound/voicegroups/fortree.inc index 0c4d0281d3..6f12c7ad94 100644 --- a/sound/voicegroups/fortree.inc +++ b/sound/voicegroups/fortree.inc @@ -1,6 +1,6 @@ voice_group fortree voice_keysplit_all voicegroup_petalburg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/frlg_sfx.inc b/sound/voicegroups/frlg_sfx.inc index 44a933ac1c..eadd0959c4 100644 --- a/sound/voicegroups/frlg_sfx.inc +++ b/sound/voicegroups/frlg_sfx.inc @@ -57,7 +57,7 @@ voice_group frlg_sfx voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/game_corner.inc b/sound/voicegroups/game_corner.inc index 9a06e577f4..127fe4ea05 100644 --- a/sound/voicegroups/game_corner.inc +++ b/sound/voicegroups/game_corner.inc @@ -1,6 +1,6 @@ voice_group game_corner voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group game_corner voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group game_corner voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/gym.inc b/sound/voicegroups/gym.inc index 715abccf18..c4297ff663 100644 --- a/sound/voicegroups/gym.inc +++ b/sound/voicegroups/gym.inc @@ -47,7 +47,7 @@ voice_group gym voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group gym voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/hall_of_fame.inc b/sound/voicegroups/hall_of_fame.inc index 6e831e4c2b..82651a41e6 100644 --- a/sound/voicegroups/hall_of_fame.inc +++ b/sound/voicegroups/hall_of_fame.inc @@ -1,6 +1,6 @@ voice_group hall_of_fame voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group hall_of_fame voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group hall_of_fame voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/hall_of_fame_room.inc b/sound/voicegroups/hall_of_fame_room.inc index efbc1a4f33..842ef77514 100644 --- a/sound/voicegroups/hall_of_fame_room.inc +++ b/sound/voicegroups/hall_of_fame_room.inc @@ -47,7 +47,7 @@ voice_group hall_of_fame_room voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group hall_of_fame_room voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/help.inc b/sound/voicegroups/help.inc index d7530853c5..6bb535c8a3 100644 --- a/sound/voicegroups/help.inc +++ b/sound/voicegroups/help.inc @@ -47,7 +47,7 @@ voice_group help voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group help voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/intro.inc b/sound/voicegroups/intro.inc index 3a1a123cc4..66da0b3051 100644 --- a/sound/voicegroups/intro.inc +++ b/sound/voicegroups/intro.inc @@ -1,6 +1,6 @@ voice_group intro voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group intro voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 128, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group intro voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/intro_battle.inc b/sound/voicegroups/intro_battle.inc index a01918d871..8845d3c714 100644 --- a/sound/voicegroups/intro_battle.inc +++ b/sound/voicegroups/intro_battle.inc @@ -1,6 +1,6 @@ voice_group intro_battle voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 1, 1, 1, 6, 2 @@ -47,7 +47,7 @@ voice_group intro_battle voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group intro_battle voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/lilycove.inc b/sound/voicegroups/lilycove.inc index d016db496f..8988ade2b1 100644 --- a/sound/voicegroups/lilycove.inc +++ b/sound/voicegroups/lilycove.inc @@ -47,7 +47,7 @@ voice_group lilycove voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group lilycove voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/lilycove_museum.inc b/sound/voicegroups/lilycove_museum.inc index ab9c5d3bd5..06ee86ea9d 100644 --- a/sound/voicegroups/lilycove_museum.inc +++ b/sound/voicegroups/lilycove_museum.inc @@ -1,5 +1,5 @@ voice_group lilycove_museum - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group lilycove_museum voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,7 +57,7 @@ voice_group lilycove_museum voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/link_contest_p1.inc b/sound/voicegroups/link_contest_p1.inc index aae277742f..7b1857db1c 100644 --- a/sound/voicegroups/link_contest_p1.inc +++ b/sound/voicegroups/link_contest_p1.inc @@ -47,7 +47,7 @@ voice_group link_contest_p1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group link_contest_p1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/link_contest_p2.inc b/sound/voicegroups/link_contest_p2.inc index bfbfcb9090..dd547e3662 100644 --- a/sound/voicegroups/link_contest_p2.inc +++ b/sound/voicegroups/link_contest_p2.inc @@ -47,7 +47,7 @@ voice_group link_contest_p2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group link_contest_p2 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/link_contest_p3.inc b/sound/voicegroups/link_contest_p3.inc index ef038d5dd6..f9d5559a5e 100644 --- a/sound/voicegroups/link_contest_p3.inc +++ b/sound/voicegroups/link_contest_p3.inc @@ -47,7 +47,7 @@ voice_group link_contest_p3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group link_contest_p3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/link_contest_p4.inc b/sound/voicegroups/link_contest_p4.inc index 235ebb1d9a..2abcd10dab 100644 --- a/sound/voicegroups/link_contest_p4.inc +++ b/sound/voicegroups/link_contest_p4.inc @@ -47,7 +47,7 @@ voice_group link_contest_p4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group link_contest_p4 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/littleroot.inc b/sound/voicegroups/littleroot.inc index 594f7202f3..2817a022af 100644 --- a/sound/voicegroups/littleroot.inc +++ b/sound/voicegroups/littleroot.inc @@ -1,6 +1,6 @@ voice_group littleroot voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 2, 1, 4, 4, 2 @@ -47,7 +47,7 @@ voice_group littleroot voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 99 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/littleroot_test.inc b/sound/voicegroups/littleroot_test.inc index e094ed33fa..1788f263c0 100644 --- a/sound/voicegroups/littleroot_test.inc +++ b/sound/voicegroups/littleroot_test.inc @@ -1,6 +1,6 @@ voice_group littleroot_test voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 1, 4, 2 @@ -47,7 +47,7 @@ voice_group littleroot_test voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/mt_chimney.inc b/sound/voicegroups/mt_chimney.inc index b4de7d7ac6..2255c50d75 100644 --- a/sound/voicegroups/mt_chimney.inc +++ b/sound/voicegroups/mt_chimney.inc @@ -47,7 +47,7 @@ voice_group mt_chimney voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group mt_chimney voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/mt_pyre.inc b/sound/voicegroups/mt_pyre.inc index 402b222ccd..5d7caa771b 100644 --- a/sound/voicegroups/mt_pyre.inc +++ b/sound/voicegroups/mt_pyre.inc @@ -47,7 +47,7 @@ voice_group mt_pyre voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group mt_pyre voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/mt_pyre_exterior.inc b/sound/voicegroups/mt_pyre_exterior.inc index e7336bf2c6..7f4c2e4363 100644 --- a/sound/voicegroups/mt_pyre_exterior.inc +++ b/sound/voicegroups/mt_pyre_exterior.inc @@ -47,7 +47,7 @@ voice_group mt_pyre_exterior voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group mt_pyre_exterior voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/oceanic_museum.inc b/sound/voicegroups/oceanic_museum.inc index 422bc6d776..1b072e2f44 100644 --- a/sound/voicegroups/oceanic_museum.inc +++ b/sound/voicegroups/oceanic_museum.inc @@ -1,5 +1,5 @@ voice_group oceanic_museum - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_keysplit_all voicegroup_rs_drumset voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group oceanic_museum voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group oceanic_museum voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/oldale.inc b/sound/voicegroups/oldale.inc index 0ecc1f9d2b..177f45c53e 100644 --- a/sound/voicegroups/oldale.inc +++ b/sound/voicegroups/oldale.inc @@ -47,7 +47,7 @@ voice_group oldale voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group oldale voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/petalburg.inc b/sound/voicegroups/petalburg.inc index 16abe3f128..ff49460b51 100644 --- a/sound/voicegroups/petalburg.inc +++ b/sound/voicegroups/petalburg.inc @@ -1,6 +1,6 @@ voice_group petalburg voice_keysplit_all voicegroup_petalburg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group petalburg voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/petalburg_woods.inc b/sound/voicegroups/petalburg_woods.inc index 5cf1de28c8..5dbe72c9a9 100644 --- a/sound/voicegroups/petalburg_woods.inc +++ b/sound/voicegroups/petalburg_woods.inc @@ -1,6 +1,6 @@ voice_group petalburg_woods voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 0, 0, 1, 7, 1 @@ -47,7 +47,7 @@ voice_group petalburg_woods voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/poke_center.inc b/sound/voicegroups/poke_center.inc index 6b14b67e7f..edcf645bfa 100644 --- a/sound/voicegroups/poke_center.inc +++ b/sound/voicegroups/poke_center.inc @@ -1,5 +1,5 @@ voice_group poke_center - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_programmable_wave_alt 60, 0, ProgrammableWaveData_14, 0, 1, 12, 0 voice_square_1_alt 60, 0, 0, 0, 1, 1, 9, 0 voice_square_2_alt 60, 0, 2, 0, 2, 6, 3 @@ -47,7 +47,7 @@ voice_group poke_center voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/poke_mart.inc b/sound/voicegroups/poke_mart.inc index aaf53d83ad..cc6580d5ae 100644 --- a/sound/voicegroups/poke_mart.inc +++ b/sound/voicegroups/poke_mart.inc @@ -1,6 +1,6 @@ voice_group poke_mart voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_caught_intro.inc b/sound/voicegroups/rg_caught_intro.inc index c3719d9c02..b2623ba7a0 100644 --- a/sound/voicegroups/rg_caught_intro.inc +++ b/sound/voicegroups/rg_caught_intro.inc @@ -1,7 +1,7 @@ voice_group rg_caught_intro voice_keysplit_all voicegroup_frlg_fanfare_drumset_1 voice_keysplit_all voicegroup_frlg_fanfare_drumset_2 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_caught_intro voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_caught_intro voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_celadon.inc b/sound/voicegroups/rg_celadon.inc index 91efdad253..9f9dc36cf9 100644 --- a/sound/voicegroups/rg_celadon.inc +++ b/sound/voicegroups/rg_celadon.inc @@ -1,6 +1,6 @@ voice_group rg_celadon voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_celadon voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group rg_celadon voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_cinnabar.inc b/sound/voicegroups/rg_cinnabar.inc index c527c0bf6c..90c207b675 100644 --- a/sound/voicegroups/rg_cinnabar.inc +++ b/sound/voicegroups/rg_cinnabar.inc @@ -1,6 +1,6 @@ voice_group rg_cinnabar voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_cinnabar voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group rg_cinnabar voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_credits.inc b/sound/voicegroups/rg_credits.inc index 6d16fee802..951a578236 100644 --- a/sound/voicegroups/rg_credits.inc +++ b/sound/voicegroups/rg_credits.inc @@ -1,6 +1,6 @@ voice_group rg_credits voice_keysplit_all voicegroup_rg_credits_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1_alt 60, 0, 0, 2, 0, 0, 12, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_credits voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 165, 154, 153 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_credits voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_cycling.inc b/sound/voicegroups/rg_cycling.inc index a693dd36f6..57e225141b 100644 --- a/sound/voicegroups/rg_cycling.inc +++ b/sound/voicegroups/rg_cycling.inc @@ -1,6 +1,6 @@ voice_group rg_cycling voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_cycling voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group rg_cycling voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_encounter_boy.inc b/sound/voicegroups/rg_encounter_boy.inc index 34447dc15e..27d34d9136 100644 --- a/sound/voicegroups/rg_encounter_boy.inc +++ b/sound/voicegroups/rg_encounter_boy.inc @@ -1,6 +1,6 @@ voice_group rg_encounter_boy voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_encounter_boy voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_encounter_girl.inc b/sound/voicegroups/rg_encounter_girl.inc index 101e2d3641..6e9989e6be 100644 --- a/sound/voicegroups/rg_encounter_girl.inc +++ b/sound/voicegroups/rg_encounter_girl.inc @@ -1,6 +1,6 @@ voice_group rg_encounter_girl voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_encounter_girl voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_encounter_rival.inc b/sound/voicegroups/rg_encounter_rival.inc index 3b918569e2..445cbad320 100644 --- a/sound/voicegroups/rg_encounter_rival.inc +++ b/sound/voicegroups/rg_encounter_rival.inc @@ -1,6 +1,6 @@ voice_group rg_encounter_rival voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_encounter_rival voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_encounter_rival voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 209 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_follow_me.inc b/sound/voicegroups/rg_follow_me.inc index 198cef9680..5f7563da82 100644 --- a/sound/voicegroups/rg_follow_me.inc +++ b/sound/voicegroups/rg_follow_me.inc @@ -1,6 +1,6 @@ voice_group rg_follow_me voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_directsound 60, 0, DirectSoundWaveData_steinway_b_piano, 128, 204, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_fuchsia.inc b/sound/voicegroups/rg_fuchsia.inc index fd41166c1d..c2b9ff1d16 100644 --- a/sound/voicegroups/rg_fuchsia.inc +++ b/sound/voicegroups/rg_fuchsia.inc @@ -55,7 +55,7 @@ voice_group rg_fuchsia voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_game_corner.inc b/sound/voicegroups/rg_game_corner.inc index aee7c99a15..fb7c6f615e 100644 --- a/sound/voicegroups/rg_game_corner.inc +++ b/sound/voicegroups/rg_game_corner.inc @@ -47,7 +47,7 @@ voice_group rg_game_corner voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 165, 154, 235 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_game_corner voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_game_freak.inc b/sound/voicegroups/rg_game_freak.inc index 98e0cad897..8a7d475dc9 100644 --- a/sound/voicegroups/rg_game_freak.inc +++ b/sound/voicegroups/rg_game_freak.inc @@ -1,6 +1,6 @@ voice_group rg_game_freak voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_gym.inc b/sound/voicegroups/rg_gym.inc index cc85606a66..78791967fa 100644 --- a/sound/voicegroups/rg_gym.inc +++ b/sound/voicegroups/rg_gym.inc @@ -47,7 +47,7 @@ voice_group rg_gym voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_gym voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_hall_of_fame.inc b/sound/voicegroups/rg_hall_of_fame.inc index e9539c8fa9..b982805140 100644 --- a/sound/voicegroups/rg_hall_of_fame.inc +++ b/sound/voicegroups/rg_hall_of_fame.inc @@ -1,6 +1,6 @@ voice_group rg_hall_of_fame voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_hall_of_fame voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group rg_hall_of_fame voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_intro_fight.inc b/sound/voicegroups/rg_intro_fight.inc index 5476348ca2..3b7d70b77b 100644 --- a/sound/voicegroups/rg_intro_fight.inc +++ b/sound/voicegroups/rg_intro_fight.inc @@ -1,6 +1,6 @@ voice_group rg_intro_fight voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_intro_fight voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_lavender.inc b/sound/voicegroups/rg_lavender.inc index f5707972cd..59dcb20293 100644 --- a/sound/voicegroups/rg_lavender.inc +++ b/sound/voicegroups/rg_lavender.inc @@ -1,6 +1,6 @@ voice_group rg_lavender voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_lavender voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 226 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 2, 0, 2, 3, 1 voice_square_2_alt 60, 0, 3, 0, 2, 7, 2 @@ -57,9 +57,9 @@ voice_group rg_lavender voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_mt_moon.inc b/sound/voicegroups/rg_mt_moon.inc index bb575cf50f..026bb7edc8 100644 --- a/sound/voicegroups/rg_mt_moon.inc +++ b/sound/voicegroups/rg_mt_moon.inc @@ -1,6 +1,6 @@ voice_group rg_mt_moon voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_mt_moon voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_new_game.inc b/sound/voicegroups/rg_new_game.inc index 3206ae717d..ffcbcdf748 100644 --- a/sound/voicegroups/rg_new_game.inc +++ b/sound/voicegroups/rg_new_game.inc @@ -47,7 +47,7 @@ voice_group rg_new_game voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 76 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_new_game voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_oak.inc b/sound/voicegroups/rg_oak.inc index 5965bc59fb..be46da360b 100644 --- a/sound/voicegroups/rg_oak.inc +++ b/sound/voicegroups/rg_oak.inc @@ -1,6 +1,6 @@ voice_group rg_oak voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_oak voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,9 +55,9 @@ voice_group rg_oak voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_oak_lab.inc b/sound/voicegroups/rg_oak_lab.inc index 40352f6060..65fa559da3 100644 --- a/sound/voicegroups/rg_oak_lab.inc +++ b/sound/voicegroups/rg_oak_lab.inc @@ -47,7 +47,7 @@ voice_group rg_oak_lab voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_pallet.inc b/sound/voicegroups/rg_pallet.inc index ccd491e720..91836ad8dc 100644 --- a/sound/voicegroups/rg_pallet.inc +++ b/sound/voicegroups/rg_pallet.inc @@ -47,7 +47,7 @@ voice_group rg_pallet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_pewter.inc b/sound/voicegroups/rg_pewter.inc index e986eafa65..bdac72177d 100644 --- a/sound/voicegroups/rg_pewter.inc +++ b/sound/voicegroups/rg_pewter.inc @@ -1,6 +1,6 @@ voice_group rg_pewter voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_pewter voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_photo.inc b/sound/voicegroups/rg_photo.inc index 88177033bb..a871efd3d4 100644 --- a/sound/voicegroups/rg_photo.inc +++ b/sound/voicegroups/rg_photo.inc @@ -1,6 +1,6 @@ voice_group rg_photo voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 64, 249, 0, 188 diff --git a/sound/voicegroups/rg_poke_center.inc b/sound/voicegroups/rg_poke_center.inc index a66f7b2bb4..26abb41add 100644 --- a/sound/voicegroups/rg_poke_center.inc +++ b/sound/voicegroups/rg_poke_center.inc @@ -47,7 +47,7 @@ voice_group rg_poke_center voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_poke_mansion.inc b/sound/voicegroups/rg_poke_mansion.inc index 6e2ca3c56e..a1d24e89fd 100644 --- a/sound/voicegroups/rg_poke_mansion.inc +++ b/sound/voicegroups/rg_poke_mansion.inc @@ -47,7 +47,7 @@ voice_group rg_poke_mansion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,7 +57,7 @@ voice_group rg_poke_mansion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_poke_tower.inc b/sound/voicegroups/rg_poke_tower.inc index e815316240..a05561c50a 100644 --- a/sound/voicegroups/rg_poke_tower.inc +++ b/sound/voicegroups/rg_poke_tower.inc @@ -1,6 +1,6 @@ voice_group rg_poke_tower voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_poke_tower voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 226 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1_alt 60, 0, 0, 2, 0, 2, 10, 1 voice_square_2_alt 60, 0, 2, 0, 2, 6, 6 @@ -57,9 +57,9 @@ voice_group rg_poke_tower voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_rocket_hideout.inc b/sound/voicegroups/rg_rocket_hideout.inc index b84e5ee17a..8d3d81a008 100644 --- a/sound/voicegroups/rg_rocket_hideout.inc +++ b/sound/voicegroups/rg_rocket_hideout.inc @@ -1,6 +1,6 @@ voice_group rg_rocket_hideout voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_rocket_hideout voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_rocket_hideout voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_route11.inc b/sound/voicegroups/rg_route11.inc index c166b346ba..1ee794137b 100644 --- a/sound/voicegroups/rg_route11.inc +++ b/sound/voicegroups/rg_route11.inc @@ -1,6 +1,6 @@ voice_group rg_route11 voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_route11 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_route11 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_route24.inc b/sound/voicegroups/rg_route24.inc index e9e89db09e..7e50c4824f 100644 --- a/sound/voicegroups/rg_route24.inc +++ b/sound/voicegroups/rg_route24.inc @@ -47,7 +47,7 @@ voice_group rg_route24 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 127 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_route24 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_route3.inc b/sound/voicegroups/rg_route3.inc index 0b49ff7fe2..781d2b9a41 100644 --- a/sound/voicegroups/rg_route3.inc +++ b/sound/voicegroups/rg_route3.inc @@ -47,7 +47,7 @@ voice_group rg_route3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_route3 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_sevii_45.inc b/sound/voicegroups/rg_sevii_45.inc index 13b33f4af0..c81a569a9b 100644 --- a/sound/voicegroups/rg_sevii_45.inc +++ b/sound/voicegroups/rg_sevii_45.inc @@ -1,6 +1,6 @@ voice_group rg_sevii_45 voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_sevii_45 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_sevii_67.inc b/sound/voicegroups/rg_sevii_67.inc index 0804e0fc9c..6a35208337 100644 --- a/sound/voicegroups/rg_sevii_67.inc +++ b/sound/voicegroups/rg_sevii_67.inc @@ -1,6 +1,6 @@ voice_group rg_sevii_67 voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_sevii_67 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_sevii_route.inc b/sound/voicegroups/rg_sevii_route.inc index 48724cbe82..5b5370a15e 100644 --- a/sound/voicegroups/rg_sevii_route.inc +++ b/sound/voicegroups/rg_sevii_route.inc @@ -1,6 +1,6 @@ voice_group rg_sevii_route voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_sevii_route voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_sevii_route voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_silph.inc b/sound/voicegroups/rg_silph.inc index 20e2288942..0de5b368fa 100644 --- a/sound/voicegroups/rg_silph.inc +++ b/sound/voicegroups/rg_silph.inc @@ -1,6 +1,6 @@ voice_group rg_silph voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_silph voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_silph voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 236, 188 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_ss_anne.inc b/sound/voicegroups/rg_ss_anne.inc index e69ac24ce2..931b86ed10 100644 --- a/sound/voicegroups/rg_ss_anne.inc +++ b/sound/voicegroups/rg_ss_anne.inc @@ -1,6 +1,6 @@ voice_group rg_ss_anne voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_ss_anne voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group rg_ss_anne voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_unknown_18, 255, 0, 206, 204 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_surf.inc b/sound/voicegroups/rg_surf.inc index a8e63e46b0..b134793f73 100644 --- a/sound/voicegroups/rg_surf.inc +++ b/sound/voicegroups/rg_surf.inc @@ -1,6 +1,6 @@ voice_group rg_surf voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 128, 180, 108, 209 @@ -47,7 +47,7 @@ voice_group rg_surf voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_teachy_tv_menu.inc b/sound/voicegroups/rg_teachy_tv_menu.inc index 1d51f7692e..160fbf3d07 100644 --- a/sound/voicegroups/rg_teachy_tv_menu.inc +++ b/sound/voicegroups/rg_teachy_tv_menu.inc @@ -1,6 +1,6 @@ voice_group rg_teachy_tv_menu voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_title.inc b/sound/voicegroups/rg_title.inc index 425bcb7f62..abfea6de70 100644 --- a/sound/voicegroups/rg_title.inc +++ b/sound/voicegroups/rg_title.inc @@ -47,7 +47,7 @@ voice_group rg_title voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_title voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vermillion.inc b/sound/voicegroups/rg_vermillion.inc index c6c475aef4..8c840c14c1 100644 --- a/sound/voicegroups/rg_vermillion.inc +++ b/sound/voicegroups/rg_vermillion.inc @@ -1,6 +1,6 @@ voice_group rg_vermillion voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 188, 128, 226 @@ -47,7 +47,7 @@ voice_group rg_vermillion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group rg_vermillion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_victory_gym_leader.inc b/sound/voicegroups/rg_victory_gym_leader.inc index f3753388d2..76b53e7c32 100644 --- a/sound/voicegroups/rg_victory_gym_leader.inc +++ b/sound/voicegroups/rg_victory_gym_leader.inc @@ -47,7 +47,7 @@ voice_group rg_victory_gym_leader voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_victory_gym_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_victory_road.inc b/sound/voicegroups/rg_victory_road.inc index ff703c4ab5..5b578c74e4 100644 --- a/sound/voicegroups/rg_victory_road.inc +++ b/sound/voicegroups/rg_victory_road.inc @@ -47,7 +47,7 @@ voice_group rg_victory_road voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 127, 154, 235 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_victory_road voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_victory_trainer.inc b/sound/voicegroups/rg_victory_trainer.inc index 9cb14bb46e..eb1d34f117 100644 --- a/sound/voicegroups/rg_victory_trainer.inc +++ b/sound/voicegroups/rg_victory_trainer.inc @@ -55,9 +55,9 @@ voice_group rg_victory_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_victory_wild.inc b/sound/voicegroups/rg_victory_wild.inc index c19ee7b264..bb48fcadea 100644 --- a/sound/voicegroups/rg_victory_wild.inc +++ b/sound/voicegroups/rg_victory_wild.inc @@ -55,9 +55,9 @@ voice_group rg_victory_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_viridian_forest.inc b/sound/voicegroups/rg_viridian_forest.inc index d171e3cb67..4c703102c9 100644 --- a/sound/voicegroups/rg_viridian_forest.inc +++ b/sound/voicegroups/rg_viridian_forest.inc @@ -47,7 +47,7 @@ voice_group rg_viridian_forest voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vs_champion.inc b/sound/voicegroups/rg_vs_champion.inc index 3f7f59ed76..9068f8d504 100644 --- a/sound/voicegroups/rg_vs_champion.inc +++ b/sound/voicegroups/rg_vs_champion.inc @@ -1,6 +1,6 @@ voice_group rg_vs_champion voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 @@ -47,7 +47,7 @@ voice_group rg_vs_champion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 153 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_vs_champion voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 255, 0, 255, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 236, 188 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vs_deoxys.inc b/sound/voicegroups/rg_vs_deoxys.inc index 35d2b6f591..172ec41bd0 100644 --- a/sound/voicegroups/rg_vs_deoxys.inc +++ b/sound/voicegroups/rg_vs_deoxys.inc @@ -47,7 +47,7 @@ voice_group rg_vs_deoxys voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_vs_deoxys voice_directsound 60, 0, DirectSoundWaveData_classical_choir_voice_ahhs, 85, 0, 154, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 209 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vs_gym_leader.inc b/sound/voicegroups/rg_vs_gym_leader.inc index 75341ae46a..85d7705a27 100644 --- a/sound/voicegroups/rg_vs_gym_leader.inc +++ b/sound/voicegroups/rg_vs_gym_leader.inc @@ -1,6 +1,6 @@ voice_group rg_vs_gym_leader voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 255, 249, 0, 165 @@ -47,7 +47,7 @@ voice_group rg_vs_gym_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_vs_gym_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 165, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vs_trainer.inc b/sound/voicegroups/rg_vs_trainer.inc index 5808a9b15c..265366c166 100644 --- a/sound/voicegroups/rg_vs_trainer.inc +++ b/sound/voicegroups/rg_vs_trainer.inc @@ -1,6 +1,6 @@ voice_group rg_vs_trainer voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_programmable_wave_alt 60, 0, ProgrammableWaveData_5, 0, 7, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rg_vs_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_vs_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rg_vs_wild.inc b/sound/voicegroups/rg_vs_wild.inc index d07bc73771..b006a5dc2b 100644 --- a/sound/voicegroups/rg_vs_wild.inc +++ b/sound/voicegroups/rg_vs_wild.inc @@ -1,6 +1,6 @@ voice_group rg_vs_wild voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 2, 6, 5 @@ -47,7 +47,7 @@ voice_group rg_vs_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group rg_vs_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route101.inc b/sound/voicegroups/route101.inc index 223763608d..2fb66ade3e 100644 --- a/sound/voicegroups/route101.inc +++ b/sound/voicegroups/route101.inc @@ -47,7 +47,7 @@ voice_group route101 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route104.inc b/sound/voicegroups/route104.inc index 59b47960cd..9a4056df70 100644 --- a/sound/voicegroups/route104.inc +++ b/sound/voicegroups/route104.inc @@ -47,7 +47,7 @@ voice_group route104 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route104 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route110.inc b/sound/voicegroups/route110.inc index f26f1ad74b..30cb3dedf5 100644 --- a/sound/voicegroups/route110.inc +++ b/sound/voicegroups/route110.inc @@ -47,7 +47,7 @@ voice_group route110 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route110 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route111.inc b/sound/voicegroups/route111.inc index f253a4051c..b4ef9e9fae 100644 --- a/sound/voicegroups/route111.inc +++ b/sound/voicegroups/route111.inc @@ -47,7 +47,7 @@ voice_group route111 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 204, 193, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route111 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route113.inc b/sound/voicegroups/route113.inc index e21c37f002..9751155097 100644 --- a/sound/voicegroups/route113.inc +++ b/sound/voicegroups/route113.inc @@ -47,7 +47,7 @@ voice_group route113 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group route113 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route119.inc b/sound/voicegroups/route119.inc index c18dbd1da0..a6b76d54cd 100644 --- a/sound/voicegroups/route119.inc +++ b/sound/voicegroups/route119.inc @@ -47,7 +47,7 @@ voice_group route119 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route119 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route120.inc b/sound/voicegroups/route120.inc index 8badc8b531..b1a529d292 100644 --- a/sound/voicegroups/route120.inc +++ b/sound/voicegroups/route120.inc @@ -1,6 +1,6 @@ voice_group route120 voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 1, 6, 1 @@ -47,7 +47,7 @@ voice_group route120 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route120 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/route122.inc b/sound/voicegroups/route122.inc index b81d75d7b3..a18d0142df 100644 --- a/sound/voicegroups/route122.inc +++ b/sound/voicegroups/route122.inc @@ -47,7 +47,7 @@ voice_group route122 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group route122 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rs_sfx_1.inc b/sound/voicegroups/rs_sfx_1.inc index 31d514a328..d07f1d8812 100644 --- a/sound/voicegroups/rs_sfx_1.inc +++ b/sound/voicegroups/rs_sfx_1.inc @@ -47,7 +47,7 @@ voice_group rs_sfx_1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/rustboro.inc b/sound/voicegroups/rustboro.inc index a0292d77a8..035c96f073 100644 --- a/sound/voicegroups/rustboro.inc +++ b/sound/voicegroups/rustboro.inc @@ -9,7 +9,7 @@ voice_group rustboro voice_programmable_wave_alt 60, 0, ProgrammableWaveData_4, 1, 7, 15, 1 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group rustboro voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/sailing.inc b/sound/voicegroups/sailing.inc index 3c2e1885c2..4dc40de7d9 100644 --- a/sound/voicegroups/sailing.inc +++ b/sound/voicegroups/sailing.inc @@ -47,7 +47,7 @@ voice_group sailing voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/school.inc b/sound/voicegroups/school.inc index b7eb6deb30..8490de2e67 100644 --- a/sound/voicegroups/school.inc +++ b/sound/voicegroups/school.inc @@ -1,4 +1,4 @@ voice_group school voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano diff --git a/sound/voicegroups/sealed_chamber.inc b/sound/voicegroups/sealed_chamber.inc index 9ab3a67924..98fda0afa6 100644 --- a/sound/voicegroups/sealed_chamber.inc +++ b/sound/voicegroups/sealed_chamber.inc @@ -47,7 +47,7 @@ voice_group sealed_chamber voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group sealed_chamber voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/slateport.inc b/sound/voicegroups/slateport.inc index 669b089855..10aea36b33 100644 --- a/sound/voicegroups/slateport.inc +++ b/sound/voicegroups/slateport.inc @@ -1,6 +1,6 @@ voice_group slateport voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group slateport voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/sootopolis.inc b/sound/voicegroups/sootopolis.inc index fdd0ed9d4a..742e4e4dfa 100644 --- a/sound/voicegroups/sootopolis.inc +++ b/sound/voicegroups/sootopolis.inc @@ -1,6 +1,6 @@ voice_group sootopolis voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group sootopolis voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group sootopolis voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/surf.inc b/sound/voicegroups/surf.inc index cadc04e077..924a9c7832 100644 --- a/sound/voicegroups/surf.inc +++ b/sound/voicegroups/surf.inc @@ -47,7 +47,7 @@ voice_group surf voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 204 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group surf voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/title.inc b/sound/voicegroups/title.inc index abb6d853a9..629171779c 100644 --- a/sound/voicegroups/title.inc +++ b/sound/voicegroups/title.inc @@ -1,6 +1,6 @@ voice_group title voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 1, 1, 1, 6, 2 @@ -47,7 +47,7 @@ voice_group title voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 239 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group title voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/trick_house.inc b/sound/voicegroups/trick_house.inc index f0c2e1f6ca..beb29c395f 100644 --- a/sound/voicegroups/trick_house.inc +++ b/sound/voicegroups/trick_house.inc @@ -47,7 +47,7 @@ voice_group trick_house voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group trick_house voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/underwater.inc b/sound/voicegroups/underwater.inc index 03526599ad..40d42107de 100644 --- a/sound/voicegroups/underwater.inc +++ b/sound/voicegroups/underwater.inc @@ -47,7 +47,7 @@ voice_group underwater voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 0, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 193, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/verdanturf.inc b/sound/voicegroups/verdanturf.inc index f58ffed848..afaeca5043 100644 --- a/sound/voicegroups/verdanturf.inc +++ b/sound/voicegroups/verdanturf.inc @@ -1,5 +1,5 @@ voice_group verdanturf - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group verdanturf voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 226, 0, 38 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_aqua_magma.inc b/sound/voicegroups/victory_aqua_magma.inc index cd9a7645a6..f507d1fc98 100644 --- a/sound/voicegroups/victory_aqua_magma.inc +++ b/sound/voicegroups/victory_aqua_magma.inc @@ -47,7 +47,7 @@ voice_group victory_aqua_magma voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,7 +55,7 @@ voice_group victory_aqua_magma voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_gym_leader.inc b/sound/voicegroups/victory_gym_leader.inc index 8e91c799a0..18dc32f568 100644 --- a/sound/voicegroups/victory_gym_leader.inc +++ b/sound/voicegroups/victory_gym_leader.inc @@ -47,7 +47,7 @@ voice_group victory_gym_leader voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group victory_gym_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_league.inc b/sound/voicegroups/victory_league.inc index 7d4d669662..5e5b517bc4 100644 --- a/sound/voicegroups/victory_league.inc +++ b/sound/voicegroups/victory_league.inc @@ -47,7 +47,7 @@ voice_group victory_league voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group victory_league voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_road.inc b/sound/voicegroups/victory_road.inc index 043789e6c5..eb20af9e8e 100644 --- a/sound/voicegroups/victory_road.inc +++ b/sound/voicegroups/victory_road.inc @@ -1,6 +1,6 @@ voice_group victory_road voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group victory_road voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 0, 180, 246 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group victory_road voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_trainer.inc b/sound/voicegroups/victory_trainer.inc index cfa101e98e..c4674a9cde 100644 --- a/sound/voicegroups/victory_trainer.inc +++ b/sound/voicegroups/victory_trainer.inc @@ -55,9 +55,9 @@ voice_group victory_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/victory_wild.inc b/sound/voicegroups/victory_wild.inc index f250bf92e2..de30836168 100644 --- a/sound/voicegroups/victory_wild.inc +++ b/sound/voicegroups/victory_wild.inc @@ -55,9 +55,9 @@ voice_group victory_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_aqua_magma.inc b/sound/voicegroups/vs_aqua_magma.inc index a83533f90c..4c1f5578dc 100644 --- a/sound/voicegroups/vs_aqua_magma.inc +++ b/sound/voicegroups/vs_aqua_magma.inc @@ -47,7 +47,7 @@ voice_group vs_aqua_magma voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -57,9 +57,9 @@ voice_group vs_aqua_magma voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_aqua_magma_leader.inc b/sound/voicegroups/vs_aqua_magma_leader.inc index 78c23d136a..3ca3c3afa4 100644 --- a/sound/voicegroups/vs_aqua_magma_leader.inc +++ b/sound/voicegroups/vs_aqua_magma_leader.inc @@ -47,7 +47,7 @@ voice_group vs_aqua_magma_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_aqua_magma_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_champion.inc b/sound/voicegroups/vs_champion.inc index f18c9182d7..802dde8a45 100644 --- a/sound/voicegroups/vs_champion.inc +++ b/sound/voicegroups/vs_champion.inc @@ -1,6 +1,6 @@ voice_group vs_champion voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -47,7 +47,7 @@ voice_group vs_champion voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_champion voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_elite_four.inc b/sound/voicegroups/vs_elite_four.inc index 551e34e36e..9c99b4e03b 100644 --- a/sound/voicegroups/vs_elite_four.inc +++ b/sound/voicegroups/vs_elite_four.inc @@ -47,7 +47,7 @@ voice_group vs_elite_four voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_elite_four voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_frontier_brain.inc b/sound/voicegroups/vs_frontier_brain.inc index c544475e77..0167389e38 100644 --- a/sound/voicegroups/vs_frontier_brain.inc +++ b/sound/voicegroups/vs_frontier_brain.inc @@ -1,6 +1,6 @@ voice_group vs_frontier_brain voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_detuned_ep1_low, 128, 249, 0, 188 @@ -47,7 +47,7 @@ voice_group vs_frontier_brain voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 242, 51, 242 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_frontier_brain voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 165, 180, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_gym_leader.inc b/sound/voicegroups/vs_gym_leader.inc index 058b180e67..8aad0a65bc 100644 --- a/sound/voicegroups/vs_gym_leader.inc +++ b/sound/voicegroups/vs_gym_leader.inc @@ -1,6 +1,6 @@ voice_group vs_gym_leader voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 2, 6, 1 @@ -47,7 +47,7 @@ voice_group vs_gym_leader voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_gym_leader voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_kyogre_groudon.inc b/sound/voicegroups/vs_kyogre_groudon.inc index 4ece3f9e26..326a190438 100644 --- a/sound/voicegroups/vs_kyogre_groudon.inc +++ b/sound/voicegroups/vs_kyogre_groudon.inc @@ -47,7 +47,7 @@ voice_group vs_kyogre_groudon voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_kyogre_groudon voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_mew.inc b/sound/voicegroups/vs_mew.inc index 14f3c536f7..052284f396 100644 --- a/sound/voicegroups/vs_mew.inc +++ b/sound/voicegroups/vs_mew.inc @@ -1,6 +1,6 @@ voice_group vs_mew voice_keysplit_all voicegroup_frlg_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2_alt 60, 0, 3, 0, 2, 6, 5 @@ -47,7 +47,7 @@ voice_group vs_mew voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_mew voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sd90_classical_distortion_guitar_low, 255, 0, 255, 127 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_rayquaza.inc b/sound/voicegroups/vs_rayquaza.inc index 8199a8a4a0..c004be789d 100644 --- a/sound/voicegroups/vs_rayquaza.inc +++ b/sound/voicegroups/vs_rayquaza.inc @@ -47,7 +47,7 @@ voice_group vs_rayquaza voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_rayquaza voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_regi.inc b/sound/voicegroups/vs_regi.inc index be785e62e8..ebb9fabd1a 100644 --- a/sound/voicegroups/vs_regi.inc +++ b/sound/voicegroups/vs_regi.inc @@ -47,7 +47,7 @@ voice_group vs_regi voice_directsound 60, 0, DirectSoundWaveData_sc88pro_pizzicato_strings, 255, 216, 0, 165 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -59,7 +59,7 @@ voice_group vs_regi voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_rival.inc b/sound/voicegroups/vs_rival.inc index e3d07742c0..8613db3964 100644 --- a/sound/voicegroups/vs_rival.inc +++ b/sound/voicegroups/vs_rival.inc @@ -1,6 +1,6 @@ voice_group vs_rival voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 2, 0, 2, 3, 1 @@ -47,7 +47,7 @@ voice_group vs_rival voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_rival voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_trainer.inc b/sound/voicegroups/vs_trainer.inc index 1470990f55..5c8f5b305e 100644 --- a/sound/voicegroups/vs_trainer.inc +++ b/sound/voicegroups/vs_trainer.inc @@ -1,6 +1,6 @@ voice_group vs_trainer voice_keysplit_all voicegroup_rs_drumset - voice_keysplit voicegroup_piano_keysplit, KeySplitTable1 + voice_keysplit voicegroup_piano_keysplit, keysplit_piano voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_2 60, 0, 0, 0, 2, 4, 1 @@ -47,7 +47,7 @@ voice_group vs_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound_no_resample 60, 0, DirectSoundWaveData_sc88pro_timpani_with_snare, 255, 246, 0, 226 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_trainer voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 diff --git a/sound/voicegroups/vs_wild.inc b/sound/voicegroups/vs_wild.inc index c3944d50a7..5ce57a0d54 100644 --- a/sound/voicegroups/vs_wild.inc +++ b/sound/voicegroups/vs_wild.inc @@ -47,7 +47,7 @@ voice_group vs_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_harp, 255, 246, 0, 235 voice_directsound 60, 0, DirectSoundWaveData_sc88pro_timpani, 255, 246, 0, 226 - voice_keysplit voicegroup_strings_keysplit, KeySplitTable2 + voice_keysplit voicegroup_strings_keysplit, keysplit_strings voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 @@ -55,11 +55,11 @@ voice_group vs_wild voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_trumpet_keysplit, KeySplitTable3 + voice_keysplit voicegroup_trumpet_keysplit, keysplit_trumpet voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_tuba_keysplit, KeySplitTable4 + voice_keysplit voicegroup_tuba_keysplit, keysplit_tuba voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 - voice_keysplit voicegroup_french_horn_keysplit, KeySplitTable5 + voice_keysplit voicegroup_french_horn_keysplit, keysplit_french_horn voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 voice_square_1 60, 0, 0, 2, 0, 0, 15, 0 From 469a0b476a17d485046153456a0dac5e27a4f103 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 2 Aug 2025 12:54:39 +0200 Subject: [PATCH 158/283] Update trainer.h usage warning (#7439) Co-authored-by: Hedara --- tools/trainerproc/main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index dc812cb153..5330c9fe3d 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -1733,9 +1733,7 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprintf(f, "//\n"); fprintf(f, "// DO NOT MODIFY THIS FILE! It is auto-generated from %s\n", parsed->source->path); fprintf(f, "//\n"); - fprintf(f, "// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE\n"); - fprintf(f, "// in include/config/general.h and remove this notice.\n"); - fprintf(f, "// Use sed -i '/^#line/d' '%s' to remove #line markers.\n", output_path); + fprintf(f, "// If you want to modify this file see expansion PR #7154\n"); fprintf(f, "//\n"); fprintf(f, "\n"); From ed44da86444248ce541508461db6f5ed828896fc Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 2 Aug 2025 12:56:00 +0200 Subject: [PATCH 159/283] Add a heal animation to Hospitality recovery (#7426) --- data/battle_scripts_1.s | 1 + 1 file changed, 1 insertion(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5984fcd319..e6bf8e1db8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7613,6 +7613,7 @@ BattleScript_HospitalityActivates:: printstring STRINGID_HOSPITALITYRESTORATION waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + playanimation BS_EFFECT_BATTLER, B_ANIM_SIMPLE_HEAL healthbarupdate BS_EFFECT_BATTLER datahpupdate BS_EFFECT_BATTLER end3 From 3841fee8880bc47a931fc4475be048f966841307 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 2 Aug 2025 15:17:44 +0200 Subject: [PATCH 160/283] Clean up noResultString (#7408) --- include/battle.h | 4 +--- include/constants/battle.h | 7 +++++++ src/battle_script_commands.c | 24 ++++++++++++------------ src/battle_util.c | 21 +++++++++++---------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/include/battle.h b/include/battle.h index 176adf7343..de25626c6b 100644 --- a/include/battle.h +++ b/include/battle.h @@ -764,7 +764,7 @@ struct BattleStruct s16 critChance[MAX_BATTLERS_COUNT]; u16 moveResultFlags[MAX_BATTLERS_COUNT]; u8 missStringId[MAX_BATTLERS_COUNT]; - u8 noResultString[MAX_BATTLERS_COUNT]; + enum CalcDamageState noResultString[MAX_BATTLERS_COUNT]; u8 doneDoublesSpreadHit:1; u8 calculatedDamageDone:1; u8 calculatedSpreadMoveAccuracy:1; @@ -865,8 +865,6 @@ static inline bool32 IsBattleMoveStatus(u32 move) #define SET_STATCHANGER(statId, stage, goesDown) (gBattleScripting.statChanger = (statId) + ((stage) << 3) + (goesDown << 7)) #define SET_STATCHANGER2(dst, statId, stage, goesDown)(dst = (statId) + ((stage) << 3) + (goesDown << 7)) -#define DO_ACCURACY_CHECK 2 // Don't skip the accuracy check before the move might be absorbed - // NOTE: The members of this struct have hard-coded offsets // in include/constants/battle_script_commands.h struct BattleScripting diff --git a/include/constants/battle.h b/include/constants/battle.h index 5faa91ad7e..730dbd63c7 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -700,4 +700,11 @@ enum MonState MON_OUTSIDE_BATTLE, }; +enum __attribute__((packed)) CalcDamageState +{ + CAN_DAMAGE, + WILL_FAIL, + CHECK_ACCURACY, +}; + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9c4da75feb..162e55dba9 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1407,7 +1407,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u if ((!calcSpreadMove && battlerDef != gBattlerTarget) || IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; numTargets++; @@ -1743,7 +1743,7 @@ static void Cmd_critcalc(void) continue; if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) continue; @@ -1819,7 +1819,7 @@ static void Cmd_damagecalc(void) for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) continue; @@ -1882,7 +1882,7 @@ static void Cmd_adjustdamage(void) continue; if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) - || gBattleStruct->noResultString[battlerDef]) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; if (DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)) @@ -2029,8 +2029,8 @@ static u32 UpdateEffectivenessResultFlagsForDoubleSpreadMoves(u32 resultFlags) { for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { - if ((gBattleStruct->moveResultFlags[battlerDef] & (MOVE_RESULT_MISSED | MOVE_RESULT_NO_EFFECT) - || gBattleStruct->noResultString[battlerDef])) + if (gBattleStruct->moveResultFlags[battlerDef] & (MOVE_RESULT_MISSED | MOVE_RESULT_NO_EFFECT) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; switch (sound) @@ -2115,7 +2115,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) || (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY)) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; if (TryStrongWindsWeakenAttack(battlerDef, moveType)) @@ -2127,7 +2127,7 @@ static bool32 ProcessPreAttackAnimationFuncs(void) { if (IsBattlerInvalidForSpreadMove(gBattlerAttacker, battlerDef, moveTarget) || (battlerDef == BATTLE_PARTNER(gBattlerAttacker) && !(moveTarget & MOVE_TARGET_FOES_AND_ALLY)) - || (gBattleStruct->noResultString[battlerDef] && gBattleStruct->noResultString[battlerDef] != DO_ACCURACY_CHECK)) + || gBattleStruct->noResultString[battlerDef] == WILL_FAIL) continue; if (TryTeraShellDistortTypeMatchups(battlerDef)) @@ -2255,7 +2255,7 @@ static void DoublesHPBarReduction(void) { if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT || gBattleStruct->moveDamage[battlerDef] == 0 - || gBattleStruct->noResultString[battlerDef] + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE || DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove) || DoesDisguiseBlockMove(battlerDef, gCurrentMove)) continue; @@ -2534,7 +2534,7 @@ static inline bool32 ShouldPrintTwoFoesMessage(u32 moveResult) { return gBattlerTarget == BATTLE_OPPOSITE(gBattlerAttacker) && gBattleStruct->moveResultFlags[BATTLE_PARTNER(gBattlerTarget)] & moveResult - && !gBattleStruct->noResultString[BATTLE_PARTNER(gBattlerTarget)]; + && gBattleStruct->noResultString[BATTLE_PARTNER(gBattlerTarget)] == CAN_DAMAGE; } static inline bool32 ShouldRelyOnTwoFoesMessage(u32 moveResult) @@ -2542,7 +2542,7 @@ static inline bool32 ShouldRelyOnTwoFoesMessage(u32 moveResult) return gBattlerTarget == BATTLE_PARTNER(BATTLE_OPPOSITE(gBattlerAttacker)) && gBattleStruct->moveResultFlags[BATTLE_OPPOSITE(gBattlerAttacker)] & moveResult && !(gBattleStruct->moveResultFlags[BATTLE_OPPOSITE(gBattlerAttacker)] & MOVE_RESULT_MISSED && gBattleStruct->missStringId[BATTLE_OPPOSITE(gBattlerAttacker)] > B_MSG_AVOIDED_ATK) - && !gBattleStruct->noResultString[BATTLE_OPPOSITE(gBattlerAttacker)]; + && gBattleStruct->noResultString[BATTLE_OPPOSITE(gBattlerAttacker)] == CAN_DAMAGE; } static void Cmd_resultmessage(void) @@ -8247,7 +8247,7 @@ static void Cmd_hitanimation(void) for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { if (gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT - || gBattleStruct->noResultString[battlerDef]) + || gBattleStruct->noResultString[battlerDef] != CAN_DAMAGE) continue; if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) diff --git a/src/battle_util.c b/src/battle_util.c index ce82a997cc..caa4be0191 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -205,7 +205,7 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = // Helper function for actual dmg calcs during battle. For simulated AI dmg, CalcTypeEffectivenessMultiplier should be used directly // This should stay a static function. Ideally everything else is handled through CalcTypeEffectivenessMultiplier just like AI -static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u32 defAbility, bool32 recordAbilities) +static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, bool32 recordAbilities) { struct DamageContext ctx = {0}; ctx.battlerAtk = battlerAtk; @@ -213,8 +213,8 @@ static uq4_12_t CalcTypeEffectivenessMultiplierHelper(u32 move, u32 moveType, u3 ctx.move = move; ctx.moveType = moveType; ctx.updateFlags = recordAbilities; - ctx.abilityAtk = GetBattlerAbility(battlerAtk); - ctx.abilityDef = defAbility; + ctx.abilityAtk = abilityAtk; + ctx.abilityDef = abilityDef; ctx.holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); ctx.holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); @@ -2541,22 +2541,23 @@ static enum MoveCanceller CancellerMultiTargetMoves(void) || IsBattlerProtected(gBattlerAttacker, battlerDef, gCurrentMove)) // Missing Invulnerable check { gBattleStruct->moveResultFlags[battlerDef] = MOVE_RESULT_NO_EFFECT; - gBattleStruct->noResultString[battlerDef] = TRUE; + gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } else if (CanAbilityBlockMove(gBattlerAttacker, battlerDef, abilityAtk, abilityDef, gCurrentMove, CHECK_TRIGGER) || (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN) && GetBattleMovePriority(gBattlerAttacker, abilityAtk, gCurrentMove) > 0)) { gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = TRUE; + gBattleStruct->noResultString[battlerDef] = WILL_FAIL; } else if (CanAbilityAbsorbMove(gBattlerAttacker, battlerDef, abilityDef, gCurrentMove, GetBattleMoveType(gCurrentMove), CHECK_TRIGGER)) { gBattleStruct->moveResultFlags[battlerDef] = 0; - gBattleStruct->noResultString[battlerDef] = DO_ACCURACY_CHECK; + gBattleStruct->noResultString[battlerDef] = CHECK_ACCURACY; } else { - CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); + CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), gBattlerAttacker, battlerDef, abilityAtk, abilityDef, TRUE); // Sets moveResultFlags + gBattleStruct->noResultString[battlerDef] = CAN_DAMAGE; } } if (moveTarget == MOVE_TARGET_BOTH) @@ -5669,7 +5670,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u battleScript = BattleScript_NotAffected; } else if (option == RUN_SCRIPT // Check only important during battle execution for moves - && CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), battlerAtk, battlerDef, abilityDef, TRUE) + && CalcTypeEffectivenessMultiplierHelper(gCurrentMove, GetBattleMoveType(gCurrentMove), battlerAtk, battlerDef, abilityAtk, abilityDef, TRUE) && gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) { battleScript = BattleScript_ButItFailed; @@ -11223,7 +11224,7 @@ static inline bool32 DoesBattlerHaveAbilityImmunity(u32 battlerAtk, u32 battlerD bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef) { u32 moveType = GetBattleMoveType(gCurrentMove); - return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) + return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) || IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove) || IsSemiInvulnerable(battlerDef, gCurrentMove) || DoesBattlerHaveAbilityImmunity(battlerAtk, battlerDef, moveType)); @@ -11284,7 +11285,7 @@ void ClearDamageCalcResults(void) { gBattleStruct->moveDamage[battler] = 0; gBattleStruct->critChance[battler] = 0; - gBattleStruct->moveResultFlags[battler] = 0; + gBattleStruct->moveResultFlags[battler] = CAN_DAMAGE; gBattleStruct->noResultString[battler] = 0; gBattleStruct->missStringId[battler] = 0; gSpecialStatuses[battler].criticalHit = FALSE; From 297cd83871890e040a7f37d4cfb16518bdbafae0 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 2 Aug 2025 17:43:44 +0200 Subject: [PATCH 161/283] Clean up some Normalize tests to make them make sense (#7461) Co-authored-by: Hedara --- test/battle/ability/normalize.c | 40 +++++++-------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/test/battle/ability/normalize.c b/test/battle/ability/normalize.c index 2a449f74a5..33fe89c587 100644 --- a/test/battle/ability/normalize.c +++ b/test/battle/ability/normalize.c @@ -156,53 +156,29 @@ SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s1 } } -SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Electrify's effect", s16 damage) +SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Electrify's effect") { - u32 ability, genConfig; - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; } - GIVEN { ASSUME(GetMoveEffect(MOVE_ELECTRIFY) == EFFECT_ELECTRIFY); - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); - PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_SKITTY) { Ability(ABILITY_NORMALIZE); } + OPPONENT(SPECIES_ROOKIDEE) { Item(ITEM_WACAN_BERRY); } } WHEN { TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_WATER_GUN); } } SCENE { - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - if (genConfig >= GEN_7) - EXPECT_EQ(results[0].damage, results[2].damage); - else - EXPECT_EQ(results[1].damage, results[3].damage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); } } -SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Deluge's effect", s16 damage) +SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Deluge's effect") { - u32 ability, genConfig; - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; } - GIVEN { ASSUME(GetMoveEffect(MOVE_ION_DELUGE) == EFFECT_ION_DELUGE); - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); - PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_SKITTY) { Ability(ABILITY_NORMALIZE); Moves(MOVE_WATER_GUN); } + OPPONENT(SPECIES_ROOKIDEE) { Item(ITEM_WACAN_BERRY); } } WHEN { TURN { MOVE(opponent, MOVE_ION_DELUGE); MOVE(player, MOVE_WATER_GUN); } } SCENE { - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - if (genConfig >= GEN_7) - EXPECT_EQ(results[0].damage, results[2].damage); - else - EXPECT_EQ(results[1].damage, results[3].damage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); } } From 4d31693005bf628bfe259a7be9f3f47f87b3f810 Mon Sep 17 00:00:00 2001 From: pokesidv <216572922+pokesidv@users.noreply.github.com> Date: Sun, 3 Aug 2025 14:52:07 +0200 Subject: [PATCH 162/283] Rock climb by ghoulslash (#7432) Co-authored-by: Evan Co-authored-by: Jaizu Co-authored-by: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Co-authored-by: ghoulslash Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- data/field_effect_scripts.s | 10 + data/scripts/field_move_scripts.inc | 33 +++ graphics/field_effects/palettes/big_dust.pal | 19 ++ .../field_effects/pics/rock_climb_blob.png | Bin 0 -> 383 bytes .../field_effects/pics/rock_climb_dust.png | Bin 0 -> 558 bytes include/config/overworld.h | 1 + include/constants/event_object_movement.h | 5 + include/constants/field_effects.h | 5 + include/constants/field_move.h | 3 + include/constants/metatile_behaviors.h | 2 +- include/event_scripts.h | 1 + include/field_effect.h | 2 +- include/metatile_behavior.h | 1 + include/party_menu.h | 1 + spritesheet_rules.mk | 6 + .../field_effect_object_template_pointers.h | 4 + src/data/field_effects/field_effect_objects.h | 44 +++ .../movement_action_func_tables.h | 43 +++ .../object_events/object_event_graphics.h | 3 + src/event_object_movement.c | 47 ++- src/field_control_avatar.c | 3 + src/field_effect.c | 271 +++++++++++++++++- src/field_effect_helpers.c | 26 +- src/field_move.c | 18 +- src/metatile_behavior.c | 9 + src/party_menu.c | 23 ++ 26 files changed, 567 insertions(+), 13 deletions(-) create mode 100644 graphics/field_effects/palettes/big_dust.pal create mode 100644 graphics/field_effects/pics/rock_climb_blob.png create mode 100644 graphics/field_effects/pics/rock_climb_dust.png diff --git a/data/field_effect_scripts.s b/data/field_effect_scripts.s index 98ed66a13d..34678bb293 100644 --- a/data/field_effect_scripts.s +++ b/data/field_effect_scripts.s @@ -81,6 +81,8 @@ gFieldEffectScriptPointers:: .4byte gFieldEffectScript_TracksSpot @ FLDEFF_TRACKS_SPOT .4byte gFieldEffectScript_CaveDust @ FLDEFF_CAVE_DUST .4byte gFieldEffectScript_Defog @ FLDEFF_DEFOG + .4byte gFieldEffectScript_UseRockClimb @ FLDEFF_USE_ROCK_CLIMB + .4byte gFieldEffectScript_RockClimbDust @ FLDEFF_ROCK_CLIMB_DUST gFieldEffectScript_ExclamationMarkIcon1:: field_eff_callnative FldEff_ExclamationMarkIcon @@ -384,3 +386,11 @@ gFieldEffectScript_CaveDust:: gFieldEffectScript_Defog:: field_eff_callnative FldEff_Defog field_eff_end +gFieldEffectScript_UseRockClimb:: @ 82DBC3F + field_eff_callnative FldEff_UseRockClimb + field_eff_end + +gFieldEffectScript_RockClimbDust:: @ 82DBB28 + field_eff_loadfadedpal_callnative gSpritePalette_BigDust, FldEff_RockClimbDust + field_eff_end + diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index bfc6958138..e9a88367a7 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -441,3 +441,36 @@ EventScript_UseDefog:: waitstate releaseall end + +EventScript_UseRockClimb:: + lockall + checkfieldmove FIELD_MOVE_ROCK_CLIMB + goto_if_eq VAR_RESULT, PARTY_SIZE, EventScript_CantRockClimb + bufferpartymonnick STR_VAR_1, VAR_RESULT + setfieldeffectargument 0, VAR_RESULT + msgbox Text_WantToRockClimb, MSGBOX_YESNO + goto_if_eq VAR_RESULT, NO, EventScript_EndRockClimb + msgbox Text_MonUsedRockClimb, MSGBOX_DEFAULT + closemessage + dofieldeffect FLDEFF_USE_ROCK_CLIMB + waitstate + goto EventScript_EndRockClimb + end + +EventScript_CantRockClimb:: + msgbox Text_CantRockClimb, MSGBOX_DEFAULT + +EventScript_EndRockClimb:: + releaseall + end + +Text_WantToRockClimb: + .string "The cliff is steep.\n" + .string "Would you like to use Rock Climb?$" + +Text_MonUsedRockClimb: + .string "{STR_VAR_1} used Rock Climb!$" + +Text_CantRockClimb: + .string "The cliff is steep.\n" + .string "A Pokémon may be able to climb it.$" diff --git a/graphics/field_effects/palettes/big_dust.pal b/graphics/field_effects/palettes/big_dust.pal new file mode 100644 index 0000000000..34beaf0371 --- /dev/null +++ b/graphics/field_effects/palettes/big_dust.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +98 172 238 +198 181 156 +165 140 115 +181 165 140 +148 123 99 +206 198 173 +189 173 148 +82 74 57 +222 180 148 +140 123 82 +173 156 123 +238 213 180 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/field_effects/pics/rock_climb_blob.png b/graphics/field_effects/pics/rock_climb_blob.png new file mode 100644 index 0000000000000000000000000000000000000000..19a9a7cea9b64d8b91262792826091934322e1cf GIT binary patch literal 383 zcmV-_0f7FAP)5Fk0;=I(RNb4rv_|6*FjK|%lj{{R30FCfkm00009 za7bBm000&x000&x0ZCFM@Bjb+^+`lQR5*?8Q#*FUFbvb=Ri~3ydx=+G-AlBhvPnp! zlfJ$VnObh301*16^k09gfa7=kN0FcaJX+-D*ZIXOmiDN!x%IXS9L^`dD+d2GsFQ)c zukKFKE`F&TA(ugI(Qn|Co+>B@11V%Eg9FoHWD+x2)iS>b#2RJYT%wU7Gr-DB7!x!T zXrM=n7Xc#_I|mw66O2eaCw8jc4lUPj1t8%F3^9RCteApk4HbwPz%~uLIB*ZkrKqDJ zY9Lc^J&h^oBeV{0ATEIw@8M(sVPYU;#C1|8mN1Yb9A7D0gr3khj6H?A{kXefjvwkx d{Ydy+eE}yq7eUcLbl?C0002ovPDHLkV1g59m4pBQ literal 0 HcmV?d00001 diff --git a/graphics/field_effects/pics/rock_climb_dust.png b/graphics/field_effects/pics/rock_climb_dust.png new file mode 100644 index 0000000000000000000000000000000000000000..541c6ba9b8b3f3dba8f8546fe42f643169103d96 GIT binary patch literal 558 zcmV+}0@3}6P)=jL9sbPN{d@04`5?qC0JaozJOq5XKm{X z`p@jeM9pC`9Jd)V-^@S%#u$y4%uEZSayg+qBckKmF5j}drwTxH`<)%9hZ|b<`K|+( z33yK_vQ}rVd{6nZ>rZs|QEO_WO|PSkC@7CQV3z9uYMMw5ad0c7&o(w%Giz)-2fyxs zed&+@+fdGKApqMJh`bY!9{`6m@L5cNy=HGdxi5(?6(F(zM3e5^M3q{~RPenE%Fw|W z&s_chYz*?&+X$efb!+F+?2B(%V211n6IGID(mv>o76AH^hJXY1E&(p^J@}Ijcti*2 zf+R7Pu(bG!LqLOrg+J|pCv-4b`MqXn~xIssJ!|uBhZJsx-0h zlKzp}3PH8gZ=*&CAg37!Ovr)AwYhDLk`2X{2jsK5TXz}N5q@=LF$wL|Hq!&#*T~n6Z1+oDC%k~ wpx;7Wj}>ILUya0KB%o8SCKM|$R?g)30(n1Mi4fg(6#xJL07*qoM6N<$g5})wKL7v# literal 0 HcmV?d00001 diff --git a/include/config/overworld.h b/include/config/overworld.h index b1f107ce63..480c5dbcea 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -11,6 +11,7 @@ #define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last. #define OW_WHITEOUT_CUTSCENE GEN_LATEST // In Gen4+, whiting out shows an additional message and post whiteout event script cutscene with a healing NPC. (While this change was also in FRLG, for the sake of simplicity, setting this to GEN_3 will result in RSE behavior.) #define OW_DEFOG_FIELD_MOVE FALSE // If enabled, Defog can be used as a Field Move as seen in DPPt. +#define OW_ROCK_CLIMB_FIELD_MOVE FALSE // If enabled, Rock Climb can be used as a Field Move as seen in DPPt. // Item Obtain Description Box #define OW_ITEM_DESCRIPTIONS_OFF 0 // never show descriptions diff --git a/include/constants/event_object_movement.h b/include/constants/event_object_movement.h index 4e1b3a34ea..4f183d7667 100755 --- a/include/constants/event_object_movement.h +++ b/include/constants/event_object_movement.h @@ -259,6 +259,11 @@ #define MOVEMENT_ACTION_SURF_STILL_UP 0xAB #define MOVEMENT_ACTION_SURF_STILL_LEFT 0xAC #define MOVEMENT_ACTION_SURF_STILL_RIGHT 0xAD +//fast diagonal movement +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT 0xAE +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT 0xAF +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT 0xB0 +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT 0xB1 #define MOVEMENT_ACTION_STEP_END 0xFE #define MOVEMENT_ACTION_NONE 0xFF diff --git a/include/constants/field_effects.h b/include/constants/field_effects.h index e47cc292c3..e38b25cac7 100644 --- a/include/constants/field_effects.h +++ b/include/constants/field_effects.h @@ -77,6 +77,8 @@ #define FLDEFF_TRACKS_BUG 72 #define FLDEFF_CAVE_DUST 73 #define FLDEFF_DEFOG 74 +#define FLDEFF_USE_ROCK_CLIMB 75 +#define FLDEFF_ROCK_CLIMB_DUST 76 #define FLDEFFOBJ_SHADOW_S 0 #define FLDEFFOBJ_SHADOW_M 1 @@ -119,6 +121,8 @@ #define FLDEFFOBJ_TRACKS_SPOT 38 #define FLDEFFOBJ_TRACKS_BUG 39 #define FLDEFFOBJ_CAVE_DUST 40 +#define FLDEFFOBJ_ROCK_CLIMB_BLOB 41 +#define FLDEFFOBJ_ROCK_CLIMB_DUST 42 #define FLDEFF_PAL_TAG_CUT_GRASS 0x1000 #define FLDEFF_PAL_TAG_SECRET_POWER_TREE 0x1003 @@ -133,6 +137,7 @@ #define FLDEFF_PAL_TAG_HOF_MONITOR 0x1010 #define FLDEFF_PAL_TAG_UNKNOWN 0x1011 #define FLDEFF_PAL_TAG_CAVE_DUST 0x1012 +#define FLDEFF_PAL_TAG_DUST_CLOUD 0x1013 #define FLDEFF_PAL_TAG_FIELD_MOVE_MON 0x8400 // tile tags, for field effects that may have many copies on screen at once diff --git a/include/constants/field_move.h b/include/constants/field_move.h index 1d0fb83977..c6c49c8708 100644 --- a/include/constants/field_move.h +++ b/include/constants/field_move.h @@ -18,6 +18,9 @@ enum FieldMove FIELD_MOVE_MILK_DRINK, FIELD_MOVE_SOFT_BOILED, FIELD_MOVE_SWEET_SCENT, +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE + FIELD_MOVE_ROCK_CLIMB, +#endif #if OW_DEFOG_FIELD_MOVE == TRUE FIELD_MOVE_DEFOG, #endif diff --git a/include/constants/metatile_behaviors.h b/include/constants/metatile_behaviors.h index 505f279f73..12ced67a9f 100755 --- a/include/constants/metatile_behaviors.h +++ b/include/constants/metatile_behaviors.h @@ -241,7 +241,7 @@ enum { MB_UP_LEFT_STAIR_WARP, MB_DOWN_RIGHT_STAIR_WARP, MB_DOWN_LEFT_STAIR_WARP, - MB_UNUSED_EF, + MB_ROCK_CLIMB, NUM_METATILE_BEHAVIORS }; diff --git a/include/event_scripts.h b/include/event_scripts.h index fa2df54740..646b054195 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -573,6 +573,7 @@ extern const u8 EventScript_UseWaterfall[]; extern const u8 EventScript_CannotUseWaterfall[]; extern const u8 EventScript_UseDive[]; extern const u8 EventScript_UseDiveUnderwater[]; +extern const u8 EventScript_UseRockClimb[]; extern const u8 EventScript_FallDownHole[]; extern const u8 EventScript_FieldPoison[]; extern const u8 EventScript_EggHatch[]; diff --git a/include/field_effect.h b/include/field_effect.h index 2e13879353..2b933e0c1f 100644 --- a/include/field_effect.h +++ b/include/field_effect.h @@ -49,5 +49,5 @@ void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId); u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority); void StartEscapeRopeFieldEffect(void); void FieldEffectFreeGraphicsResources(struct Sprite *sprite); - +bool8 IsRockClimbActive(void); #endif // GUARD_FIELD_EFFECTS_H diff --git a/include/metatile_behavior.h b/include/metatile_behavior.h index ecdc696d41..5e268d7262 100644 --- a/include/metatile_behavior.h +++ b/include/metatile_behavior.h @@ -164,5 +164,6 @@ bool8 MetatileBehavior_IsSidewaysStairsRightSideBottom(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsLeftSideBottom(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsRightSideAny(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsLeftSideAny(u8 metatileBehavior); +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior); #endif // GUARD_METATILE_BEHAVIOR_H diff --git a/include/party_menu.h b/include/party_menu.h index 5aa9472dac..c450ab02c0 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -110,5 +110,6 @@ bool32 SetUpFieldMove_Surf(void); bool32 SetUpFieldMove_Fly(void); bool32 SetUpFieldMove_Waterfall(void); bool32 SetUpFieldMove_Dive(void); +bool32 SetUpFieldMove_RockClimb(void); #endif // GUARD_PARTY_MENU_H diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index aaa346ccf1..ef5da9c091 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -663,6 +663,9 @@ $(FLDEFFGFXDIR)/deep_sand_footprints.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/ground_impact_dust.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 1 +$(FLDEFFGFXDIR)/rock_climb_dust.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/ash_puff.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 @@ -687,6 +690,9 @@ $(FLDEFFGFXDIR)/short_grass.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/surf_blob.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 +$(FLDEFFGFXDIR)/rock_climb_blob.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/tall_grass.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 diff --git a/src/data/field_effects/field_effect_object_template_pointers.h b/src/data/field_effects/field_effect_object_template_pointers.h index 7173ffbe58..281c664f03 100755 --- a/src/data/field_effects/field_effect_object_template_pointers.h +++ b/src/data/field_effects/field_effect_object_template_pointers.h @@ -40,6 +40,8 @@ extern const struct SpriteTemplate gFieldEffectObjectTemplate_SlitherTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_BugTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_SpotTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_CaveDust; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust; const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_SHADOW_S] = &gFieldEffectObjectTemplate_ShadowSmall, @@ -83,4 +85,6 @@ const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_TRACKS_SPOT] = &gFieldEffectObjectTemplate_SpotTracks, [FLDEFFOBJ_TRACKS_BUG] = &gFieldEffectObjectTemplate_BugTracks, [FLDEFFOBJ_CAVE_DUST] = &gFieldEffectObjectTemplate_CaveDust, + [FLDEFFOBJ_ROCK_CLIMB_BLOB] = &gFieldEffectObjectTemplate_RockClimbBlob, + [FLDEFFOBJ_ROCK_CLIMB_DUST] = &gFieldEffectObjectTemplate_RockClimbDust, }; diff --git a/src/data/field_effects/field_effect_objects.h b/src/data/field_effects/field_effect_objects.h index 5638ea46e2..aae9ad1948 100755 --- a/src/data/field_effects/field_effect_objects.h +++ b/src/data/field_effects/field_effect_objects.h @@ -1404,3 +1404,47 @@ const struct SpriteTemplate gFieldEffectObjectTemplate_CaveDust = { }; const struct SpritePalette gSpritePalette_CaveDust = {gFieldEffectObjectPalette_CaveDust, FLDEFF_PAL_TAG_CAVE_DUST}; +static const struct SpriteFrameImage sPicTable_RockClimbBlob[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 2), +}; + +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob = { + .tileTag = 0xFFFF, + .paletteTag = 0xFFFF, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_SurfBlob, + .images = sPicTable_RockClimbBlob, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateSurfBlobFieldEffect, +}; + + +static const union AnimCmd sAnim_RockClimbDust[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(2, 12), + ANIMCMD_END, +}; +static const union AnimCmd *const sAnimTable_RockClimbDust[] = +{ + sAnim_RockClimbDust, +}; +static const struct SpriteFrameImage sPicTable_RockClimbDust[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 2), +}; +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust = { + .tileTag = 0xFFFF, + .paletteTag = FLDEFF_PAL_TAG_DUST_CLOUD, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_RockClimbDust, + .images = sPicTable_RockClimbDust, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateJumpImpactEffect, +}; + +const struct SpritePalette gSpritePalette_BigDust = {gFieldEffectPal_DustCloud, FLDEFF_PAL_TAG_DUST_CLOUD}; diff --git a/src/data/object_events/movement_action_func_tables.h b/src/data/object_events/movement_action_func_tables.h index 44639b6c9b..686e468fca 100755 --- a/src/data/object_events/movement_action_func_tables.h +++ b/src/data/object_events/movement_action_func_tables.h @@ -287,6 +287,12 @@ u8 MovementAction_SurfStillLeft_Step0(struct ObjectEvent *objectEvent, struct Sp u8 MovementAction_SurfStillLeft_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite); u8 MovementAction_SurfStillRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); u8 MovementAction_SurfStillRight_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite); +//fast diagonal +u8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *); @@ -463,6 +469,12 @@ u8 (*const gMovementActionFuncs_SurfStillDown[])(struct ObjectEvent *, struct Sp u8 (*const gMovementActionFuncs_SurfStillUp[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_SurfStillLeft[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_SurfStillRight[])(struct ObjectEvent *, struct Sprite *); +//fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *); + u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) = { [MOVEMENT_ACTION_FACE_DOWN] = gMovementActionFuncs_FaceDown, @@ -639,6 +651,12 @@ u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) [MOVEMENT_ACTION_SURF_STILL_UP] = gMovementActionFuncs_SurfStillUp, [MOVEMENT_ACTION_SURF_STILL_LEFT] = gMovementActionFuncs_SurfStillLeft, [MOVEMENT_ACTION_SURF_STILL_RIGHT] = gMovementActionFuncs_SurfStillRight, + //fast diagonal + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT] = gMovementActionFuncs_WalkFastDiagonalUpLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT] = gMovementActionFuncs_WalkFastDiagonalUpRight, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT] = gMovementActionFuncs_WalkFastDiagonalDownLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT] = gMovementActionFuncs_WalkFastDiagonalDownRight, + }; u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *) = { @@ -1676,3 +1694,28 @@ u8 (*const gMovementActionFuncs_SurfStillRight[])(struct ObjectEvent *, struct S MovementAction_SurfStillRight_Step1, MovementAction_PauseSpriteAnim, }; +// fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + diff --git a/src/data/object_events/object_event_graphics.h b/src/data/object_events/object_event_graphics.h index c7b92def91..e3d2c674ad 100755 --- a/src/data/object_events/object_event_graphics.h +++ b/src/data/object_events/object_event_graphics.h @@ -286,6 +286,8 @@ const u32 gObjectEventPic_CustapBerryTree[] = INCBIN_U32("graphics/object_events const u32 gObjectEventPic_JabocaBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/jaboca.4bpp"); const u32 gObjectEventPic_RowapBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/rowap.4bpp"); const u32 gFieldEffectObjectPic_SurfBlob[] = INCBIN_U32("graphics/field_effects/pics/surf_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbBlob[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbDust[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_dust.4bpp"); const u32 gObjectEventPic_QuintyPlump[] = INCBIN_U32("graphics/object_events/pics/people/quinty_plump.4bpp"); const u16 gObjectEventPal_QuintyPlump[] = INCBIN_U16("graphics/object_events/palettes/quinty_plump.gbapal"); const u16 gObjectEventPal_QuintyPlumpReflection[] = INCBIN_U16("graphics/object_events/palettes/quinty_plump_reflection.gbapal"); @@ -330,6 +332,7 @@ const u32 gFieldEffectObjectPic_MountainDisguise[] = INCBIN_U32("graphics/field_ const u32 gFieldEffectObjectPic_SandDisguisePlaceholder[] = INCBIN_U32("graphics/field_effects/pics/sand_disguise_placeholder.4bpp"); const u32 gFieldEffectObjectPic_HotSpringsWater[] = INCBIN_U32("graphics/field_effects/pics/hot_springs_water.4bpp"); const u16 gFieldEffectPal_Ash[] = INCBIN_U16("graphics/field_effects/palettes/ash.gbapal"); +const u16 gFieldEffectPal_DustCloud[] = INCBIN_U16("graphics/field_effects/palettes/big_dust.gbapal"); const u32 gFieldEffectObjectPic_AshPuff[] = INCBIN_U32("graphics/field_effects/pics/ash_puff.4bpp"); const u32 gFieldEffectObjectPic_AshLaunch[] = INCBIN_U32("graphics/field_effects/pics/ash_launch.4bpp"); const u32 gFieldEffectObjectPic_Bubbles[] = INCBIN_U32("graphics/field_effects/pics/bubbles.4bpp"); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 7f4e7ec142..a91bb04b25 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -820,10 +820,10 @@ static const u8 sJumpSpecialDirectionAnimNums[] = { // used for jumping onto sur [DIR_NORTH] = ANIM_GET_ON_OFF_POKEMON_NORTH, [DIR_WEST] = ANIM_GET_ON_OFF_POKEMON_WEST, [DIR_EAST] = ANIM_GET_ON_OFF_POKEMON_EAST, - [DIR_SOUTHWEST] = ANIM_GET_ON_OFF_POKEMON_SOUTH, - [DIR_SOUTHEAST] = ANIM_GET_ON_OFF_POKEMON_SOUTH, - [DIR_NORTHWEST] = ANIM_GET_ON_OFF_POKEMON_NORTH, - [DIR_NORTHEAST] = ANIM_GET_ON_OFF_POKEMON_NORTH, + [DIR_SOUTHWEST] = ANIM_GET_ON_OFF_POKEMON_WEST, + [DIR_SOUTHEAST] = ANIM_GET_ON_OFF_POKEMON_EAST, + [DIR_NORTHWEST] = ANIM_GET_ON_OFF_POKEMON_WEST, + [DIR_NORTHEAST] = ANIM_GET_ON_OFF_POKEMON_EAST, }; static const u8 sAcroWheelieDirectionAnimNums[] = { [DIR_NONE] = ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH, @@ -1068,6 +1068,10 @@ const u8 gJumpSpecialMovementActions[] = { MOVEMENT_ACTION_JUMP_SPECIAL_UP, MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, }; const u8 gWalkInPlaceSlowMovementActions[] = { [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, @@ -11353,6 +11357,41 @@ bool8 MovementAction_WalkSlowStairsUp_Step1(struct ObjectEvent *objectEvent, str return FALSE; } +// fast diagonal +bool8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_NORTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_NORTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_SOUTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_SOUTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (UpdateMovementNormal(objectEvent, sprite)) + { + sprite->data[2] = 2; + return TRUE; + } + return FALSE; +} + bool8 MovementAction_WalkSlowStairsDown_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { InitWalkSlow(objectEvent, sprite, DIR_SOUTH); diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index ebcd775ed9..f35c349fc6 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -13,6 +13,7 @@ #include "field_control_avatar.h" #include "field_message_box.h" #include "field_move.h" +#include "field_effect.h" #include "field_player_avatar.h" #include "field_poison.h" #include "field_screen_effect.h" @@ -521,6 +522,8 @@ static const u8 *GetInteractedMetatileScript(struct MapPosition *position, u8 me SetMsgSignPostAndVarFacing(direction); return Common_EventScript_ShowPokemonCenterSign; } + if (MetatileBehavior_IsRockClimbable(metatileBehavior) == TRUE && !IsRockClimbActive()) + return EventScript_UseRockClimb; elevation = position->elevation; if (elevation == MapGridGetElevationAt(position->x, position->y)) diff --git a/src/field_effect.c b/src/field_effect.c index 5cdc3472fb..8a11f56a68 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -245,6 +245,18 @@ static void UseVsSeeker_DoPlayerAnimation(struct Task *task); static void UseVsSeeker_ResetPlayerGraphics(struct Task *task); static void UseVsSeeker_CleanUpFieldEffect(struct Task *task); +static void Task_UseRockClimb(u8); +static bool8 RockClimb_Init(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_FieldMovePose(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ShowMon(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent); +//static bool8 RockClimb_RideUp(struct Task *, struct ObjectEvent *); +//static bool8 RockClimb_RideDown(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ContinueRideOrEnd(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent); // Static RAM declarations static u8 sActiveList[32]; @@ -1987,7 +1999,7 @@ static bool8 WaterfallFieldEffect_ContinueRideOrEnd(struct Task *task, struct Ob { if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) return FALSE; - + if (MetatileBehavior_IsWaterfall(objectEvent->currentMetatileBehavior)) { // Still ascending waterfall, back to WaterfallFieldEffect_RideUp @@ -4156,6 +4168,263 @@ u8 FldEff_CaveDust(void) return spriteId; } +// ROCK CLIMB +enum RockClimbState +{ + STATE_ROCK_CLIMB_INIT, + STATE_ROCK_CLIMB_POSE, + STATE_ROCK_CLIMB_SHOW_MON, + STATE_ROCK_CLIMB_JUMP_ON, + STATE_ROCK_CLIMB_WAIT_JUMP, + STATE_ROCK_CLIMB_RIDE, + STATE_ROCK_CLIMB_CONTINUE_RIDE, + STATE_ROCK_CLIMB_STOP_INIT, + STATE_ROCK_CLIMB_WAIT_STOP +}; + +#define tState data[0] +#define tDestX data[1] +#define tDestY data[2] +#define tMonId data[15] + +static u8 CreateRockClimbBlob(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_BLOB], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x96); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.paletteNum = LoadPlayerObjectEventPalette(gSaveBlock2Ptr->playerGender); + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = -1; + sprite->data[6] = -1; + sprite->data[7] = -1; + } + + return spriteId; +} + +bool8 (*const sRockClimbFieldEffectFuncs[])(struct Task *, struct ObjectEvent *) = +{ + [STATE_ROCK_CLIMB_INIT] = RockClimb_Init, + [STATE_ROCK_CLIMB_POSE] = RockClimb_FieldMovePose, + [STATE_ROCK_CLIMB_SHOW_MON] = RockClimb_ShowMon, + [STATE_ROCK_CLIMB_JUMP_ON] = RockClimb_JumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_WAIT_JUMP] = RockClimb_WaitJumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_RIDE] = RockClimb_Ride, + [STATE_ROCK_CLIMB_CONTINUE_RIDE] = RockClimb_ContinueRideOrEnd, + [STATE_ROCK_CLIMB_STOP_INIT] = RockClimb_StopRockClimbInit, + [STATE_ROCK_CLIMB_WAIT_STOP] = RockClimb_WaitStopRockClimb +}; + +bool8 FldEff_UseRockClimb(void) +{ + u8 taskId; + taskId = CreateTask(Task_UseRockClimb, 0xff); + gTasks[taskId].tMonId = gFieldEffectArguments[0]; + Task_UseRockClimb(taskId); + return FALSE; +} + +static void Task_UseRockClimb(u8 taskId) +{ + while (sRockClimbFieldEffectFuncs[gTasks[taskId].tState](&gTasks[taskId], &gObjectEvents[gPlayerAvatar.objectEventId])); +} + +static bool8 RockClimb_Init(struct Task *task, struct ObjectEvent *objectEvent) +{ + LockPlayerFieldControls(); + FreezeObjectEvents(); + // Put follower into pokeball before using Rock Climb + HideFollowerForFieldEffect(); + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_SURFING); + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].movementDirection, &task->tDestX, &task->tDestY); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_FieldMovePose(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventIsMovementOverridden(objectEvent) || ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetPlayerAvatarFieldMove(); + ObjectEventSetHeldMovement(objectEvent, MOVEMENT_ACTION_START_ANIM_IN_DIRECTION); + task->tState++; + } + return FALSE; +} + +static bool8 RockClimb_ShowMon(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventCheckHeldMovementStatus(objectEvent)) + { + gFieldEffectArguments[0] = task->tMonId | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->tState++; + return TRUE; + } + return FALSE; +} + +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + objectEvent->noShadow = TRUE; // hide shadow + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_SURFING)); + ObjectEventClearHeldMovementIfFinished(objectEvent); + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(objectEvent->movementDirection)); + gFieldEffectArguments[0] = task->tDestX; + gFieldEffectArguments[1] = task->tDestY; + gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; + objectEvent->fieldEffectSpriteId = CreateRockClimbBlob(); + task->tState++; + } + + return FALSE; +} + +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_PLAYER_AND_MON); + switch (objectEvent->facingDirection) + { + case DIR_EAST: + //check southeast then northeast + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHEAST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHEAST; + break; + case DIR_WEST: + //check northwest then southwest + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHWEST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHWEST; + break; + } + + task->tState = STATE_ROCK_CLIMB_CONTINUE_RIDE; + } + + return FALSE; +} + +struct RockClimbRide +{ + u8 action; + s8 dx; + s8 dy; + u8 jumpDir; +}; +static const struct RockClimbRide sRockClimbMovement[] = +{ + [DIR_NONE] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, 0, DIR_NONE}, + [DIR_SOUTH] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, -1, DIR_SOUTH}, + [DIR_NORTH] = {MOVEMENT_ACTION_WALK_FAST_UP, 0, 1, DIR_NORTH}, + [DIR_WEST] = {MOVEMENT_ACTION_WALK_FAST_LEFT, 1, 1, DIR_WEST}, + [DIR_EAST] = {MOVEMENT_ACTION_WALK_FAST_RIGHT, -1, -1, DIR_EAST}, + [DIR_SOUTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT, 1, -1, DIR_WEST}, + [DIR_SOUTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT, -1, -1, DIR_EAST}, + [DIR_NORTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT, 1, 1, DIR_WEST}, + [DIR_NORTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT, -1, 1, DIR_EAST}, +}; + +static void RockClimbDust(struct ObjectEvent *objectEvent, u8 direction) +{ + s8 dx = sRockClimbMovement[direction].dx; + s8 dy = sRockClimbMovement[direction].dy; + + gFieldEffectArguments[0] = objectEvent->currentCoords.x + dx; + gFieldEffectArguments[1] = objectEvent->currentCoords.y + dy; + gFieldEffectArguments[2] = objectEvent->previousElevation; + gFieldEffectArguments[3] = gSprites[objectEvent->spriteId].oam.priority; + FieldEffectStart(FLDEFF_ROCK_CLIMB_DUST); +} + +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent) +{ + ObjectEventSetHeldMovement(objectEvent, sRockClimbMovement[objectEvent->movementDirection].action); + PlaySE(SE_M_ROCK_THROW); + RockClimbDust(objectEvent, objectEvent->movementDirection); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(objectEvent->movementDirection, &task->tDestX, &task->tDestY); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX, task->tDestY))) + { + task->tState = STATE_ROCK_CLIMB_RIDE; + return TRUE; + } + + LockPlayerFieldControls(); + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; + task->tState++; + return FALSE; +} + +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventIsMovementOverridden(objectEvent)) + { + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + } + + RockClimbDust(objectEvent, DIR_NONE); //dust on final spot + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(sRockClimbMovement[objectEvent->movementDirection].jumpDir)); + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_NONE); + task->tState++; + return TRUE; +} + +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent) +{ + struct ObjectEvent *followerObject = GetFollowerObject(); + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_NORMAL)); + ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->facingDirection)); + gPlayerAvatar.preventStep = FALSE; + if (followerObject) + ObjectEventClearHeldMovementIfFinished(followerObject); // restore follower to normal + objectEvent->noShadow = FALSE; // restore shadow + UnfreezeObjectEvents(); + UnlockPlayerFieldControls(); + DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); + FieldEffectActiveListRemove(FLDEFF_USE_ROCK_CLIMB); + objectEvent->triggerGroundEffectsOnMove = TRUE; // e.g. if dismount on grass + DestroyTask(FindTaskIdByFunc(Task_UseRockClimb)); + } + + return FALSE; +} + +bool8 IsRockClimbActive(void) +{ + if (FieldEffectActiveListContains(FLDEFF_USE_ROCK_CLIMB)) + return TRUE; + else + return FALSE; +} + #undef tState #undef tSpriteId #undef tTargetX diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index f7a6531ec2..2e9e1a8510 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -1263,10 +1263,10 @@ static void SynchroniseSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sp [DIR_NORTH] = 1, [DIR_WEST] = 2, [DIR_EAST] = 3, - [DIR_SOUTHWEST] = 0, - [DIR_SOUTHEAST] = 0, - [DIR_NORTHWEST] = 1, - [DIR_NORTHEAST] = 1, + [DIR_SOUTHWEST] = 2, + [DIR_SOUTHEAST] = 3, + [DIR_NORTHWEST] = 2, + [DIR_NORTHEAST] = 3, }; if (!GetSurfBlob_DontSyncAnim(sprite)) @@ -1389,6 +1389,24 @@ u32 FldEff_Dust(void) return 0; } +u32 FldEff_RockClimbDust(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_DUST], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = FLDEFF_ROCK_CLIMB_DUST; + } + return 0; +} + // Sprite data for FLDEFF_SAND_PILE #define sLocalId data[0] #define sMapNum data[1] diff --git a/src/field_move.c b/src/field_move.c index ff9c986436..49c81bec9a 100644 --- a/src/field_move.c +++ b/src/field_move.c @@ -48,6 +48,13 @@ static bool32 IsFieldMoveUnlocked_Waterfall(void) return FlagGet(FLAG_BADGE08_GET); } +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE +static bool32 IsFieldMoveUnlocked_RockClimb(void) +{ + return TRUE; +} +#endif + static bool32 IsFieldMoveUnlocked_Teleport(void) { return TRUE; @@ -198,7 +205,15 @@ const struct FieldMoveInfo gFieldMoveInfo[FIELD_MOVES_COUNT] = .moveID = MOVE_SWEET_SCENT, .partyMsgID = PARTY_MSG_CANT_USE_HERE, }, - +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE + [FIELD_MOVE_ROCK_CLIMB] = + { + .fieldMoveFunc = SetUpFieldMove_RockClimb, + .isUnlockedFunc = IsFieldMoveUnlocked_RockClimb, + .moveID = MOVE_ROCK_CLIMB, + .partyMsgID = PARTY_MSG_CANT_USE_HERE, + }, +#endif #if OW_DEFOG_FIELD_MOVE == TRUE [FIELD_MOVE_DEFOG] = { @@ -208,5 +223,4 @@ const struct FieldMoveInfo gFieldMoveInfo[FIELD_MOVES_COUNT] = .partyMsgID = PARTY_MSG_CANT_USE_HERE, }, #endif - }; diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c index 2d61e9a75a..687b98ca27 100644 --- a/src/metatile_behavior.c +++ b/src/metatile_behavior.c @@ -133,6 +133,7 @@ static const u8 sTileBitAttributes[NUM_METATILE_BEHAVIORS] = [MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, [MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, [MB_ROCK_STAIRS] = TILE_FLAG_UNUSED, + [MB_ROCK_CLIMB] = TILE_FLAG_UNUSED, }; bool8 MetatileBehavior_IsATile(u8 metatileBehavior) @@ -1542,3 +1543,11 @@ bool8 MetatileBehavior_IsRockStairs(u8 metatileBehavior) else return FALSE; } + +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior) +{ + if (metatileBehavior == MB_ROCK_CLIMB) + return TRUE; + else + return FALSE; +} diff --git a/src/party_menu.c b/src/party_menu.c index 71464969ba..9b48152b9b 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -489,6 +489,7 @@ void TryItemHoldFormChange(struct Pokemon *mon, s8 slotId); static void ShowMoveSelectWindow(u8 slot); static void Task_HandleWhichMoveInput(u8 taskId); static void Task_HideFollowerNPCForTeleport(u8); +static void FieldCallback_RockClimb(void); // static const data #include "data/party_menu.h" @@ -4194,6 +4195,21 @@ bool32 SetUpFieldMove_Waterfall(void) return FALSE; } +bool32 SetUpFieldMove_RockClimb(void) +{ + s16 x, y; + + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(x, y))) + { + gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu; + gPostMenuFieldCallback = FieldCallback_RockClimb; + return TRUE; + } + + return FALSE; +} + static void FieldCallback_Dive(void) { gFieldEffectArguments[0] = GetCursorSelectionMonId(); @@ -7997,3 +8013,10 @@ void CursorCb_MoveItem(u8 taskId) gTasks[taskId].func = Task_UpdateHeldItemSprite; } } + +static void FieldCallback_RockClimb(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + FieldEffectStart(FLDEFF_USE_ROCK_CLIMB); +} + From 54ffc6bf0856661be1289afa7961d30e1a2c3414 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sun, 3 Aug 2025 21:59:48 +0200 Subject: [PATCH 163/283] Fixes Leech Seed recovery not applying behind Sub --- data/battle_scripts_1.s | 1 + test/battle/move_effect/leech_seed.c | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 13d3c09012..23c1e10aa9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5776,6 +5776,7 @@ BattleScript_LeechSeedTurnDrainHealBlock:: BattleScript_LeechSeedTurnDrainRecovery:: call BattleScript_LeechSeedTurnDrain BattleScript_LeechSeedTurnDrainGainHp: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_TARGET datahpupdate BS_TARGET printfromtable gLeechSeedStringIds diff --git a/test/battle/move_effect/leech_seed.c b/test/battle/move_effect/leech_seed.c index 56da50a12b..49f963f416 100644 --- a/test/battle/move_effect/leech_seed.c +++ b/test/battle/move_effect/leech_seed.c @@ -66,11 +66,11 @@ DOUBLE_BATTLE_TEST("Leech Seed will drain HP based on speed of the drained mon") OPPONENT(SPECIES_WYNAUT) { Speed(3); } OPPONENT(SPECIES_WOBBUFFET) { Speed(4); } } WHEN { - TURN { - MOVE(playerLeft, MOVE_LEECH_SEED, target: opponentLeft); - MOVE(playerRight, MOVE_LEECH_SEED, target: opponentRight); - MOVE(opponentLeft, MOVE_LEECH_SEED, target: playerLeft); - MOVE(opponentRight, MOVE_LEECH_SEED, target: playerRight); + TURN { + MOVE(playerLeft, MOVE_LEECH_SEED, target: opponentLeft); + MOVE(playerRight, MOVE_LEECH_SEED, target: opponentRight); + MOVE(opponentLeft, MOVE_LEECH_SEED, target: playerLeft); + MOVE(opponentRight, MOVE_LEECH_SEED, target: playerRight); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, opponentRight); @@ -88,6 +88,24 @@ DOUBLE_BATTLE_TEST("Leech Seed will drain HP based on speed of the drained mon") } } +SINGLE_BATTLE_TEST("Leech Seeded recovers health through Substitute") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); } + TURN { MOVE(player, MOVE_LEECH_SEED); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player); + HP_BAR(player); + HP_BAR(opponent); + HP_BAR(player); + } +} + TO_DO_BATTLE_TEST("Leech Seed doesn't affect already seeded targets") TO_DO_BATTLE_TEST("Leech Seed's effect is paused until a new battler replaces the original user's position") // Faint, can't be replaced, then revived. TO_DO_BATTLE_TEST("Leech Seed's effect pause still prevents it from being seeded again") From 014f289ea9e279d5f2008b0c8ebecdfc24d84c70 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:41:43 +0100 Subject: [PATCH 164/283] Fixes Round and Fusion moves doubling power from previous turn's move (#7476) --- src/battle_script_commands.c | 7 ++++--- src/battle_util.c | 22 ++++++++++------------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6798b9bd9c..d749d450d7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6829,6 +6829,7 @@ static void Cmd_moveend(void) UpdateStallMons(); if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) + || gBattleStruct->pledgeMove == TRUE // Is the battler that uses the first Pledge move in the combo || gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility) gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2; @@ -12194,7 +12195,7 @@ void BS_RemoveStockpileCounters(void) { NATIVE_ARGS(); - if (GetMoveEffect(gCurrentMove) == EFFECT_SWALLOW + if (GetMoveEffect(gCurrentMove) == EFFECT_SPIT_UP && gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) { @@ -16996,7 +16997,7 @@ static void TryUpdateRoundTurnOrder(void) } // update turn order for round users - for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && roundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = roundUsers[i]; gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again @@ -17004,7 +17005,7 @@ static void TryUpdateRoundTurnOrder(void) } // Update turn order for non-round users - for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && nonRoundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; currRounder++; diff --git a/src/battle_util.c b/src/battle_util.c index e580c63616..fb28a6129c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8072,6 +8072,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData u32 battlerAtk = damageCalcData->battlerAtk; u32 battlerDef = damageCalcData->battlerDef; u32 move = damageCalcData->move; + u32 moveEffect = GetMoveEffect(move); u32 i; u32 basePower = GetMovePower(move); @@ -8083,7 +8084,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX) return GetMaxMovePower(move); - switch (GetMoveEffect(move)) + switch (moveEffect) { case EFFECT_PLEDGE: if (gBattleStruct->pledgeMove) @@ -8242,18 +8243,15 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData || gDisableStructs[battlerDef].isFirstTurn == 2) basePower *= 2; break; - case EFFECT_ROUND: - for (i = 0; i < gBattlersCount; i++) - { - if (i != battlerAtk && IsBattlerAlive(i) && GetMoveEffect(gLastUsedMove) == EFFECT_ROUND) - { - basePower *= 2; - break; - } - } - break; case EFFECT_FUSION_COMBO: - if (GetMoveEffect(gLastUsedMove) == EFFECT_FUSION_COMBO && move != gLastUsedMove) + if (move == gLastUsedMove) + break; + // fallthrough + case EFFECT_ROUND: + // don't double power due to previous turn's Round/Fusion move + if (gCurrentTurnActionNumber != 0 + && gActionsByTurnOrder[gCurrentTurnActionNumber - 1] == B_ACTION_USE_MOVE + && GetMoveEffect(gLastUsedMove) == moveEffect) basePower *= 2; break; case EFFECT_LASH_OUT: From 3dbcb2adb4a11ccec6b8a6547a401d52273d257a Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 4 Aug 2025 06:42:22 -0400 Subject: [PATCH 165/283] Add Synthesis + Utililty Umbrella test (#7472) Co-authored-by: ghoulslash --- test/battle/move_effect/synthesis.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/battle/move_effect/synthesis.c b/test/battle/move_effect/synthesis.c index 6799bd2870..954cf2e854 100644 --- a/test/battle/move_effect/synthesis.c +++ b/test/battle/move_effect/synthesis.c @@ -46,3 +46,21 @@ SINGLE_BATTLE_TEST("Synthesis recovers 1/4 of the user's max HP in Rain, Sandsto HP_BAR(player, damage: -(400 / 4)); } } + +SINGLE_BATTLE_TEST("Synthesis recovers regular amount in sandstorm if holding utility umbrella") +{ + u32 item; + PARAMETRIZE { item = ITEM_LIFE_ORB; } + PARAMETRIZE { item = ITEM_UTILITY_UMBRELLA; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SANDSTORM); MOVE(player, MOVE_SYNTHESIS); } + } SCENE { + if (item != ITEM_UTILITY_UMBRELLA) + HP_BAR(player, damage: -(400 / 4)); + else + HP_BAR(player, damage: -(400 / 2)); + } +} From 7f493948ed0abfc9354ef9e5b78175fee04e38d6 Mon Sep 17 00:00:00 2001 From: Raymond Dodge Date: Mon, 4 Aug 2025 07:48:06 -0400 Subject: [PATCH 166/283] Replace all usages of rl compression with smol (#7458) --- .../1.13/convert_compressed_files.py | 10 ++- src/contest_painting.c | 68 +++++++++---------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/migration_scripts/1.13/convert_compressed_files.py b/migration_scripts/1.13/convert_compressed_files.py index 11f29708bc..0ccb5d61c1 100644 --- a/migration_scripts/1.13/convert_compressed_files.py +++ b/migration_scripts/1.13/convert_compressed_files.py @@ -9,9 +9,10 @@ primaryTileset_pattern = re.compile(r"(.*\"data/tilesets/primary/.+\.4bpp\.)lz(\".*)") secondaryTileset_pattern = re.compile(r"(.*\"data/tilesets/secondary/.+\.4bpp\.)lz(\".*)") -tilemap_pattern = re.compile(r"(.*\"graphics/.+\.bin\.)lz(\".*)") +tilemap_pattern = re.compile(r"(.*\"graphics/.+\.bin\.)(?:lz|rl)(\".*)") lzuncomp_pattern = re.compile(r"(.*)\bLZ77UnComp([WV])ram\b(\(.*)") lzdecomp_pattern = re.compile(r"(.*)\bLZDecompress([WV])ram\b(\(.*)") +rluncomp_pattern = re.compile(r"(.*)\bRLUnComp([WV])ram\b(\(.*)") def handle_file(fileInput): fileTest = Path(fileInput) @@ -33,8 +34,12 @@ def handle_file(fileInput): line = match.group(1) + "smolTM" + match.group(2) + "\n" elif ".4bpp.lz" in line: line = line.replace(".4bpp.lz", ".4bpp.smol") + elif ".4bpp.rl" in line: + line = line.replace(".4bpp.rl", ".4bpp.smol") elif ".8bpp.lz" in line: line = line.replace(".8bpp.lz", ".8bpp.smol") + elif ".8bpp.rl" in line: + line = line.replace(".8bpp.rl", ".8bpp.smol") elif match := lzuncomp_pattern.match(line): if allLines[-1].strip() != "case MODE_LZ77:": # do not modify DecompressDataWithHeader itself line = match.group(1) + "DecompressDataWithHeader" + match.group(2) + "ram" + match.group(3) + "\n" @@ -42,6 +47,9 @@ def handle_file(fileInput): elif match := lzdecomp_pattern.match(line): line = match.group(1) + "DecompressDataWithHeader" + match.group(2) + "ram" + match.group(3) + "\n" needs_decompress_h = True + elif match := rluncomp_pattern.match(line): + line = match.group(1) + "DecompressDataWithHeader" + match.group(2) + "ram" + match.group(3) + "\n" + needs_decompress_h = True else: pass diff --git a/src/contest_painting.c b/src/contest_painting.c index 4853b9425c..e8f929ef4b 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -70,18 +70,18 @@ extern const u8 gContestPaintingTough2[]; extern const u8 gContestPaintingTough3[]; static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); -static const u32 sPictureFrameTiles_Cool[] = INCBIN_U32("graphics/picture_frame/cool.4bpp.rl"); -static const u32 sPictureFrameTiles_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty.4bpp.rl"); -static const u32 sPictureFrameTiles_Cute[] = INCBIN_U32("graphics/picture_frame/cute.4bpp.rl"); -static const u32 sPictureFrameTiles_Smart[] = INCBIN_U32("graphics/picture_frame/smart.4bpp.rl"); -static const u32 sPictureFrameTiles_Tough[] = INCBIN_U32("graphics/picture_frame/tough.4bpp.rl"); -static const u32 sPictureFrameTiles_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby.4bpp.rl"); -static const u32 sPictureFrameTilemap_Cool[] = INCBIN_U32("graphics/picture_frame/cool_map.bin.rl"); -static const u32 sPictureFrameTilemap_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty_map.bin.rl"); -static const u32 sPictureFrameTilemap_Cute[] = INCBIN_U32("graphics/picture_frame/cute_map.bin.rl"); -static const u32 sPictureFrameTilemap_Smart[] = INCBIN_U32("graphics/picture_frame/smart_map.bin.rl"); -static const u32 sPictureFrameTilemap_Tough[] = INCBIN_U32("graphics/picture_frame/tough_map.bin.rl"); -static const u32 sPictureFrameTilemap_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby_map.bin.rl"); +static const u32 sPictureFrameTiles_Cool[] = INCBIN_U32("graphics/picture_frame/cool.4bpp.smol"); +static const u32 sPictureFrameTiles_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty.4bpp.smol"); +static const u32 sPictureFrameTiles_Cute[] = INCBIN_U32("graphics/picture_frame/cute.4bpp.smol"); +static const u32 sPictureFrameTiles_Smart[] = INCBIN_U32("graphics/picture_frame/smart.4bpp.smol"); +static const u32 sPictureFrameTiles_Tough[] = INCBIN_U32("graphics/picture_frame/tough.4bpp.smol"); +static const u32 sPictureFrameTiles_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby.4bpp.smol"); +static const u32 sPictureFrameTilemap_Cool[] = INCBIN_U32("graphics/picture_frame/cool_map.bin.smolTM"); +static const u32 sPictureFrameTilemap_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty_map.bin.smolTM"); +static const u32 sPictureFrameTilemap_Cute[] = INCBIN_U32("graphics/picture_frame/cute_map.bin.smolTM"); +static const u32 sPictureFrameTilemap_Smart[] = INCBIN_U32("graphics/picture_frame/smart_map.bin.smolTM"); +static const u32 sPictureFrameTilemap_Tough[] = INCBIN_U32("graphics/picture_frame/tough_map.bin.smolTM"); +static const u32 sPictureFrameTilemap_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby_map.bin.smolTM"); static const u8 *const sContestCategoryNames_Unused[] = { @@ -424,24 +424,24 @@ static void LoadContestPaintingFrame(u8 contestWinnerId, bool8 isForArtist) switch (gContestPaintingWinner->contestCategory / NUM_PAINTING_CAPTIONS) { case CONTEST_CATEGORY_COOL: - RLUnCompVram(sPictureFrameTiles_Cool, (void *)VRAM); - RLUnCompWram(sPictureFrameTilemap_Cool, gContestMonPixels); + DecompressDataWithHeaderVram(sPictureFrameTiles_Cool, (void *)VRAM); + DecompressDataWithHeaderWram(sPictureFrameTilemap_Cool, gContestMonPixels); break; case CONTEST_CATEGORY_BEAUTY: - RLUnCompVram(sPictureFrameTiles_Beauty, (void *)VRAM); - RLUnCompWram(sPictureFrameTilemap_Beauty, gContestMonPixels); + DecompressDataWithHeaderVram(sPictureFrameTiles_Beauty, (void *)VRAM); + DecompressDataWithHeaderWram(sPictureFrameTilemap_Beauty, gContestMonPixels); break; case CONTEST_CATEGORY_CUTE: - RLUnCompVram(sPictureFrameTiles_Cute, (void *)VRAM); - RLUnCompWram(sPictureFrameTilemap_Cute, gContestMonPixels); + DecompressDataWithHeaderVram(sPictureFrameTiles_Cute, (void *)VRAM); + DecompressDataWithHeaderWram(sPictureFrameTilemap_Cute, gContestMonPixels); break; case CONTEST_CATEGORY_SMART: - RLUnCompVram(sPictureFrameTiles_Smart, (void *)VRAM); - RLUnCompWram(sPictureFrameTilemap_Smart, gContestMonPixels); + DecompressDataWithHeaderVram(sPictureFrameTiles_Smart, (void *)VRAM); + DecompressDataWithHeaderWram(sPictureFrameTilemap_Smart, gContestMonPixels); break; case CONTEST_CATEGORY_TOUGH: - RLUnCompVram(sPictureFrameTiles_Tough, (void *)VRAM); - RLUnCompWram(sPictureFrameTilemap_Tough, gContestMonPixels); + DecompressDataWithHeaderVram(sPictureFrameTiles_Tough, (void *)VRAM); + DecompressDataWithHeaderWram(sPictureFrameTilemap_Tough, gContestMonPixels); break; } @@ -466,8 +466,8 @@ static void LoadContestPaintingFrame(u8 contestWinnerId, bool8 isForArtist) else if (contestWinnerId < MUSEUM_CONTEST_WINNERS_START) { // Load Contest Hall lobby frame - RLUnCompVram(sPictureFrameTiles_HallLobby, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_HallLobby, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_HallLobby, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_HallLobby, (void *)(BG_SCREEN_ADDR(12))); } else { @@ -475,24 +475,24 @@ static void LoadContestPaintingFrame(u8 contestWinnerId, bool8 isForArtist) switch (gContestPaintingWinner->contestCategory / NUM_PAINTING_CAPTIONS) { case CONTEST_CATEGORY_COOL: - RLUnCompVram(sPictureFrameTiles_Cool, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_Cool, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_Cool, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_Cool, (void *)(BG_SCREEN_ADDR(12))); break; case CONTEST_CATEGORY_BEAUTY: - RLUnCompVram(sPictureFrameTiles_Beauty, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_Beauty, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_Beauty, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_Beauty, (void *)(BG_SCREEN_ADDR(12))); break; case CONTEST_CATEGORY_CUTE: - RLUnCompVram(sPictureFrameTiles_Cute, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_Cute, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_Cute, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_Cute, (void *)(BG_SCREEN_ADDR(12))); break; case CONTEST_CATEGORY_SMART: - RLUnCompVram(sPictureFrameTiles_Smart, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_Smart, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_Smart, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_Smart, (void *)(BG_SCREEN_ADDR(12))); break; case CONTEST_CATEGORY_TOUGH: - RLUnCompVram(sPictureFrameTiles_Tough, (void *)VRAM); - RLUnCompVram(sPictureFrameTilemap_Tough, (void *)(BG_SCREEN_ADDR(12))); + DecompressDataWithHeaderVram(sPictureFrameTiles_Tough, (void *)VRAM); + DecompressDataWithHeaderVram(sPictureFrameTilemap_Tough, (void *)(BG_SCREEN_ADDR(12))); break; } } From 523390ac5151b4a7bc70bc77baf901f10ee0e09e Mon Sep 17 00:00:00 2001 From: Kevin <85093953+kevinwklawrence@users.noreply.github.com> Date: Mon, 4 Aug 2025 07:49:05 -0400 Subject: [PATCH 167/283] Update how_to_new_pokemon.md (#7440) --- docs/tutorials/how_to_new_pokemon.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/tutorials/how_to_new_pokemon.md b/docs/tutorials/how_to_new_pokemon.md index de2d41d57c..37c0d28ae3 100644 --- a/docs/tutorials/how_to_new_pokemon.md +++ b/docs/tutorials/how_to_new_pokemon.md @@ -524,9 +524,9 @@ Edit [src/data/graphics/pokemon.h](https://github.com/rh-hideout/pokeemerald-exp ```diff #if P_FAMILY_PECHARUNT const u32 gMonFrontPic_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/front.4bpp.lz"); - const u32 gMonPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/normal.gbapal.lz"); + const u16 gMonPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/normal.gbapal"); const u32 gMonBackPic_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/back.4bpp.lz"); - const u32 gMonShinyPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/shiny.gbapal.lz"); + const u16 gMonShinyPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/shiny.gbapal"); const u8 gMonIcon_Pecharunt[] = INCBIN_U8("graphics/pokemon/pecharunt/icon.4bpp"); #if P_FOOTPRINTS const u8 gMonFootprint_Pecharunt[] = INCBIN_U8("graphics/pokemon/pecharunt/footprint.1bpp"); @@ -534,20 +534,20 @@ Edit [src/data/graphics/pokemon.h](https://github.com/rh-hideout/pokeemerald-exp #if OW_POKEMON_OBJECT_EVENTS const u32 gObjectEventPic_Pecharunt[] = INCBIN_COMP("graphics/pokemon/pecharunt/overworld.4bpp"); #if OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE - const u32 gOverworldPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/overworld_normal.gbapal.lz"); - const u32 gShinyOverworldPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/overworld_shiny.gbapal.lz"); + const u16 gOverworldPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/overworld_normal.gbapal"); + const u16 gShinyOverworldPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/overworld_shiny.gbapal"); #endif //OW_PKMN_OBJECTS_SHARE_PALETTES #endif //OW_POKEMON_OBJECT_EVENTS #endif //P_FAMILY_PECHARUNT const u32 gMonFrontPic_Egg[] = INCBIN_U32("graphics/pokemon/egg/anim_front.4bpp.lz"); - const u32 gMonPalette_Egg[] = INCBIN_U32("graphics/pokemon/egg/normal.gbapal.lz"); + const u16 gMonPalette_Egg[] = INCBIN_U16("graphics/pokemon/egg/normal.gbapal"); const u8 gMonIcon_Egg[] = INCBIN_U8("graphics/pokemon/egg/icon.4bpp"); + const u32 gMonFrontPic_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/anim_front.4bpp.lz"); + const u32 gMonBackPic_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/back.4bpp.lz"); -+ const u32 gMonPalette_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/normal.gbapal.lz"); -+ const u32 gMonShinyPalette_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/shiny.gbapal.lz"); ++ const u16 gMonPalette_Mewthree[] = INCBIN_U16("graphics/pokemon/mewthree/normal.gbapal"); ++ const u16 gMonShinyPalette_Mewthree[] = INCBIN_U16("graphics/pokemon/mewthree/shiny.gbapal"); + const u8 gMonIcon_Mewthree[] = INCBIN_U8("graphics/pokemon/mewthree/icon.4bpp"); + const u8 gMonFootprint_Mewthree[] = INCBIN_U8("graphics/pokemon/mewthree/footprint.1bpp"); ``` From c037ba252240e693dcfb27c5ca09b7c0545f0436 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Mon, 4 Aug 2025 14:44:58 +0200 Subject: [PATCH 168/283] Clear gScanlineEffect to fix timeout in acid downpour animation (#7442) --- src/battle_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 8bab8fd1ef..a5dd01485d 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -487,10 +487,9 @@ static void CB2_InitBattleInternal(void) else { gBattle_WIN0V = WIN_RANGE(DISPLAY_HEIGHT / 2, DISPLAY_HEIGHT / 2 + 1); + ScanlineEffect_Clear(); if (B_FAST_INTRO_NO_SLIDE == FALSE && !gTestRunnerHeadless) { - ScanlineEffect_Clear(); - for (i = 0; i < DISPLAY_HEIGHT / 2; i++) { gScanlineEffectRegBuffers[0][i] = 0xF0; From f6a120310e69be91646201ab2121e3847f076797 Mon Sep 17 00:00:00 2001 From: Bivurnum <147376167+Bivurnum@users.noreply.github.com> Date: Mon, 4 Aug 2025 08:10:20 -0500 Subject: [PATCH 169/283] Bug fix: add handling for forced movements into/after ledge jumps with follower NPCs (#7055) --- include/follower_npc.h | 7 ++++-- include/global.h | 3 ++- src/field_player_avatar.c | 23 +++++++++++++----- src/follower_npc.c | 49 +++++++++++---------------------------- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/include/follower_npc.h b/include/follower_npc.h index 52355a78b7..abfbf0962a 100644 --- a/include/follower_npc.h +++ b/include/follower_npc.h @@ -20,6 +20,7 @@ enum FollowerNPCDataTypes FNPC_DATA_WARP_END, FNPC_DATA_SURF_BLOB, FNPC_DATA_COME_OUT_DOOR, + FNPC_DATA_FORCED_MOVEMENT, FNPC_DATA_OBJ_ID, FNPC_DATA_CURRENT_SPRITE, FNPC_DATA_DELAYED_STATE, @@ -62,7 +63,8 @@ enum FollowerNPCSurfBlobStates FNPC_SURF_BLOB_DESTROY }; -enum FollowerNPCOutOfDoorTaskStates{ +enum FollowerNPCOutOfDoorTaskStates +{ OPEN_DOOR, NPC_WALK_OUT, CLOSE_DOOR, @@ -70,7 +72,8 @@ enum FollowerNPCOutOfDoorTaskStates{ REALLOW_MOVEMENT }; -enum FollowerNPCHandleEscalatorFinishTaskStates{ +enum FollowerNPCHandleEscalatorFinishTaskStates +{ MOVE_TO_PLAYER_POS, WAIT_FOR_PLAYER_MOVE, SHOW_FOLLOWER_DOWN, diff --git a/include/global.h b/include/global.h index f4c944b64f..27c0a85e15 100644 --- a/include/global.h +++ b/include/global.h @@ -219,7 +219,8 @@ struct NPCFollower u8 inProgress:1; u8 warpEnd:1; u8 createSurfBlob:3; - u8 comeOutDoorStairs:3; + u8 comeOutDoorStairs:2; + u8 forcedMovement:1; u8 objId; u8 currentSprite; u8 delayedState; diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index d02ecbd9fc..55542a3588 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -382,8 +382,16 @@ void PlayerStep(u8 direction, u16 newKeys, u16 heldKeys) DoPlayerAvatarTransition(); if (TryDoMetatileBehaviorForcedMovement() == 0) { - MovePlayerAvatarUsingKeypadInput(direction, newKeys, heldKeys); - PlayerAllowForcedMovementIfMovingSameDirection(); + if (GetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT) != FALSE) + { + gPlayerAvatar.preventStep = TRUE; + CreateTask(Task_MoveNPCFollowerAfterForcedMovement, 1); + } + else + { + MovePlayerAvatarUsingKeypadInput(direction, newKeys, heldKeys); + PlayerAllowForcedMovementIfMovingSameDirection(); + } } } } @@ -510,7 +518,11 @@ static bool8 DoForcedMovement(u8 direction, void (*moveFunc)(u8)) else { if (collision == COLLISION_LEDGE_JUMP) + { + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FALSE); PlayerJumpLedge(direction); + } + playerAvatar->flags |= PLAYER_AVATAR_FLAG_FORCED_MOVE; playerAvatar->runningState = MOVING; return TRUE; @@ -518,12 +530,11 @@ static bool8 DoForcedMovement(u8 direction, void (*moveFunc)(u8)) } else { + if (PlayerHasFollowerNPC()) + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, TRUE); + playerAvatar->runningState = MOVING; moveFunc(direction); - if (PlayerHasFollowerNPC() - && gObjectEvents[GetFollowerNPCObjectId()].invisible == FALSE - && FindTaskIdByFunc(Task_MoveNPCFollowerAfterForcedMovement) == TASK_NONE) - CreateTask(Task_MoveNPCFollowerAfterForcedMovement, 3); return TRUE; } } diff --git a/src/follower_npc.c b/src/follower_npc.c index d9882b61bf..fcfe60dda8 100644 --- a/src/follower_npc.c +++ b/src/follower_npc.c @@ -83,6 +83,9 @@ void SetFollowerNPCData(enum FollowerNPCDataTypes type, u32 value) case FNPC_DATA_COME_OUT_DOOR: gSaveBlock3Ptr->NPCfollower.comeOutDoorStairs = value; break; + case FNPC_DATA_FORCED_MOVEMENT: + gSaveBlock3Ptr->NPCfollower.forcedMovement = value; + break; case FNPC_DATA_OBJ_ID: gSaveBlock3Ptr->NPCfollower.objId = value; break; @@ -155,6 +158,8 @@ u32 GetFollowerNPCData(enum FollowerNPCDataTypes type) return gSaveBlock3Ptr->NPCfollower.createSurfBlob; case FNPC_DATA_COME_OUT_DOOR: return gSaveBlock3Ptr->NPCfollower.comeOutDoorStairs; + case FNPC_DATA_FORCED_MOVEMENT: + return gSaveBlock3Ptr->NPCfollower.forcedMovement; case FNPC_DATA_OBJ_ID: return gSaveBlock3Ptr->NPCfollower.objId; case FNPC_DATA_CURRENT_SPRITE: @@ -720,9 +725,7 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc MoveCoords(direction, &followerX, &followerY); nextBehavior = MapGridGetMetatileBehaviorAt(followerX, followerY); - - if (FindTaskIdByFunc(Task_MoveNPCFollowerAfterForcedMovement) == TASK_NONE) - follower->facingDirectionLocked = FALSE; + follower->facingDirectionLocked = FALSE; // Follower won't do delayed movement until player does a movement. if (!IsStateMovement(state) && delayedState) @@ -777,10 +780,6 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc RETURN_STATE(MOVEMENT_ACTION_WALK_NORMAL_DOWN, direction); case MOVEMENT_ACTION_WALK_FAST_DOWN ... MOVEMENT_ACTION_WALK_FAST_RIGHT: - // Handle player on waterfall. - if (PlayerIsUnderWaterfall(&gObjectEvents[gPlayerAvatar.objectEventId]) && (state == MOVEMENT_ACTION_WALK_FAST_UP)) - return MOVEMENT_INVALID; - // Handle ice tile (some walking animation). if (MetatileBehavior_IsIce(follower->currentMetatileBehavior) || MetatileBehavior_IsTrickHouseSlipperyFloor(follower->currentMetatileBehavior)) follower->disableAnim = TRUE; @@ -789,6 +788,9 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc if (GetFollowerNPCData(FNPC_DATA_CURRENT_SPRITE) == FOLLOWER_NPC_SPRITE_INDEX_SURF && GetFollowerNPCSprite() == GetFollowerNPCData(FNPC_DATA_GFX_ID)) RETURN_STATE(MOVEMENT_ACTION_SURF_STILL_DOWN, direction); + if (MetatileBehavior_IsMuddySlope(follower->currentMetatileBehavior)) + follower->facingDirectionLocked = TRUE; + RETURN_STATE(MOVEMENT_ACTION_WALK_FAST_DOWN, direction); case MOVEMENT_ACTION_WALK_FASTER_DOWN ... MOVEMENT_ACTION_WALK_FASTER_RIGHT: @@ -798,10 +800,6 @@ u32 DetermineFollowerNPCState(struct ObjectEvent *follower, u32 state, u32 direc RETURN_STATE(MOVEMENT_ACTION_WALK_FASTER_DOWN, direction); case MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN ... MOVEMENT_ACTION_RIDE_WATER_CURRENT_RIGHT: - // Handle player on waterfall. - if (PlayerIsUnderWaterfall(&gObjectEvents[gPlayerAvatar.objectEventId]) && IsPlayerSurfingNorth()) - return MOVEMENT_INVALID; - RETURN_STATE(MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN, direction); // Acro bike. @@ -1544,37 +1542,20 @@ void FollowerNPC_TryRemoveFollowerOnWhiteOut(void) #undef tDoorY // Task data -#define PREVENT_PLAYER_STEP 0 -#define DO_ALL_FORCED_MOVEMENTS 1 -#define NPC_INTO_PLAYER 2 -#define ENABLE_PLAYER_STEP 3 +#define NPC_INTO_PLAYER 0 +#define ENABLE_PLAYER_STEP 1 void Task_MoveNPCFollowerAfterForcedMovement(u8 taskId) { struct ObjectEvent *follower = &gObjectEvents[GetFollowerNPCObjectId()]; struct ObjectEvent *player = &gObjectEvents[gPlayerAvatar.objectEventId]; - // Prevent player input until all forced mmovements are done and the follower is hidden. - if (gTasks[taskId].tState == PREVENT_PLAYER_STEP) - { - gPlayerAvatar.preventStep = TRUE; - gTasks[taskId].tState = DO_ALL_FORCED_MOVEMENTS; - } - // The player will keep doing forced movments until they land on a non-forced-move metatile or hit collision. - else if (gTasks[taskId].tState == DO_ALL_FORCED_MOVEMENTS && ObjectEventClearHeldMovementIfFinished(player) != 0) + // The NPC will take an extra step and be on the same tile as the player. + if (gTasks[taskId].tState == NPC_INTO_PLAYER && ObjectEventClearHeldMovementIfFinished(player) != 0 && ObjectEventClearHeldMovementIfFinished(follower) != 0) { - // Lock follower facing direction for muddy slope. if (follower->currentMetatileBehavior == MB_MUDDY_SLOPE) follower->facingDirectionLocked = TRUE; - if (TryDoMetatileBehaviorForcedMovement() == 0) - gTasks[taskId].tState = NPC_INTO_PLAYER; - - return; - } - // The NPC will take an extra step and be on the same tile as the player. - else if (gTasks[taskId].tState == NPC_INTO_PLAYER && ObjectEventClearHeldMovementIfFinished(player) != 0 && ObjectEventClearHeldMovementIfFinished(follower) != 0) - { ObjectEventSetHeldMovement(follower, GetWalkFastMovementAction(DetermineFollowerNPCDirection(player, follower))); gTasks[taskId].tState = ENABLE_PLAYER_STEP; return; @@ -1585,14 +1566,13 @@ void Task_MoveNPCFollowerAfterForcedMovement(u8 taskId) follower->facingDirectionLocked = FALSE; HideNPCFollower(); SetFollowerNPCData(FNPC_DATA_WARP_END, FNPC_WARP_REAPPEAR); + SetFollowerNPCData(FNPC_DATA_FORCED_MOVEMENT, FALSE); gPlayerAvatar.preventStep = FALSE; DestroyTask(taskId); } } #undef tState -#undef PREVENT_PLAYER_STEP -#undef DO_ALL_FORCED_MOVEMENTS #undef NPC_INTO_PLAYER #undef ENABLE_PLAYER_STEP @@ -1628,7 +1608,6 @@ void ScriptDestroyFollowerNPC(struct ScriptContext *ctx) return; RemoveObjectEvent(&gObjectEvents[GetFollowerNPCData(FNPC_DATA_OBJ_ID)]); - FlagSet(GetFollowerNPCData(FNPC_DATA_EVENT_FLAG)); ClearFollowerNPCData(); UpdateFollowingPokemon(); } From 7500fc00db63c495054062e99b578b233c95a89a Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:24:49 -0400 Subject: [PATCH 170/283] Restore git history check (#7463) --- make_tools.mk | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/make_tools.mk b/make_tools.mk index 75ebc05c96..6b3db7c873 100644 --- a/make_tools.mk +++ b/make_tools.mk @@ -12,10 +12,10 @@ TOOLDIRS := $(TOOL_NAMES:%=$(TOOLS_DIR)/%) CHECKTOOLDIRS := $(CHECK_TOOL_NAMES:%=$(TOOLS_DIR)/%) # Tool making doesnt require a pokeemerald dependency scan. -RULES_NO_SCAN += tools check-tools clean-tools clean-check-tools $(TOOLDIRS) $(CHECKTOOLDIRS) +RULES_NO_SCAN += tools check-tools clean-tools clean-check-tools history $(TOOLDIRS) $(CHECKTOOLDIRS) .PHONY: $(RULES_NO_SCAN) -tools: $(TOOLDIRS) +tools: history $(TOOLDIRS) check-tools: $(CHECKTOOLDIRS) @@ -30,3 +30,6 @@ clean-tools: clean-check-tools: @$(foreach tooldir,$(CHECKTOOLDIRS),$(MAKE) clean -C $(tooldir);) + +history: + @$(SHELL) ./check_history.sh From 27886a6577c2f587e3a79a871a5bf0422660e241 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:14:04 +0100 Subject: [PATCH 171/283] Macro-for-AI-Flag-definitions (#7471) --- include/constants/battle_ai.h | 67 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 2f97ab2234..5da20264eb 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -3,38 +3,37 @@ // AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts // See docs/ai_flags.md for more details. -#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. -#define AI_FLAG_TRY_TO_FAINT (1 << 1) // AI will prioritize KOing the player's mon if able. -#define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation. -#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. -#define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. -#define AI_FLAG_TRY_TO_2HKO (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. -#define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass. -#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner. -#define AI_FLAG_HP_AWARE (1 << 8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. -#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target. +#define AI_FLAG(x) ((u64)1 << x) + +#define AI_FLAG_CHECK_BAD_MOVE AI_FLAG(0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. +#define AI_FLAG_TRY_TO_FAINT AI_FLAG(1) // AI will prioritize KOing the player's mon if able. +#define AI_FLAG_CHECK_VIABILITY AI_FLAG(2) // AI damaging moves and move effects to determine the best available move in the current situation. +#define AI_FLAG_FORCE_SETUP_FIRST_TURN AI_FLAG(3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. +#define AI_FLAG_RISKY AI_FLAG(4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. +#define AI_FLAG_TRY_TO_2HKO AI_FLAG(5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. +#define AI_FLAG_PREFER_BATON_PASS AI_FLAG(6) // AI prefers raising its own stats and setting for / using Baton Pass. +#define AI_FLAG_DOUBLE_BATTLE AI_FLAG(7) // Automatically set for double battles, handles AI behaviour with partner. +#define AI_FLAG_HP_AWARE AI_FLAG(8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. +#define AI_FLAG_POWERFUL_STATUS AI_FLAG(9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target. // New, Trainer Handicap Flags -#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc. -#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc. +#define AI_FLAG_NEGATE_UNAWARE AI_FLAG(10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc. +#define AI_FLAG_WILL_SUICIDE AI_FLAG(11) // AI will use explosion / self destruct / final gambit / etc. // New, Trainer Strategy Flags -#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves. -#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished. -#define AI_FLAG_SMART_SWITCHING (1 << 14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES. -#define AI_FLAG_ACE_POKEMON (1 << 15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. -#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items. -#define AI_FLAG_SMART_MON_CHOICES (1 << 17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING. -#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage. -#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle. -#define AI_FLAG_DOUBLE_ACE_POKEMON (1 << 20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. -#define AI_FLAG_WEIGH_ABILITY_PREDICTION (1 << 21) // AI will predict player's ability based on aiRating -#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect -#define AI_FLAG_PREDICT_SWITCH (1 << 23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT -#define AI_FLAG_PREDICT_INCOMING_MON (1 << 24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH -#define AI_FLAG_PP_STALL_PREVENTION (1 << 25) // AI keeps track of the player's switches where the incoming mon is immune to the chosen move -#define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT - -// Flags at and after 32 need different formatting, as in -// #define AI_FLAG_PLACEHOLDER ((u64)1 << 32) +#define AI_FLAG_PREFER_STATUS_MOVES AI_FLAG(12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves. +#define AI_FLAG_STALL AI_FLAG(13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished. +#define AI_FLAG_SMART_SWITCHING AI_FLAG(14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES. +#define AI_FLAG_ACE_POKEMON AI_FLAG(15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. +#define AI_FLAG_OMNISCIENT AI_FLAG(16) // AI has full knowledge of player moves, abilities, hold items. +#define AI_FLAG_SMART_MON_CHOICES AI_FLAG(17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING. +#define AI_FLAG_CONSERVATIVE AI_FLAG(18) // AI assumes all moves will low roll damage. +#define AI_FLAG_SEQUENCE_SWITCHING AI_FLAG(19) // AI switches in mons in exactly party order, and never switches mid-battle. +#define AI_FLAG_DOUBLE_ACE_POKEMON AI_FLAG(20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. +#define AI_FLAG_WEIGH_ABILITY_PREDICTION AI_FLAG(21) // AI will predict player's ability based on aiRating +#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE AI_FLAG(22) // AI adds score to highest damage move regardless of accuracy or secondary effect +#define AI_FLAG_PREDICT_SWITCH AI_FLAG(23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT +#define AI_FLAG_PREDICT_INCOMING_MON AI_FLAG(24) // AI will score against the predicting incoming mon if it predicts the player to switch. Requires AI_FLAG_PREDICT_SWITCH +#define AI_FLAG_PP_STALL_PREVENTION AI_FLAG(25) // AI keeps track of the player's switches where the incoming mon is immune to the chosen move +#define AI_FLAG_PREDICT_MOVE AI_FLAG(26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT #define AI_FLAG_COUNT 27 @@ -45,10 +44,10 @@ #define AI_FLAG_PREDICTION (AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON | AI_FLAG_PREDICT_MOVE) // 'other' ai logic flags -#define AI_FLAG_DYNAMIC_FUNC ((u64)1 << 60) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd -#define AI_FLAG_ROAMING ((u64)1 << 61) -#define AI_FLAG_SAFARI ((u64)1 << 62) -#define AI_FLAG_FIRST_BATTLE ((u64)1 << 63) +#define AI_FLAG_DYNAMIC_FUNC AI_FLAG(60) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd +#define AI_FLAG_ROAMING AI_FLAG(61) +#define AI_FLAG_SAFARI AI_FLAG(62) +#define AI_FLAG_FIRST_BATTLE AI_FLAG(63) #define AI_SCORE_DEFAULT 100 // Default score for all AI moves. From 76b8ffc12ebd9fba51d204253c170e6d22fccd57 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Tue, 5 Aug 2025 18:24:34 +0100 Subject: [PATCH 172/283] Fix sorting bag by type (#7488) --- src/data/items.h | 2 +- src/item_menu.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/data/items.h b/src/data/items.h index 1a39f409b5..69806c26da 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -146,7 +146,7 @@ const struct Item gItemsInfo[] = .price = 0, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, - .sortType = ITEM_TYPE_FIELD_USE, + .sortType = ITEM_TYPE_UNCATEGORIZED, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .iconPic = gItemIcon_QuestionMark, diff --git a/src/item_menu.c b/src/item_menu.c index 2ac5e27da9..5ec54f07c4 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -2954,13 +2954,18 @@ static s32 CompareItemsByMost(enum Pocket pocketId, struct ItemSlot item1, struc static s32 CompareItemsByType(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) { + if (item1.itemId == ITEM_NONE) + return 1; + else if (item2.itemId == ITEM_NONE) + return -1; + enum ItemSortType type1 = gItemsInfo[item1.itemId].sortType; enum ItemSortType type2 = gItemsInfo[item2.itemId].sortType; - // Null and uncategorized items go last - if (type1 && !type2) + // Uncategorized items go last. + if (type1 != ITEM_TYPE_UNCATEGORIZED && type2 == ITEM_TYPE_UNCATEGORIZED) return -1; - else if (type2 && !type1) + else if (type2 != ITEM_TYPE_UNCATEGORIZED && type1 == ITEM_TYPE_UNCATEGORIZED) return 1; else if (type1 < type2) return -1; From 1fb895ad4858198b057ff9d9ae5897e0753191a8 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Tue, 5 Aug 2025 18:27:08 +0100 Subject: [PATCH 173/283] Bag sorting cleanup (#7489) --- src/item_menu.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/item_menu.c b/src/item_menu.c index 5ec54f07c4..e0954c0587 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -2887,12 +2887,19 @@ static void MergeSort(struct BagPocket *pocket, s32 (*comparator)(enum Pocket, s { struct ItemSlot *dummySlots = AllocZeroed(sizeof(struct ItemSlot) * pocket->capacity); - for (u32 width = 1; width < pocket->capacity; width *= 2) + u32 usedCapacity; + for (usedCapacity = 0; usedCapacity < pocket->capacity; usedCapacity++) { - for (u32 i = 0; i < pocket->capacity; i += 2 * width) - Merge(pocket, i, min(i + width, pocket->capacity), min(i + 2 * width, pocket->capacity), dummySlots, comparator); + if (BagPocket_GetSlotData(pocket, usedCapacity).itemId == ITEM_NONE) + break; + } + + for (u32 width = 1; width < usedCapacity; width *= 2) + { + for (u32 i = 0; i < usedCapacity; i += 2 * width) + Merge(pocket, i, min(i + width, usedCapacity), min(i + 2 * width, usedCapacity), dummySlots, comparator); - for (u32 j = 0; j < pocket->capacity; j++) + for (u32 j = 0; j < usedCapacity; j++) BagPocket_SetSlotData(pocket, j, dummySlots[j]); } @@ -2919,22 +2926,7 @@ static s32 CompareItemsAlphabetically(enum Pocket pocketId, struct ItemSlot item name2 = GetItemName(item2.itemId); } - for (u32 i = 0; ; ++i) - { - if (name1[i] == EOS && name2[i] != EOS) - return -1; - else if (name1[i] != EOS && name2[i] == EOS) - return 1; - else if (name1[i] == EOS && name2[i] == EOS) - return 0; - - if (name1[i] < name2[i]) - return -1; - else if (name1[i] > name2[i]) - return 1; - } - - return 0; // Will never be reached + return StringCompare(name1, name2); } static s32 CompareItemsByMost(enum Pocket pocketId, struct ItemSlot item1, struct ItemSlot item2) From acc82e7d7972175b70a0eb25e72cf8ebdfe49b40 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:28:33 +0200 Subject: [PATCH 174/283] Convert Status4 to volatiles (#7411) Co-authored-by: hedara90 <90hedara@gmail.com> --- asm/macros/battle_script.inc | 5 +- data/battle_scripts_1.s | 5 +- include/battle.h | 1 - include/battle_ai_util.h | 2 - include/battle_util.h | 2 + include/constants/battle.h | 77 +++++-------- include/move.h | 2 +- include/pokemon.h | 7 +- src/battle_ai_main.c | 6 +- src/battle_ai_switch_items.c | 6 +- src/battle_ai_util.c | 66 ++---------- src/battle_anim_effects_1.c | 7 +- src/battle_debug.c | 81 ++++---------- src/battle_end_turn.c | 23 ++-- src/battle_main.c | 26 ++--- src/battle_script_commands.c | 96 ++++++++--------- src/battle_util.c | 101 +++++++++++------- src/data/moves_info.h | 14 +-- src/item_use.c | 2 +- test/battle/hold_effect/berserk_gene.c | 2 +- test/battle/move_effect/semi_invulnerable.c | 12 +-- test/battle/move_effects_combined/hurricane.c | 6 +- 22 files changed, 231 insertions(+), 318 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index c2a10b175c..9dd0479c92 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -416,8 +416,11 @@ .4byte \argPtr .endm - .macro unused_0x47 + .macro jumpfifsemiinvulnerable battler:req, state:req, jumpInstr:req .byte 0x47 + .byte \battler + .byte \state + .4byte \jumpInstr .endm .macro unused_0x48 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e6bf8e1db8..aa4cfac123 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2613,7 +2613,8 @@ BattleScript_EffectGravitySuccess:: selectfirstvalidtarget BattleScript_GravityLoop: movevaluescleanup - jumpifstatus3 BS_TARGET, STATUS3_ON_AIR | STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop + jumpfifsemiinvulnerable BS_TARGET, STATE_ON_AIR, BattleScript_GravityLoopDrop + jumpifstatus3 BS_TARGET, STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop goto BattleScript_GravityLoopEnd BattleScript_GravityLoopDrop: gravityonairbornemons @@ -6982,7 +6983,7 @@ BattleScript_YawnMakesAsleep:: waitmessage B_WAIT_TIME_LONG updatestatusicon BS_EFFECT_BATTLER waitstate - jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_SKY_DROPPED, BattleScript_YawnEnd + jumpfifsemiinvulnerable BS_EFFECT_BATTLER, STATE_SKY_DROP, BattleScript_YawnEnd makevisible BS_EFFECT_BATTLER skydropyawn BattleScript_YawnEnd: diff --git a/include/battle.h b/include/battle.h index de25626c6b..78eed713f9 100644 --- a/include/battle.h +++ b/include/battle.h @@ -1074,7 +1074,6 @@ extern u8 gBideTarget[MAX_BATTLERS_COUNT]; extern u32 gSideStatuses[NUM_BATTLE_SIDES]; extern struct SideTimer gSideTimers[NUM_BATTLE_SIDES]; extern u32 gStatuses3[MAX_BATTLERS_COUNT]; -extern u32 gStatuses4[MAX_BATTLERS_COUNT]; extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT]; extern u16 gPauseCounterBattle; extern u16 gPaydayMoney; diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index f5af4acb33..e0f1a4de0c 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -184,7 +184,6 @@ bool32 HasAnyKnownMove(u32 battlerId); bool32 IsAromaVeilProtectedEffect(enum BattleMoveEffects moveEffect); bool32 IsNonVolatileStatusMove(u32 moveEffect); bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility); -bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsHazardMove(u32 move); bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move); bool32 IsBattlerDamagedByStatus(u32 battler); @@ -208,7 +207,6 @@ bool32 IsSwitchOutEffect(enum BattleMoveEffects effect); bool32 IsChaseEffect(enum BattleMoveEffects effect); bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect); bool32 IsUngroundingEffect(enum BattleMoveEffects effect); -bool32 IsSemiInvulnerable(u32 battlerDef, u32 move); bool32 HasMoveWithFlag(u32 battler, MoveFlag getFlag); bool32 IsHazardClearingMove(u32 move); bool32 IsSubstituteEffect(enum BattleMoveEffects effect); diff --git a/include/battle_util.h b/include/battle_util.h index 95efdd9922..8f38e0f572 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -406,5 +406,7 @@ bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType); void RemoveHazardFromField(u32 side, enum Hazards hazardType); bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); +bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander); +bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 730dbd63c7..148438237b 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -169,8 +169,14 @@ enum VolatileFlags F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \ + F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) + F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1)) \ + F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \ + F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \ + F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) /* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ #define GET_VOLATILE_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeMaxValue) @@ -188,44 +194,13 @@ enum Volatile // Helper macros #define INFATUATED_WITH(battler) (battler + 1) -// Old flags -#define STATUS2_CONFUSION (1 << 0 | 1 << 1 | 1 << 2) -#define STATUS2_CONFUSION_TURN(num) ((num) << 0) -#define STATUS2_FLINCHED (1 << 3) -#define STATUS2_UPROAR (1 << 4 | 1 << 5 | 1 << 6) -#define STATUS2_UPROAR_TURN(num) ((num) << 4) -#define STATUS2_TORMENT (1 << 7) -#define STATUS2_BIDE (1 << 8 | 1 << 9) -#define STATUS2_BIDE_TURN(num) (((num) << 8) & STATUS2_BIDE) -#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash -#define STATUS2_LOCK_CONFUSE_TURN(num)((num) << 10) -#define STATUS2_MULTIPLETURNS (1 << 12) -#define STATUS2_WRAPPED (1 << 13) -#define STATUS2_POWDER (1 << 14) -//#define STATUS2_UNUSED (1 << 15) -#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler -#define STATUS2_INFATUATED_WITH(battler) (1u << (battler + 16)) -#define STATUS2_DEFENSE_CURL (1 << 20) -#define STATUS2_TRANSFORMED (1 << 21) -#define STATUS2_RECHARGE (1 << 22) -#define STATUS2_RAGE (1 << 23) -#define STATUS2_SUBSTITUTE (1 << 24) -#define STATUS2_DESTINY_BOND (1 << 25) -#define STATUS2_ESCAPE_PREVENTION (1 << 26) -#define STATUS2_NIGHTMARE (1 << 27) -#define STATUS2_CURSED (1 << 28) -#define STATUS2_FORESIGHT (1 << 29) -#define STATUS2_DRAGON_CHEER (1 << 30) -#define STATUS2_FOCUS_ENERGY (1 << 31) -#define STATUS2_FOCUS_ENERGY_ANY (STATUS2_DRAGON_CHEER | STATUS2_FOCUS_ENERGY) - #define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed #define STATUS3_LEECHSEED (1 << 2) #define STATUS3_ALWAYS_HITS (1 << 3 | 1 << 4) #define STATUS3_ALWAYS_HITS_TURN(num) (((num) << 3) & STATUS3_ALWAYS_HITS) // "Always Hits" is set as a 2 turn timer, i.e. next turn is the last turn when it's active #define STATUS3_PERISH_SONG (1 << 5) -#define STATUS3_ON_AIR (1 << 6) -#define STATUS3_UNDERGROUND (1 << 7) +#define STATUS3_UNUSED_6 (1 << 6) +#define STATUS3_UNUSED_7 (1 << 7) #define STATUS3_MINIMIZED (1 << 8) #define STATUS3_CHARGED_UP (1 << 9) #define STATUS3_ROOTED (1 << 10) @@ -233,33 +208,39 @@ enum Volatile #define STATUS3_YAWN_TURN(num) (((num) << 11) & STATUS3_YAWN) #define STATUS3_IMPRISONED_OTHERS (1 << 13) #define STATUS3_GRUDGE (1 << 14) -#define STATUS3_COMMANDER (1 << 15) +#define STATUS3_UNUSED_15 (1 << 15) #define STATUS3_GASTRO_ACID (1 << 16) #define STATUS3_EMBARGO (1 << 17) -#define STATUS3_UNDERWATER (1 << 18) +#define STATUS3_UNUSED_18 (1 << 18) #define STATUS3_UNUSED_19 (1 << 19) #define STATUS3_UNUSED_20 (1 << 20) #define STATUS3_SMACKED_DOWN (1 << 21) #define STATUS3_UNUSED_22 (1 << 22) #define STATUS3_TELEKINESIS (1 << 23) -#define STATUS3_PHANTOM_FORCE (1 << 24) +#define STATUS3_UNUSED_24 (1 << 24) #define STATUS3_MIRACLE_EYED (1 << 25) #define STATUS3_MAGNET_RISE (1 << 26) #define STATUS3_HEAL_BLOCK (1 << 27) #define STATUS3_AQUA_RING (1 << 28) #define STATUS3_LASER_FOCUS (1 << 29) #define STATUS3_POWER_TRICK (1 << 30) -#define STATUS3_SKY_DROPPED (1 << 31) // Target of Sky Drop -#define STATUS3_SEMI_INVULNERABLE_NO_COMMANDER (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE) // Exception for Transform / Imposter -#define STATUS3_SEMI_INVULNERABLE (STATUS3_SEMI_INVULNERABLE_NO_COMMANDER | STATUS3_COMMANDER) - -#define STATUS4_ELECTRIFIED (1 << 0) -#define STATUS4_MUD_SPORT (1 << 1) // Only used if B_SPORT_TURNS < GEN_6 -#define STATUS4_WATER_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6 -#define STATUS4_INFINITE_CONFUSION (1 << 3) // Used for Berserk Gene -#define STATUS4_SALT_CURE (1 << 4) -#define STATUS4_SYRUP_BOMB (1 << 5) -#define STATUS4_GLAIVE_RUSH (1 << 6) + +enum SemiInvulnerableState +{ + STATE_NONE, + STATE_UNDERGROUND, + STATE_UNDERWATER, + STATE_ON_AIR, + STATE_PHANTOM_FORCE, + STATE_SKY_DROP, + STATE_COMMANDER, +}; + +enum SemiInvulnerableExclusion +{ + CHECK_ALL, + EXCLUDE_COMMANDER, +}; #define HITMARKER_STRING_PRINTED (1 << 4) #define HITMARKER_IGNORE_BIDE (1 << 5) diff --git a/include/move.h b/include/move.h index 61483e402e..b1e8cba99f 100644 --- a/include/move.h +++ b/include/move.h @@ -489,7 +489,7 @@ static inline u32 GetMoveTwoTurnAttackStringId(u32 moveId) static inline u32 GetMoveTwoTurnAttackStatus(u32 moveId) { - return UNCOMPRESS_BITS(gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status); + return gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status; } static inline u32 GetMoveTwoTurnAttackWeather(u32 moveId) diff --git a/include/pokemon.h b/include/pokemon.h index f36f8ba7f5..cd7925cf14 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -381,12 +381,7 @@ struct BattlePokemon /*0x45*/ u32 experience; /*0x49*/ u32 personality; /*0x4D*/ u32 status1; - /*0x51*/ union { - struct { - u32 status2; // To be expanded to include Status3/4 - }; - struct Volatiles volatiles; - }; + /*0x51*/ struct Volatiles volatiles; /*0x5D*/ u32 otId; /*0x61*/ u8 metLevel; /*0x62*/ bool8 isShiny; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index fc2ac90b1d..7a74e0d655 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1083,7 +1083,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); - if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) RETURN_SCORE_MINUS(10); if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk)) @@ -2363,7 +2363,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you if (BattlerWillFaintFromWeather(battlerAtk, aiData->abilities[battlerAtk]) - && GetMoveTwoTurnAttackStatus(move) == STATUS3_ON_AIR) + && GetMoveTwoTurnAttackStatus(move) == STATE_ON_AIR) ADJUST_SCORE(-10); // Attacker will faint while in the air break; case EFFECT_HEALING_WISH: //healing wish, lunar dance @@ -4524,7 +4524,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) || predictedEffect == EFFECT_MISTY_EXPLOSION || predictedEffect == EFFECT_PROTECT)) ADJUST_SCORE(GOOD_EFFECT); - else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) ADJUST_SCORE(GOOD_EFFECT); } break; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 526c81c7ca..fe3bb5a5ed 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -482,7 +482,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); u32 incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE); - bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); + bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); s32 i, j; if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) @@ -615,7 +615,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler) u32 opposingBattler = GetOppositeBattler(battler); u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData); - bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); + bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; @@ -2436,7 +2436,7 @@ static bool32 ShouldUseItem(u32 battler) // If teaming up with player and Pokemon is on the right, or Pokemon is currently held by Sky Drop if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT) - || gStatuses3[battler] & STATUS3_SKY_DROPPED) + || gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; if (gStatuses3[battler] & STATUS3_EMBARGO) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b4e0cbaaf4..a15fafc897 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -457,7 +457,9 @@ bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) return TRUE; if (gBattleMons[battlerDef].volatiles.escapePrevention) return TRUE; - if (gStatuses3[battlerDef] & (STATUS3_ROOTED | STATUS3_SKY_DROPPED)) + if (gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_SKY_DROP) + return TRUE; + if (gStatuses3[battlerDef] & STATUS3_ROOTED) return TRUE; if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return TRUE; @@ -1860,60 +1862,6 @@ bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility) return FALSE; } -bool32 IsSemiInvulnerable(u32 battlerDef, u32 move) -{ - if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) - return TRUE; - else if (gBattleStruct->battlerState[battlerDef].commandingDondozo) - return TRUE; - else if (!MoveDamagesAirborne(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR) - return TRUE; - else if (!MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER) - return TRUE; - else if (!MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND) - return TRUE; - else - return FALSE; -} - -bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move) -{ - u32 weather; - if (IsSemiInvulnerable(battlerDef, move)) - return FALSE; - - //TODO - anticipate protect move? - - // always hits - if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) - return TRUE; - - if (gAiLogicData->abilities[battlerDef] == ABILITY_NO_GUARD || gAiLogicData->abilities[battlerAtk] == ABILITY_NO_GUARD) - return TRUE; - - u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - if (B_TOXIC_NEVER_MISS >= GEN_6 - && nonVolatileStatus == MOVE_EFFECT_TOXIC - && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - return TRUE; - - // discouraged from hitting - weather = AI_GetWeather(); - if ((weather & B_WEATHER_SUN) && MoveHas50AccuracyInSun(move)) - return FALSE; - - if ((weather & B_WEATHER_RAIN) && MoveAlwaysHitsInRain(move)) - return TRUE; - if ((weather & B_WEATHER_ICY_ANY) && MoveAlwaysHitsInHailSnow(move)) - return TRUE; - if (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && MoveIncreasesPowerToMinimizedTargets(move)) - return TRUE; - if (GetMoveAccuracy(move) == 0) - return TRUE; - - return FALSE; -} - bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) { enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerDef]; @@ -1972,8 +1920,8 @@ bool32 IsBattlerDamagedByStatus(u32 battler) || gBattleMons[battler].volatiles.wrapped || gBattleMons[battler].volatiles.nightmare || gBattleMons[battler].volatiles.cursed + || gBattleMons[battler].volatiles.saltCure || gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED) - || gStatuses4[battler] & (STATUS4_SALT_CURE) || gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_DAMAGE_NON_TYPES); } @@ -2980,7 +2928,8 @@ static u32 GetWeatherDamage(u32 battlerId) if (weather & B_WEATHER_SANDSTORM) { if (BattlerAffectedBySandstorm(battlerId, ability) - && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = GetNonDynamaxMaxHP(battlerId) / 16; @@ -2991,7 +2940,8 @@ static u32 GetWeatherDamage(u32 battlerId) if ((weather & B_WEATHER_HAIL) && ability != ABILITY_ICE_BODY) { if (BattlerAffectedByHail(battlerId, ability) - && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = GetNonDynamaxMaxHP(battlerId) / 16; diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index fccbfb1b64..12bd7859b9 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6871,7 +6871,7 @@ static void SwapBattlerMoveData(u32 battler1, u32 battler2) SWAP(gBattleStruct->moveTarget[battler1], gBattleStruct->moveTarget[battler2], temp); SWAP(gMoveSelectionCursor[battler1], gMoveSelectionCursor[battler2], temp); SWAP(gLockedMoves[battler1], gLockedMoves[battler2], temp); - + // update last moves SWAP(gLastPrintedMoves[battler1], gLastPrintedMoves[battler2], temp); SWAP(gLastMoves[battler1], gLastMoves[battler2], temp); @@ -6907,10 +6907,9 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); - SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp); - + SwapBattlerMoveData(battlerAtk, battlerPartner); - + // Swap turn order, so that all the battlers take action SWAP(gChosenActionByBattler[battlerAtk], gChosenActionByBattler[battlerPartner], temp); for (i = 0; i < gBattlersCount; i++) diff --git a/src/battle_debug.c b/src/battle_debug.c index 6b8998de8f..a991ac341a 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -106,7 +106,6 @@ enum LIST_ITEM_STATUS1, LIST_ITEM_VOLATILE, LIST_ITEM_STATUS3, - LIST_ITEM_STATUS4, LIST_ITEM_HAZARDS, LIST_ITEM_SIDE_STATUS, LIST_ITEM_AI, @@ -147,8 +146,6 @@ enum LIST_STATUS3_LEECH_SEEDED, LIST_STATUS3_ALWAYS_HITS, LIST_STATUS3_PERISH_SONG, - LIST_STATUS3_ON_AIR, - LIST_STATUS3_UNDERGROUND, LIST_STATUS3_MINIMIZED, LIST_STATUS3_CHARGED_UP, LIST_STATUS3_ROOTED, @@ -157,7 +154,6 @@ enum LIST_STATUS3_GRUDGE, LIST_STATUS3_GASTRO_ACID, LIST_STATUS3_EMBARGO, - LIST_STATUS3_UNDERWATER, LIST_STATUS3_SMACKED_DOWN, LIST_STATUS3_TELEKINESIS, LIST_STATUS3_MIRACLE_EYED, @@ -168,14 +164,6 @@ enum LIST_STATUS3_POWER_TRICK, }; -enum -{ - LIST_STATUS4_ELECTRIFIED, - LIST_STATUS4_SALT_CURE, - LIST_STATUS4_SYRUP_BOMB, - LIST_STATUS4_GLAIVE_RUSH, -}; - enum { LIST_SIDE_STICKY_WEB, @@ -314,16 +302,6 @@ static const struct BitfieldInfo sStatus3Bitfield[] = {/*Power Trick*/ 1, 30}, }; -static const struct BitfieldInfo sStatus4Bitfield[] = -{ - {/*Electrified*/ 1, 0}, - {/*Mud Sport*/ 1, 1}, - {/*Water Sport*/ 1, 2}, - {/*Salt Cure*/ 1, 4}, - {/*Syrup Bomb*/ 1, 5}, - {/*Glaive Rush*/ 1, 6}, -}; - static const struct BitfieldInfo sAIBitfield[] = { {/*Check Bad Move*/ 1, 0}, @@ -369,7 +347,6 @@ static const struct ListMenuItem sMainListItems[] = {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, {COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3}, - {COMPOUND_STRING("Status4"), LIST_ITEM_STATUS4}, {COMPOUND_STRING("Hazards"), LIST_ITEM_HAZARDS}, {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, {COMPOUND_STRING("AI"), LIST_ITEM_AI}, @@ -405,21 +382,26 @@ static const struct ListMenuItem sStatus1ListItems[] = static const struct ListMenuItem sVolatileStatusListItems[] = { - {COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION}, - {COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED}, - {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, - {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, - {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, - {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, - {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, - {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, - {COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION}, - {COMPOUND_STRING("Cursed"), VOLATILE_CURSED}, - {COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT}, - {COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER}, - {COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY}, - {COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT}, - {COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT}, + {COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION}, + {COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED}, + {COMPOUND_STRING("Torment"), VOLATILE_TORMENT}, + {COMPOUND_STRING("Powder"), VOLATILE_POWDER}, + {COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL}, + {COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE}, + {COMPOUND_STRING("Rage"), VOLATILE_RAGE}, + {COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND}, + {COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION}, + {COMPOUND_STRING("Cursed"), VOLATILE_CURSED}, + {COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT}, + {COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER}, + {COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY}, + {COMPOUND_STRING("Electrified"), VOLATILE_ELECTRIFIED}, + {COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT}, + {COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT}, + {COMPOUND_STRING("Infinite Confusion"), VOLATILE_INFINITE_CONFUSION}, + {COMPOUND_STRING("Salt Cure"), VOLATILE_SALT_CURE}, + {COMPOUND_STRING("Syrup Bomb"), VOLATILE_SYRUP_BOMB}, + {COMPOUND_STRING("Glaive Rush"), VOLATILE_GLAIVE_RUSH}, }; static const struct ListMenuItem sStatus3ListItems[] = @@ -428,8 +410,6 @@ static const struct ListMenuItem sStatus3ListItems[] = {COMPOUND_STRING("Leech Seeded"), LIST_STATUS3_LEECH_SEEDED}, {COMPOUND_STRING("Always Hits"), LIST_STATUS3_ALWAYS_HITS}, {COMPOUND_STRING("Perish Song"), LIST_STATUS3_PERISH_SONG}, - {COMPOUND_STRING("On Air"), LIST_STATUS3_ON_AIR}, - {COMPOUND_STRING("Underground"), LIST_STATUS3_UNDERGROUND}, {COMPOUND_STRING("Minimized"), LIST_STATUS3_MINIMIZED}, {COMPOUND_STRING("Charged Up"), LIST_STATUS3_CHARGED_UP}, {COMPOUND_STRING("Rooted"), LIST_STATUS3_ROOTED}, @@ -438,7 +418,6 @@ static const struct ListMenuItem sStatus3ListItems[] = {COMPOUND_STRING("Grudge"), LIST_STATUS3_GRUDGE}, {COMPOUND_STRING("Gastro Acid"), LIST_STATUS3_GASTRO_ACID}, {COMPOUND_STRING("Embargo"), LIST_STATUS3_EMBARGO}, - {COMPOUND_STRING("Underwater"), LIST_STATUS3_UNDERWATER}, {COMPOUND_STRING("Smacked Down"), LIST_STATUS3_SMACKED_DOWN}, {COMPOUND_STRING("Telekinesis"), LIST_STATUS3_TELEKINESIS}, {COMPOUND_STRING("Miracle Eyed"), LIST_STATUS3_MIRACLE_EYED}, @@ -449,14 +428,6 @@ static const struct ListMenuItem sStatus3ListItems[] = {COMPOUND_STRING("Power Trick"), LIST_STATUS3_POWER_TRICK}, }; -static const struct ListMenuItem sStatus4ListItems[] = -{ - {COMPOUND_STRING("Electrified"), LIST_STATUS4_ELECTRIFIED}, - {COMPOUND_STRING("Salt Cure"), LIST_STATUS4_SALT_CURE}, - {COMPOUND_STRING("Syrup Bomb"), LIST_STATUS4_SYRUP_BOMB}, - {COMPOUND_STRING("Glaive Rush"), LIST_STATUS4_GLAIVE_RUSH}, -}; - static const struct ListMenuItem sHazardsListItems[] = { {COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES}, @@ -822,7 +793,7 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Chosen move: "), 74, 64, 0, NULL); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, GetMoveName(gBattleMons[data->aiBattlerId].moves[chosenMoveIndex]), 74 + 68, 64, 0, NULL); } - + CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); Free(text); } @@ -1437,11 +1408,6 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) itemsCount = ARRAY_COUNT(sStatus3ListItems); data->bitfield = sStatus3Bitfield; break; - case LIST_ITEM_STATUS4: - listTemplate.items = sStatus4ListItems; - itemsCount = ARRAY_COUNT(sStatus4ListItems); - data->bitfield = sStatus4Bitfield; - break; case LIST_ITEM_AI: listTemplate.items = sAIListItems; itemsCount = ARRAY_COUNT(sAIListItems); @@ -2084,11 +2050,6 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); data->modifyArrows.typeOfVal = VAL_BITFIELD_32; goto CASE_ITEM_STATUS; - case LIST_ITEM_STATUS4: - data->modifyArrows.modifiedValPtr = &gStatuses4[data->battlerId]; - data->modifyArrows.currValue = GetBitfieldValue(gStatuses4[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); - data->modifyArrows.typeOfVal = VAL_BITFIELD_32; - goto CASE_ITEM_STATUS; case LIST_ITEM_AI: data->modifyArrows.modifiedValPtr = &gAiThinkingStruct->aiFlags[data->battlerId]; data->modifyArrows.currValue = GetBitfieldValue(gAiThinkingStruct->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index a33aa25cc4..87ed8542a7 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -232,9 +232,10 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && ability != ABILITY_SAND_FORCE && ability != ABILITY_SAND_RUSH && ability != ABILITY_OVERCOAT - && !IS_BATTLER_ANY_TYPE(gBattlerAttacker, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) - && !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES + && !IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER + && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; @@ -257,7 +258,8 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) if (ability != ABILITY_SNOW_CLOAK && ability != ABILITY_OVERCOAT && !IS_BATTLER_OF_TYPE(battler, TYPE_ICE) - && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { @@ -306,7 +308,7 @@ static bool32 HandleEndTurnEmergencyExit(u32 battler) && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) && CountUsablePartyMons(battler) > 0 - && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) // Not currently held by Sky Drop + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) // Not currently held by Sky Drop { gBattlerAbility = battler; gLastUsedAbility = ability; @@ -458,7 +460,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_THRASH: - if (gBattleMons[battler].volatiles.lockConfusionTurns && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + if (gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) { gBattleMons[battler].volatiles.lockConfusionTurns--; if (WasUnableToUseMove(battler)) @@ -484,7 +486,8 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK)) + && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + && !IsSemiInvulnerable(battler, CHECK_ALL) && IsBattlerGrounded(battler)) { gBattlerAttacker = battler; @@ -795,7 +798,7 @@ static bool32 HandleEndTurnSaltCure(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses4[battler] & STATUS4_SALT_CURE + if (gBattleMons[battler].volatiles.saltCure && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { @@ -836,10 +839,10 @@ static bool32 HandleEndTurnSyrupBomb(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (IsBattlerAlive(battler))) + if (gBattleMons[battler].volatiles.syrupBomb && (IsBattlerAlive(battler))) { if (gDisableStructs[battler].syrupBombTimer > 0 && --gDisableStructs[battler].syrupBombTimer == 0) - gStatuses4[battler] &= ~STATUS4_SYRUP_BOMB; + gBattleMons[battler].volatiles.syrupBomb = FALSE; PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn; BattleScriptExecute(gBattlescriptCurrInstr); diff --git a/src/battle_main.c b/src/battle_main.c index 2b3edabad2..cd9544ef28 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -194,7 +194,6 @@ EWRAM_DATA u8 gBideTarget[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u32 gSideStatuses[NUM_BATTLE_SIDES] = {0}; EWRAM_DATA struct SideTimer gSideTimers[NUM_BATTLE_SIDES] = {0}; EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0}; -EWRAM_DATA u32 gStatuses4[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gPauseCounterBattle = 0; EWRAM_DATA u16 gPaydayMoney = 0; @@ -3028,7 +3027,6 @@ static void BattleStartClearSetData(void) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { gStatuses3[i] = 0; - gStatuses4[i] = 0; gDisableStructs[i].isFirstTurn = 2; gLastMoves[i] = MOVE_NONE; gLastLandedMoves[i] = MOVE_NONE; @@ -3174,7 +3172,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK | STATUS3_AQUA_RING | STATUS3_POWER_TRICK); - gStatuses4[battler] &= STATUS4_INFINITE_CONFUSION; for (i = 0; i < gBattlersCount; i++) { if (!IsBattlerAlly(battler, i) @@ -3191,7 +3188,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) else { gStatuses3[battler] = 0; - gStatuses4[battler] = 0; } for (i = 0; i < gBattlersCount; i++) @@ -3200,8 +3196,8 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) gBattleMons[i].volatiles.infatuation = 0; if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) gBattleMons[i].volatiles.wrapped = FALSE; - if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) - gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + gBattleMons[i].volatiles.syrupBomb = FALSE; } gActionSelectionCursor[battler] = 0; @@ -3308,7 +3304,6 @@ const u8* FaintClearSetData(u32 battler) memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); gStatuses3[battler] &= STATUS3_GASTRO_ACID; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. - gStatuses4[battler] = 0; for (i = 0; i < gBattlersCount; i++) { @@ -3318,8 +3313,8 @@ const u8* FaintClearSetData(u32 battler) gBattleMons[i].volatiles.infatuation = 0; if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler) gBattleMons[i].volatiles.wrapped = FALSE; - if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) - gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler) + gBattleMons[i].volatiles.syrupBomb = FALSE; } gActionSelectionCursor[battler] = 0; @@ -3410,10 +3405,10 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->skyDropTargets[otherSkyDropper] = SKY_DROP_NO_TARGET; // If the other Pokemon involved in this Sky Drop was the target, not the attacker - if (gStatuses3[otherSkyDropper] & STATUS3_SKY_DROPPED) + if (gBattleMons[otherSkyDropper].volatiles.semiInvulnerable == STATE_SKY_DROP) { // Release the target and take them out of the semi-invulnerable state - gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_NONE; // Make the target's sprite visible gSprites[gBattlerSpriteIds[otherSkyDropper]].invisible = FALSE; @@ -4019,7 +4014,7 @@ void BattleTurnPassed(void) gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; - gStatuses4[i] &= ~STATUS4_ELECTRIFIED; + gBattleMons[i].volatiles.electrified = FALSE; gBattleMons[i].volatiles.flinched = FALSE; gBattleMons[i].volatiles.powder = FALSE; @@ -4308,7 +4303,7 @@ static void HandleTurnActionSelectionState(void) | BATTLE_TYPE_RECORDED_LINK)) && !gTestRunnerEnabled) // Or if currently held by Sky Drop - || gStatuses3[battler] & STATUS3_SKY_DROPPED) + || gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) { RecordedBattle_ClearBattlerAction(battler, 1); gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed; @@ -5133,7 +5128,7 @@ static void TurnValuesCleanUp(bool8 var0) if (gDisableStructs[i].substituteHP == 0) gBattleMons[i].volatiles.substitute = FALSE; - if (!(gStatuses3[i] & STATUS3_COMMANDER)) + if (gBattleMons[i].volatiles.semiInvulnerable != STATE_COMMANDER) gBattleStruct->battlerState[i].commandingDondozo = FALSE; gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF; @@ -6083,7 +6078,8 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler) gBattleStruct->dynamicMoveType = moveType | F_DYNAMIC_TYPE_SET; moveType = GetBattleMoveType(move); - if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL) || gStatuses4[battler] & STATUS4_ELECTRIFIED) + if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL) + || gBattleMons[battler].volatiles.electrified) gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_SET; // Check if a gem should activate. diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 162e55dba9..965745608c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -407,7 +407,7 @@ static void Cmd_jumpifabilitypresent(void); static void Cmd_endselectionscript(void); static void Cmd_playanimation(void); static void Cmd_playanimation_var(void); -static void Cmd_unused_0x47(void); +static void Cmd_jumpfifsemiinvulnerable(void); static void Cmd_unused_0x48(void); static void Cmd_moveend(void); static void Cmd_sethealblock(void); @@ -666,7 +666,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_endselectionscript, //0x44 Cmd_playanimation, //0x45 Cmd_playanimation_var, //0x46 - Cmd_unused_0x47, //0x47 + Cmd_jumpfifsemiinvulnerable, //0x47 Cmd_unused_0x48, //0x48 Cmd_moveend, //0x49 Cmd_sethealblock, //0x4A @@ -1079,7 +1079,7 @@ bool32 EmergencyExitCanBeTriggered(u32 battler) && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) && CountUsablePartyMons(battler) > 0 - && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) return TRUE; return FALSE; @@ -1366,7 +1366,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u { if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) gBattlescriptCurrInstr = nextInstr; - else if (gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE)) + else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) gBattlescriptCurrInstr = failInstr; else if (!JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, failInstr)) gBattlescriptCurrInstr = nextInstr; @@ -3372,7 +3372,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_FLAME_BURST: if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) - && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_SEMI_INVULNERABLE) + && !IsSemiInvulnerable(BATTLE_PARTNER(gBattlerTarget), CHECK_ALL) && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD) { gBattleScripting.battler = i = BATTLE_PARTNER(gBattlerTarget); @@ -3513,11 +3513,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_SYRUP_BOMB: - if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB)) + if (!gBattleMons[gEffectBattler].volatiles.syrupBomb) { struct Pokemon *mon = GetBattlerMon(gBattlerAttacker); - gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB; + gBattleMons[gEffectBattler].volatiles.syrupBomb = TRUE; gDisableStructs[gEffectBattler].syrupBombTimer = 3; gDisableStructs[gEffectBattler].syrupBombIsShiny = IsMonShiny(mon); gBattleStruct->stickySyrupdBy[gEffectBattler] = gBattlerAttacker; @@ -3655,9 +3655,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } break; case MOVE_EFFECT_SALT_CURE: - if (!(gStatuses4[gBattlerTarget] & STATUS4_SALT_CURE)) + if (!gBattleMons[gBattlerTarget].volatiles.saltCure) { - gStatuses4[gBattlerTarget] |= STATUS4_SALT_CURE; + gBattleMons[gBattlerTarget].volatiles.saltCure = TRUE; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectSaltCure; } @@ -5455,7 +5455,7 @@ static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *n MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = nextInstr; } - else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + else if (IsSemiInvulnerable(battler, CHECK_ALL)) { gBattlescriptCurrInstr = nextInstr; } @@ -5484,8 +5484,15 @@ static void Cmd_playanimation_var(void) PlayAnimation(battler, *(cmd->animIdPtr), cmd->argPtr, cmd->nextInstr); } -static void Cmd_unused_0x47(void) +static void Cmd_jumpfifsemiinvulnerable(void) { + CMD_ARGS(u8 battler, u8 state, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gBattleMons[battler].volatiles.semiInvulnerable == cmd->state) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_0x48(void) @@ -5764,7 +5771,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) - && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER)) + && gBattleMons[BATTLE_PARTNER(gBattlerTarget)].volatiles.semiInvulnerable != STATE_COMMANDER) { u32 targetAbility = GetBattlerAbility(gBattlerTarget); if (targetAbility == ABILITY_GUARD_DOG) @@ -5796,8 +5803,9 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) && IsBattlerAlive(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); + gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS); BattleScriptCall(BattleScript_MoveEffectSmackDown); effect = TRUE; } @@ -6156,7 +6164,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible - if (gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL) && gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)) { BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, TRUE); @@ -6168,12 +6176,12 @@ static void Cmd_moveend(void) break; case MOVEEND_ATTACKER_VISIBLE: // make attacker sprite visible if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT - || !(gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE)) + || !IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL) || WasUnableToUseMove(gBattlerAttacker)) { BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, FALSE); MarkBattlerForControllerExec(gBattlerAttacker); - gStatuses3[gBattlerAttacker] &= ~STATUS3_SEMI_INVULNERABLE; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE; gSpecialStatuses[gBattlerAttacker].restoredBattlerSprite = TRUE; gBattleScripting.moveendState++; return; @@ -6182,11 +6190,11 @@ static void Cmd_moveend(void) break; case MOVEEND_TARGET_VISIBLE: // make target sprite visible if (!gSpecialStatuses[gBattlerTarget].restoredBattlerSprite && gBattlerTarget < gBattlersCount - && !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE)) + && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) { BtlController_EmitSpriteInvisibility(gBattlerTarget, B_COMM_TO_CONTROLLER, FALSE); MarkBattlerForControllerExec(gBattlerTarget); - gStatuses3[gBattlerTarget] &= ~STATUS3_SEMI_INVULNERABLE; + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; gBattleScripting.moveendState++; return; } @@ -6927,7 +6935,7 @@ static void Cmd_moveend(void) u32 partner = BATTLE_PARTNER(i); gBattleStruct->battlerState[i].commanderSpecies = SPECIES_NONE; if (IsBattlerAlive(partner)) - gStatuses3[partner] &= ~STATUS3_COMMANDER; + gBattleMons[partner].volatiles.semiInvulnerable = STATE_NONE; } } @@ -8468,7 +8476,7 @@ static void Cmd_statusanimation(void) { u32 battler = GetBattlerForBattleScript(cmd->battler), statusFlag = (cmd->isVolatile || cmd->status) ? cmd->status : gBattleMons[battler].status1; - if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (!IsSemiInvulnerable(battler, CHECK_ALL) && gDisableStructs[battler].substituteHP == 0 && !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))) { @@ -9322,7 +9330,7 @@ static bool32 IsRototillerAffected(u32 battler) return FALSE; // Only grounded battlers affected if (!IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) return FALSE; // Only grass types affected - if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; // Rototiller doesn't affected semi-invulnerable battlers if (BlocksPrankster(MOVE_ROTOTILLER, gBattlerAttacker, battler, FALSE)) return FALSE; @@ -9352,7 +9360,7 @@ static bool32 IsTeatimeAffected(u32 battler) { if (GetItemPocket(gBattleMons[battler].item) != POCKET_BERRIES) return FALSE; // Only berries - if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; // Teatime doesn't affected semi-invulnerable battlers return TRUE; } @@ -11151,7 +11159,7 @@ static void Cmd_transformdataexecution(void) gBattlescriptCurrInstr = cmd->nextInstr; if (gBattleMons[gBattlerTarget].volatiles.transformed || gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER) + || IsSemiInvulnerable(gBattlerTarget, EXCLUDE_COMMANDER)) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORM_FAILED; @@ -11552,7 +11560,7 @@ static void Cmd_settypetorandomresistance(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove)) + else if (!BreaksThroughSemiInvulnerablity(gBattlerTarget, gCurrentMove)) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -11705,7 +11713,7 @@ static void Cmd_trychoosesleeptalkmove(void) gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition]; } gCurrMovePos = movePosition; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); gBattlescriptCurrInstr = cmd->failInstr; } @@ -12005,7 +12013,7 @@ static void Cmd_trysetperishsong(void) if (gStatuses3[i] & STATUS3_PERISH_SONG || GetBattlerAbility(i) == ABILITY_SOUNDPROOF || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE) - || gStatuses3[i] & STATUS3_COMMANDER) + || gBattleMons[i].volatiles.semiInvulnerable == STATE_COMMANDER) { notAffectedCount++; } @@ -12557,9 +12565,9 @@ static void Cmd_setsemiinvulnerablebit(void) { u32 semiInvulnerableEffect = GetMoveTwoTurnAttackStatus(gCurrentMove); if (cmd->clear) - gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE; else - gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect; + gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = semiInvulnerableEffect; } gBattlescriptCurrInstr = cmd->nextInstr; @@ -12618,7 +12626,7 @@ static void Cmd_trymemento(void) if (B_MEMENTO_FAIL >= GEN_4 && (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE + || IsSemiInvulnerable(gBattlerTarget, CHECK_ALL) || IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove) || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))) { @@ -15094,7 +15102,7 @@ void BS_ItemCureStatus(void) if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP) gBattleMons[battler].volatiles.nightmare = FALSE; if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION)) - gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } if (statusChanged) @@ -15234,15 +15242,6 @@ void BS_JumpIfElectricAbilityAffected(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_ApplySaltCure(void) -{ - NATIVE_ARGS(u8 battler); - - u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses4[battler] |= STATUS4_SALT_CURE; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_SetTerrain(void) { NATIVE_ARGS(const u8 *jumpInstr); @@ -15362,7 +15361,7 @@ void BS_TrySetOctolock(void) void BS_SetGlaiveRush(void) { NATIVE_ARGS(); - gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH; + gBattleMons[gBattlerAttacker].volatiles.glaiveRush = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -15985,7 +15984,7 @@ void BS_TeatimeInvul(void) NATIVE_ARGS(u8 battler, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))) + if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) gBattlescriptCurrInstr = cmd->nextInstr; else gBattlescriptCurrInstr = cmd->jumpInstr; @@ -16107,7 +16106,7 @@ void BS_JumpIfCommanderActive(void) if (gBattleStruct->battlerState[gBattlerTarget].commanderSpecies != SPECIES_NONE) gBattlescriptCurrInstr = cmd->jumpInstr; - else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER) + else if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_COMMANDER) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -16887,10 +16886,11 @@ void BS_GravityOnAirborneMons(void) { NATIVE_ARGS(); // Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop. - if (gStatuses3[gBattlerTarget] & STATUS3_ON_AIR && !(gStatuses3[gBattlerTarget] & STATUS3_SKY_DROPPED)) + if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_ON_AIR) CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_GRAVITY_ON_AIRBORNE); - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED); + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; + gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -17460,7 +17460,7 @@ void BS_TryElectrify(void) } else { - gStatuses4[gBattlerTarget] |= STATUS4_ELECTRIFIED; + gBattleMons[gBattlerTarget].volatiles.electrified = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -17964,7 +17964,7 @@ void BS_JumpIfUnder200(void) void BS_SetSkyDrop(void) { NATIVE_ARGS(); - gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_SKY_DROP; /* skyDropTargets holds the information of who is in a particular instance of Sky Drop. This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if the target of a Sky Drop faints while in the air.*/ @@ -17998,7 +17998,7 @@ void BS_ClearSkyDrop(void) { gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET; gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET; - gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18010,7 +18010,7 @@ void BS_ClearSkyDrop(void) void BS_SkyDropYawn(void) { NATIVE_ARGS(); - if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED)) + if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && gBattleMons[gEffectBattler].volatiles.semiInvulnerable != STATE_SKY_DROP) { // Set the target of Sky Drop as gEffectBattler gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler]; diff --git a/src/battle_util.c b/src/battle_util.c index caa4be0191..bc5eafc56f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1047,7 +1047,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) const u8 *result = NULL; u8 otherSkyDropper = gBattleStruct->skyDropTargets[battler]; - gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR); + gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE; // Makes both attacker and target's sprites visible gSprites[gBattlerSpriteIds[battler]].invisible = FALSE; @@ -1075,9 +1075,9 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) } else if (skyDropState == SKY_DROP_GRAVITY_ON_AIRBORNE) { - // Reapplying STATUS3_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target. + // Reapplying STATE_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target. gBattleStruct->skyDropTargets[battler] = SKY_DROP_RELEASED_TARGET; - gStatuses3[otherSkyDropper] |= STATUS3_SKY_DROPPED; + gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_SKY_DROP; } else if (skyDropState == SKY_DROP_CANCEL_MULTI_TURN_MOVES) { @@ -1121,10 +1121,10 @@ const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState) } // Clear battler's semi-invulnerable bits if they are not held by Sky Drop. - if (!(gStatuses3[battler] & STATUS3_SKY_DROPPED)) - gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE); + if (gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) + gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE; - if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) result = CheckSkyDropState(battler, skyDropState); gDisableStructs[battler].rolloutTimer = 0; @@ -1893,7 +1893,7 @@ static enum MoveCanceller CancellerFlags(void) { gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE; gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; - gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH; + gBattleMons[gBattlerAttacker].volatiles.glaiveRush = FALSE; return MOVE_STEP_SUCCESS; } @@ -1907,7 +1907,7 @@ static enum MoveCanceller CancellerStanceChangeOne(void) static enum MoveCanceller CancellerSkyDrop(void) { // If Pokemon is being held in Sky Drop - if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED) + if (gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_SKY_DROP) { gBattlescriptCurrInstr = BattleScript_MoveEnd; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; @@ -2157,7 +2157,7 @@ static enum MoveCanceller CancellerConfused(void) if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) { - if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION)) + if (!gBattleMons[gBattlerAttacker].volatiles.infiniteConfusion) gBattleMons[gBattlerAttacker].volatiles.confusionTurns--; if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns) { @@ -3577,7 +3577,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gBattleMons[diagonalBattler].volatiles.transformed && !gBattleMons[battler].volatiles.transformed && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON - && !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER)) + && !IsSemiInvulnerable(diagonalBattler, EXCLUDE_COMMANDER)) { SaveBattlerAttacker(gBattlerAttacker); SaveBattlerTarget(gBattlerTarget); @@ -4169,9 +4169,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlerAttacker = partner; gBattleStruct->battlerState[battler].commandingDondozo = TRUE; gBattleStruct->battlerState[partner].commanderSpecies = gBattleMons[battler].species; - gStatuses3[battler] |= STATUS3_COMMANDER; - if (gBattleMons[battler].volatiles.confusionTurns > 0 - && !(gStatuses4[battler] & STATUS4_INFINITE_CONFUSION)) + gBattleMons[battler].volatiles.semiInvulnerable = STATE_COMMANDER; + if (gBattleMons[battler].volatiles.confusionTurns > 0 && !gBattleMons[battler].volatiles.infiniteConfusion) gBattleMons[battler].volatiles.confusionTurns--; BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE); MarkBattlerForControllerExec(battler); @@ -4212,7 +4211,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ICE_BODY: if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND + && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { BattleScriptPushCursorAndCallback(BattleScript_IceBodyHeal); @@ -4985,7 +4985,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_GULP_MISSILE: if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) - && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_UNDERWATER) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { gBattleScripting.battler = gBattlerAttacker; @@ -5506,7 +5506,7 @@ bool32 CanBattlerEscape(u32 battler) // no ability check return FALSE; else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return FALSE; - else if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + else if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; else return TRUE; @@ -5531,7 +5531,7 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) { if (!(gFieldStatuses & terrainFlag)) return FALSE; - else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battler, CHECK_ALL)) return FALSE; return IsBattlerGrounded(battler); @@ -6066,7 +6066,7 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID) { if (CanBeInfinitelyConfused(battler)) - gStatuses4[battler] |= STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.infiniteConfusion = TRUE; BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE); gBattlerAttacker = gEffectBattler = battler; @@ -7300,8 +7300,8 @@ void ClearVariousBattlerFlags(u32 battler) { gDisableStructs[battler].furyCutterCounter = 0; gBattleMons[battler].volatiles.destinyBond = FALSE; + gBattleMons[battler].volatiles.glaiveRush = FALSE; gStatuses3[battler] &= ~STATUS3_GRUDGE; - gStatuses4[battler] &= ~ STATUS4_GLAIVE_RUSH; } void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands @@ -8286,7 +8286,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) break; case EFFECT_MAGNITUDE: case EFFECT_EARTHQUAKE: - if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_KNOCK_OFF: @@ -9077,7 +9077,7 @@ static inline uq4_12_t GetCriticalModifier(bool32 isCrit) static inline uq4_12_t GetGlaiveRushModifier(u32 battlerDef) { - if (gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH) + if (gBattleMons[battlerDef].volatiles.glaiveRush) return UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9102,21 +9102,21 @@ static inline uq4_12_t GetMinimizeModifier(u32 move, u32 battlerDef) static inline uq4_12_t GetUndergroundModifier(u32 move, u32 battlerDef) { - if (MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND) + if (MoveDamagesUnderground(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERGROUND) return UQ_4_12(2.0); return UQ_4_12(1.0); } static inline uq4_12_t GetDiveModifier(u32 move, u32 battlerDef) { - if (MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER) + if (MoveDamagesUnderWater(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERWATER) return UQ_4_12(2.0); return UQ_4_12(1.0); } static inline uq4_12_t GetAirborneModifier(u32 move, u32 battlerDef) { - if (MoveDamagesAirborneDoubleDamage(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR) + if (MoveDamagesAirborneDoubleDamage(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_ON_AIR) return UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9934,7 +9934,7 @@ bool32 CanMegaEvolve(u32 battler) return FALSE; // Check if battler is currently held by Sky Drop. - if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; // Check if battler is holding a Z-Crystal. @@ -9972,7 +9972,7 @@ bool32 CanUltraBurst(u32 battler) return FALSE; // Check if mon is currently held by Sky Drop - if (gStatuses3[battler] & STATUS3_SKY_DROPPED) + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; // Check if there is an entry in the form change table for Ultra Burst and battler is holding a Z-Crystal. @@ -10784,7 +10784,7 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return FALSE; if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)) return FALSE; - if (gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE) + if (IsSemiInvulnerable(battlerDef, CHECK_ALL)) return FALSE; return TRUE; @@ -10915,7 +10915,7 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing) void RemoveConfusionStatus(u32 battler) { gBattleMons[battler].volatiles.confusionTurns = 0; - gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION; + gBattleMons[battler].volatiles.infiniteConfusion = FALSE; } static bool32 CanBeInfinitelyConfused(u32 battler) @@ -11226,7 +11226,7 @@ bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef) u32 moveType = GetBattleMoveType(gCurrentMove); return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0)) || IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove) - || IsSemiInvulnerable(battlerDef, gCurrentMove) + || !BreaksThroughSemiInvulnerablity(battlerDef, gCurrentMove) || DoesBattlerHaveAbilityImmunity(battlerAtk, battlerDef, moveType)); } @@ -11614,13 +11614,13 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u if ((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) || (B_TOXIC_NEVER_MISS >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) - || gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH) + || gBattleMons[battlerDef].volatiles.glaiveRush) { effect = TRUE; } // If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits. else if (abilityAtk == ABILITY_NO_GUARD - && !(gStatuses3[battlerDef] & STATUS3_COMMANDER) + && gBattleMons[battlerDef].volatiles.semiInvulnerable != STATE_COMMANDER && (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET)) { effect = TRUE; @@ -11635,7 +11635,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u } // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. else if (gStatuses3[battlerDef] & STATUS3_TELEKINESIS - && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE) + && !IsSemiInvulnerable(battlerDef, CHECK_ALL) && moveEffect != EFFECT_OHKO && moveEffect != EFFECT_SHEER_COLD) { @@ -11645,15 +11645,11 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { effect = TRUE; } - else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) + else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !IsSemiInvulnerable(battlerDef, CHECK_ALL)) { effect = TRUE; } - else if ((gStatuses3[battlerDef] & STATUS3_COMMANDER) - || (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) - || ((gStatuses3[battlerDef] & STATUS3_ON_AIR) && !(MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move))) - || ((gStatuses3[battlerDef] & STATUS3_UNDERGROUND) && !MoveDamagesUnderground(move)) - || ((gStatuses3[battlerDef] & STATUS3_UNDERWATER) && !MoveDamagesUnderWater(move))) + else if (!BreaksThroughSemiInvulnerablity(battlerDef, move)) { if (option == RUN_SCRIPT) { @@ -11813,3 +11809,32 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u return calc; } + +bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander) +{ + if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_COMMANDER) + return excludeCommander != EXCLUDE_COMMANDER; + return gBattleMons[battler].volatiles.semiInvulnerable != STATE_NONE; +} + +bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move) +{ + switch (gBattleMons[battler].volatiles.semiInvulnerable) + { + case STATE_UNDERGROUND: + return MoveDamagesUnderground(move); + case STATE_UNDERWATER: + return MoveDamagesUnderWater(move); + case STATE_ON_AIR: + case STATE_SKY_DROP: + return MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move); + case STATE_PHANTOM_FORCE: + return FALSE; + case STATE_COMMANDER: + return FALSE; + case STATE_NONE: + return TRUE; + } + + return FALSE; +} diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 4edf88f17a..a4cff9c375 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -604,7 +604,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = STATE_ON_AIR }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -2461,7 +2461,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = COMPRESS_BITS(STATUS3_UNDERGROUND) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = STATE_UNDERGROUND }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -7715,7 +7715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .instructBanned = TRUE, .assistBanned = TRUE, .skyBattleBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = COMPRESS_BITS(STATUS3_UNDERWATER) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = STATE_UNDERWATER }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE, .contestCategory = CONTEST_CATEGORY_BEAUTY, .contestComboStarterId = COMBO_STARTER_DIVE, @@ -8974,7 +8974,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = STATE_ON_AIR }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_PARALYSIS, .chance = 30, @@ -12100,7 +12100,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), @@ -13065,7 +13065,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) }, + .argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = STATE_ON_AIR }, .contestEffect = CONTEST_EFFECT_AVOID_STARTLE, .contestCategory = CONTEST_CATEGORY_SMART, .contestComboStarterId = 0, @@ -14505,7 +14505,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, - .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) }, + .argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE }, .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_FEINT, }), diff --git a/src/item_use.c b/src/item_use.c index 328a258f2e..af1395f011 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1110,7 +1110,7 @@ static u32 GetBallThrowableState(void) return BALL_THROW_UNABLE_TWO_MONS; else if (IsPlayerPartyAndPokemonStorageFull() == TRUE) return BALL_THROW_UNABLE_NO_ROOM; - else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE)) + else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && IsSemiInvulnerable(GetCatchingBattler(), CHECK_ALL)) return BALL_THROW_UNABLE_SEMI_INVULNERABLE; else if (FlagGet(B_FLAG_NO_CATCHING)) return BALL_THROW_UNABLE_DISABLED_FLAG; diff --git a/test/battle/hold_effect/berserk_gene.c b/test/battle/hold_effect/berserk_gene.c index bbeb356701..5331f57849 100644 --- a/test/battle/hold_effect/berserk_gene.c +++ b/test/battle/hold_effect/berserk_gene.c @@ -213,7 +213,7 @@ SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is TURN {} } SCENE { } THEN { - EXPECT(gStatuses4[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] & STATUS4_INFINITE_CONFUSION); + EXPECT(gBattleMons[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)].volatiles.infiniteConfusion); } } diff --git a/test/battle/move_effect/semi_invulnerable.c b/test/battle/move_effect/semi_invulnerable.c index 331413121c..66086ca458 100644 --- a/test/battle/move_effect/semi_invulnerable.c +++ b/test/battle/move_effect/semi_invulnerable.c @@ -4,17 +4,17 @@ ASSUMPTIONS { ASSUME(GetMoveEffect(MOVE_FLY) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATUS3_ON_AIR); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATE_ON_AIR); ASSUME(GetMoveEffect(MOVE_DIG) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIG) == STATUS3_UNDERGROUND); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIG) == STATE_UNDERGROUND); ASSUME(GetMoveEffect(MOVE_BOUNCE) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATUS3_ON_AIR); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATE_ON_AIR); ASSUME(GetMoveEffect(MOVE_DIVE) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIVE) == STATUS3_UNDERWATER); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIVE) == STATE_UNDERWATER); ASSUME(GetMoveEffect(MOVE_PHANTOM_FORCE) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_PHANTOM_FORCE) == STATUS3_PHANTOM_FORCE); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_PHANTOM_FORCE) == STATE_PHANTOM_FORCE); ASSUME(GetMoveEffect(MOVE_SHADOW_FORCE) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SHADOW_FORCE) == STATUS3_PHANTOM_FORCE); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SHADOW_FORCE) == STATE_PHANTOM_FORCE); } SINGLE_BATTLE_TEST("Semi-invulnerable moves make the user semi-invulnerable turn 1, then strike turn 2") diff --git a/test/battle/move_effects_combined/hurricane.c b/test/battle/move_effects_combined/hurricane.c index 91a3435cf4..96773ce585 100644 --- a/test/battle/move_effects_combined/hurricane.c +++ b/test/battle/move_effects_combined/hurricane.c @@ -41,9 +41,9 @@ SINGLE_BATTLE_TEST("Hurricane can hit airborne targets (Fly, Bounce)") PARAMETRIZE { move = MOVE_BOUNCE; } GIVEN { ASSUME(GetMoveEffect(MOVE_FLY) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATUS3_ON_AIR); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATE_ON_AIR); ASSUME(GetMoveEffect(MOVE_BOUNCE) == EFFECT_SEMI_INVULNERABLE); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATUS3_ON_AIR); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATE_ON_AIR); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Moves(move); } } WHEN { @@ -59,7 +59,7 @@ DOUBLE_BATTLE_TEST("Hurricane can hit airborne targets (Sky Drop)") { GIVEN { ASSUME(GetMoveEffect(MOVE_SKY_DROP) == EFFECT_SKY_DROP); - ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SKY_DROP) == STATUS3_ON_AIR); + ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SKY_DROP) == STATE_ON_AIR); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); From f8cbea91673ee83089666f69478ddf792f1e259e Mon Sep 17 00:00:00 2001 From: "Danny Wang (ThePeeps191)" <74725787+ThePeeps191@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:50:32 -0600 Subject: [PATCH 175/283] Updating a link to porytiles in INSTALL.md (#7490) --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index d2e511dace..d265d588a1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -179,6 +179,6 @@ If you targeted a specific version that is not the latest version listed on the # Useful additional tools * [porymap](https://github.com/huderlem/porymap) for viewing and editing maps -* [porytiles](https://github.com/gruntlucas/porytiles) for add new metatiles for maps +* [porytiles](https://github.com/grunt-lucas/porytiles) for add new metatiles for maps * [poryscript](https://github.com/huderlem/poryscript) for scripting ([VS Code extension](https://marketplace.visualstudio.com/items?itemName=karathan.poryscript)) * [Tilemap Studio](https://github.com/Rangi42/tilemap-studio) for viewing and editing tilemaps From d3a5ddcb4b12a44400a0b7fcdbd41ba443a9ee1d Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Tue, 5 Aug 2025 21:14:21 +0200 Subject: [PATCH 176/283] remove leftover --- include/constants/moves.h | 4 ---- src/field_effect.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/include/constants/moves.h b/include/constants/moves.h index f8fa1773bf..dc8bc59a3f 100644 --- a/include/constants/moves.h +++ b/include/constants/moves.h @@ -1,10 +1,6 @@ #ifndef GUARD_CONSTANTS_MOVES_H #define GUARD_CONSTANTS_MOVES_H -#ifndef BATTLE_ENGINE - #define MOVE_ROCK_CLIMB 1 -#endif - #define MOVE_NONE 0 #define MOVE_POUND 1 #define MOVE_KARATE_CHOP 2 diff --git a/src/field_effect.c b/src/field_effect.c index a79409fd93..427bac13a3 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -259,10 +259,6 @@ static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent * static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent); // Static RAM declarations -#if FOLLOW_ME_IMPLEMENTED -static void TryAttachFollowerToPlayer(void); -#endif - static u8 sActiveList[32]; // External declarations From 1cb053e8e778775c60a32daa85eae392d74b5c7c Mon Sep 17 00:00:00 2001 From: Hedara Date: Tue, 5 Aug 2025 13:39:01 +0200 Subject: [PATCH 177/283] Add test for BoxPokemon integrity --- test/pokemon.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/test/pokemon.c b/test/pokemon.c index ac57314f9c..82a95dfd0d 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -4,6 +4,7 @@ #include "pokemon.h" #include "test/overworld_script.h" #include "test/test.h" +#include "constants/characters.h" TEST("Nature independent from Hidden Nature") { @@ -450,3 +451,99 @@ TEST("Pokémon level up learnsets fit within MAX_LEVEL_UP_MOVES and MAX_RELEARNE EXPECT_LT(count, MAX_LEVEL_UP_MOVES); EXPECT_LT(count, MAX_RELEARNER_MOVES - 1); // - 1 because at least one move is already known } + +TEST("BoxPokemon encryption works") +{ + u32 raw[20] = + { + 990384375, + 2948624514, + 3907508686, + 14410461, + 35316705, + 3907508686, + 64742109, + 718729, + 3102307966, + 2160206402, + 49956971, + 2495766612, + 1424318580, + 273408756, + 2371630199, + 2708871082, + 3059937332, + 2529190026, + 2290634828, + 2870614922 + }; + + struct Pokemon mon; + BoxMonToMon((struct BoxPokemon *)&raw, &mon); + + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPECIES), SPECIES_TORCHIC); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MARKINGS), 3); + const u8 *actualNickname = COMPOUND_STRING("Testing mon"); + u8 nickname[12]; + GetMonData(&mon, MON_DATA_NICKNAME, nickname); + u32 charIndex = 0; + while (actualNickname[charIndex] != EOS) + { + EXPECT_EQ(actualNickname[charIndex], nickname[charIndex]); + charIndex++; + } + EXPECT_EQ(GetNature(&mon), NATURE_HARDY); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HIDDEN_NATURE), NATURE_ADAMANT); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HP_LOST), 10); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HELD_ITEM), ITEM_ORAN_BERRY); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MOVE1), MOVE_TACKLE); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MOVE2), MOVE_SCRATCH); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MOVE3), MOVE_POUND); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MOVE4), MOVE_GROWL); + EXPECT_EQ(GetMonData(&mon, MON_DATA_PP1), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_PP2), 2); + EXPECT_EQ(GetMonData(&mon, MON_DATA_PP3), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_PP4), 4); + EXPECT_EQ(GetMonData(&mon, MON_DATA_PP_BONUSES), 255); + EXPECT_EQ(GetMonData(&mon, MON_DATA_COOL), 10); + EXPECT_EQ(GetMonData(&mon, MON_DATA_BEAUTY), 20); + EXPECT_EQ(GetMonData(&mon, MON_DATA_CUTE), 30); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SMART), 40); + EXPECT_EQ(GetMonData(&mon, MON_DATA_TOUGH), 50); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SHEEN), 150); + EXPECT_EQ(GetMonData(&mon, MON_DATA_EXP), 12345); + EXPECT_EQ(GetMonData(&mon, MON_DATA_MET_LEVEL), 20); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HP_EV), 11); + EXPECT_EQ(GetMonData(&mon, MON_DATA_ATK_EV), 22); + EXPECT_EQ(GetMonData(&mon, MON_DATA_DEF_EV), 33); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPEED_EV), 44); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPATK_EV), 55); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPDEF_EV), 66); + EXPECT_EQ(GetMonData(&mon, MON_DATA_FRIENDSHIP), 123); + EXPECT_EQ(GetMonData(&mon, MON_DATA_POKERUS), 2); + EXPECT_EQ(GetMonData(&mon, MON_DATA_POKEBALL), BALL_FRIEND); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HP_IV), 31); + EXPECT_EQ(GetMonData(&mon, MON_DATA_ATK_IV), 30); + EXPECT_EQ(GetMonData(&mon, MON_DATA_DEF_IV), 29); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPEED_IV), 28); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPATK_IV), 27); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPDEF_IV), 26); + EXPECT_EQ(GetMonData(&mon, MON_DATA_CUTE_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_BEAUTY_RIBBON), 0); + EXPECT_EQ(GetMonData(&mon, MON_DATA_TOUGH_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SMART_RIBBON), 0); + EXPECT_EQ(GetMonData(&mon, MON_DATA_CHAMPION_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_VICTORY_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_EFFORT_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_LAND_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_COUNTRY_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_EARTH_RIBBON), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_HP), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_ATK), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_DEF), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_SPEED), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_SPATK), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HYPER_TRAINED_SPDEF), 1); + EXPECT_EQ(GetMonData(&mon, MON_DATA_DYNAMAX_LEVEL), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_OT_GENDER), 0); +} From e8fefbcc75406118c49c5eab861564ca42c94de0 Mon Sep 17 00:00:00 2001 From: Hedara Date: Tue, 5 Aug 2025 13:49:11 +0200 Subject: [PATCH 178/283] Add bad egg check --- test/pokemon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/pokemon.c b/test/pokemon.c index 82a95dfd0d..47ec6af519 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -481,6 +481,7 @@ TEST("BoxPokemon encryption works") struct Pokemon mon; BoxMonToMon((struct BoxPokemon *)&raw, &mon); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SANITY_IS_BAD_EGG), 0); EXPECT_EQ(GetMonData(&mon, MON_DATA_SPECIES), SPECIES_TORCHIC); EXPECT_EQ(GetMonData(&mon, MON_DATA_MARKINGS), 3); const u8 *actualNickname = COMPOUND_STRING("Testing mon"); From e8b6d40f18a795425e9b90d2e04406f37bd2696c Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 6 Aug 2025 10:22:34 -0400 Subject: [PATCH 179/283] AI_FLAG_ATTACKS_PARTNER with a config for bloodthirstiness (#7401) --- docs/tutorials/ai_flags.md | 3 + include/battle_ai_util.h | 11 +- include/config/ai.h | 3 + include/constants/battle_ai.h | 5 +- src/battle_ai_field_statuses.c | 38 +++--- src/battle_ai_main.c | 154 ++++++++++++++--------- src/battle_ai_util.c | 118 ++++++++++++----- src/battle_controller_opponent.c | 24 +--- test/battle/ai/ai_doubles.c | 2 +- test/battle/ai/ai_flag_attacks_partner.c | 78 ++++++++++++ 10 files changed, 312 insertions(+), 124 deletions(-) create mode 100644 test/battle/ai/ai_flag_attacks_partner.c diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 98657210d9..2c13cee8bd 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -54,6 +54,9 @@ This flag is divided into two components to calculate the best available move fo This is different to `AI_FLAG_CHECK_BAD_MOVE` as it calculates how poor a move is and not whether it will fail or not. +## `AI_FLAG_ATTACKS_PARTNER` +This flag is meant for double battles where both of the opponents hate each other. They prioritize damage to their 'partner' over the player. + ## `AI_FLAG_FORCE_SETUP_FIRST_TURN` AI will prioritize using setup moves on the first turn at the expense of all else. These include stat buffs, field effects, status moves, etc. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index e0f1a4de0c..22efc06d0e 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -241,8 +241,16 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData // partner logic bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef); +// IsTargetingPartner includes a check to make sure the adjacent pokemon is truly a partner. u32 GetAllyChosenMove(u32 battlerId); -bool32 IsValidDoubleBattle(u32 battlerAtk); +bool32 IsBattle1v1(); +// IsBattle1v1 is distinct from !IsDoubleBattle. If the player is fighting Maxie and Tabitha, with Steven as their partner, and both Tabitha and Steven have run out of Pokemon, the battle is 1v1, even though mechanically it is a Double Battle for how battlers and flags are set. +// Most AI checks should be using IsBattle1v1; most engine checks should be using !IsDoubleBattle +bool32 HasTwoOpponents(u32 battler); +// HasTwoOpponents checks if the opposing side has two pokemon. Partner state is irrelevant. e.g., Dragon Darts hits one time with two opponents and twice with one opponent. +bool32 HasPartner(u32 battler); +bool32 HasPartnerIgnoreFlags(u32 battler); +// HasPartner respects the Attacks Partner AI flag; HasPartnerIgnoreFlags checks only if a live pokemon is adjacent. bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove); bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove); @@ -290,5 +298,6 @@ u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); u32 GetThinkingBattler(u32 battler); +bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); #endif //GUARD_BATTLE_AI_UTIL_H diff --git a/include/config/ai.h b/include/config/ai.h index d5f42696eb..8d015ce9e4 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -101,6 +101,9 @@ #define DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE 35 // both pokemon use Trick Room on turn Trick Room expires in the hopes both opponents used Protect to stall, getting a free refresh on the timer #define TAILWIND_IN_TRICK_ROOM_CHANCE 35 // use Tailwind on turn Trick Room expires in the hopes both opponents used Protect to stall +#define AI_FLAG_ATTACKS_PARTNER_FOCUSES_PARTNER FALSE // if TRUE, AI_FLAG_ATTACKS_PARTNER prefers attacking the partner over the ally. + // This is treated as true regardless during wild battles with AI. + // AI's desired stat changes for Guard Split and Power Split, treated as % #define GUARD_SPLIT_ALLY_PERCENTAGE 200 #define GUARD_SPLIT_ENEMY_PERCENTAGE 50 diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 8781640d60..f3a62398b3 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -34,9 +34,10 @@ #define AI_FLAG_PREDICT_MOVE (1 << 26) // AI will predict the player's move based on what move it would use in the same situation. Recommend using AI_FLAG_OMNISCIENT #define AI_FLAG_SMART_TERA (1 << 27) // AI will make smarter decisions when choosing whether to terrastalize (default is to always tera whenever available). #define AI_FLAG_ASSUME_STAB (1 << 28) // AI knows player's STAB moves, but nothing else. Restricted version of AI_FLAG_OMNISCIENT. -#define AI_FLAG_ASSUME_STATUS_MOVES (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ASSUME_STATUS_MOVES (1 << 29) // AI has a chance to know certain non-damaging moves, and also Fake Out and Super Fang. Restricted version of AI_FLAG_OMNISCIENT. +#define AI_FLAG_ATTACKS_PARTNER (1 << 30) // AI specific to double battles; AI can deliberately attack its 'partner.' -#define AI_FLAG_COUNT 30 +#define AI_FLAG_COUNT 31 // Flags at and after 32 need different formatting, as in // #define AI_FLAG_PLACEHOLDER ((u64)1 << 32) diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c index fc5ea0ccf6..d04f00d4b5 100644 --- a/src/battle_ai_field_statuses.c +++ b/src/battle_ai_field_statuses.c @@ -57,7 +57,7 @@ bool32 WeatherChecker(u32 battler, u32 weather, enum FieldEffectOutcome desiredR u32 i; u32 battlersOnSide = 1; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) battlersOnSide = 2; for (i = 0; i < battlersOnSide; i++) @@ -92,7 +92,7 @@ bool32 FieldStatusChecker(u32 battler, u32 fieldStatus, enum FieldEffectOutcome u32 battlersOnSide = 1; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) battlersOnSide = 2; for (i = 0; i < battlersOnSide; i++) @@ -230,7 +230,7 @@ static enum FieldEffectOutcome BenefitsFromSun(u32 battler) if (DoesAbilityBenefitFromWeather(ability, B_WEATHER_SUN) || HasLightSensitiveMove(battler) || HasDamagingMoveOfType(battler, TYPE_FIRE) - || HasBattlerSideMoveWithEffect(battler, EFFECT_HYDRO_STEAM)) + || HasMoveWithEffect(battler, EFFECT_HYDRO_STEAM)) return FIELD_EFFECT_POSITIVE; if (HasMoveWithFlag(battler, MoveHas50AccuracyInSun) || HasDamagingMoveOfType(battler, TYPE_WATER) || gAiLogicData->abilities[battler] == ABILITY_DRY_SKIN) @@ -243,8 +243,7 @@ static enum FieldEffectOutcome BenefitsFromSun(u32 battler) static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler) { if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_SANDSTORM) - || IS_BATTLER_OF_TYPE(battler, TYPE_ROCK) - || HasBattlerSideMoveWithEffect(battler, EFFECT_SHORE_UP)) + || IS_BATTLER_OF_TYPE(battler, TYPE_ROCK)) return FIELD_EFFECT_POSITIVE; if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) @@ -314,7 +313,7 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) return FIELD_EFFECT_POSITIVE; bool32 grounded = IsBattlerGrounded(battler); - if (grounded && HasBattlerSideUsedMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) + if (grounded && HasBattlerSideMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) return FIELD_EFFECT_POSITIVE; if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) @@ -322,6 +321,10 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) || HasDamagingMoveOfType(battler, TYPE_ELECTRIC))) return FIELD_EFFECT_POSITIVE; + if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_RISING_VOLTAGE)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; } @@ -331,21 +334,25 @@ static enum FieldEffectOutcome BenefitsFromGrassyTerrain(u32 battler) if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_GRASSY_TERRAIN)) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) + if (HasMoveWithEffect(battler, EFFECT_GRASSY_GLIDE)) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideUsedMoveWithAdditionalEffect(battler, MOVE_EFFECT_FLORAL_HEALING)) + if (HasMoveWithAdditionalEffect(battler, MOVE_EFFECT_FLORAL_HEALING)) return FIELD_EFFECT_POSITIVE; bool32 grounded = IsBattlerGrounded(battler); // Weaken spamming Earthquake, Magnitude, and Bulldoze. - if (grounded && (HasBattlerSideUsedMoveWithEffect(FOE(battler), EFFECT_EARTHQUAKE) - || HasBattlerSideUsedMoveWithEffect(FOE(battler), EFFECT_MAGNITUDE))) + if (grounded && (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_EARTHQUAKE) + || HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_MAGNITUDE))) return FIELD_EFFECT_POSITIVE; if (grounded && HasDamagingMoveOfType(battler, TYPE_GRASS)) return FIELD_EFFECT_POSITIVE; + if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_GRASSY_GLIDE)) + return FIELD_EFFECT_NEGATIVE; + + return FIELD_EFFECT_NEUTRAL; } @@ -360,7 +367,7 @@ static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) bool32 grounded = IsBattlerGrounded(battler); bool32 allyGrounded = FALSE; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); if (HasMoveWithEffect(FOE(battler), EFFECT_REST) && IsBattlerGrounded(FOE(battler))) @@ -387,12 +394,12 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) if (DoesAbilityBenefitFromFieldStatus(gAiLogicData->abilities[battler], STATUS_FIELD_PSYCHIC_TERRAIN)) return FIELD_EFFECT_POSITIVE; - if (HasBattlerSideMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) + if (HasMoveWithEffect(battler, EFFECT_EXPANDING_FORCE)) return FIELD_EFFECT_POSITIVE; bool32 grounded = IsBattlerGrounded(battler); bool32 allyGrounded = FALSE; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) allyGrounded = IsBattlerGrounded(BATTLE_PARTNER(battler)); // don't bother if we're not grounded @@ -408,6 +415,9 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) if (grounded && (HasDamagingMoveOfType(battler, TYPE_PSYCHIC))) return FIELD_EFFECT_POSITIVE; + if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_EXPANDING_FORCE)) + return FIELD_EFFECT_NEGATIVE; + if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) || HasBattlerSideAbility(battler, ABILITY_TRIAGE, gAiLogicData) || HasBattlerSideAbility(battler, ABILITY_PRANKSTER, gAiLogicData)) @@ -429,7 +439,7 @@ static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) else return FIELD_EFFECT_NEGATIVE; } - + // First checking if we have enough priority for one pokemon to disregard Trick Room entirely. if (!(gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN)) { diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 7a74e0d655..c6d488211a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -51,6 +51,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); +static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Roaming(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); @@ -91,10 +92,10 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = [24] = NULL, // AI_FLAG_PREDICT_INCOMING_MON [25] = AI_CheckPpStall, // AI_FLAG_PP_STALL_PREVENTION [26] = NULL, // AI_FLAG_PREDICT_MOVE - [27] = NULL, // Unused - [28] = NULL, // Unused - [29] = NULL, // Unused - [30] = NULL, // Unused + [27] = NULL, // AI_FLAG_SMART_TERA + [28] = NULL, // AI_FLAG_ASSUME_STAB + [29] = NULL, // AI_FLAG_ASSUME_STATUS_MOVES + [30] = AI_AttacksPartner, // AI_FLAG_ATTACKS_PARTNER [31] = NULL, // Unused [32] = NULL, // Unused [33] = NULL, // Unused @@ -247,6 +248,18 @@ void BattleAI_SetupFlags(void) // smart wild AI gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] = GetAiFlags(0xFFFF); gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] = GetAiFlags(0xFFFF); + + // The check is here because wild natural enemies are not symmetrical. + if (B_WILD_NATURAL_ENEMIES && IsDoubleBattle()) + { + u32 speciesLeft = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES); + u32 speciesRight = GetMonData(&gEnemyParty[1], MON_DATA_SPECIES); + if (IsNaturalEnemy(speciesLeft, speciesRight)) + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] |= AI_FLAG_ATTACKS_PARTNER; + if (IsNaturalEnemy(speciesRight, speciesLeft)) + gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] |= AI_FLAG_ATTACKS_PARTNER; + } + } else { @@ -1059,6 +1072,9 @@ void BattleAI_DoAIProcessing_PredictedSwitchin(struct AiThinkingStruct *aiThink, // AI_FLAG_CHECK_BAD_MOVE - decreases move scores static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { + if (IsTargetingPartner(battlerAtk, battlerDef)) + return score; + // move data enum BattleMoveEffects moveEffect = GetMoveEffect(move); u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); @@ -1066,7 +1082,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move); struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; - bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); + bool32 isBattle1v1 = IsBattle1v1(); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); + bool32 hasPartner = HasPartner(battlerAtk); u32 i; u32 weather; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); @@ -1074,9 +1092,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 abilityDef = aiData->abilities[battlerDef]; s32 atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); - if (IsTargetingPartner(battlerAtk, battlerDef)) - return score; - SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); @@ -1208,7 +1223,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // def ability checks // target partner ability checks & not attacking partner - if (isDoubleBattle) + if (hasTwoOpponents) { switch (aiData->abilities[BATTLE_PARTNER(battlerDef)]) { @@ -1479,7 +1494,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_ROTOTILLER: - if (isDoubleBattle) + if (hasPartner) { if (!(IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && IsBattlerGrounded(battlerAtk) @@ -1510,12 +1525,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; } - else if (!isDoubleBattle) + else if (!hasPartner) { ADJUST_SCORE(-10); // no partner and our stats wont rise, so don't use } - if (isDoubleBattle) + if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1541,12 +1556,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (!BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) ADJUST_SCORE(-8); } - else if (!isDoubleBattle) + else if (!hasPartner) { ADJUST_SCORE(-10); // our stats wont rise from this move } - if (isDoubleBattle) + if (hasPartner) { if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_PLUS || aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_MINUS) { @@ -1875,7 +1890,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-9); break; case EFFECT_PERISH_SONG: - if (isDoubleBattle) + if (!isBattle1v1) { if (CountUsablePartyMons(battlerAtk) == 0 && aiData->abilities[battlerAtk] != ABILITY_SOUNDPROOF @@ -1908,23 +1923,23 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SANDSTORM: if (weather & (B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_SUNNY_DAY: if (weather & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_RAIN_DANCE: if (weather & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_HAIL: case EFFECT_SNOWSCAPE: if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) - || IsMoveEffectWeather(aiData->partnerMove)) + || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_ATTRACT: @@ -2022,8 +2037,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_FOLLOW_ME: case EFFECT_HELPING_HAND: - if (!isDoubleBattle - || !IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) + if (!hasPartner || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove)) || gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battlerAtk)] != PARTY_SIZE) //Partner is switching out. @@ -2102,11 +2116,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_FLOWER_SHIELD: if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) - && !(isDoubleBattle && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) + && !(hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) ADJUST_SCORE(-10); break; case EFFECT_AROMATIC_MIST: - if (!isDoubleBattle || gBattleMons[BATTLE_PARTNER(battlerAtk)].hp == 0 || !BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPDEF)) + if (!hasPartner || !BattlerStatCanRise(BATTLE_PARTNER(battlerAtk), aiData->abilities[BATTLE_PARTNER(battlerAtk)], STAT_SPDEF)) ADJUST_SCORE(-10); break; case EFFECT_BIDE: @@ -2243,7 +2257,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) decreased = TRUE; } case PROTECT_CRAFTY_SHIELD: - if (!isDoubleBattle) + if (!hasPartner) { ADJUST_SCORE(-10); decreased = TRUE; @@ -2279,7 +2293,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else if (gDisableStructs[battlerAtk].protectUses == 1 && Random() % 100 < 50) { - if (!isDoubleBattle) + if (isBattle1v1) ADJUST_SCORE(-6); else ADJUST_SCORE(-10); //Don't try double protecting in doubles @@ -2327,7 +2341,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; } - if (isDoubleBattle) + if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the potential Defog @@ -2540,7 +2554,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_PLEDGE: - if (isDoubleBattle && gBattleMons[BATTLE_PARTNER(battlerAtk)].hp > 0) + if (hasPartner && gBattleMons[BATTLE_PARTNER(battlerAtk)].hp > 0) { if (aiData->partnerMove != MOVE_NONE && GetMoveEffect(aiData->partnerMove) == EFFECT_PLEDGE @@ -2723,7 +2737,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) ADJUST_SCORE(-10); - else if (isDoubleBattle) + else if (hasPartner) { if (!IsTargetingPartner(battlerAtk, battlerDef)) ADJUST_SCORE(-10); @@ -2742,14 +2756,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_QUASH: - if (!isDoubleBattle + if (!hasPartner || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: if (!IsTargetingPartner(battlerAtk, battlerDef) - || !isDoubleBattle + || !hasPartner || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -2976,15 +2990,16 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - + + bool32 hasPartner = HasPartner(battlerAtk); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING); - bool32 wouldPartnerFaint = CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) - && !partnerProtecting && IsBattlerAlive(battlerAtkPartner); + bool32 wouldPartnerFaint = hasPartner && CanIndexMoveFaintTarget(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING) + && !partnerProtecting; bool32 isFriendlyFireOK = !wouldPartnerFaint && (noOfHitsToKOPartner == 0 || noOfHitsToKOPartner > friendlyFireThreshold); // check what effect partner is using - if (aiData->partnerMove != 0) + if (aiData->partnerMove != 0 && hasPartner) { switch (partnerEffect) { @@ -3040,7 +3055,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (effect) { case EFFECT_HELPING_HAND: - if (!IsBattlerAlive(battlerAtkPartner) || !HasDamagingMove(battlerAtkPartner)) + if (!hasPartner || !HasDamagingMove(battlerAtkPartner)) ADJUST_SCORE(-20); break; case EFFECT_PERISH_SONG: @@ -3076,7 +3091,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. // This unsets Trick Room and resets it with a full timer. case EFFECT_TRICK_ROOM: - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM) && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) @@ -3702,9 +3717,8 @@ static inline bool32 ShouldUseSpreadDamageMove(u32 battlerAtk, u32 move, u32 mov u32 partnerBattler = BATTLE_PARTNER(battlerAtk); u32 noOfHitsToFaintPartner = GetNoOfHitsToKOBattler(battlerAtk, partnerBattler, moveIndex, AI_ATTACKING); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); - return (IsDoubleBattle() + return (HasPartnerIgnoreFlags(battlerAtk) && noOfHitsToFaintPartner != 0 // Immunity check - && IsBattlerAlive(partnerBattler) && GetBattlerMoveTargetType(battlerAtk, move) == MOVE_TARGET_FOES_AND_ALLY && !(noOfHitsToFaintPartner < friendlyFireThreshold && hitsToFaintOpposingBattler == 1) && noOfHitsToFaintPartner < (friendlyFireThreshold * 2)); @@ -3906,7 +3920,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); u32 predictedType = GetMoveType(predictedMove); u32 predictedMoveSlot = GetMoveSlot(GetMovesArray(battlerDef), predictedMove); - bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); + bool32 isBattle1v1 = IsBattle1v1(); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); + bool32 hasPartner = HasPartner(battlerAtk); + bool32 moveTargetsBothOpponents = hasTwoOpponents && (gMovesInfo[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_ALL_BATTLERS)); u32 i; // The AI should understand that while Dynamaxed, status moves function like Protect. @@ -4083,7 +4100,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk)) || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) break; - score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; case EFFECT_ROAR: if ((IsSoundMove(move) && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) @@ -4091,7 +4108,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; case EFFECT_MULTI_HIT: case EFFECT_TRIPLE_KICK: @@ -4228,7 +4245,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_HIT_ESCAPE: case EFFECT_PARTING_SHOT: case EFFECT_CHILLY_RECEPTION: - if (!IsDoubleBattle()) + if (!hasPartner) { switch (ShouldPivot(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, movesetIndex)) { @@ -4346,7 +4363,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove)); } - else if (isDoubleBattle && GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) + else if (hasPartner && GetBattlerMoveTargetType(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) & MOVE_TARGET_FOES_AND_ALLY) { if (aiData->abilities[battlerAtk] != ABILITY_TELEPATHY) ADJUST_SCORE(ProtectChecks(battlerAtk, battlerDef, move, predictedMove)); @@ -4516,7 +4533,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef); break; case EFFECT_SEMI_INVULNERABLE: - if (predictedMove != MOVE_NONE && !isDoubleBattle) + if (predictedMove != MOVE_NONE && isBattle1v1) { enum BattleMoveEffects predictedEffect = GetMoveEffect(predictedMove); if ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) @@ -4565,11 +4582,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); break; case EFFECT_FURY_CUTTER: - if (!isDoubleBattle && aiData->holdEffects[battlerAtk] == HOLD_EFFECT_METRONOME) + if (isBattle1v1 && aiData->holdEffects[battlerAtk] == HOLD_EFFECT_METRONOME) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_ATTRACT: - if (!isDoubleBattle + if (isBattle1v1 && (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) && BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef])) break; // Don't use if the attract won't have a change to activate @@ -4594,7 +4611,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) } else if (!AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) || CountUsablePartyMons(battlerDef) == 0) //Don't blow away hazards if you set them up { - if (isDoubleBattle) + if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // Partner is going to set up hazards && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move, predictedMove, CONSIDER_PRIORITY)) // Partner going first @@ -4606,11 +4623,11 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_TORMENT: break; case EFFECT_FOLLOW_ME: - if (isDoubleBattle + if (hasPartner && GetMoveTarget(move) == MOVE_TARGET_USER && !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) // Rage Powder doesn't affect powder immunities - && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) + // Rage Powder doesn't affect powder immunities { u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; if (predictedMoveOnPartner != MOVE_NONE && !IsBattleMoveStatus(predictedMoveOnPartner)) @@ -4684,7 +4701,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case HOLD_EFFECT_EJECT_BUTTON: //if (!IsRaidBattle() && GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX && gNewBS->dynamaxData.timer[battlerDef] > 1 && if (HasDamagingMove(battlerAtk) - || (isDoubleBattle && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && HasDamagingMove(BATTLE_PARTNER(battlerAtk)))) + || (hasPartner && HasDamagingMove(BATTLE_PARTNER(battlerAtk)))) ADJUST_SCORE(DECENT_EFFECT); // Force 'em out next turn break; default: @@ -5013,7 +5030,7 @@ case EFFECT_GUARD_SPLIT: } break; case EFFECT_PLEDGE: - if (isDoubleBattle && HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_PLEDGE)) + if (hasPartner && HasMoveWithEffect(BATTLE_PARTNER(battlerAtk), EFFECT_PLEDGE)) ADJUST_SCORE(GOOD_EFFECT); // Partner might use pledge move break; case EFFECT_TRICK_ROOM: @@ -5030,7 +5047,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(WEAK_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_NONE && aiData->holdEffects[battlerDef] != HOLD_EFFECT_NONE) ADJUST_SCORE(WEAK_EFFECT); - if (isDoubleBattle && aiData->holdEffects[BATTLE_PARTNER(battlerAtk)] == HOLD_EFFECT_NONE && aiData->holdEffects[BATTLE_PARTNER(battlerDef)] != HOLD_EFFECT_NONE) + if (!isBattle1v1 && aiData->holdEffects[BATTLE_PARTNER(battlerAtk)] == HOLD_EFFECT_NONE && aiData->holdEffects[BATTLE_PARTNER(battlerDef)] != HOLD_EFFECT_NONE) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_WONDER_ROOM: @@ -5125,7 +5142,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_QUASH: - if (isDoubleBattle && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) + if (hasPartner && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target break; case EFFECT_TAILWIND: @@ -5133,7 +5150,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_LUCKY_CHANT: - if (!isDoubleBattle && CountUsablePartyMons(battlerDef) > 0) + if (isBattle1v1 && CountUsablePartyMons(battlerDef) > 0) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_MAGNET_RISE: @@ -5431,7 +5448,7 @@ case EFFECT_GUARD_SPLIT: IncreasePoisonScore(battlerAtk, battlerDef, move, &score); break; case MOVE_EFFECT_CLEAR_SMOG: - score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE); + score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; case MOVE_EFFECT_BUG_BITE: // And pluck if (gBattleMons[battlerDef].volatiles.substitute || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD) @@ -5710,6 +5727,31 @@ static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) return score; } +// Adds score bonus to targeting "partner" +static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) +{ + if (battlerDef == BATTLE_PARTNER(battlerAtk) + // natural enemies in wild battles try to kill each other + && ((IsNaturalEnemy(gBattleMons[battlerAtk].species, gBattleMons[battlerDef].species) && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER))) + || AI_FLAG_ATTACKS_PARTNER_FOCUSES_PARTNER)) + { + u32 movesetIndex = gAiThinkingStruct->movesetIndex; + + if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, AI_ATTACKING)) + ADJUST_SCORE(BEST_EFFECT); + + u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING); + + if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 && + (GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) + ADJUST_SCORE(BEST_EFFECT); + + if (hitsToKO > 0) + ADJUST_SCORE(DECENT_EFFECT); + } + return score; +} + // Prefers moves that are good for baton pass static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a15fafc897..a3598e6800 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1337,7 +1337,7 @@ bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) enum BattleMoveEffects effect = GetMoveEffect(move); if (!AI_BattlerAtMaxHp(battlerTarget) || effect == EFFECT_MULTI_HIT) return FALSE; - if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && IsValidDoubleBattle(battlerTarget))) + if (GetMoveStrikeCount(move) > 1 && !(effect == EFFECT_DRAGON_DARTS && !HasTwoOpponents(battler))) return FALSE; if (gAiLogicData->holdEffects[battlerTarget] == HOLD_EFFECT_FOCUS_SASH) return TRUE; @@ -1947,7 +1947,7 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove) } else { - if (IsDoubleBattle()) + if (!IsBattle1v1()) score -= (2 * min(uses, 3)); else score -= (min(uses, 3)); @@ -2225,7 +2225,7 @@ bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect) { if (HasMoveWithEffect(battler, effect)) return TRUE; - if (IsDoubleBattle() && HasMoveWithEffect(BATTLE_OPPOSITE(battler), effect)) + if (HasPartnerIgnoreFlags(battler) && HasMoveWithEffect(BATTLE_PARTNER(battler), effect)) return TRUE; return FALSE; } @@ -2240,7 +2240,7 @@ bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect) { if (GetMoveEffect(gBattleHistory->usedMoves[battler][i]) == effect) return TRUE; - if (IsDoubleBattle() && GetMoveEffect(gBattleHistory->usedMoves[BATTLE_OPPOSITE(battler)][i]) == effect) + if (HasPartnerIgnoreFlags(battler) && GetMoveEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) == effect) return TRUE; } return FALSE; @@ -2295,7 +2295,7 @@ bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect) { if (HasMoveWithAdditionalEffect(battler, moveEffect)) return TRUE; - if (IsDoubleBattle() && HasMoveWithAdditionalEffect(BATTLE_OPPOSITE(battler), moveEffect)) + if (HasPartnerIgnoreFlags(battler) && HasMoveWithAdditionalEffect(BATTLE_PARTNER(battler), moveEffect)) return TRUE; return FALSE; } @@ -2310,7 +2310,7 @@ bool32 HasBattlerSideUsedMoveWithAdditionalEffect(u32 battler, u32 moveEffect) { if (MoveHasAdditionalEffect(gBattleHistory->usedMoves[battler][i], moveEffect)) return TRUE; - if (IsDoubleBattle() && MoveHasAdditionalEffect(gBattleHistory->usedMoves[BATTLE_OPPOSITE(battler)][i], moveEffect)) + if (HasPartnerIgnoreFlags(battler) && MoveHasAdditionalEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i], moveEffect)) return TRUE; } return FALSE; @@ -3073,7 +3073,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (PartyBattlerShouldAvoidHazards(battlerAtk, battlerToSwitch)) return DONT_PIVOT; - if (!IsDoubleBattle()) + if (IsBattle1v1()) { if (CountUsablePartyMons(battlerAtk) == 0) return CAN_TRY_PIVOT; // can't switch, but attack might still be useful @@ -3543,7 +3543,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) party = GetBattlerParty(battlerId); - if (IsDoubleBattle()) + if (HasPartner(battlerId)) { battlerOnField1 = gBattlerPartyIndexes[battlerId]; battlerOnField2 = gBattlerPartyIndexes[GetPartnerBattler(battlerId)]; @@ -3595,7 +3595,7 @@ u32 GetBattlerSideSpeedAverage(u32 battler) numBattlersAlive++; } - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) { speed2 = gAiLogicData->speedStats[BATTLE_PARTNER(battler)]; numBattlersAlive++; @@ -3709,17 +3709,48 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo } // Partner Logic -bool32 IsValidDoubleBattle(u32 battlerAtk) +bool32 IsBattle1v1() +{ + if (IsDoubleBattle() + && ((IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) + || (IsBattlerAlive(B_POSITION_OPPONENT_LEFT) && IsBattlerAlive(B_POSITION_OPPONENT_RIGHT)))) + return FALSE; + return TRUE; +} + +bool32 HasTwoOpponents(u32 battler) { if (IsDoubleBattle() - && ((IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk)) && IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerAtk)))) || IsBattlerAlive(BATTLE_PARTNER(battlerAtk)))) + && IsBattlerAlive(FOE(battler)) && IsBattlerAlive(BATTLE_PARTNER(FOE(battler)))) return TRUE; return FALSE; } -// TODO: Handling for when the 'partner' is not actually a partner, a la Battle Royale or B_WILD_NATURAL_ENEMIES +bool32 HasPartner(u32 battler) +{ + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ATTACKS_PARTNER) + return FALSE; + else + return TRUE; + } + return FALSE; +} + +bool32 HasPartnerIgnoreFlags(u32 battler) +{ + if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + { + return TRUE; + } + return FALSE; +} + bool32 IsTargetingPartner(u32 battlerAtk, u32 battlerDef) { + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_ATTACKS_PARTNER) + return FALSE; return ((battlerAtk) == (battlerDef ^ BIT_FLANK)); } @@ -3738,7 +3769,7 @@ u32 GetAllyChosenMove(u32 battlerId) //PARTNER_MOVE_EFFECT_IS_SAME bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (GetMoveEffect(move) == GetMoveEffect(partnerMove) @@ -3753,7 +3784,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 //PARTNER_MOVE_EFFECT_IS_SAME_NO_TARGET bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (GetMoveEffect(move) == GetMoveEffect(partnerMove) @@ -3765,7 +3796,7 @@ bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u3 //PARTNER_MOVE_EFFECT_IS_STATUS_SAME_TARGET bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove); @@ -3799,7 +3830,7 @@ bool32 IsMoveEffectWeather(u32 move) //PARTNER_MOVE_EFFECT_IS_TERRAIN bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove); @@ -3816,7 +3847,7 @@ bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove) //PARTNER_MOVE_EFFECT_IS bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMoveEffects effectCheck) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && GetMoveEffect(partnerMove) == effectCheck) @@ -3828,7 +3859,7 @@ bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMo //PARTNER_MOVE_IS_TAILWIND_TRICKROOM bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && partnerMove == moveCheck) @@ -3839,7 +3870,7 @@ bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck) //PARTNER_MOVE_IS_SAME bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && move == partnerMove && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) @@ -3850,7 +3881,7 @@ bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 mo //PARTNER_MOVE_IS_SAME_NO_TARGET bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove) { - if (!IsDoubleBattle()) + if (!HasPartner(battlerAtkPartner)) return FALSE; if (partnerMove != MOVE_NONE && move == partnerMove) return TRUE; @@ -3859,7 +3890,7 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov bool32 PartnerMoveActivatesSleepClause(u32 partnerMove) { - if (!IsDoubleBattle() || !IsSleepClauseEnabled()) + if (IsBattle1v1() || !IsSleepClauseEnabled()) return FALSE; return IsMoveSleepClauseTrigger(partnerMove); } @@ -3894,7 +3925,7 @@ bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) } } - if (!IsDoubleBattle()) + if (IsBattle1v1()) { switch (GetMoveEffect(move)) { @@ -4086,7 +4117,7 @@ bool32 PartyHasMoveCategory(u32 battlerId, enum DamageCategory category) bool32 SideHasMoveCategory(u32 battlerId, enum DamageCategory category) { - if (IsDoubleBattle()) + if (HasPartnerIgnoreFlags(battlerId)) { if (HasMoveWithCategory(battlerId, category) || HasMoveWithCategory(BATTLE_PARTNER(battlerId), category)) return TRUE; @@ -4612,7 +4643,7 @@ void DecideTerastal(u32 battler) return; // TODO: Currently only single battles are considered. - if (IsDoubleBattle()) + if (!IsBattle1v1()) return; // TODO: A lot of these checks are most effective for an omnicient ai. @@ -5030,7 +5061,7 @@ bool32 HasBattlerSideAbility(u32 battler, u32 ability, struct AiLogicData *aiDat { if (aiData->abilities[battler] == ability) return TRUE; - if (IsDoubleBattle() && gAiLogicData->abilities[BATTLE_PARTNER(battler)] == ability) + if (HasPartnerIgnoreFlags(battler) && gAiLogicData->abilities[BATTLE_PARTNER(battler)] == ability) return TRUE; return FALSE; } @@ -5041,6 +5072,8 @@ u32 GetFriendlyFireKOThreshold(u32 battler) return FRIENDLY_FIRE_RISKY_THRESHOLD; if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_CONSERVATIVE) return FRIENDLY_FIRE_CONSERVATIVE_THRESHOLD; + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ATTACKS_PARTNER) + return 0; return FRIENDLY_FIRE_NORMAL_THRESHOLD; } @@ -5192,7 +5225,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct if (hasSameAbility || gAbilitiesInfo[atkAbility].cantBeSuppressed || gAbilitiesInfo[defAbility].cantBeCopied) return FALSE; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + if (HasPartnerIgnoreFlags(battlerAtk)) { u32 partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; if (gAbilitiesInfo[partnerAbility].cantBeSuppressed) @@ -5293,7 +5326,7 @@ void AbilityChangeScore(u32 battlerAtk, u32 battlerDef, u32 effect, s32 *score, bool32 attackerHasBadAbility = (gAbilitiesInfo[abilityAtk].aiRating < 0); s32 currentAbilityScore, transferredAbilityScore = 0; - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + if (HasPartner(battlerAtk)) { partnerAbility = aiData->abilities[BATTLE_PARTNER(battlerAtk)]; if (!(gAbilitiesInfo[partnerAbility].cantBeSuppressed) && (gAbilitiesInfo[partnerAbility].aiRating < 0)) @@ -5387,7 +5420,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData case ABILITY_FRIEND_GUARD: case ABILITY_POWER_SPOT: case ABILITY_VICTORY_STAR: - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)) && aiData->abilities[BATTLE_PARTNER(battler)] != ability) + if (HasPartner(battler) && aiData->abilities[BATTLE_PARTNER(battler)] != ability) return BEST_EFFECT; break; case ABILITY_GUTS: @@ -5414,7 +5447,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData } else { - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(FOE(battler)))) + if (HasTwoOpponents(battler)) { abilityDef = aiData->abilities[BATTLE_PARTNER(FOE(battler))]; if (DoesIntimidateRaiseStats(abilityDef)) @@ -5457,7 +5490,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData case ABILITY_SWORD_OF_RUIN: case ABILITY_TABLETS_OF_RUIN: case ABILITY_VESSEL_OF_RUIN: - if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler))) + if (HasPartner(battler)) { if (aiData->abilities[BATTLE_PARTNER(battler)] != ability) return GOOD_EFFECT; @@ -5480,3 +5513,28 @@ u32 GetThinkingBattler(u32 battler) return gAiLogicData->battlerDoingPrediction; return battler; } + +bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget) +{ + if (B_WILD_NATURAL_ENEMIES != TRUE) + return FALSE; + + switch (speciesAttacker) + { + case SPECIES_ZANGOOSE: + return (speciesTarget == SPECIES_SEVIPER); + case SPECIES_SEVIPER: + return (speciesTarget == SPECIES_ZANGOOSE); + case SPECIES_HEATMOR: + return (speciesTarget == SPECIES_DURANT); + case SPECIES_DURANT: + return (speciesTarget == SPECIES_HEATMOR); + case SPECIES_SABLEYE: + return (speciesTarget == SPECIES_CARBINK); + case SPECIES_MAREANIE: + return (speciesTarget == SPECIES_CORSOLA); + default: + return FALSE; + } + return FALSE; +} diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index c907309280..84b3d3c0a8 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -473,31 +473,15 @@ static void OpponentHandleChooseMove(u32 battler) target = GetBattlerAtPosition(Random() & 2); } while (!CanTargetBattler(battler, target, move)); - // Don't bother to loop through table if the move can't attack ally + // Don't bother to check if they're enemies if the move can't attack ally if (B_WILD_NATURAL_ENEMIES == TRUE && !(GetBattlerMoveTargetType(battler, move) & MOVE_TARGET_BOTH)) { - u16 i, speciesAttacker, speciesTarget, isPartnerEnemy = FALSE; - static const u16 naturalEnemies[][2] = - { - // Attacker Target - {SPECIES_ZANGOOSE, SPECIES_SEVIPER}, - {SPECIES_SEVIPER, SPECIES_ZANGOOSE}, - {SPECIES_HEATMOR, SPECIES_DURANT}, - {SPECIES_DURANT, SPECIES_HEATMOR}, - {SPECIES_SABLEYE, SPECIES_CARBINK}, - {SPECIES_MAREANIE, SPECIES_CORSOLA}, - }; + u32 speciesAttacker, speciesTarget; speciesAttacker = gBattleMons[battler].species; speciesTarget = gBattleMons[GetBattlerAtPosition(BATTLE_PARTNER(battler))].species; - for (i = 0; i < ARRAY_COUNT(naturalEnemies); i++) - { - if (speciesAttacker == naturalEnemies[i][0] && speciesTarget == naturalEnemies[i][1]) - { - isPartnerEnemy = TRUE; - break; - } - } + bool32 isPartnerEnemy = IsNaturalEnemy(speciesAttacker, speciesTarget); + if (isPartnerEnemy && CanTargetBattler(battler, target, move)) BtlController_EmitTwoReturnValues(battler, B_COMM_TO_ENGINE, B_ACTION_EXEC_SCRIPT, (chosenMoveIndex) | (GetBattlerAtPosition(BATTLE_PARTNER(battler)) << 8)); else diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 60dce82801..5589f7bb0e 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -510,7 +510,7 @@ AI_DOUBLE_BATTLE_TEST("AI sets up weather for its ally") PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_TORNADUS) { Item(ITEM_SAFETY_GOGGLES); Ability(ABILITY_PRANKSTER); Moves(goodWeather, badWeather, MOVE_RETURN, MOVE_TAUNT); } - OPPONENT(SPECIES_WOBBUFFET) { Moves(weatherTrigger, MOVE_EARTH_POWER); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); Moves(weatherTrigger, MOVE_EARTH_POWER); } } WHEN { TURN { EXPECT_MOVE(opponentLeft, goodWeather); } } diff --git a/test/battle/ai/ai_flag_attacks_partner.c b/test/battle/ai/ai_flag_attacks_partner.c new file mode 100644 index 0000000000..4f2533fa5b --- /dev/null +++ b/test/battle/ai/ai_flag_attacks_partner.c @@ -0,0 +1,78 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_DOUBLE_BATTLE_TEST("AI_FLAG_ATTACKS_PARTNER is willing to kill either the partner or the player") +{ + ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); + + u32 move, level; + + PARAMETRIZE { move = MOVE_BRUTAL_SWING; level = 1; } + PARAMETRIZE { move = MOVE_MIGHTY_CLEAVE; level = 1; } + PARAMETRIZE { move = MOVE_BRUTAL_SWING; level = 100; } + PARAMETRIZE { move = MOVE_MIGHTY_CLEAVE; level = 100; } + PARAMETRIZE { move = MOVE_BRUTAL_SWING; level = 50; } + PARAMETRIZE { move = MOVE_MIGHTY_CLEAVE; level = 50; } + + GIVEN { + ASSUME(GetMovePower(MOVE_OVERDRIVE) == 80); + ASSUME(GetMovePower(MOVE_BRUTAL_SWING) == 60); + ASSUME(GetMovePower(MOVE_MIGHTY_CLEAVE) == 95); + ASSUME(gSpeciesInfo[SPECIES_ZIGZAGOON].baseAttack == gSpeciesInfo[SPECIES_ZIGZAGOON].baseSpAttack); + ASSUME(gSpeciesInfo[SPECIES_ZIGZAGOON].baseDefense == gSpeciesInfo[SPECIES_ZIGZAGOON].baseSpDefense); + ASSUME(gSpeciesInfo[SPECIES_ZIGZAGOON].baseHP == 38); + ASSUME(gSpeciesInfo[SPECIES_ZIGZAGOON].baseAttack == 30); + ASSUME(gSpeciesInfo[SPECIES_ZIGZAGOON].baseDefense == 41); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ATTACKS_PARTNER); + PLAYER(SPECIES_ZIGZAGOON) { Level(50); } + PLAYER(SPECIES_ZIGZAGOON) { Level(16); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(50); Moves(move, MOVE_OVERDRIVE, MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(level); Moves(MOVE_CELEBRATE); } + } WHEN { + TURN + { + if (move == MOVE_MIGHTY_CLEAVE) + { + if (level == 1) + EXPECT_MOVE(opponentLeft, move, target: opponentRight); + else + EXPECT_MOVE(opponentLeft, move, target: playerRight); + } + else + { + if (level == 1 || AI_FLAG_ATTACKS_PARTNER_FOCUSES_PARTNER) + EXPECT_MOVE(opponentLeft, move); + else + EXPECT_MOVE(opponentLeft, MOVE_OVERDRIVE); + } + } + } +} + +AI_DOUBLE_BATTLE_TEST("AI_FLAG_ATTACKS_PARTNER steps on its ally's weather") +{ + u32 weather1, move1, weather2, move2; + + PARAMETRIZE { weather1 = MOVE_SUNNY_DAY; move1 = MOVE_SOLAR_BEAM; weather2 = MOVE_RAIN_DANCE; move2 = MOVE_THUNDER; } + PARAMETRIZE { weather1 = MOVE_RAIN_DANCE; move1 = MOVE_THUNDER; weather2 = MOVE_SUNNY_DAY; move2 = MOVE_SOLAR_BEAM; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ATTACKS_PARTNER); + PLAYER(SPECIES_WOBBUFFET) { Speed(50); } + PLAYER(SPECIES_WOBBUFFET) { Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(75); Moves(weather1, move1, MOVE_HEADBUTT); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); Moves(weather2, move2, MOVE_HEADBUTT); } + } WHEN { + TURN + { + EXPECT_MOVE(opponentLeft, weather1); + EXPECT_MOVE(opponentRight, weather2); + } + TURN + { + EXPECT_MOVE(opponentLeft, move1); + EXPECT_MOVE(opponentRight, weather2); + } + } +} From 3f9359765c56f7ebace7f6688f1f00cb36024107 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:20:03 -0400 Subject: [PATCH 180/283] Fix doubles switch AI to use new type matchup system (#7495) --- src/battle_ai_switch_items.c | 23 ++++------------------- test/battle/ai/ai_switching.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index fe3bb5a5ed..d6ac5d025e 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1444,33 +1444,18 @@ static u32 GetBestMonBatonPass(struct Pokemon *party, int firstId, int lastId, u static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, u8 invalidMons, u32 battler, u32 opposingBattler) { int i, bits = 0; - while (bits != 0x3F) // All mons were checked. { - uq4_12_t bestResist = UQ_4_12(1.0); + u32 bestResist = UQ_4_12(2.0); int bestMonId = PARTY_SIZE; // Find the mon whose type is the most suitable defensively. for (i = firstId; i < lastId; i++) { if (!((1u << i) & invalidMons) && !((1u << i) & bits)) { - u16 species = GetMonData(&party[i], MON_DATA_SPECIES); - uq4_12_t typeEffectiveness = UQ_4_12(1.0); - - u8 atkType1 = gBattleMons[opposingBattler].types[0]; - u8 atkType2 = gBattleMons[opposingBattler].types[1]; - u8 defType1 = GetSpeciesType(species, 0); - u8 defType2 = GetSpeciesType(species, 1); - - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType1))); - if (defType2 != defType1) - { - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType2))); - if (atkType2 != atkType1) - typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType2, defType2))); - } + InitializeSwitchinCandidate(&party[i]); + + u32 typeEffectiveness = GetBattleMonTypeMatchup(gBattleMons[opposingBattler], gAiLogicData->switchinCandidate.battleMon); if (typeEffectiveness < bestResist) { bestResist = typeEffectiveness; diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 45b50b7638..a858c33ded 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1316,6 +1316,21 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will properly consider immu } } +AI_DOUBLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will properly consider immunities when determining switchin type matchup (Doubles)") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_POLIWRATH) { Moves(MOVE_WATER_GUN, MOVE_KARATE_CHOP); } + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(1); Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_ZIGZAGOON) { Level(1); Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_CERULEDGE) { Moves(MOVE_SPARK); } + OPPONENT(SPECIES_WHIMSICOTT) { Moves(MOVE_MEGA_DRAIN); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_KARATE_CHOP, target:opponentLeft); MOVE(playerRight, MOVE_CELEBRATE); EXPECT_MOVE(opponentLeft, MOVE_CELEBRATE); EXPECT_MOVE(opponentRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(opponentLeft, 3); } + } +} + AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out due to bad odds if it can OHKO with a priority move") { PASSES_RANDOMLY(100, 100, RNG_AI_SWITCH_HASBADODDS); From 13a8f655b5e382211be682f127981700556a0b69 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:29:37 -0400 Subject: [PATCH 181/283] Fix Bad Odds not seeing damage properly (#7492) --- src/battle_ai_switch_items.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index d6ac5d025e..3180550e59 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -207,7 +207,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) //Variable initialization u8 opposingPosition; s32 i, damageDealt = 0, maxDamageDealt = 0, damageTaken = 0, maxDamageTaken = 0, maxDamageTakenPriority = 0; - u32 aiMove, playerMove, bestPlayerPriorityMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; + u32 aiMove, playerMove, bestPlayerPriorityMove = MOVE_NONE, bestPlayerMove = MOVE_NONE, expectedMove = MOVE_NONE, aiAbility = gAiLogicData->abilities[battler], opposingBattler; bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE; u32 typeMatchup; enum BattleMoveEffects aiMoveEffect; @@ -236,6 +236,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) { maxDamageTaken = damageTaken; + bestPlayerMove = playerMove; } if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[battler], playerMove) > 0 && damageTaken > maxDamageTakenPriority && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) { @@ -247,6 +248,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler); hitsToKoAIPriority = GetNoOfHitsToKOBattlerDmg(maxDamageTakenPriority, battler); + expectedMove = gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE ? GetIncomingMove(battler, opposingBattler, gAiLogicData) : bestPlayerMove; for (i = 0; i < MAX_MON_MOVES; i++) { @@ -279,10 +281,12 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) // Get maximum damage mon can deal damageDealt = AI_GetDamage(battler, opposingBattler, i, AI_ATTACKING, gAiLogicData); + if (damageDealt > maxDamageDealt) + maxDamageDealt = damageDealt; if (!canBattlerWin1v1 ) // Once we can win a 1v1 we don't need to track this, but want to run the rest of the function to keep the runtime the same regardless of when we find the winning move { hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); - isBattlerFirst = AI_IsFaster(battler, opposingBattler, aiMove, GetIncomingMove(battler, opposingBattler, gAiLogicData), CONSIDER_PRIORITY); + isBattlerFirst = AI_IsFaster(battler, opposingBattler, aiMove, expectedMove, CONSIDER_PRIORITY); isBattlerFirstPriority = AI_IsFaster(battler, opposingBattler, aiMove, bestPlayerPriorityMove, CONSIDER_PRIORITY); canBattlerWin1v1 = CanBattlerWin1v1(hitsToKoAI, hitsToKoPlayer, isBattlerFirst) && CanBattlerWin1v1(hitsToKoAIPriority, hitsToKoPlayer, isBattlerFirstPriority); } @@ -310,11 +314,8 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) // Start assessing whether or not mon has bad odds // Jump straight to switching out in cases where mon gets OHKO'd - if (((getsOneShot && gBattleMons[opposingBattler].speed > gBattleMons[battler].speed) // If the player OHKOs and outspeeds OR OHKOs, doesn't outspeed but isn't 2HKO'd - || (getsOneShot && gBattleMons[opposingBattler].speed <= gBattleMons[battler].speed && maxDamageDealt < gBattleMons[opposingBattler].hp / 2)) - && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator - || (aiAbility == ABILITY_REGENERATOR - && gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4))) + if ((getsOneShot && !canBattlerWin1v1) && (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2 // And the current mon has at least 1/2 their HP, or 1/4 HP and Regenerator + || (aiAbility == ABILITY_REGENERATOR && gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4))) { // 50% chance to stay in regardless if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !gAiLogicData->aiPredictionInProgress) From e778d3cdfee6329b2a3551b5256cc0f213c83bee Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 6 Aug 2025 17:39:43 -0400 Subject: [PATCH 182/283] Improved Guaranteed Flinch logic (fake out et al) (#7501) --- include/battle_ai_util.h | 3 +- src/battle_ai_main.c | 16 ++++++++-- src/battle_ai_util.c | 59 ++++++++++++++++++++++++++++++------- test/battle/ai/ai_doubles.c | 13 ++++++++ 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 22efc06d0e..52b5764b00 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -197,7 +197,8 @@ bool32 IsHealingMove(u32 move); bool32 HasHealingEffect(u32 battler); bool32 IsTrappingMove(u32 move); bool32 HasTrappingMoveEffect(u32 battler); -bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move); +bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move); +bool32 HasChoiceEffect(u32 battler); bool32 HasThawingMove(u32 battler); bool32 IsStatRaisingEffect(enum BattleMoveEffects effect); bool32 IsStatLoweringEffect(enum BattleMoveEffects effect); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index c6d488211a..2fbe68f0ee 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1138,6 +1138,12 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)) abilityDef = ABILITY_NONE; + // If a pokemon can be guaranteed flinched, don't target the pokemon that can't be flinched. + if (hasTwoOpponents + && !IsFlinchGuaranteed(battlerAtk, battlerDef, move) && IsFlinchGuaranteed(battlerAtk, BATTLE_PARTNER(battlerDef), move) + && aiData->effectiveness[battlerAtk][BATTLE_PARTNER(battlerDef)][gAiThinkingStruct->movesetIndex] != UQ_4_12(0.0)) + ADJUST_SCORE(-5); + // check non-user target if (!(moveTarget & MOVE_TARGET_USER)) { @@ -1999,6 +2005,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_FIRST_TURN_ONLY: if (!gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(-10); + if (HasChoiceEffect(battlerAtk)) + ADJUST_SCORE(-5); break; case EFFECT_STOCKPILE: if (gDisableStructs[battlerAtk].stockpileCounter >= 3) @@ -3946,6 +3954,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(-20); // Force switch if all your attacking moves are physical and you have Natural Cure. } + // check guaranteed flinch, a la Fake Out + if (IsFlinchGuaranteed(battlerAtk, battlerDef, move)) + ADJUST_SCORE(BEST_EFFECT); + // Non-volatile statuses switch(GetMoveNonVolatileStatus(move)) { @@ -4551,9 +4563,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; case EFFECT_FIRST_TURN_ONLY: - if (ShouldFakeOut(battlerAtk, battlerDef, move) && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100)) - ADJUST_SCORE(GOOD_EFFECT); - else if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + if (gDisableStructs[battlerAtk].isFirstTurn && GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_STOCKPILE: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a3598e6800..0f6fc16fb7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3502,18 +3502,57 @@ bool32 ShouldTrap(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; } -bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move) -{ - if ((!gDisableStructs[battlerAtk].isFirstTurn && MoveHasAdditionalEffectWithChance(move, MOVE_EFFECT_FLINCH, 100)) - || gAiLogicData->abilities[battlerAtk] == ABILITY_GORILLA_TACTICS - || gAiLogicData->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND - || gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK - || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - || (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) - && (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS))) +bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move) +{ + if (!MoveHasAdditionalEffect(move, MOVE_EFFECT_FLINCH)) return FALSE; - return TRUE; + if (AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) + return FALSE; + + u32 i; + u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + // check move additional effects that are likely to happen + for (i = 0; i < additionalEffectCount; i++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + // Only consider effects with a guaranteed chance to happen + if (!MoveEffectIsGuaranteed(battlerAtk, gAiLogicData->abilities[battlerAtk], additionalEffect)) + continue; + + if (additionalEffect->moveEffect == MOVE_EFFECT_FLINCH) + { + if (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) + || (!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) + && (gAiLogicData->abilities[battlerDef] == ABILITY_SHIELD_DUST || gAiLogicData->abilities[battlerDef] == ABILITY_INNER_FOCUS))) + return FALSE; + else + return TRUE; + } + } + return FALSE; +} + +bool32 HasChoiceEffect(u32 battler) +{ + u32 ability = gAiLogicData->abilities[battler]; + if (ability == ABILITY_GORILLA_TACTICS) + return TRUE; + + if (ability == ABILITY_KLUTZ) + return FALSE; + + enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; + switch (holdEffect) + { + case HOLD_EFFECT_CHOICE_BAND: + case HOLD_EFFECT_CHOICE_SCARF: + case HOLD_EFFECT_CHOICE_SPECS: + return TRUE; + default: + return FALSE; + } } static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x) diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 5589f7bb0e..e0eac1eeed 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -648,3 +648,16 @@ AI_DOUBLE_BATTLE_TEST("AI uses Power Split to improve its stats") } } +AI_DOUBLE_BATTLE_TEST("AI prefers to Fake Out the opponent vulnerable to flinching.") +{ + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); } + PLAYER(SPECIES_BRAIXEN) { Ability(ABILITY_BLAZE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_FAKE_OUT, MOVE_BRANCH_POKE, MOVE_ROCK_SMASH); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_FAKE_OUT, target:playerRight); } + } +} From 6158d21448f60a81c3be6475aaadfbf0dd9af85e Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 7 Aug 2025 11:27:35 -0400 Subject: [PATCH 183/283] Fix GetSwitchinHitsToKO one shot heal calcs (#7502) --- src/battle_ai_switch_items.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 3180550e59..1c436e81cf 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1807,13 +1807,13 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) u32 recurringDamage = GetSwitchinRecurringDamage(); u32 recurringHealing = GetSwitchinRecurringHealing(); u32 statusDamage = GetSwitchinStatusDamage(battler); - u32 hitsToKO = 0, singleUseItemHeal = 0; + u32 hitsToKO = 0; u16 maxHP = gAiLogicData->switchinCandidate.battleMon.maxHP, item = gAiLogicData->switchinCandidate.battleMon.item, heldItemEffect = GetItemHoldEffect(item); u8 weatherDuration = gWishFutureKnock.weatherDuration, holdEffectParam = GetItemHoldEffectParam(item); u32 opposingBattler = GetOppositeBattler(battler); u32 opposingAbility = gAiLogicData->abilities[opposingBattler], ability = gAiLogicData->switchinCandidate.battleMon.ability; bool32 usedSingleUseHealingItem = FALSE, opponentCanBreakMold = IsMoldBreakerTypeAbility(opposingBattler, opposingAbility); - s32 currentHP = startingHP; + s32 currentHP = startingHP, singleUseItemHeal = 0; // No damage being dealt if ((damageTaken + statusDamage + recurringDamage <= recurringHealing) || damageTaken + statusDamage + recurringDamage == 0) @@ -1838,11 +1838,11 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) currentHP = 1; // If mon is still alive, apply weather impact first, as it might KO the mon before it can heal with its item (order is weather -> item -> status) - if (currentHP != 0) + if (currentHP > 0) currentHP = currentHP - weatherImpact; // Check if we're at a single use healing item threshold - if (gAiLogicData->switchinCandidate.battleMon.ability != ABILITY_KLUTZ && usedSingleUseHealingItem == FALSE + if (currentHP > 0 && gAiLogicData->switchinCandidate.battleMon.ability != ABILITY_KLUTZ && usedSingleUseHealingItem == FALSE && !(opposingAbility == ABILITY_UNNERVE && GetItemPocket(item) == POCKET_BERRIES)) { switch (heldItemEffect) @@ -1885,7 +1885,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) } // Healing from items occurs before status so we can do the rest in one line - if (currentHP >= 0) + if (currentHP > 0) currentHP = currentHP + recurringHealing - recurringDamage - statusDamage; // Recalculate toxic damage if needed @@ -1900,7 +1900,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) } // Disguise will always add an extra hit to KO - if (opponentCanBreakMold && gAiLogicData->switchinCandidate.battleMon.species == SPECIES_MIMIKYU_DISGUISED) + if (!opponentCanBreakMold && gAiLogicData->switchinCandidate.battleMon.species == SPECIES_MIMIKYU_DISGUISED) hitsToKO++; // If mon had a hypothetical status from TSpikes, clear it From 521363ed8b6bf2cbbe0da364f92b95c5697fdd34 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 7 Aug 2025 13:43:07 -0400 Subject: [PATCH 184/283] Fixed compile issue `OW_TIMES_OF_DAY` is `GEN_3` (#7499) --- src/overworld.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overworld.c b/src/overworld.c index d827d46a2c..2cd7d42b4f 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -916,7 +916,7 @@ static void LoadMapFromWarp(bool32 a1) ClearTempFieldEventData(); ResetDexNavSearch(); // reset hours override on every warp - sHoursOverride = 0; + sHoursOverride = 0; ResetCyclingRoadChallengeData(); RestartWildEncounterImmunitySteps(); #if FREE_MATCH_CALL == FALSE @@ -1559,7 +1559,7 @@ const struct BlendSettings gTimeOfDayBlend[] = }; #define DEFAULT_WEIGHT 256 -#define TIME_BLEND_WEIGHT(begin, end) (DEFAULT_WEIGHT - (DEFAULT_WEIGHT * ((hours - begin) * MINUTES_PER_HOUR + minutes) / ((end - begin) * MINUTES_PER_HOUR))) +#define TIME_BLEND_WEIGHT(begin, end) (DEFAULT_WEIGHT - (DEFAULT_WEIGHT * SAFE_DIV(((hours - begin) * MINUTES_PER_HOUR + minutes), ((end - begin) * MINUTES_PER_HOUR)))) #define MORNING_HOUR_MIDDLE (MORNING_HOUR_BEGIN + ((MORNING_HOUR_END - MORNING_HOUR_BEGIN) / 2)) From bef3e990ef665e2845a5b958400a74a64a05ebb2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 7 Aug 2025 13:47:16 -0400 Subject: [PATCH 185/283] Fixes shadows and mon animations for transformed battlers (#7500) --- src/battle_gfx_sfx_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 9b272a51b4..6ca847a272 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -1272,8 +1272,8 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite) } else if (transformSpecies != SPECIES_NONE) { - xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset; - yOffset = gSpeciesInfo[transformSpecies].enemyShadowYOffset; + xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset + (shadowSprite->tSpriteSide == SPRITE_SIDE_LEFT ? -16 : 16); + yOffset = gSpeciesInfo[transformSpecies].enemyShadowYOffset + 16; size = gSpeciesInfo[transformSpecies].enemyShadowSize; invisible = (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE) From 729abca05887e35484a8575324abdb48c10b4f50 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Thu, 7 Aug 2025 13:53:01 -0400 Subject: [PATCH 186/283] Fix using town map as registered item (#7482) --- src/item_use.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/item_use.c b/src/item_use.c index 2c1f892197..3d2c828786 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1609,8 +1609,7 @@ void ItemUseOutOfBattle_TownMap(u8 taskId) } else { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); + gTasks[taskId].func = ItemUseOnFieldCB_TownMap; } } From bf68865e0d88aca9b781cbd8078b59a53c949120 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Thu, 7 Aug 2025 15:21:33 -0400 Subject: [PATCH 187/283] Implement using party menu items from field (#7481) --- include/party_menu.h | 4 +- src/item_use.c | 101 ++++++++++++++++++------------------------- src/party_menu.c | 6 +++ 3 files changed, 50 insertions(+), 61 deletions(-) diff --git a/include/party_menu.h b/include/party_menu.h index 7c4af8c3a4..80deab2a85 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -16,10 +16,12 @@ struct PartyMenu s8 slotId2; u8 action; u16 bagItem; - s16 data1; // used variously as a move, counter, moveSlotId, or cursorPos + s16 data1; // used variously as a move, counter, moveSlotId, cursorPos, or indicator that the menu is opened from the field s16 learnMoveState; // data2, used only as a learn move state }; +#define DATA1_PARTY_MENU_FROM_FIELD -1 + extern struct PartyMenu gPartyMenu; extern bool8 gPartyMenuUseExitCallback; extern u8 gSelectedMonPartyId; diff --git a/src/item_use.c b/src/item_use.c index 3d2c828786..0a8a5be06e 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -50,6 +50,7 @@ static void SetUpItemUseCallback(u8); static void FieldCB_UseItemOnField(void); static void Task_CallItemUseOnFieldCallback(u8); +static void Task_PartyMenuItemUseFromField(u8); static void Task_UseItemfinder(u8); static void Task_CloseItemfinderMessage(u8); static void Task_HiddenItemNearby(u8); @@ -128,15 +129,25 @@ static void SetUpItemUseCallback(u8 taskId) type = gTasks[taskId].tEnigmaBerryType - 1; else type = GetItemType(gSpecialVar_ItemId) - 1; - if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) + + if (gTasks[taskId].tUsingRegisteredKeyItem && type == (ITEM_USE_PARTY_MENU - 1)) { - gBagMenu->newScreenCallback = sItemUseCallbacks[type]; - Task_FadeAndCloseBagMenu(taskId); + FadeScreen(FADE_TO_BLACK, 0); + gPartyMenu.data1 = DATA1_PARTY_MENU_FROM_FIELD; + gTasks[taskId].func = Task_PartyMenuItemUseFromField; } else { - gPyramidBagMenu->newScreenCallback = sItemUseCallbacks[type]; - CloseBattlePyramidBag(taskId); + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) + { + gBagMenu->newScreenCallback = sItemUseCallbacks[type]; + Task_FadeAndCloseBagMenu(taskId); + } + else + { + gPyramidBagMenu->newScreenCallback = sItemUseCallbacks[type]; + CloseBattlePyramidBag(taskId); + } } } @@ -165,6 +176,16 @@ static void Task_CallItemUseOnFieldCallback(u8 taskId) sItemUseOnFieldCB(taskId); } +static void Task_PartyMenuItemUseFromField(u8 taskId) +{ + if (!gPaletteFade.active) + { + CleanupOverworldWindowsAndTilemaps(); + SetMainCallback2(CB2_ShowPartyMenuForItemUse); + DestroyTask(taskId); + } +} + static void DisplayCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyItemOnField, const u8 *str) { StringExpandPlaceholders(gStringVar4, str); @@ -1380,77 +1401,37 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) void ItemUseOutOfBattle_FormChange(u8 taskId) { - if (!gTasks[taskId].tUsingRegisteredKeyItem) - { - gItemUseCB = ItemUseCB_FormChange; - gTasks[taskId].data[0] = FALSE; - SetUpItemUseOnFieldCallback(taskId); - } - else - { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } + gItemUseCB = ItemUseCB_FormChange; + gTasks[taskId].data[0] = FALSE; + SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8 taskId) { - if (!gTasks[taskId].tUsingRegisteredKeyItem) - { - gItemUseCB = ItemUseCB_FormChange_ConsumedOnUse; - gTasks[taskId].data[0] = TRUE; - SetUpItemUseOnFieldCallback(taskId); - } - else - { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } + gItemUseCB = ItemUseCB_FormChange_ConsumedOnUse; + gTasks[taskId].data[0] = TRUE; + SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_RotomCatalog(u8 taskId) { - if (!gTasks[taskId].tUsingRegisteredKeyItem) - { - gItemUseCB = ItemUseCB_RotomCatalog; - gTasks[taskId].data[0] = TRUE; - SetUpItemUseOnFieldCallback(taskId); - } - else - { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } + gItemUseCB = ItemUseCB_RotomCatalog; + gTasks[taskId].data[0] = TRUE; + SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_ZygardeCube(u8 taskId) { - if (!gTasks[taskId].tUsingRegisteredKeyItem) - { - gItemUseCB = ItemUseCB_ZygardeCube; - gTasks[taskId].data[0] = TRUE; - SetUpItemUseOnFieldCallback(taskId); - } - else - { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } + gItemUseCB = ItemUseCB_ZygardeCube; + gTasks[taskId].data[0] = TRUE; + SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_Fusion(u8 taskId) { - if (!gTasks[taskId].tUsingRegisteredKeyItem) - { - gItemUseCB = ItemUseCB_Fusion; - gTasks[taskId].data[0] = FALSE; - SetUpItemUseCallback(taskId); - } - else - { - // TODO: handle key items with callbacks to menus allow to be used by registering them. - DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem); - } + gItemUseCB = ItemUseCB_Fusion; + gTasks[taskId].data[0] = FALSE; + SetUpItemUseCallback(taskId); } void Task_UseHoneyOnField(u8 taskId) diff --git a/src/party_menu.c b/src/party_menu.c index 146a06cb69..419909407a 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4559,6 +4559,12 @@ void CB2_ShowPartyMenuForItemUse(void) u8 msgId; TaskFunc task; + if (gPartyMenu.data1 == DATA1_PARTY_MENU_FROM_FIELD) + { + callback = CB2_ReturnToField; + gPartyMenu.data1 = 0; + } + if (gMain.inBattle) { menuType = PARTY_MENU_TYPE_IN_BATTLE; From 27539239dbcf152ae473a8654a3fe3ec4f66c539 Mon Sep 17 00:00:00 2001 From: Hedara Date: Sat, 2 Aug 2025 16:25:11 +0200 Subject: [PATCH 188/283] Clear out parties between battle tests --- test/test_runner_battle.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 20271a588d..bfbf4c899d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1341,6 +1341,18 @@ void TestRunner_Battle_AfterLastTurn(void) static void TearDownBattle(void) { + // Zero out the parties, data in them could potentially carry over + for (u32 i = 0; i < 6; i++) + { + u32 *playerPtr = (u32 *)(&gPlayerParty[i]); + u32 *opponentPtr = (u32 *)(&gEnemyParty[i]); + for (u32 j = 0; j < sizeof(struct Pokemon)/4; j++) + { + playerPtr[j] = 0; + opponentPtr[j] = 0; + } + } + FreeMonSpritesGfx(); FreeBattleSpritesData(); FreeBattleResources(); From b553278a3d79ccab0e1b46bba695e9be91c1e1ac Mon Sep 17 00:00:00 2001 From: Hedara Date: Sat, 2 Aug 2025 16:33:42 +0200 Subject: [PATCH 189/283] Replaced manual zeroing with existing function calls --- test/test_runner_battle.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index bfbf4c899d..0e78d44ee4 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1344,13 +1344,8 @@ static void TearDownBattle(void) // Zero out the parties, data in them could potentially carry over for (u32 i = 0; i < 6; i++) { - u32 *playerPtr = (u32 *)(&gPlayerParty[i]); - u32 *opponentPtr = (u32 *)(&gEnemyParty[i]); - for (u32 j = 0; j < sizeof(struct Pokemon)/4; j++) - { - playerPtr[j] = 0; - opponentPtr[j] = 0; - } + ZeroPlayerPartyMons(); + ZeroEnemyPartyMons(); } FreeMonSpritesGfx(); From 8d8cf1b5d489efeb922a9672d25a8d633383744e Mon Sep 17 00:00:00 2001 From: Hedara Date: Sat, 2 Aug 2025 16:34:36 +0200 Subject: [PATCH 190/283] Removed now unnecessary loop --- test/test_runner_battle.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 0e78d44ee4..ea26432137 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1342,11 +1342,8 @@ void TestRunner_Battle_AfterLastTurn(void) static void TearDownBattle(void) { // Zero out the parties, data in them could potentially carry over - for (u32 i = 0; i < 6; i++) - { - ZeroPlayerPartyMons(); - ZeroEnemyPartyMons(); - } + ZeroPlayerPartyMons(); + ZeroEnemyPartyMons(); FreeMonSpritesGfx(); FreeBattleSpritesData(); From 0b299b3ffd91ce2b7934c95406405a1368dd9c1c Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 8 Aug 2025 03:44:12 -0400 Subject: [PATCH 191/283] Fixed most failed tests with `GEN_LATEST GEN_8` (#7498) --- include/constants/generational_changes.h | 8 +++++ include/generational_changes.h | 8 +++++ src/battle_ai_switch_items.c | 2 +- src/battle_ai_util.c | 4 +-- src/battle_script_commands.c | 16 +++++----- src/battle_util.c | 12 ++++---- test/battle/ability/dauntless_shield.c | 29 +++++++++++++++---- test/battle/ability/intrepid_sword.c | 28 ++++++++++++++---- test/battle/ability/keen_eye.c | 7 ++++- test/battle/ability/pickup.c | 4 +-- test/battle/ability/protean.c | 28 ++++++++++++++++-- test/battle/ability/refrigerate.c | 1 + test/battle/ability/snow_warning.c | 22 +++++++++----- test/battle/ai/ai_switching.c | 1 + test/battle/move_effect/ally_switch.c | 21 ++++++++++++-- test/battle/move_effect/chloroblast.c | 7 ++++- .../battle/move_effect_secondary/steal_item.c | 4 +-- 17 files changed, 154 insertions(+), 48 deletions(-) diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 060d4167ef..a1e0a43074 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -17,6 +17,14 @@ enum GenConfigTag GEN_CONFIG_BATTLE_BOND, GEN_CONFIG_ATE_MULTIPLIER, GEN_CONFIG_FELL_STINGER_STAT_RAISE, + GEN_PICKUP_WILD, + GEN_PROTEAN_LIBERO, + GEN_INTREPID_SWORD, + GEN_DAUNTLESS_SHIELD, + GEN_ILLUMINATE_EFFECT, + GEN_STEAL_WILD_ITEMS, + GEN_SNOW_WARNING, + GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index 2a97728d0d..87f8586cff 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -20,6 +20,14 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND, [GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE, [GEN_CONFIG_ATE_MULTIPLIER] = B_ATE_MULTIPLIER, + [GEN_PICKUP_WILD] = B_PICKUP_WILD, + [GEN_PROTEAN_LIBERO] = B_PROTEAN_LIBERO, + [GEN_INTREPID_SWORD] = B_INTREPID_SWORD, + [GEN_DAUNTLESS_SHIELD] = B_DAUNTLESS_SHIELD, + [GEN_ILLUMINATE_EFFECT] = B_ILLUMINATE_EFFECT, + [GEN_STEAL_WILD_ITEMS] = B_STEAL_WILD_ITEMS, + [GEN_SNOW_WARNING] = B_SNOW_WARNING, + [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, }; #if TESTING diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index c044ff2804..aa7d819a1e 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -691,7 +691,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && gAiLogicData->abilities[opposingBattler] != ABILITY_UNAWARE && gAiLogicData->abilities[opposingBattler] != ABILITY_KEEN_EYE && gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE - && (B_ILLUMINATE_EFFECT >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) + && (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) && !(gBattleMons[battler].status2 & STATUS2_FORESIGHT) && !(gStatuses3[battler] & STATUS3_MIRACLE_EYED)) switchMon = FALSE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 7b5e8e0d37..667c6199a4 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1945,7 +1945,7 @@ bool32 ShouldLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat) if (stat == STAT_DEF) return FALSE; case ABILITY_ILLUMINATE: - if (B_ILLUMINATE_EFFECT < GEN_9) + if (GetGenConfig(GEN_ILLUMINATE_EFFECT) < GEN_9) break; case ABILITY_KEEN_EYE: case ABILITY_MINDS_EYE: @@ -2128,7 +2128,7 @@ bool32 ShouldLowerAccuracy(u32 battlerAtk, u32 battlerDef, u32 defAbility) && defAbility != ABILITY_FULL_METAL_BODY && defAbility != ABILITY_KEEN_EYE && defAbility != ABILITY_MINDS_EYE - && (B_ILLUMINATE_EFFECT >= GEN_9 && defAbility != ABILITY_ILLUMINATE) + && (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && defAbility != ABILITY_ILLUMINATE) && gAiLogicData->holdEffects[battlerDef] != HOLD_EFFECT_CLEAR_AMULET) return TRUE; return FALSE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d749d450d7..0f3fbdba61 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1584,7 +1584,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE || atkAbility == ABILITY_MINDS_EYE - || (B_ILLUMINATE_EFFECT >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) + || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && atkAbility == ABILITY_ILLUMINATE)) evasionStage = DEFAULT_STAT_STAGE; if (MoveIgnoresDefenseEvasionStages(move)) evasionStage = DEFAULT_STAT_STAGE; @@ -3137,7 +3137,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) gLastUsedItem = gBattleMons[battlerItem].item; gBattleMons[battlerItem].item = ITEM_NONE; - if (B_STEAL_WILD_ITEMS >= GEN_9 + if (GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)) && GetMoveEffect(gCurrentMove) == EFFECT_STEAL_ITEM && battlerStealer == gBattlerAttacker) // ensure that Pickpocket isn't activating this @@ -5971,7 +5971,7 @@ static void Cmd_playstatchangeanimation(void) && ability != ABILITY_FULL_METAL_BODY && ability != ABILITY_WHITE_SMOKE && !((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC) - && !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) + && !(GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC) && !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK) && !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF)) { @@ -6303,7 +6303,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) { StealTargetItem(gBattlerAttacker, gBattlerTarget); // Attacker steals target item - if (!(B_STEAL_WILD_ITEMS >= GEN_9 + if (!(GetGenConfig(GEN_STEAL_WILD_ITEMS) >= GEN_9 && !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE)))) { gBattleMons[gBattlerAttacker].item = ITEM_NONE; // Item assigned later on with thief (see MOVEEND_CHANGED_ITEMS) @@ -11715,8 +11715,8 @@ static void TryResetProtectUseCounter(u32 battler) enum BattleMoveEffects lastEffect = GetMoveEffect(lastMove); if (lastMove == MOVE_UNAVAILABLE || (!gBattleMoveEffects[lastEffect].usesProtectCounter - && ((B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) - || B_ALLY_SWITCH_FAIL_CHANCE < GEN_9))) + && ((GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9 && lastEffect != EFFECT_ALLY_SWITCH) + || GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) < GEN_9))) gDisableStructs[battler].protectUses = 0; } @@ -12418,7 +12418,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr } else if (!certain && (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC) - || (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) + || (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC) || (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK) || (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF))) { @@ -17759,7 +17759,7 @@ void BS_TryAllySwitch(void) { gBattlescriptCurrInstr = cmd->failInstr; } - else if (B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9) + else if (GetGenConfig(GEN_ALLY_SWITCH_FAIL_CHANCE) >= GEN_9) { TryResetProtectUseCounter(gBattlerAttacker); if (sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] < Random()) diff --git a/src/battle_util.c b/src/battle_util.c index fb28a6129c..31c5229d0f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2311,7 +2311,7 @@ static void CancellerProtean(u32 *effect) u32 moveType = GetBattleMoveType(gCurrentMove); if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType)) { - if (B_PROTEAN_LIBERO == GEN_9) + if (GetGenConfig(GEN_PROTEAN_LIBERO) >= GEN_9) gDisableStructs[gBattlerAttacker].usedProteanLibero = TRUE; PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); gBattlerAbility = gBattlerAttacker; @@ -3785,12 +3785,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SNOW_WARNING: - if (B_SNOW_WARNING >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, TRUE)) + if (GetGenConfig(GEN_SNOW_WARNING) >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow); effect++; } - else if (B_SNOW_WARNING < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, TRUE)) + else if (GetGenConfig(GEN_SNOW_WARNING) < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail); effect++; @@ -3890,7 +3890,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; - if (B_INTREPID_SWORD == GEN_9) + if (GetGenConfig(GEN_INTREPID_SWORD) >= GEN_9) gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].intrepidSwordBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_ATK, 1, FALSE); @@ -3904,7 +3904,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { gBattleScripting.savedBattler = gBattlerAttacker; gBattlerAttacker = battler; - if (B_DAUNTLESS_SHIELD == GEN_9) + if (GetGenConfig(GEN_DAUNTLESS_SHIELD) >= GEN_9) gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].dauntlessShieldBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; SET_STATCHANGER(STAT_DEF, 1, FALSE); @@ -10889,7 +10889,7 @@ u16 GetUsedHeldItem(u32 battler) bool32 CantPickupItem(u32 battler) { // Used by RandomUniformExcept() for RNG_PICKUP - if (battler == gBattlerAttacker && (B_PICKUP_WILD < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) + if (battler == gBattlerAttacker && (GetGenConfig(GEN_PICKUP_WILD) < GEN_9 || gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_LINK))) return TRUE; return !(IsBattlerAlive(battler) && GetUsedHeldItem(battler) && gBattleStruct->battlerState[battler].canPickupItem); } diff --git a/test/battle/ability/dauntless_shield.c b/test/battle/ability/dauntless_shield.c index ada4ace786..6fed2f0b5c 100644 --- a/test/battle/ability/dauntless_shield.c +++ b/test/battle/ability/dauntless_shield.c @@ -1,30 +1,48 @@ #include "global.h" #include "test/battle.h" -ASSUMPTIONS +SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage") { - ASSUME(B_DAUNTLESS_SHIELD == GEN_9); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_DAUNTLESS_SHIELD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Zamazenta's Dauntless Shield raised its Defense!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } } -SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage") +SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage every time it switches in (Gen8)") { GIVEN { + WITH_CONFIG(GEN_DAUNTLESS_SHIELD, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } + OPPONENT(SPECIES_WYNAUT); } WHEN { - TURN { } + TURN { SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } } SCENE { ABILITY_POPUP(opponent, ABILITY_DAUNTLESS_SHIELD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("The opposing Zamazenta's Dauntless Shield raised its Defense!"); + ABILITY_POPUP(opponent, ABILITY_DAUNTLESS_SHIELD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Zamazenta's Dauntless Shield raised its Defense!"); } THEN { EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); } } -SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage only once per battle") +SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage only once per battle (Gen 9+)") { GIVEN { + WITH_CONFIG(GEN_DAUNTLESS_SHIELD, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZAMAZENTA) { Ability(ABILITY_DAUNTLESS_SHIELD); } OPPONENT(SPECIES_WYNAUT); @@ -63,4 +81,3 @@ SINGLE_BATTLE_TEST("Dauntless Shield activates when it's no longer effected by N MESSAGE("The opposing Zamazenta's Dauntless Shield raised its Defense!"); } } - diff --git a/test/battle/ability/intrepid_sword.c b/test/battle/ability/intrepid_sword.c index 58fd9883eb..a260e78d0d 100644 --- a/test/battle/ability/intrepid_sword.c +++ b/test/battle/ability/intrepid_sword.c @@ -1,30 +1,48 @@ #include "global.h" #include "test/battle.h" -ASSUMPTIONS +SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage") { - ASSUME(B_INTREPID_SWORD == GEN_9); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Zacian's Intrepid Sword raised its Attack!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } } -SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage") +SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage every time it switches in (Gen8)") { GIVEN { + WITH_CONFIG(GEN_INTREPID_SWORD, GEN_8); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } + OPPONENT(SPECIES_WYNAUT); } WHEN { - TURN { } + TURN { SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } } SCENE { ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); MESSAGE("The opposing Zacian's Intrepid Sword raised its Attack!"); + ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Zacian's Intrepid Sword raised its Attack!"); } THEN { EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); } } -SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage only once per battle") +SINGLE_BATTLE_TEST("Intrepid Sword raises Attack by one stage only once per battle (Gen9+)") { GIVEN { + WITH_CONFIG(GEN_INTREPID_SWORD, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); } OPPONENT(SPECIES_WYNAUT); diff --git a/test/battle/ability/keen_eye.c b/test/battle/ability/keen_eye.c index 6874e5a6bf..ee10c446fb 100644 --- a/test/battle/ability/keen_eye.c +++ b/test/battle/ability/keen_eye.c @@ -5,7 +5,6 @@ ASSUMPTIONS { ASSUME(GetMoveAccuracy(MOVE_SCRATCH) == 100); ASSUME(GetMoveEffect(MOVE_SAND_ATTACK) == EFFECT_ACCURACY_DOWN); - ASSUME(B_ILLUMINATE_EFFECT >= GEN_9); } SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stage reduction from moves") @@ -19,6 +18,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye prevent accuracy stag PASSES_RANDOMLY(100, 100, RNG_ACCURACY); GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) { Ability(ability); } } WHEN { @@ -47,6 +47,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye ignore target's evasi PASSES_RANDOMLY(100, 100, RNG_ACCURACY); GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_DOUBLE_TEAM) == EFFECT_EVASION_UP); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) { Ability(ability); } @@ -80,6 +81,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye are ignored by Mold B PASSES_RANDOMLY(GetMoveAccuracy(MOVE_SCRATCH) * 3 / 4, 100, RNG_ACCURACY); GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); PLAYER(speciesPlayer) { Ability(abilityPlayer); } OPPONENT(speciesOpponent) { Ability(abilityOpponent); } } WHEN { @@ -102,6 +104,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent Topsy-T PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; } GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP); ASSUME(GetMoveEffect(MOVE_TOPSY_TURVY) == EFFECT_TOPSY_TURVY); PLAYER(SPECIES_WOBBUFFET); @@ -141,6 +144,7 @@ SINGLE_BATTLE_TEST("Keen Eye, Gen9+ Illuminate & Minds Eye don't prevent receivi PARAMETRIZE { species = SPECIES_URSALUNA_BLOODMOON; ability = ABILITY_MINDS_EYE; } GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -173,6 +177,7 @@ SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief fro PARAMETRIZE { species = SPECIES_STARYU; ability = ABILITY_ILLUMINATE; } GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); ASSUME(GetMoveEffect(MOVE_HONE_CLAWS) == EFFECT_ATTACK_ACCURACY_UP); ASSUME(GetMoveEffect(MOVE_SPECTRAL_THIEF) == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/pickup.c b/test/battle/ability/pickup.c index 9db7c0f2de..cc9ae37e9d 100644 --- a/test/battle/ability/pickup.c +++ b/test/battle/ability/pickup.c @@ -23,10 +23,10 @@ SINGLE_BATTLE_TEST("Pickup grants an item used by another Pokémon") } } -WILD_BATTLE_TEST("Pickup grants an item used by itself in wild battles (Gen 9)") +WILD_BATTLE_TEST("Pickup grants an item used by itself in wild battles (Gen9+)") { GIVEN { - ASSUME(B_PICKUP_WILD >= GEN_9); + WITH_CONFIG(GEN_PICKUP_WILD, GEN_9); PLAYER(SPECIES_ZIGZAGOON) { Ability(ABILITY_PICKUP); MaxHP(100); HP(51); Item(ITEM_SITRUS_BERRY); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ability/protean.c b/test/battle/ability/protean.c index 88144670a1..c5d141d244 100644 --- a/test/battle/ability/protean.c +++ b/test/battle/ability/protean.c @@ -1,14 +1,36 @@ #include "global.h" #include "test/battle.h" -ASSUMPTIONS +SINGLE_BATTLE_TEST("Protean changes the type of the user to the move used every time (Gen6-8)") { - ASSUME(B_PROTEAN_LIBERO == GEN_9); + GIVEN { + WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_6); + PLAYER(SPECIES_REGIROCK); + OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + TURN { MOVE(opponent, MOVE_SCRATCH); } + TURN { SWITCH(opponent, 1); } + 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!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + ABILITY_POPUP(opponent, ABILITY_PROTEAN); + MESSAGE("The opposing Kecleon 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!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + } } -SINGLE_BATTLE_TEST("Protean changes the type of the user only once per switch in") +SINGLE_BATTLE_TEST("Protean changes the type of the user only once per switch in (Gen9+)") { GIVEN { + WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_9); PLAYER(SPECIES_REGIROCK); OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/refrigerate.c b/test/battle/ability/refrigerate.c index 5f5092f93f..7b3af0277c 100644 --- a/test/battle/ability/refrigerate.c +++ b/test/battle/ability/refrigerate.c @@ -52,6 +52,7 @@ SINGLE_BATTLE_TEST("Refrigerate doesn't affect Weather Ball's type", s16 damage) PARAMETRIZE { move = MOVE_CELEBRATE; ability = ABILITY_REFRIGERATE; } PARAMETRIZE { move = MOVE_SUNNY_DAY; ability = ABILITY_REFRIGERATE; } GIVEN { + WITH_CONFIG(GEN_SNOW_WARNING, GEN_9); //To prevent capturing hail damage ASSUME(GetMoveEffect(MOVE_WEATHER_BALL) == EFFECT_WEATHER_BALL); ASSUME(gSpeciesInfo[SPECIES_PINSIR].types[0] == TYPE_BUG); PLAYER(SPECIES_AMAURA) { Ability(ability); } diff --git a/test/battle/ability/snow_warning.c b/test/battle/ability/snow_warning.c index 17f18814b8..171ad23b49 100644 --- a/test/battle/ability/snow_warning.c +++ b/test/battle/ability/snow_warning.c @@ -1,24 +1,30 @@ #include "global.h" #include "test/battle.h" -#if B_SNOW_WARNING < GEN_9 -SINGLE_BATTLE_TEST("Snow Warning summons hail") -#elif B_SNOW_WARNING >= GEN_9 -SINGLE_BATTLE_TEST("Snow Warning summons snow") -#endif +SINGLE_BATTLE_TEST("Snow Warning summons hail (Gen4-8)") { GIVEN { + WITH_CONFIG(GEN_SNOW_WARNING, GEN_8); PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN {} } SCENE { - #if B_SNOW_WARNING < GEN_9 MESSAGE("It started to hail!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HAIL_CONTINUES); - #elif B_SNOW_WARNING >= GEN_9 + } +} + +SINGLE_BATTLE_TEST("Snow Warning summons snow (Gen9+)") +{ + GIVEN { + WITH_CONFIG(GEN_SNOW_WARNING, GEN_9); + PLAYER(SPECIES_ABOMASNOW) { Ability(ABILITY_SNOW_WARNING); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {} + } SCENE { MESSAGE("It started to snow!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SNOW_CONTINUES); - #endif } } diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 03334e04c2..75ff02cb88 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -842,6 +842,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an PARAMETRIZE { aiMon = SPECIES_SHIFTRY; absorbingAbility = ABILITY_WIND_RIDER; move = MOVE_HURRICANE;} GIVEN { ASSUME(B_REDIRECT_ABILITY_IMMUNITY >= GEN_5); + ASSUME(P_UPDATED_ABILITIES >= GEN_9); //For the predicted ability for Shiftry AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING); PLAYER(SPECIES_ZIGZAGOON) { Moves(move); } OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index a8e9944e34..59844879d4 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -185,10 +185,25 @@ DOUBLE_BATTLE_TEST("Ally Switch doesn't make self-targeting status moves fail") } } -DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter") +DOUBLE_BATTLE_TEST("Ally Switch doesn't increase the Protect-like moves counter (Gen5-8)") { GIVEN { - ASSUME(B_ALLY_SWITCH_FAIL_CHANCE >= GEN_9); + WITH_CONFIG(GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_8); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); } + } THEN { + EXPECT(gDisableStructs[B_POSITION_PLAYER_RIGHT].protectUses == 0); + } +} + +DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter (Gen9+)") +{ + GIVEN { + WITH_CONFIG(GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_9); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -319,7 +334,7 @@ DOUBLE_BATTLE_TEST("Ally switch updates last used moves for Mimic") OPPONENT(SPECIES_FEAROW) { Speed(20); } OPPONENT(SPECIES_ARON) { Speed(30); } } WHEN { - TURN { MOVE(playerRight, MOVE_FAKE_OUT, target: opponentRight); MOVE(playerLeft, MOVE_ALLY_SWITCH); + TURN { MOVE(playerRight, MOVE_FAKE_OUT, target: opponentRight); MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(opponentLeft, MOVE_MIMIC, target: playerLeft); } } SCENE { diff --git a/test/battle/move_effect/chloroblast.c b/test/battle/move_effect/chloroblast.c index 6452736478..d60449324f 100644 --- a/test/battle/move_effect/chloroblast.c +++ b/test/battle/move_effect/chloroblast.c @@ -137,9 +137,14 @@ SINGLE_BATTLE_TEST("Chloroblast is not affected by Reckless", s16 damage) u32 move; PARAMETRIZE { move = MOVE_CHLOROBLAST; } - PARAMETRIZE { move = MOVE_FRENZY_PLANT; } + if (B_UPDATED_MOVE_DATA >= GEN_9) { + PARAMETRIZE { move = MOVE_FRENZY_PLANT; } // 150 power + } else { + PARAMETRIZE { move = MOVE_SEED_FLARE; } // 120 power + } GIVEN { + ASSUME(GetMovePower(MOVE_CHLOROBLAST) == GetMovePower(move)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect_secondary/steal_item.c b/test/battle/move_effect_secondary/steal_item.c index 7dd922e8b2..79c293757f 100644 --- a/test/battle/move_effect_secondary/steal_item.c +++ b/test/battle/move_effect_secondary/steal_item.c @@ -107,13 +107,13 @@ SINGLE_BATTLE_TEST("Thief and Covet don't steal target's held item if target has } // Test can't currently verify if the item is sent to Bag -WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag in wild battles (Gen 9)") +WILD_BATTLE_TEST("Thief and Covet steal target's held item and it's added to Bag in wild battles (Gen 9+)") { u32 move; PARAMETRIZE { move = MOVE_THIEF; } PARAMETRIZE { move = MOVE_COVET; } GIVEN { - ASSUME(B_STEAL_WILD_ITEMS >= GEN_9); + WITH_CONFIG(GEN_STEAL_WILD_ITEMS, GEN_9); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_HYPER_POTION); } } WHEN { From 6cb18f2048480522d75c657cee36220b976cf185 Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 8 Aug 2025 03:53:13 -0400 Subject: [PATCH 192/283] Fiddling with CanLowerStat. (#7510) --- include/battle_ai_util.h | 2 +- src/battle_ai_main.c | 30 ++++++++--------- src/battle_ai_util.c | 70 +++++++++++++++++++++++----------------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 52b5764b00..b6b16524af 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -144,7 +144,7 @@ bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move); // stat stage checks bool32 AnyStatIsRaised(u32 battlerId); -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat); +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat); bool32 BattlerStatCanRise(u32 battler, u32 battlerAbility, u32 stat); bool32 AreBattlersStatsMaxed(u32 battler); u32 CountPositiveStatStages(u32 battlerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2fbe68f0ee..4b7f8bddd9 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1585,40 +1585,40 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // stat lowering effects case EFFECT_ATTACK_DOWN: case EFFECT_ATTACK_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); break; case EFFECT_DEFENSE_DOWN: case EFFECT_DEFENSE_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_DEF)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_DEF)) ADJUST_SCORE(-10); break; case EFFECT_SPEED_DOWN: case EFFECT_SPEED_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-10); break; case EFFECT_SPECIAL_ATTACK_DOWN: case EFFECT_SPECIAL_ATTACK_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-10); break; case EFFECT_SPECIAL_DEFENSE_DOWN: case EFFECT_SPECIAL_DEFENSE_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPDEF)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPDEF)) ADJUST_SCORE(-10); break; case EFFECT_ACCURACY_DOWN: case EFFECT_ACCURACY_DOWN_2: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ACC)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ACC)) ADJUST_SCORE(-10); break; case EFFECT_EVASION_DOWN: case EFFECT_EVASION_DOWN_2: case EFFECT_TICKLE: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_DEF)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_DEF)) ADJUST_SCORE(-8); break; case EFFECT_VENOM_DRENCH: @@ -1628,18 +1628,18 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-8); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-6); } break; case EFFECT_NOBLE_ROAR: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPATK)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPATK)) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-8); break; case EFFECT_CAPTIVATE: @@ -1703,7 +1703,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_TOXIC_THREAD: - if (!CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_SPEED)) + if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED)) ADJUST_SCORE(-1); // may still want to just poison //fallthrough case EFFECT_LIGHT_SCREEN: @@ -2112,7 +2112,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_STRENGTH_SAP: if (aiData->abilities[battlerDef] == ABILITY_CONTRARY) ADJUST_SCORE(-10); - else if (!CanLowerStat(battlerAtk, battlerDef, aiData->abilities[battlerDef], STAT_ATK)) + else if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_ATK)) ADJUST_SCORE(-10); break; case EFFECT_COPYCAT: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 0f6fc16fb7..229a9a8c68 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1079,7 +1079,7 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 case MOVE_EFFECT_SP_DEF_MINUS_1: case MOVE_EFFECT_ACC_MINUS_1: case MOVE_EFFECT_EVS_MINUS_1: - if (CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1) + if (CanLowerStat(battlerAtk, battlerDef, gAiLogicData, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1) return TRUE; break; case MOVE_EFFECT_ATK_MINUS_2: @@ -1089,7 +1089,7 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 case MOVE_EFFECT_SP_DEF_MINUS_2: case MOVE_EFFECT_ACC_MINUS_2: case MOVE_EFFECT_EVS_MINUS_2: - if (CanLowerStat(battlerAtk, battlerDef, abilityDef, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1) + if (CanLowerStat(battlerAtk, battlerDef, gAiLogicData, STAT_ATK + (additionalEffect->moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1) return TRUE; break; default: @@ -1967,49 +1967,59 @@ s32 ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove) } // stat stages -bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 stat) +bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, u32 stat) { if (gBattleMons[battlerDef].statStages[stat] == MIN_STAT_STAGE) return FALSE; - if (gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_CLEAR_AMULET) + if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_CLEAR_AMULET) return FALSE; - switch (abilityDef) + u32 move = gAiThinkingStruct->moveConsidered; + u32 abilityAtk = aiData->abilities[battlerAtk]; + + if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MIST && abilityAtk != ABILITY_INFILTRATOR) + return FALSE; + + if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, abilityAtk, move)) { - case ABILITY_SPEED_BOOST: - if (stat == STAT_SPEED) - return FALSE; - case ABILITY_HYPER_CUTTER: - if (stat == STAT_ATK) + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) && AI_IsAbilityOnSide(battlerDef, ABILITY_FLOWER_VEIL)) return FALSE; - case ABILITY_BIG_PECKS: - if (stat == STAT_DEF) + + switch (aiData->abilities[battlerDef]) + { + case ABILITY_SPEED_BOOST: + if (stat == STAT_SPEED) + return FALSE; + case ABILITY_HYPER_CUTTER: + if (stat == STAT_ATK) + return FALSE; + case ABILITY_BIG_PECKS: + if (stat == STAT_DEF) + return FALSE; + case ABILITY_ILLUMINATE: + if (B_ILLUMINATE_EFFECT < GEN_9) + break; + case ABILITY_KEEN_EYE: + case ABILITY_MINDS_EYE: + if (stat == STAT_ACC) + return FALSE; + case ABILITY_CONTRARY: + case ABILITY_CLEAR_BODY: + case ABILITY_WHITE_SMOKE: + case ABILITY_FULL_METAL_BODY: return FALSE; - case ABILITY_ILLUMINATE: - if (B_ILLUMINATE_EFFECT < GEN_9) + default: break; - case ABILITY_KEEN_EYE: - case ABILITY_MINDS_EYE: - if (stat == STAT_ACC) - return FALSE; - case ABILITY_FLOWER_VEIL: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)) - return FALSE; - break; - case ABILITY_CONTRARY: - case ABILITY_CLEAR_BODY: - case ABILITY_WHITE_SMOKE: - case ABILITY_FULL_METAL_BODY: - return FALSE; + } } if (stat == STAT_SPEED) { // If AI is faster and doesn't have any mons left, lowering speed doesn't give any - return !(AI_IsFaster(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY) + return !(AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY) && CountUsablePartyMons(battlerAtk) == 0 - && !HasMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); + && !HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); } return TRUE; @@ -2027,7 +2037,7 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) if (GetBattlerSecondaryDamage(battlerDef) >= gBattleMons[battlerDef].hp) return NO_INCREASE; - // Don't decrese stat if opposing battler has Encore + // Don't decrease stat if opposing battler has Encore if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) return NO_INCREASE; From 070a4f1dfada102c2389cd02bf5d170672ee9be3 Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 8 Aug 2025 03:54:30 -0400 Subject: [PATCH 193/283] Improved hazards logic and Mycelium Might ignores ability checks (#7509) --- include/battle_ai_util.h | 2 +- src/battle_ai_main.c | 18 +++++------------ src/battle_ai_util.c | 43 ++++++++++++++++++++++++++++++---------- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b6b16524af..62cba4949e 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -289,7 +289,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 aiMoveConsidered, u32 playerMoveConsidered, enum ConsiderPriority ConsiderPriority); s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle); bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef); -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData); +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData); void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData); u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 4b7f8bddd9..528bcbd859 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4416,11 +4416,13 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(GOOD_EFFECT); } break; + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)) { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -5319,16 +5321,6 @@ case EFFECT_GUARD_SPLIT: break; } break; - case EFFECT_STONE_AXE: - case EFFECT_CEASELESS_EDGE: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); - { - if (gDisableStructs[battlerAtk].isFirstTurn) - ADJUST_SCORE(BEST_EFFECT); - else - ADJUST_SCORE(DECENT_EFFECT); - } - break; default: break; } // move effect checks @@ -5473,7 +5465,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case MOVE_EFFECT_STEALTH_ROCK: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData)); + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, aiData)); { if (gDisableStructs[battlerAtk].isFirstTurn) ADJUST_SCORE(BEST_EFFECT); @@ -6062,7 +6054,7 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score case EFFECT_STEALTH_ROCK: case EFFECT_STICKY_WEB: case EFFECT_TOXIC_SPIKES: - if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, gAiLogicData)) + if (AI_ShouldSetUpHazards(battlerAtk, battlerDef, move, gAiLogicData)) ADJUST_SCORE(POWERFUL_STATUS_MOVE); break; case EFFECT_GRASSY_TERRAIN: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 229a9a8c68..8e6f0d79a2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1639,6 +1639,9 @@ bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move) if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_NEGATE_UNAWARE) return FALSE; // AI handicap flag: doesn't understand ability suppression concept + if (atkAbility == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(move)) + return TRUE; + if (IsMoldBreakerTypeAbility(battlerAtk, atkAbility) || MoveIgnoresTargetAbility(move)) return TRUE; @@ -1750,10 +1753,12 @@ bool32 IsHazardMove(u32 move) u32 i, moveEffect = GetMoveEffect(move); switch (moveEffect) { + case EFFECT_CEASELESS_EDGE: case EFFECT_SPIKES: - case EFFECT_TOXIC_SPIKES: - case EFFECT_STICKY_WEB: case EFFECT_STEALTH_ROCK: + case EFFECT_STICKY_WEB: + case EFFECT_STONE_AXE: + case EFFECT_TOXIC_SPIKES: return TRUE; } @@ -1763,6 +1768,7 @@ bool32 IsHazardMove(u32 move) const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); switch (additionalEffect->moveEffect) { + case MOVE_EFFECT_STEALTH_ROCK: case MOVE_EFFECT_STEELSURGE: return TRUE; default: @@ -4967,17 +4973,32 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) } //TODO - track entire opponent party data to determine hazard effectiveness -bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData) -{ - if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE - || CountUsablePartyMons(battlerDef) == 0 - || HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) - || HasMoveWithEffect(battlerDef, EFFECT_TIDY_UP) - || HasMoveWithEffect(battlerDef, EFFECT_DEFOG) - || HasMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_DEFOG) - || HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) +bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) +{ + if (CountUsablePartyMons(battlerDef) == 0 + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_COURT_CHANGE) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_DEFOG) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) + || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_TIDY_UP) + || HasBattlerSideMoveWithEffect(battlerDef, MOVE_EFFECT_DEFOG)) return FALSE; + if (IsBattleMoveStatus(move)) + { + if (HasMoveWithEffect(battlerDef, EFFECT_MAGIC_COAT)) + return FALSE; + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE) + return FALSE; + } + else + { + if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) + return TRUE; + if (aiData->abilities[battlerDef] == ABILITY_SHIELD_DUST) + return FALSE; + } return TRUE; } From 80a3a3b7efcab7735a58eafe06bda417fb392bc6 Mon Sep 17 00:00:00 2001 From: cornixsenex <80906795+cornixsenex@users.noreply.github.com> Date: Fri, 8 Aug 2025 02:22:42 -0700 Subject: [PATCH 194/283] Remove shadow and hide follower on stair warp (#7368) --- include/field_effect.h | 1 + src/field_effect.c | 2 +- src/field_screen_effect.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/field_effect.h b/include/field_effect.h index 2e13879353..8a3de2b8de 100644 --- a/include/field_effect.h +++ b/include/field_effect.h @@ -37,6 +37,7 @@ bool8 FieldEffectCmd_loadgfx_callnative(u8 **script, u32 *val); bool8 FieldEffectCmd_loadtiles_callnative(u8 **script, u32 *val); bool8 FieldEffectCmd_loadfadedpal_callnative(u8 **script, u32 *val); void FieldCB_FallWarpExit(void); +void HideFollowerForFieldEffect(void); void StartEscalatorWarp(u8 metatileBehavior, u8 priority); void StartLavaridgeGymB1FWarp(u8 priority); void StartLavaridgeGym1FWarp(u8 priority); diff --git a/src/field_effect.c b/src/field_effect.c index 1f2feaba8f..82a5394821 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -1650,7 +1650,7 @@ static bool8 FallWarpEffect_End(struct Task *task) #define tState data[0] #define tGoingUp data[1] -static void HideFollowerForFieldEffect(void) +void HideFollowerForFieldEffect(void) { struct ObjectEvent *followerObj = GetFollowerObject(); if (!followerObj || followerObj->invisible) diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 7b17f53666..0cf752fd6a 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -1571,12 +1571,14 @@ static void Task_ExitStairs(u8 taskId) tState++; break; } + gObjectEvents[gPlayerAvatar.objectEventId].noShadow = FALSE; } static void ForceStairsMovement(u32 metatileBehavior, s16 *speedX, s16 *speedY) { ObjectEventForceSetHeldMovement(&gObjectEvents[gPlayerAvatar.objectEventId], GetWalkInPlaceNormalMovementAction(GetPlayerFacingDirection())); GetStairsMovementDirection(metatileBehavior, speedX, speedY); + gObjectEvents[gPlayerAvatar.objectEventId].noShadow = TRUE; } #undef tSpeedX #undef tSpeedY @@ -1620,6 +1622,7 @@ static void Task_StairWarp(u8 taskId) LockPlayerFieldControls(); FreezeObjectEvents(); CameraObjectFreeze(); + HideFollowerForFieldEffect(); tState++; break; case 1: From 38eb3461b941b5f4fe1fc4ba3f631880b954a985 Mon Sep 17 00:00:00 2001 From: Nephrite Date: Fri, 8 Aug 2025 19:51:16 +0100 Subject: [PATCH 195/283] Changed item name/pluralName to a compound string (#7359) --- include/item.h | 5 +- include/metaprogram.h | 6 + src/data/items.h | 2066 +++++++++++++++++++++-------------------- src/item.c | 6 +- 4 files changed, 1050 insertions(+), 1033 deletions(-) diff --git a/include/item.h b/include/item.h index 9cecce661a..1f3b1fab1b 100644 --- a/include/item.h +++ b/include/item.h @@ -93,8 +93,8 @@ struct Item ItemUseFunc fieldUseFunc; const u8 *description; const u8 *effect; - u8 name[ITEM_NAME_LENGTH]; - u8 pluralName[ITEM_NAME_PLURAL_LENGTH]; + const u8 *name; + const u8 *pluralName; u8 holdEffect; u8 holdEffectParam; u8 importance:2; @@ -121,6 +121,7 @@ struct TmHmIndexKey u16 moveId; }; +extern const u8 gQuestionMarksItemName[]; extern const struct Item gItemsInfo[]; extern struct BagPocket gBagPockets[]; extern const struct TmHmIndexKey gTMHMItemMoveIds[]; diff --git a/include/metaprogram.h b/include/metaprogram.h index 542d62f9dd..1bf77265ff 100644 --- a/include/metaprogram.h +++ b/include/metaprogram.h @@ -32,6 +32,12 @@ /* Converts a string to a compound literal, essentially making it a pointer to const u8 */ #define COMPOUND_STRING(str) (const u8[]) _(str) +#define COMPOUND_STRING_SIZE_LIMIT(str, limit) (const u8[COMPOUND_STRING_CHECK_SIZE(str, limit)]) _(str) + +/* Used for COMPOUND_STRING_SIZE_LIMIT. Stupid, but makes sure we only get + * one error message regardless of how many characters over the limit we are. + * Otherwise, GCC gives an error for each and every character (which is annoying). */ +#define COMPOUND_STRING_CHECK_SIZE(str, limit) (sizeof(COMPOUND_STRING(str)) > limit ? sizeof(COMPOUND_STRING(str)) - 1 : sizeof(COMPOUND_STRING(str))) /* Expands to the first/second/third/fourth argument. */ #define FIRST(a, ...) a diff --git a/src/data/items.h b/src/data/items.h index 69806c26da..d86a610eb4 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -14,6 +14,9 @@ #define TREASURE_FACTOR ((I_SELL_VALUE_FRACTION >= GEN_9) ? 2 : 1) +#define ITEM_NAME(str) COMPOUND_STRING_SIZE_LIMIT(str, ITEM_NAME_LENGTH) +#define ITEM_PLURAL_NAME(str) COMPOUND_STRING_SIZE_LIMIT(str, ITEM_NAME_PLURAL_LENGTH) + // Shared Item Description entries static const u8 sFullHealDesc[] = _("Heals all the\n" @@ -124,6 +127,8 @@ static const u8 sFigyBerryDesc[] = _("A hold item that\n" "restores HP but\n" "may confuse."); +const u8 gQuestionMarksItemName[] = _("????????"); + static const u8 sQuestionMarksDesc[] = _("?????"); static const u8 sKeyToRoomDesc[] = _("A key that opens a\n" @@ -142,7 +147,7 @@ const struct Item gItemsInfo[] = { [ITEM_NONE] = { - .name = _("????????"), + .name = gQuestionMarksItemName, .price = 0, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -157,7 +162,7 @@ const struct Item gItemsInfo[] = [ITEM_STRANGE_BALL] = { - .name = _("Strange Ball"), + .name = ITEM_NAME("Strange Ball"), .price = 0, .description = COMPOUND_STRING( "An unusual Ball\n" @@ -173,7 +178,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_BALL] = { - .name = _("Poké Ball"), + .name = ITEM_NAME("Poké Ball"), .price = 200, .description = COMPOUND_STRING( "A tool used for\n" @@ -189,7 +194,7 @@ const struct Item gItemsInfo[] = [ITEM_GREAT_BALL] = { - .name = _("Great Ball"), + .name = ITEM_NAME("Great Ball"), .price = 600, .description = COMPOUND_STRING( "A good Ball with a\n" @@ -205,7 +210,7 @@ const struct Item gItemsInfo[] = [ITEM_ULTRA_BALL] = { - .name = _("Ultra Ball"), + .name = ITEM_NAME("Ultra Ball"), .price = (I_PRICE >= GEN_7) ? 800 : 1200, .description = COMPOUND_STRING( "A better Ball with\n" @@ -221,7 +226,7 @@ const struct Item gItemsInfo[] = [ITEM_MASTER_BALL] = { - .name = _("Master Ball"), + .name = ITEM_NAME("Master Ball"), .price = 0, .description = COMPOUND_STRING( "The best Ball that\n" @@ -237,7 +242,7 @@ const struct Item gItemsInfo[] = [ITEM_PREMIER_BALL] = { - .name = _("Premier Ball"), + .name = ITEM_NAME("Premier Ball"), .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING( "A rare Ball made\n" @@ -253,7 +258,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAL_BALL] = { - .name = _("Heal Ball"), + .name = ITEM_NAME("Heal Ball"), .price = 300, .description = COMPOUND_STRING( "A remedial Ball\n" @@ -269,7 +274,7 @@ const struct Item gItemsInfo[] = [ITEM_NET_BALL] = { - .name = _("Net Ball"), + .name = ITEM_NAME("Net Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works\n" @@ -285,7 +290,7 @@ const struct Item gItemsInfo[] = [ITEM_NEST_BALL] = { - .name = _("Nest Ball"), + .name = ITEM_NAME("Nest Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works\n" @@ -301,7 +306,7 @@ const struct Item gItemsInfo[] = [ITEM_DIVE_BALL] = { - .name = _("Dive Ball"), + .name = ITEM_NAME("Dive Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works\n" @@ -317,7 +322,7 @@ const struct Item gItemsInfo[] = [ITEM_DUSK_BALL] = { - .name = _("Dusk Ball"), + .name = ITEM_NAME("Dusk Ball"), .price = 1000, .description = COMPOUND_STRING( "Works well if\n" @@ -333,7 +338,7 @@ const struct Item gItemsInfo[] = [ITEM_TIMER_BALL] = { - .name = _("Timer Ball"), + .name = ITEM_NAME("Timer Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that gains\n" @@ -349,7 +354,7 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_BALL] = { - .name = _("Quick Ball"), + .name = ITEM_NAME("Quick Ball"), .price = 1000, .description = COMPOUND_STRING( "Works well if\n" @@ -365,7 +370,7 @@ const struct Item gItemsInfo[] = [ITEM_REPEAT_BALL] = { - .name = _("Repeat Ball"), + .name = ITEM_NAME("Repeat Ball"), .price = 1000, .description = COMPOUND_STRING( "A Ball that works\n" @@ -381,7 +386,7 @@ const struct Item gItemsInfo[] = [ITEM_LUXURY_BALL] = { - .name = _("Luxury Ball"), + .name = ITEM_NAME("Luxury Ball"), .price = (I_PRICE >= GEN_8) ? 3000 : 1000, .description = COMPOUND_STRING( "A cozy Ball that\n" @@ -397,7 +402,7 @@ const struct Item gItemsInfo[] = [ITEM_LEVEL_BALL] = { - .name = _("Level Ball"), + .name = ITEM_NAME("Level Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works\n" @@ -413,7 +418,7 @@ const struct Item gItemsInfo[] = [ITEM_LURE_BALL] = { - .name = _("Lure Ball"), + .name = ITEM_NAME("Lure Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works\n" @@ -429,7 +434,7 @@ const struct Item gItemsInfo[] = [ITEM_MOON_BALL] = { - .name = _("Moon Ball"), + .name = ITEM_NAME("Moon Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that works\n" @@ -445,7 +450,7 @@ const struct Item gItemsInfo[] = [ITEM_FRIEND_BALL] = { - .name = _("Friend Ball"), + .name = ITEM_NAME("Friend Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "A Ball that makes\n" @@ -461,7 +466,7 @@ const struct Item gItemsInfo[] = [ITEM_LOVE_BALL] = { - .name = _("Love Ball"), + .name = ITEM_NAME("Love Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on\n" @@ -477,7 +482,7 @@ const struct Item gItemsInfo[] = [ITEM_FAST_BALL] = { - .name = _("Fast Ball"), + .name = ITEM_NAME("Fast Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on\n" @@ -493,7 +498,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAVY_BALL] = { - .name = _("Heavy Ball"), + .name = ITEM_NAME("Heavy Ball"), .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING( "Works well on\n" @@ -509,7 +514,7 @@ const struct Item gItemsInfo[] = [ITEM_DREAM_BALL] = { - .name = _("Dream Ball"), + .name = ITEM_NAME("Dream Ball"), .price = 0, .description = COMPOUND_STRING( #if B_DREAM_BALL_MODIFIER >= GEN_8 @@ -530,7 +535,7 @@ const struct Item gItemsInfo[] = [ITEM_SAFARI_BALL] = { - .name = _("Safari Ball"), + .name = ITEM_NAME("Safari Ball"), .price = 0, .description = COMPOUND_STRING( "A special Ball that\n" @@ -546,7 +551,7 @@ const struct Item gItemsInfo[] = [ITEM_SPORT_BALL] = { - .name = _("Sport Ball"), + .name = ITEM_NAME("Sport Ball"), .price = (I_PRICE < GEN_3 || I_PRICE >= GEN_9) ? 0 : 300, .description = COMPOUND_STRING( "A special Ball\n" @@ -562,7 +567,7 @@ const struct Item gItemsInfo[] = [ITEM_PARK_BALL] = { - .name = _("Park Ball"), + .name = ITEM_NAME("Park Ball"), .price = 0, .description = COMPOUND_STRING( "A special Ball for\n" @@ -577,7 +582,7 @@ const struct Item gItemsInfo[] = [ITEM_BEAST_BALL] = { - .name = _("Beast Ball"), + .name = ITEM_NAME("Beast Ball"), .price = 0, .description = COMPOUND_STRING( "A Ball designed to\n" @@ -592,7 +597,7 @@ const struct Item gItemsInfo[] = [ITEM_CHERISH_BALL] = { - .name = _("Cherish Ball"), + .name = ITEM_NAME("Cherish Ball"), .price = 0, .description = COMPOUND_STRING( "A rare Ball made\n" @@ -610,7 +615,7 @@ const struct Item gItemsInfo[] = [ITEM_POTION] = { - .name = _("Potion"), + .name = ITEM_NAME("Potion"), .price = (I_PRICE >= GEN_7) ? 200 : 300, .holdEffectParam = 20, .description = COMPOUND_STRING( @@ -630,7 +635,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_POTION] = { - .name = _("Super Potion"), + .name = ITEM_NAME("Super Potion"), .price = 700, .holdEffectParam = 60, .description = COMPOUND_STRING( @@ -654,7 +659,7 @@ const struct Item gItemsInfo[] = [ITEM_HYPER_POTION] = { - .name = _("Hyper Potion"), + .name = ITEM_NAME("Hyper Potion"), .price = (I_PRICE >= GEN_2 && I_PRICE <= GEN_6) ? 1200 : 1500, .holdEffectParam = 120, .description = COMPOUND_STRING( @@ -678,7 +683,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_POTION] = { - .name = _("Max Potion"), + .name = ITEM_NAME("Max Potion"), .price = 2500, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -697,7 +702,7 @@ const struct Item gItemsInfo[] = [ITEM_FULL_RESTORE] = { - .name = _("Full Restore"), + .name = ITEM_NAME("Full Restore"), .price = 3000, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -717,7 +722,7 @@ const struct Item gItemsInfo[] = [ITEM_REVIVE] = { - .name = _("Revive"), + .name = ITEM_NAME("Revive"), .price = (I_PRICE >= GEN_7) ? 2000 : 1500, .description = COMPOUND_STRING( "Revives a fainted\n" @@ -736,7 +741,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_REVIVE] = { - .name = _("Max Revive"), + .name = ITEM_NAME("Max Revive"), .price = 4000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, @@ -752,7 +757,7 @@ const struct Item gItemsInfo[] = [ITEM_FRESH_WATER] = { - .name = _("Fresh Water"), + .name = ITEM_NAME("Fresh Water"), .price = 200, .holdEffectParam = 30, .description = COMPOUND_STRING( @@ -776,7 +781,7 @@ const struct Item gItemsInfo[] = [ITEM_SODA_POP] = { - .name = _("Soda Pop"), + .name = ITEM_NAME("Soda Pop"), .price = 300, .holdEffectParam = 50, .description = COMPOUND_STRING( @@ -800,7 +805,7 @@ const struct Item gItemsInfo[] = [ITEM_LEMONADE] = { - .name = _("Lemonade"), + .name = ITEM_NAME("Lemonade"), .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 70, #if I_HEALTH_RECOVERY >= GEN_7 @@ -827,8 +832,8 @@ const struct Item gItemsInfo[] = [ITEM_MOOMOO_MILK] = { - .name = _("Moomoo Milk"), - .pluralName = _("Moomoo Milk"), + .name = ITEM_NAME("Moomoo Milk"), + .pluralName = ITEM_PLURAL_NAME("Moomoo Milk"), .price = (I_PRICE >= GEN_7) ? 600 : 500, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -848,8 +853,8 @@ const struct Item gItemsInfo[] = [ITEM_ENERGY_POWDER] = { - .name = _("Energy Powder"), - .pluralName = _("Energy Powder"), + .name = ITEM_NAME("Energy Powder"), + .pluralName = ITEM_PLURAL_NAME("Energy Powder"), .price = 500, .description = COMPOUND_STRING( "A bitter powder\n" @@ -872,7 +877,7 @@ const struct Item gItemsInfo[] = [ITEM_ENERGY_ROOT] = { - .name = _("Energy Root"), + .name = ITEM_NAME("Energy Root"), .price = (I_PRICE >= GEN_7) ? 1200 : 800, .description = COMPOUND_STRING( "A bitter root\n" @@ -895,8 +900,8 @@ const struct Item gItemsInfo[] = [ITEM_HEAL_POWDER] = { - .name = _("Heal Powder"), - .pluralName = _("Heal Powder"), + .name = ITEM_NAME("Heal Powder"), + .pluralName = ITEM_PLURAL_NAME("Heal Powder"), .price = (I_PRICE >= GEN_7) ? 300 : 450, .description = COMPOUND_STRING( "A bitter powder\n" @@ -915,7 +920,7 @@ const struct Item gItemsInfo[] = [ITEM_REVIVAL_HERB] = { - .name = _("Revival Herb"), + .name = ITEM_NAME("Revival Herb"), .price = 2800, .description = COMPOUND_STRING( "A very bitter herb\n" @@ -934,7 +939,7 @@ const struct Item gItemsInfo[] = [ITEM_ANTIDOTE] = { - .name = _("Antidote"), + .name = ITEM_NAME("Antidote"), .price = (I_PRICE >= GEN_7) ? 200 : 100, .description = COMPOUND_STRING( "Heals a poisoned\n" @@ -952,7 +957,7 @@ const struct Item gItemsInfo[] = [ITEM_PARALYZE_HEAL] = { - .name = _("Paralyze Heal"), + .name = ITEM_NAME("Paralyze Heal"), .price = (I_PRICE == GEN_7) ? 300 : 200, .description = COMPOUND_STRING( "Heals a paralyzed\n" @@ -970,7 +975,7 @@ const struct Item gItemsInfo[] = [ITEM_BURN_HEAL] = { - .name = _("Burn Heal"), + .name = ITEM_NAME("Burn Heal"), .price = (I_PRICE == GEN_7) ? 300 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING( "Heals Pokémon\n" @@ -988,7 +993,7 @@ const struct Item gItemsInfo[] = [ITEM_ICE_HEAL] = { - .name = _("Ice Heal"), + .name = ITEM_NAME("Ice Heal"), .price = (I_PRICE == GEN_7) ? 100 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING( "Defrosts a frozen\n" @@ -1006,7 +1011,7 @@ const struct Item gItemsInfo[] = [ITEM_AWAKENING] = { - .name = _("Awakening"), + .name = ITEM_NAME("Awakening"), .price = (I_PRICE >= GEN_2 && I_PRICE <= GEN_6) ? 250 : ((I_PRICE == GEN_7) ? 100 : 200), .description = COMPOUND_STRING( "Awakens a sleeping\n" @@ -1024,7 +1029,7 @@ const struct Item gItemsInfo[] = [ITEM_FULL_HEAL] = { - .name = _("Full Heal"), + .name = ITEM_NAME("Full Heal"), .price = (I_PRICE >= GEN_7) ? 400 : 600, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1040,7 +1045,7 @@ const struct Item gItemsInfo[] = [ITEM_ETHER] = { - .name = _("Ether"), + .name = ITEM_NAME("Ether"), .price = (I_PRICE >= GEN_2) ? 1200 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING( @@ -1060,7 +1065,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_ETHER] = { - .name = _("Max Ether"), + .name = ITEM_NAME("Max Ether"), .price = (I_PRICE >= GEN_2) ? 2000 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -1080,7 +1085,7 @@ const struct Item gItemsInfo[] = [ITEM_ELIXIR] = { - .name = _("Elixir"), + .name = ITEM_NAME("Elixir"), .price = (I_PRICE >= GEN_2) ? 3000 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING( @@ -1099,7 +1104,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_ELIXIR] = { - .name = _("Max Elixir"), + .name = ITEM_NAME("Max Elixir"), .price = (I_PRICE >= GEN_2) ? 4500 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING( @@ -1119,8 +1124,8 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_JUICE] = { - .name = _("Berry Juice"), - .pluralName = _("Berry Juice"), + .name = ITEM_NAME("Berry Juice"), + .pluralName = ITEM_PLURAL_NAME("Berry Juice"), .price = 100, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 20, @@ -1141,8 +1146,8 @@ const struct Item gItemsInfo[] = [ITEM_SACRED_ASH] = { - .name = _("Sacred Ash"), - .pluralName = _("Sacred Ashes"), + .name = ITEM_NAME("Sacred Ash"), + .pluralName = ITEM_PLURAL_NAME("Sacred Ashes"), .price = (I_PRICE >= GEN_7) ? 50000 : 200, .description = COMPOUND_STRING( "Fully revives and\n" @@ -1160,7 +1165,7 @@ const struct Item gItemsInfo[] = [ITEM_SWEET_HEART] = { - .name = _("Sweet Heart"), + .name = ITEM_NAME("Sweet Heart"), .price = (I_PRICE >= GEN_7) ? 3000 : 100, .holdEffectParam = 20, .description = COMPOUND_STRING( @@ -1180,8 +1185,8 @@ const struct Item gItemsInfo[] = [ITEM_MAX_HONEY] = { - .name = _("Max Honey"), - .pluralName = _("Max Honey"), + .name = ITEM_NAME("Max Honey"), + .pluralName = ITEM_PLURAL_NAME("Max Honey"), .price = 8000, .description = sMaxReviveDesc, .pocket = POCKET_ITEMS, @@ -1199,8 +1204,8 @@ const struct Item gItemsInfo[] = [ITEM_PEWTER_CRUNCHIES] = { - .name = _("Pewter Crunchies"), - .pluralName = _("Pewter Crunchies"), + .name = ITEM_NAME("Pewter Crunchies"), + .pluralName = ITEM_PLURAL_NAME("Pewter Crunchies"), .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1216,7 +1221,7 @@ const struct Item gItemsInfo[] = [ITEM_RAGE_CANDY_BAR] = { - .name = _("Rage Candy Bar"), + .name = ITEM_NAME("Rage Candy Bar"), .price = (I_PRICE >= GEN_7) ? 350 : 300, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1232,7 +1237,7 @@ const struct Item gItemsInfo[] = [ITEM_LAVA_COOKIE] = { - .name = _("Lava Cookie"), + .name = ITEM_NAME("Lava Cookie"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = COMPOUND_STRING( "A local specialty\n" @@ -1251,8 +1256,8 @@ const struct Item gItemsInfo[] = [ITEM_OLD_GATEAU] = { - .name = _("Old Gateau"), - .pluralName = _("Old Gateaux"), + .name = ITEM_NAME("Old Gateau"), + .pluralName = ITEM_PLURAL_NAME("Old Gateaux"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1268,7 +1273,7 @@ const struct Item gItemsInfo[] = [ITEM_CASTELIACONE] = { - .name = _("Casteliacone"), + .name = ITEM_NAME("Casteliacone"), .price = (I_PRICE >= GEN_7) ? 350 : 100, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1284,7 +1289,7 @@ const struct Item gItemsInfo[] = [ITEM_LUMIOSE_GALETTE] = { - .name = _("Lumiose Galette"), + .name = ITEM_NAME("Lumiose Galette"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1300,7 +1305,7 @@ const struct Item gItemsInfo[] = [ITEM_SHALOUR_SABLE] = { - .name = _("Shalour Sable"), + .name = ITEM_NAME("Shalour Sable"), .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1316,7 +1321,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_MALASADA] = { - .name = _("Big Malasada"), + .name = ITEM_NAME("Big Malasada"), .price = 350, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -1334,7 +1339,7 @@ const struct Item gItemsInfo[] = [ITEM_HP_UP] = { - .name = _("HP Up"), + .name = ITEM_NAME("HP Up"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base HP\n" @@ -1351,7 +1356,7 @@ const struct Item gItemsInfo[] = [ITEM_PROTEIN] = { - .name = _("Protein"), + .name = ITEM_NAME("Protein"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base\n" @@ -1369,7 +1374,7 @@ const struct Item gItemsInfo[] = [ITEM_IRON] = { - .name = _("Iron"), + .name = ITEM_NAME("Iron"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base\n" @@ -1387,7 +1392,7 @@ const struct Item gItemsInfo[] = [ITEM_CALCIUM] = { - .name = _("Calcium"), + .name = ITEM_NAME("Calcium"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base\n" @@ -1405,7 +1410,7 @@ const struct Item gItemsInfo[] = [ITEM_ZINC] = { - .name = _("Zinc"), + .name = ITEM_NAME("Zinc"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base\n" @@ -1423,8 +1428,8 @@ const struct Item gItemsInfo[] = [ITEM_CARBOS] = { - .name = _("Carbos"), - .pluralName = _("Carbos"), + .name = ITEM_NAME("Carbos"), + .pluralName = ITEM_PLURAL_NAME("Carbos"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the base\n" @@ -1442,7 +1447,7 @@ const struct Item gItemsInfo[] = [ITEM_PP_UP] = { - .name = _("PP Up"), + .name = ITEM_NAME("PP Up"), .price = (I_PRICE == GEN_1) ? 1 : ((I_PRICE >= GEN_7) ? 10000 : 9800), .description = COMPOUND_STRING( "Raises the maximum\n" @@ -1460,8 +1465,8 @@ const struct Item gItemsInfo[] = [ITEM_PP_MAX] = { - .name = _("PP Max"), - .pluralName = _("PP Maxes"), + .name = ITEM_NAME("PP Max"), + .pluralName = ITEM_PLURAL_NAME("PP Maxes"), .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING( "Raises the PP of a\n" @@ -1481,7 +1486,7 @@ const struct Item gItemsInfo[] = [ITEM_HEALTH_FEATHER] = { - .name = _("Health Feather"), + .name = ITEM_NAME("Health Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, @@ -1496,7 +1501,7 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_FEATHER] = { - .name = _("Muscle Feather"), + .name = ITEM_NAME("Muscle Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, @@ -1511,7 +1516,7 @@ const struct Item gItemsInfo[] = [ITEM_RESIST_FEATHER] = { - .name = _("Resist Feather"), + .name = ITEM_NAME("Resist Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, @@ -1526,7 +1531,7 @@ const struct Item gItemsInfo[] = [ITEM_GENIUS_FEATHER] = { - .name = _("Genius Feather"), + .name = ITEM_NAME("Genius Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, @@ -1541,7 +1546,7 @@ const struct Item gItemsInfo[] = [ITEM_CLEVER_FEATHER] = { - .name = _("Clever Feather"), + .name = ITEM_NAME("Clever Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, @@ -1556,7 +1561,7 @@ const struct Item gItemsInfo[] = [ITEM_SWIFT_FEATHER] = { - .name = _("Swift Feather"), + .name = ITEM_NAME("Swift Feather"), .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, @@ -1573,7 +1578,7 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_CAPSULE] = { - .name = _("Ability Capsule"), + .name = ITEM_NAME("Ability Capsule"), .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE < GEN_9) ? 10000 : 100000), .holdEffectParam = 0, .description = COMPOUND_STRING( @@ -1589,8 +1594,8 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_PATCH] = { - .name = _("Ability Patch"), - .pluralName = _("Ability Patches"), + .name = ITEM_NAME("Ability Patch"), + .pluralName = ITEM_PLURAL_NAME("Ability Patches"), .price = (I_PRICE >= GEN_9) ? 250000 : 20, .holdEffectParam = 0, .description = COMPOUND_STRING( @@ -1609,7 +1614,7 @@ const struct Item gItemsInfo[] = [ITEM_LONELY_MINT] = { - .name = _("Lonely Mint"), + .name = ITEM_NAME("Lonely Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1627,7 +1632,7 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_MINT] = { - .name = _("Adamant Mint"), + .name = ITEM_NAME("Adamant Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1645,7 +1650,7 @@ const struct Item gItemsInfo[] = [ITEM_NAUGHTY_MINT] = { - .name = _("Naughty Mint"), + .name = ITEM_NAME("Naughty Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1663,7 +1668,7 @@ const struct Item gItemsInfo[] = [ITEM_BRAVE_MINT] = { - .name = _("Brave Mint"), + .name = ITEM_NAME("Brave Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1681,7 +1686,7 @@ const struct Item gItemsInfo[] = [ITEM_BOLD_MINT] = { - .name = _("Bold Mint"), + .name = ITEM_NAME("Bold Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1699,7 +1704,7 @@ const struct Item gItemsInfo[] = [ITEM_IMPISH_MINT] = { - .name = _("Impish Mint"), + .name = ITEM_NAME("Impish Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1717,7 +1722,7 @@ const struct Item gItemsInfo[] = [ITEM_LAX_MINT] = { - .name = _("Lax Mint"), + .name = ITEM_NAME("Lax Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1735,7 +1740,7 @@ const struct Item gItemsInfo[] = [ITEM_RELAXED_MINT] = { - .name = _("Relaxed Mint"), + .name = ITEM_NAME("Relaxed Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1753,7 +1758,7 @@ const struct Item gItemsInfo[] = [ITEM_MODEST_MINT] = { - .name = _("Modest Mint"), + .name = ITEM_NAME("Modest Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1771,7 +1776,7 @@ const struct Item gItemsInfo[] = [ITEM_MILD_MINT] = { - .name = _("Mild Mint"), + .name = ITEM_NAME("Mild Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1789,7 +1794,7 @@ const struct Item gItemsInfo[] = [ITEM_RASH_MINT] = { - .name = _("Rash Mint"), + .name = ITEM_NAME("Rash Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1807,7 +1812,7 @@ const struct Item gItemsInfo[] = [ITEM_QUIET_MINT] = { - .name = _("Quiet Mint"), + .name = ITEM_NAME("Quiet Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1825,7 +1830,7 @@ const struct Item gItemsInfo[] = [ITEM_CALM_MINT] = { - .name = _("Calm Mint"), + .name = ITEM_NAME("Calm Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1843,7 +1848,7 @@ const struct Item gItemsInfo[] = [ITEM_GENTLE_MINT] = { - .name = _("Gentle Mint"), + .name = ITEM_NAME("Gentle Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1861,7 +1866,7 @@ const struct Item gItemsInfo[] = [ITEM_CAREFUL_MINT] = { - .name = _("Careful Mint"), + .name = ITEM_NAME("Careful Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1879,7 +1884,7 @@ const struct Item gItemsInfo[] = [ITEM_SASSY_MINT] = { - .name = _("Sassy Mint"), + .name = ITEM_NAME("Sassy Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1897,7 +1902,7 @@ const struct Item gItemsInfo[] = [ITEM_TIMID_MINT] = { - .name = _("Timid Mint"), + .name = ITEM_NAME("Timid Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1915,7 +1920,7 @@ const struct Item gItemsInfo[] = [ITEM_HASTY_MINT] = { - .name = _("Hasty Mint"), + .name = ITEM_NAME("Hasty Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1933,7 +1938,7 @@ const struct Item gItemsInfo[] = [ITEM_JOLLY_MINT] = { - .name = _("Jolly Mint"), + .name = ITEM_NAME("Jolly Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1951,7 +1956,7 @@ const struct Item gItemsInfo[] = [ITEM_NAIVE_MINT] = { - .name = _("Naive Mint"), + .name = ITEM_NAME("Naive Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1969,7 +1974,7 @@ const struct Item gItemsInfo[] = [ITEM_SERIOUS_MINT] = { - .name = _("Serious Mint"), + .name = ITEM_NAME("Serious Mint"), .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING( "Can be smelled. It\n" @@ -1989,8 +1994,8 @@ const struct Item gItemsInfo[] = [ITEM_RARE_CANDY] = { - .name = _("Rare Candy"), - .pluralName = _("Rare Candies"), + .name = ITEM_NAME("Rare Candy"), + .pluralName = ITEM_PLURAL_NAME("Rare Candies"), .price = (I_PRICE >= GEN_7) ? 10000 : 4800, .description = COMPOUND_STRING( "Raises the level\n" @@ -2008,8 +2013,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_XS] = { - .name = _("Exp. Candy XS"), - .pluralName = _("Exp. Candies XS"), + .name = ITEM_NAME("Exp. Candy XS"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies XS"), .price = 20, .holdEffectParam = EXP_100, .description = COMPOUND_STRING( @@ -2028,8 +2033,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_S] = { - .name = _("Exp. Candy S"), - .pluralName = _("Exp. Candies S"), + .name = ITEM_NAME("Exp. Candy S"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies S"), .price = 240, .holdEffectParam = EXP_800, .description = COMPOUND_STRING( @@ -2048,8 +2053,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_M] = { - .name = _("Exp. Candy M"), - .pluralName = _("Exp. Candies M"), + .name = ITEM_NAME("Exp. Candy M"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies M"), .price = 1000, .holdEffectParam = EXP_3000, .description = COMPOUND_STRING( @@ -2068,8 +2073,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_L] = { - .name = _("Exp. Candy L"), - .pluralName = _("Exp. Candies L"), + .name = ITEM_NAME("Exp. Candy L"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies L"), .price = 3000, .holdEffectParam = EXP_10000, .description = COMPOUND_STRING( @@ -2088,8 +2093,8 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CANDY_XL] = { - .name = _("Exp. Candy XL"), - .pluralName = _("Exp. Candies XL"), + .name = ITEM_NAME("Exp. Candy XL"), + .pluralName = ITEM_PLURAL_NAME("Exp. Candies XL"), .price = 10000, .holdEffectParam = EXP_30000, .description = COMPOUND_STRING( @@ -2108,8 +2113,8 @@ const struct Item gItemsInfo[] = [ITEM_DYNAMAX_CANDY] = { - .name = _("Dynamax Candy"), - .pluralName = _("Dynamax Candies"), + .name = ITEM_NAME("Dynamax Candy"), + .pluralName = ITEM_PLURAL_NAME("Dynamax Candies"), .price = 0, .description = COMPOUND_STRING( "Raises the Dynamax\n" @@ -2128,7 +2133,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_FLUTE] = { - .name = _("Blue Flute"), + .name = ITEM_NAME("Blue Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 100, .description = COMPOUND_STRING( "A glass flute that\n" @@ -2148,7 +2153,7 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_FLUTE] = { - .name = _("Yellow Flute"), + .name = ITEM_NAME("Yellow Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 300, .description = COMPOUND_STRING( "A glass flute that\n" @@ -2168,7 +2173,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_FLUTE] = { - .name = _("Red Flute"), + .name = ITEM_NAME("Red Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING( "A glass flute that\n" @@ -2190,7 +2195,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_FLUTE] = { - .name = _("Black Flute"), + .name = ITEM_NAME("Black Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 400, .holdEffectParam = 50, .description = COMPOUND_STRING( @@ -2209,7 +2214,7 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_FLUTE] = { - .name = _("White Flute"), + .name = ITEM_NAME("White Flute"), .price = (I_PRICE >= GEN_7) ? 20 : 500, .holdEffectParam = 150, .description = COMPOUND_STRING( @@ -2229,7 +2234,7 @@ const struct Item gItemsInfo[] = [ITEM_REPEL] = { - .name = _("Repel"), + .name = ITEM_NAME("Repel"), .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -2247,7 +2252,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_REPEL] = { - .name = _("Super Repel"), + .name = ITEM_NAME("Super Repel"), .price = (I_PRICE >= GEN_7) ? 700 : 500, .holdEffectParam = 200, .description = COMPOUND_STRING( @@ -2265,7 +2270,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_REPEL] = { - .name = _("Max Repel"), + .name = ITEM_NAME("Max Repel"), .price = (I_PRICE >= GEN_7) ? 900 : 700, .holdEffectParam = 250, .description = COMPOUND_STRING( @@ -2283,7 +2288,7 @@ const struct Item gItemsInfo[] = [ITEM_LURE] = { - .name = _("Lure"), + .name = ITEM_NAME("Lure"), .price = 400, .holdEffectParam = 100, .description = COMPOUND_STRING( @@ -2302,7 +2307,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_LURE] = { - .name = _("Super Lure"), + .name = ITEM_NAME("Super Lure"), .price = 700, .holdEffectParam = 200, .description = COMPOUND_STRING( @@ -2321,7 +2326,7 @@ const struct Item gItemsInfo[] = [ITEM_MAX_LURE] = { - .name = _("Max Lure"), + .name = ITEM_NAME("Max Lure"), .price = 900, .holdEffectParam = 250, .description = COMPOUND_STRING( @@ -2340,7 +2345,7 @@ const struct Item gItemsInfo[] = [ITEM_ESCAPE_ROPE] = { - .name = _("Escape Rope"), + .name = ITEM_NAME("Escape Rope"), .description = COMPOUND_STRING( "Use to escape\n" "instantly from a\n" @@ -2365,7 +2370,7 @@ const struct Item gItemsInfo[] = [ITEM_X_ATTACK] = { - .name = _("X Attack"), + .name = ITEM_NAME("X Attack"), .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2391,7 +2396,7 @@ const struct Item gItemsInfo[] = [ITEM_X_DEFENSE] = { - .name = _("X Defense"), + .name = ITEM_NAME("X Defense"), .price = (I_PRICE >= GEN_7) ? 2000 : 550, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2417,7 +2422,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SP_ATK] = { - .name = _("X Sp. Atk"), + .name = ITEM_NAME("X Sp. Atk"), .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2443,7 +2448,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SP_DEF] = { - .name = _("X Sp. Def"), + .name = ITEM_NAME("X Sp. Def"), .price = (I_PRICE >= GEN_7) ? 2000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2469,7 +2474,7 @@ const struct Item gItemsInfo[] = [ITEM_X_SPEED] = { - .name = _("X Speed"), + .name = ITEM_NAME("X Speed"), .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2495,8 +2500,8 @@ const struct Item gItemsInfo[] = [ITEM_X_ACCURACY] = { - .name = _("X Accuracy"), - .pluralName = _("X Accuracies"), + .name = ITEM_NAME("X Accuracy"), + .pluralName = ITEM_PLURAL_NAME("X Accuracies"), .price = (I_PRICE >= GEN_7) ? 1000 : 950, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -2522,7 +2527,7 @@ const struct Item gItemsInfo[] = [ITEM_DIRE_HIT] = { - .name = _("Dire Hit"), + .name = ITEM_NAME("Dire Hit"), .price = (I_PRICE >= GEN_7) ? 1000 : 650, .description = COMPOUND_STRING( "Raises the\n" @@ -2541,8 +2546,8 @@ const struct Item gItemsInfo[] = [ITEM_GUARD_SPEC] = { - .name = _("Guard Spec."), - .pluralName = _("Guard Specs."), + .name = ITEM_NAME("Guard Spec."), + .pluralName = ITEM_PLURAL_NAME("Guard Specs."), .price = (I_PRICE >= GEN_7) ? 1500 : 700, .description = COMPOUND_STRING( "Prevents stat\n" @@ -2561,7 +2566,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_DOLL] = { - .name = _("Poké Doll"), + .name = ITEM_NAME("Poké Doll"), .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE == GEN_7) ? 100 : 300), .description = sPokeDollDesc, .pocket = POCKET_ITEMS, @@ -2576,7 +2581,7 @@ const struct Item gItemsInfo[] = [ITEM_FLUFFY_TAIL] = { - .name = _("Fluffy Tail"), + .name = ITEM_NAME("Fluffy Tail"), .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, @@ -2591,7 +2596,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_TOY] = { - .name = _("Poké Toy"), + .name = ITEM_NAME("Poké Toy"), .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, @@ -2606,8 +2611,8 @@ const struct Item gItemsInfo[] = [ITEM_MAX_MUSHROOMS] = { - .name = _("Max Mushrooms"), - .pluralName = _("Max Mushrooms"), + .name = ITEM_NAME("Max Mushrooms"), + .pluralName = ITEM_PLURAL_NAME("Max Mushrooms"), .price = 8000, .description = COMPOUND_STRING( "Raises every stat\n" @@ -2627,7 +2632,7 @@ const struct Item gItemsInfo[] = [ITEM_BOTTLE_CAP] = { - .name = _("Bottle Cap"), + .name = ITEM_NAME("Bottle Cap"), .price = (I_PRICE >= GEN_9) ? 20000 : 5000, .description = COMPOUND_STRING( "A beautiful bottle\n" @@ -2644,7 +2649,7 @@ const struct Item gItemsInfo[] = [ITEM_GOLD_BOTTLE_CAP] = { - .name = _("Gold Bottle Cap"), + .name = ITEM_NAME("Gold Bottle Cap"), .price = (I_PRICE >= GEN_9) ? 60000 : 10000, .description = COMPOUND_STRING( "A beautiful bottle\n" @@ -2661,7 +2666,7 @@ const struct Item gItemsInfo[] = [ITEM_NUGGET] = { - .name = _("Nugget"), + .name = ITEM_NAME("Nugget"), .price = 10000 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A nugget of pure\n" @@ -2678,7 +2683,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_NUGGET] = { - .name = _("Big Nugget"), + .name = ITEM_NAME("Big Nugget"), .price = (I_PRICE >= GEN_7) ? (40000 * TREASURE_FACTOR) : 20000, .description = COMPOUND_STRING( "A big nugget made\n" @@ -2695,7 +2700,7 @@ const struct Item gItemsInfo[] = [ITEM_TINY_MUSHROOM] = { - .name = _("Tiny Mushroom"), + .name = ITEM_NAME("Tiny Mushroom"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A plain mushroom\n" @@ -2712,7 +2717,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_MUSHROOM] = { - .name = _("Big Mushroom"), + .name = ITEM_NAME("Big Mushroom"), .price = 5000 * TREASURE_FACTOR, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, @@ -2726,7 +2731,7 @@ const struct Item gItemsInfo[] = [ITEM_BALM_MUSHROOM] = { - .name = _("Balm Mushroom"), + .name = ITEM_NAME("Balm Mushroom"), .price = (I_PRICE >= GEN_7) ? 15000 * TREASURE_FACTOR: 12500, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, @@ -2740,7 +2745,7 @@ const struct Item gItemsInfo[] = [ITEM_PEARL] = { - .name = _("Pearl"), + .name = ITEM_NAME("Pearl"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR: 1400, .description = COMPOUND_STRING( "A pretty pearl\n" @@ -2757,7 +2762,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_PEARL] = { - .name = _("Big Pearl"), + .name = ITEM_NAME("Big Pearl"), .price = (I_PRICE >= GEN_7) ? 8000 * TREASURE_FACTOR: 7500, .description = COMPOUND_STRING( "A lovely large pearl\n" @@ -2774,7 +2779,7 @@ const struct Item gItemsInfo[] = [ITEM_PEARL_STRING] = { - .name = _("Pearl String"), + .name = ITEM_NAME("Pearl String"), .price = (I_PRICE >= GEN_8) ? 15000 * TREASURE_FACTOR: ((I_PRICE == GEN_7) ? 30000 : 15000), .description = COMPOUND_STRING( "Very large pearls\n" @@ -2791,8 +2796,8 @@ const struct Item gItemsInfo[] = [ITEM_STARDUST] = { - .name = _("Stardust"), - .pluralName = _("Stardust"), + .name = ITEM_NAME("Stardust"), + .pluralName = ITEM_PLURAL_NAME("Stardust"), .price = (I_PRICE >= GEN_7) ? 3000 * TREASURE_FACTOR: 2000, .description = COMPOUND_STRING( "Beautiful red sand.\n" @@ -2809,7 +2814,7 @@ const struct Item gItemsInfo[] = [ITEM_STAR_PIECE] = { - .name = _("Star Piece"), + .name = ITEM_NAME("Star Piece"), .price = (I_PRICE >= GEN_7) ? 12000 * TREASURE_FACTOR: 9800, .description = COMPOUND_STRING( "A red gem shard.\n" @@ -2826,7 +2831,7 @@ const struct Item gItemsInfo[] = [ITEM_COMET_SHARD] = { - .name = _("Comet Shard"), + .name = ITEM_NAME("Comet Shard"), .price = (I_PRICE <= GEN_5) ? 0 : ((I_PRICE == GEN_6) ? 30000 : ((I_PRICE == GEN_7) ? 60000 : 25000 * TREASURE_FACTOR)), .description = COMPOUND_STRING( "A comet's shard.\n" @@ -2843,8 +2848,8 @@ const struct Item gItemsInfo[] = [ITEM_SHOAL_SALT] = { - .name = _("Shoal Salt"), - .pluralName = _("Shoal Salt"), + .name = ITEM_NAME("Shoal Salt"), + .pluralName = ITEM_PLURAL_NAME("Shoal Salt"), .price = 20, .description = COMPOUND_STRING( "Salt obtained from\n" @@ -2861,7 +2866,7 @@ const struct Item gItemsInfo[] = [ITEM_SHOAL_SHELL] = { - .name = _("Shoal Shell"), + .name = ITEM_NAME("Shoal Shell"), .price = 20, .description = COMPOUND_STRING( "A seashell found\n" @@ -2878,7 +2883,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_SHARD] = { - .name = _("Red Shard"), + .name = ITEM_NAME("Red Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, @@ -2892,7 +2897,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_SHARD] = { - .name = _("Blue Shard"), + .name = ITEM_NAME("Blue Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, @@ -2906,7 +2911,7 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_SHARD] = { - .name = _("Yellow Shard"), + .name = ITEM_NAME("Yellow Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, @@ -2920,7 +2925,7 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_SHARD] = { - .name = _("Green Shard"), + .name = ITEM_NAME("Green Shard"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, @@ -2934,7 +2939,7 @@ const struct Item gItemsInfo[] = [ITEM_HEART_SCALE] = { - .name = _("Heart Scale"), + .name = ITEM_NAME("Heart Scale"), .price = 100, .description = COMPOUND_STRING( "A lovely scale.\n" @@ -2951,8 +2956,8 @@ const struct Item gItemsInfo[] = [ITEM_HONEY] = { - .name = _("Honey"), - .pluralName = _("Honey"), + .name = ITEM_NAME("Honey"), + .pluralName = ITEM_PLURAL_NAME("Honey"), .price = (I_PRICE < GEN_5) ? 100 : ((I_PRICE < GEN_8) ? 300 : 900), .description = COMPOUND_STRING( "Sweet honey that\n" @@ -2969,7 +2974,7 @@ const struct Item gItemsInfo[] = [ITEM_RARE_BONE] = { - .name = _("Rare Bone"), + .name = ITEM_NAME("Rare Bone"), .price = (I_PRICE >= GEN_7) ? 5000 * TREASURE_FACTOR: 10000, .description = COMPOUND_STRING( "A very rare bone.\n" @@ -2986,7 +2991,7 @@ const struct Item gItemsInfo[] = [ITEM_ODD_KEYSTONE] = { - .name = _("Odd Keystone"), + .name = ITEM_NAME("Odd Keystone"), .price = 2100, .description = COMPOUND_STRING( "Voices can be heard\n" @@ -3003,7 +3008,7 @@ const struct Item gItemsInfo[] = [ITEM_PRETTY_FEATHER] = { - .name = _("Pretty Feather"), + .name = ITEM_NAME("Pretty Feather"), .price = (I_PRICE >= GEN_7) ? 1000 * TREASURE_FACTOR: 200, .description = COMPOUND_STRING( "A beautiful yet\n" @@ -3020,7 +3025,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_COPPER] = { - .name = _("Relic Copper"), + .name = ITEM_NAME("Relic Copper"), .price = 0, .description = COMPOUND_STRING( "A copper coin used\n" @@ -3037,7 +3042,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_SILVER] = { - .name = _("Relic Silver"), + .name = ITEM_NAME("Relic Silver"), .price = 0, .description = COMPOUND_STRING( "A silver coin used\n" @@ -3054,7 +3059,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_GOLD] = { - .name = _("Relic Gold"), + .name = ITEM_NAME("Relic Gold"), .price = 0, .description = COMPOUND_STRING( "A gold coin used\n" @@ -3071,7 +3076,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_VASE] = { - .name = _("Relic Vase"), + .name = ITEM_NAME("Relic Vase"), .price = 0, .description = COMPOUND_STRING( "A vase made long\n" @@ -3088,7 +3093,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_BAND] = { - .name = _("Relic Band"), + .name = ITEM_NAME("Relic Band"), .price = 0, .description = COMPOUND_STRING( "An old bracelet.\n" @@ -3105,7 +3110,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_STATUE] = { - .name = _("Relic Statue"), + .name = ITEM_NAME("Relic Statue"), .price = 0, .description = COMPOUND_STRING( "An old statue.\n" @@ -3122,7 +3127,7 @@ const struct Item gItemsInfo[] = [ITEM_RELIC_CROWN] = { - .name = _("Relic Crown"), + .name = ITEM_NAME("Relic Crown"), .price = 0, .description = COMPOUND_STRING( "An old crown.\n" @@ -3139,7 +3144,7 @@ const struct Item gItemsInfo[] = [ITEM_STRANGE_SOUVENIR] = { - .name = _("Strange Souvenir"), + .name = ITEM_NAME("Strange Souvenir"), .price = (I_PRICE >= GEN_7) ? 3000 : 10, .description = COMPOUND_STRING( "An ornament that\n" @@ -3158,7 +3163,7 @@ const struct Item gItemsInfo[] = [ITEM_HELIX_FOSSIL] = { - .name = _("Helix Fossil"), + .name = ITEM_NAME("Helix Fossil"), .description = COMPOUND_STRING( "A piece of an\n" "ancient marine\n" @@ -3181,7 +3186,7 @@ const struct Item gItemsInfo[] = [ITEM_DOME_FOSSIL] = { - .name = _("Dome Fossil"), + .name = ITEM_NAME("Dome Fossil"), .description = COMPOUND_STRING( "A piece of an\n" "ancient marine\n" @@ -3204,7 +3209,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_AMBER] = { - .name = _("Old Amber"), + .name = ITEM_NAME("Old Amber"), .description = COMPOUND_STRING( "A stone containing\n" "the genes of an\n" @@ -3227,7 +3232,7 @@ const struct Item gItemsInfo[] = [ITEM_ROOT_FOSSIL] = { - .name = _("Root Fossil"), + .name = ITEM_NAME("Root Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, @@ -3247,7 +3252,7 @@ const struct Item gItemsInfo[] = [ITEM_CLAW_FOSSIL] = { - .name = _("Claw Fossil"), + .name = ITEM_NAME("Claw Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 .price = (I_PRICE >= GEN_7) ? 7000: 1000, @@ -3267,7 +3272,7 @@ const struct Item gItemsInfo[] = [ITEM_ARMOR_FOSSIL] = { - .name = _("Armor Fossil"), + .name = ITEM_NAME("Armor Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3284,7 +3289,7 @@ const struct Item gItemsInfo[] = [ITEM_SKULL_FOSSIL] = { - .name = _("Skull Fossil"), + .name = ITEM_NAME("Skull Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3301,7 +3306,7 @@ const struct Item gItemsInfo[] = [ITEM_COVER_FOSSIL] = { - .name = _("Cover Fossil"), + .name = ITEM_NAME("Cover Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3318,7 +3323,7 @@ const struct Item gItemsInfo[] = [ITEM_PLUME_FOSSIL] = { - .name = _("Plume Fossil"), + .name = ITEM_NAME("Plume Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3335,7 +3340,7 @@ const struct Item gItemsInfo[] = [ITEM_JAW_FOSSIL] = { - .name = _("Jaw Fossil"), + .name = ITEM_NAME("Jaw Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3352,7 +3357,7 @@ const struct Item gItemsInfo[] = [ITEM_SAIL_FOSSIL] = { - .name = _("Sail Fossil"), + .name = ITEM_NAME("Sail Fossil"), .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING( "A piece of a\n" @@ -3369,7 +3374,7 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_BIRD] = { - .name = _("Fossilized Bird"), + .name = ITEM_NAME("Fossilized Bird"), .price = 5000, .description = COMPOUND_STRING( "A fossil of an\n" @@ -3386,8 +3391,8 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_FISH] = { - .name = _("Fossilized Fish"), - .pluralName = _("Fossilized Fishes"), + .name = ITEM_NAME("Fossilized Fish"), + .pluralName = ITEM_PLURAL_NAME("Fossilized Fishes"), .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, @@ -3401,7 +3406,7 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_DRAKE] = { - .name = _("Fossilized Drake"), + .name = ITEM_NAME("Fossilized Drake"), .price = 5000, .description = COMPOUND_STRING( "A fossil of an\n" @@ -3418,7 +3423,7 @@ const struct Item gItemsInfo[] = [ITEM_FOSSILIZED_DINO] = { - .name = _("Fossilized Dino"), + .name = ITEM_NAME("Fossilized Dino"), .price = 5000, .description = sFossilizedFishDesc, .pocket = POCKET_ITEMS, @@ -3434,8 +3439,8 @@ const struct Item gItemsInfo[] = [ITEM_GROWTH_MULCH] = { - .name = _("Growth Mulch"), - .pluralName = _("Growth Mulch"), + .name = ITEM_NAME("Growth Mulch"), + .pluralName = ITEM_PLURAL_NAME("Growth Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3457,8 +3462,8 @@ const struct Item gItemsInfo[] = [ITEM_DAMP_MULCH] = { - .name = _("Damp Mulch"), - .pluralName = _("Damp Mulch"), + .name = ITEM_NAME("Damp Mulch"), + .pluralName = ITEM_PLURAL_NAME("Damp Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3480,8 +3485,8 @@ const struct Item gItemsInfo[] = [ITEM_STABLE_MULCH] = { - .name = _("Stable Mulch"), - .pluralName = _("Stable Mulch"), + .name = ITEM_NAME("Stable Mulch"), + .pluralName = ITEM_PLURAL_NAME("Stable Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3503,8 +3508,8 @@ const struct Item gItemsInfo[] = [ITEM_GOOEY_MULCH] = { - .name = _("Gooey Mulch"), - .pluralName = _("Gooey Mulch"), + .name = ITEM_NAME("Gooey Mulch"), + .pluralName = ITEM_PLURAL_NAME("Gooey Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3526,8 +3531,8 @@ const struct Item gItemsInfo[] = [ITEM_RICH_MULCH] = { - .name = _("Rich Mulch"), - .pluralName = _("Rich Mulch"), + .name = ITEM_NAME("Rich Mulch"), + .pluralName = ITEM_PLURAL_NAME("Rich Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3549,8 +3554,8 @@ const struct Item gItemsInfo[] = [ITEM_SURPRISE_MULCH] = { - .name = _("Surprise Mulch"), - .pluralName = _("Surprise Mulch"), + .name = ITEM_NAME("Surprise Mulch"), + .pluralName = ITEM_PLURAL_NAME("Surprise Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3572,8 +3577,8 @@ const struct Item gItemsInfo[] = [ITEM_BOOST_MULCH] = { - .name = _("Boost Mulch"), - .pluralName = _("Boost Mulch"), + .name = ITEM_NAME("Boost Mulch"), + .pluralName = ITEM_PLURAL_NAME("Boost Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3595,8 +3600,8 @@ const struct Item gItemsInfo[] = [ITEM_AMAZE_MULCH] = { - .name = _("Amaze Mulch"), - .pluralName = _("Amaze Mulch"), + .name = ITEM_NAME("Amaze Mulch"), + .pluralName = ITEM_PLURAL_NAME("Amaze Mulch"), .price = 200, #if OW_BERRY_MULCH_USAGE == TRUE .description = COMPOUND_STRING( @@ -3620,7 +3625,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_APRICORN] = { - .name = _("Red Apricorn"), + .name = ITEM_NAME("Red Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A red apricorn.\n" @@ -3636,7 +3641,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_APRICORN] = { - .name = _("Blue Apricorn"), + .name = ITEM_NAME("Blue Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A blue apricorn.\n" @@ -3652,7 +3657,7 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_APRICORN] = { - .name = _("Yellow Apricorn"), + .name = ITEM_NAME("Yellow Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A yellow apricorn.\n" @@ -3668,7 +3673,7 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_APRICORN] = { - .name = _("Green Apricorn"), + .name = ITEM_NAME("Green Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A green apricorn.\n" @@ -3684,7 +3689,7 @@ const struct Item gItemsInfo[] = [ITEM_PINK_APRICORN] = { - .name = _("Pink Apricorn"), + .name = ITEM_NAME("Pink Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A pink apricorn.\n" @@ -3700,7 +3705,7 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_APRICORN] = { - .name = _("White Apricorn"), + .name = ITEM_NAME("White Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A white apricorn.\n" @@ -3716,7 +3721,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_APRICORN] = { - .name = _("Black Apricorn"), + .name = ITEM_NAME("Black Apricorn"), .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING( "A black apricorn.\n" @@ -3732,7 +3737,7 @@ const struct Item gItemsInfo[] = [ITEM_WISHING_PIECE] = { - .name = _("Wishing Piece"), + .name = ITEM_NAME("Wishing Piece"), .price = 20, .description = COMPOUND_STRING( "Throw into a\n" @@ -3749,7 +3754,7 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_TWIG] = { - .name = _("Galarica Twig"), + .name = ITEM_NAME("Galarica Twig"), .price = 20 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A twig from a tree\n" @@ -3766,8 +3771,8 @@ const struct Item gItemsInfo[] = [ITEM_ARMORITE_ORE] = { - .name = _("Armorite Ore"), - .pluralName = _("Armorite Ore"), + .name = ITEM_NAME("Armorite Ore"), + .pluralName = ITEM_PLURAL_NAME("Armorite Ore"), .price = 20, .description = COMPOUND_STRING( "A rare ore. Can be\n" @@ -3784,8 +3789,8 @@ const struct Item gItemsInfo[] = [ITEM_DYNITE_ORE] = { - .name = _("Dynite Ore"), - .pluralName = _("Dynite Ore"), + .name = ITEM_NAME("Dynite Ore"), + .pluralName = ITEM_PLURAL_NAME("Dynite Ore"), .price = 20, .description = COMPOUND_STRING( "A mysterious ore.\n" @@ -3804,8 +3809,8 @@ const struct Item gItemsInfo[] = [ITEM_ORANGE_MAIL] = { - .name = _("Orange Mail"), - .pluralName = _("Orange Mail"), + .name = ITEM_NAME("Orange Mail"), + .pluralName = ITEM_PLURAL_NAME("Orange Mail"), .price = 50, .description = COMPOUND_STRING( "A Zigzagoon-print\n" @@ -3822,8 +3827,8 @@ const struct Item gItemsInfo[] = [ITEM_HARBOR_MAIL] = { - .name = _("Harbor Mail"), - .pluralName = _("Harbor Mail"), + .name = ITEM_NAME("Harbor Mail"), + .pluralName = ITEM_PLURAL_NAME("Harbor Mail"), .price = 50, .description = COMPOUND_STRING( "A Wingull-print\n" @@ -3840,8 +3845,8 @@ const struct Item gItemsInfo[] = [ITEM_GLITTER_MAIL] = { - .name = _("Glitter Mail"), - .pluralName = _("Glitter Mail"), + .name = ITEM_NAME("Glitter Mail"), + .pluralName = ITEM_PLURAL_NAME("Glitter Mail"), .price = 50, .description = COMPOUND_STRING( "A Pikachu-print\n" @@ -3858,8 +3863,8 @@ const struct Item gItemsInfo[] = [ITEM_MECH_MAIL] = { - .name = _("Mech Mail"), - .pluralName = _("Mech Mail"), + .name = ITEM_NAME("Mech Mail"), + .pluralName = ITEM_PLURAL_NAME("Mech Mail"), .price = 50, .description = COMPOUND_STRING( "A Magnemite-print\n" @@ -3876,8 +3881,8 @@ const struct Item gItemsInfo[] = [ITEM_WOOD_MAIL] = { - .name = _("Wood Mail"), - .pluralName = _("Wood Mail"), + .name = ITEM_NAME("Wood Mail"), + .pluralName = ITEM_PLURAL_NAME("Wood Mail"), .price = 50, .description = COMPOUND_STRING( "A Slakoth-print\n" @@ -3894,8 +3899,8 @@ const struct Item gItemsInfo[] = [ITEM_WAVE_MAIL] = { - .name = _("Wave Mail"), - .pluralName = _("Wave Mail"), + .name = ITEM_NAME("Wave Mail"), + .pluralName = ITEM_PLURAL_NAME("Wave Mail"), .price = 50, .description = COMPOUND_STRING( "A Wailmer-print\n" @@ -3912,8 +3917,8 @@ const struct Item gItemsInfo[] = [ITEM_BEAD_MAIL] = { - .name = _("Bead Mail"), - .pluralName = _("Bead Mail"), + .name = ITEM_NAME("Bead Mail"), + .pluralName = ITEM_PLURAL_NAME("Bead Mail"), .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, @@ -3927,8 +3932,8 @@ const struct Item gItemsInfo[] = [ITEM_SHADOW_MAIL] = { - .name = _("Shadow Mail"), - .pluralName = _("Shadow Mail"), + .name = ITEM_NAME("Shadow Mail"), + .pluralName = ITEM_PLURAL_NAME("Shadow Mail"), .price = 50, .description = COMPOUND_STRING( "A Duskull-print\n" @@ -3945,8 +3950,8 @@ const struct Item gItemsInfo[] = [ITEM_TROPIC_MAIL] = { - .name = _("Tropic Mail"), - .pluralName = _("Tropic Mail"), + .name = ITEM_NAME("Tropic Mail"), + .pluralName = ITEM_PLURAL_NAME("Tropic Mail"), .price = 50, .description = COMPOUND_STRING( "A Bellossom-print\n" @@ -3963,8 +3968,8 @@ const struct Item gItemsInfo[] = [ITEM_DREAM_MAIL] = { - .name = _("Dream Mail"), - .pluralName = _("Dream Mail"), + .name = ITEM_NAME("Dream Mail"), + .pluralName = ITEM_PLURAL_NAME("Dream Mail"), .price = 50, .description = sBeadMailDesc, .pocket = POCKET_ITEMS, @@ -3978,8 +3983,8 @@ const struct Item gItemsInfo[] = [ITEM_FAB_MAIL] = { - .name = _("Fab Mail"), - .pluralName = _("Fab Mail"), + .name = ITEM_NAME("Fab Mail"), + .pluralName = ITEM_PLURAL_NAME("Fab Mail"), .price = 50, .description = COMPOUND_STRING( "A gorgeous-print\n" @@ -3996,8 +4001,8 @@ const struct Item gItemsInfo[] = [ITEM_RETRO_MAIL] = { - .name = _("Retro Mail"), - .pluralName = _("Retro Mail"), + .name = ITEM_NAME("Retro Mail"), + .pluralName = ITEM_PLURAL_NAME("Retro Mail"), .price = 50, .description = COMPOUND_STRING( "Mail featuring the\n" @@ -4016,7 +4021,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_STONE] = { - .name = _("Fire Stone"), + .name = ITEM_NAME("Fire Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4031,7 +4036,7 @@ const struct Item gItemsInfo[] = [ITEM_WATER_STONE] = { - .name = _("Water Stone"), + .name = ITEM_NAME("Water Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4046,7 +4051,7 @@ const struct Item gItemsInfo[] = [ITEM_THUNDER_STONE] = { - .name = _("Thunder Stone"), + .name = ITEM_NAME("Thunder Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4061,7 +4066,7 @@ const struct Item gItemsInfo[] = [ITEM_LEAF_STONE] = { - .name = _("Leaf Stone"), + .name = ITEM_NAME("Leaf Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4076,7 +4081,7 @@ const struct Item gItemsInfo[] = [ITEM_ICE_STONE] = { - .name = _("Ice Stone"), + .name = ITEM_NAME("Ice Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4091,7 +4096,7 @@ const struct Item gItemsInfo[] = [ITEM_SUN_STONE] = { - .name = _("Sun Stone"), + .name = ITEM_NAME("Sun Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4106,7 +4111,7 @@ const struct Item gItemsInfo[] = [ITEM_MOON_STONE] = { - .name = _("Moon Stone"), + .name = ITEM_NAME("Moon Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4121,7 +4126,7 @@ const struct Item gItemsInfo[] = [ITEM_SHINY_STONE] = { - .name = _("Shiny Stone"), + .name = ITEM_NAME("Shiny Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4136,7 +4141,7 @@ const struct Item gItemsInfo[] = [ITEM_DUSK_STONE] = { - .name = _("Dusk Stone"), + .name = ITEM_NAME("Dusk Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4151,7 +4156,7 @@ const struct Item gItemsInfo[] = [ITEM_DAWN_STONE] = { - .name = _("Dawn Stone"), + .name = ITEM_NAME("Dawn Stone"), .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, @@ -4166,7 +4171,7 @@ const struct Item gItemsInfo[] = [ITEM_SWEET_APPLE] = { - .name = _("Sweet Apple"), + .name = ITEM_NAME("Sweet Apple"), .price = 2200, .description = COMPOUND_STRING( "A very sweet apple\n" @@ -4184,7 +4189,7 @@ const struct Item gItemsInfo[] = [ITEM_TART_APPLE] = { - .name = _("Tart Apple"), + .name = ITEM_NAME("Tart Apple"), .price = 2200, .description = COMPOUND_STRING( "A very tart apple\n" @@ -4202,7 +4207,7 @@ const struct Item gItemsInfo[] = [ITEM_CRACKED_POT] = { - .name = _("Cracked Pot"), + .name = ITEM_NAME("Cracked Pot"), .price = 1600, .description = COMPOUND_STRING( "A cracked teapot\n" @@ -4220,7 +4225,7 @@ const struct Item gItemsInfo[] = [ITEM_CHIPPED_POT] = { - .name = _("Chipped Pot"), + .name = ITEM_NAME("Chipped Pot"), .price = 38000, .description = COMPOUND_STRING( "A chipped teapot\n" @@ -4238,7 +4243,7 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_CUFF] = { - .name = _("Galarica Cuff"), + .name = ITEM_NAME("Galarica Cuff"), .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING( "A cuff from Galar\n" @@ -4256,8 +4261,8 @@ const struct Item gItemsInfo[] = [ITEM_GALARICA_WREATH] = { - .name = _("Galarica Wreath"), - .pluralName = _("Galarica Wreathes"), + .name = ITEM_NAME("Galarica Wreath"), + .pluralName = ITEM_PLURAL_NAME("Galarica Wreathes"), .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING( "A wreath made in\n" @@ -4275,7 +4280,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_SCALE] = { - .name = _("Dragon Scale"), + .name = ITEM_NAME("Dragon Scale"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_DRAGON_SCALE, .holdEffectParam = 10, @@ -4295,7 +4300,7 @@ const struct Item gItemsInfo[] = [ITEM_UPGRADE] = { - .name = _("Upgrade"), + .name = ITEM_NAME("Upgrade"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_UPGRADE, .description = COMPOUND_STRING( @@ -4313,7 +4318,7 @@ const struct Item gItemsInfo[] = [ITEM_PROTECTOR] = { - .name = _("Protector"), + .name = ITEM_NAME("Protector"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain\n" @@ -4331,7 +4336,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTIRIZER] = { - .name = _("Electirizer"), + .name = ITEM_NAME("Electirizer"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain\n" @@ -4349,7 +4354,7 @@ const struct Item gItemsInfo[] = [ITEM_MAGMARIZER] = { - .name = _("Magmarizer"), + .name = ITEM_NAME("Magmarizer"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain\n" @@ -4367,7 +4372,7 @@ const struct Item gItemsInfo[] = [ITEM_DUBIOUS_DISC] = { - .name = _("Dubious Disc"), + .name = ITEM_NAME("Dubious Disc"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A clear device\n" @@ -4385,8 +4390,8 @@ const struct Item gItemsInfo[] = [ITEM_REAPER_CLOTH] = { - .name = _("Reaper Cloth"), - .pluralName = _("Reaper Cloths"), + .name = ITEM_NAME("Reaper Cloth"), + .pluralName = ITEM_PLURAL_NAME("Reaper Cloths"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "Loved by a certain\n" @@ -4404,7 +4409,7 @@ const struct Item gItemsInfo[] = [ITEM_PRISM_SCALE] = { - .name = _("Prism Scale"), + .name = ITEM_NAME("Prism Scale"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 500), .description = COMPOUND_STRING( "A mysterious scale\n" @@ -4422,8 +4427,8 @@ const struct Item gItemsInfo[] = [ITEM_WHIPPED_DREAM] = { - .name = _("Whipped Dream"), - .pluralName = _("Whipped Dream"), + .name = ITEM_NAME("Whipped Dream"), + .pluralName = ITEM_PLURAL_NAME("Whipped Dream"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A soft and sweet\n" @@ -4441,7 +4446,7 @@ const struct Item gItemsInfo[] = [ITEM_SACHET] = { - .name = _("Sachet"), + .name = ITEM_NAME("Sachet"), .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING( "A sachet of strong\n" @@ -4459,7 +4464,7 @@ const struct Item gItemsInfo[] = [ITEM_OVAL_STONE] = { - .name = _("Oval Stone"), + .name = ITEM_NAME("Oval Stone"), .price = (I_PRICE >= GEN_7) ? 2000 : 2100, .description = COMPOUND_STRING( "Peculiar stone\n" @@ -4477,7 +4482,7 @@ const struct Item gItemsInfo[] = [ITEM_STRAWBERRY_SWEET] = { - .name = _("Strawberry Sweet"), + .name = ITEM_NAME("Strawberry Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "Strawberry-shaped\n" @@ -4494,7 +4499,7 @@ const struct Item gItemsInfo[] = [ITEM_LOVE_SWEET] = { - .name = _("Love Sweet"), + .name = ITEM_NAME("Love Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A heart-shaped\n" @@ -4511,7 +4516,7 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_SWEET] = { - .name = _("Berry Sweet"), + .name = ITEM_NAME("Berry Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A berry-shaped\n" @@ -4528,7 +4533,7 @@ const struct Item gItemsInfo[] = [ITEM_CLOVER_SWEET] = { - .name = _("Clover Sweet"), + .name = ITEM_NAME("Clover Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A clover-shaped\n" @@ -4545,7 +4550,7 @@ const struct Item gItemsInfo[] = [ITEM_FLOWER_SWEET] = { - .name = _("Flower Sweet"), + .name = ITEM_NAME("Flower Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A flower-shaped\n" @@ -4562,7 +4567,7 @@ const struct Item gItemsInfo[] = [ITEM_STAR_SWEET] = { - .name = _("Star Sweet"), + .name = ITEM_NAME("Star Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A star-shaped\n" @@ -4579,7 +4584,7 @@ const struct Item gItemsInfo[] = [ITEM_RIBBON_SWEET] = { - .name = _("Ribbon Sweet"), + .name = ITEM_NAME("Ribbon Sweet"), .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING( "A ribbon-shaped\n" @@ -4596,7 +4601,7 @@ const struct Item gItemsInfo[] = [ITEM_EVERSTONE] = { - .name = _("Everstone"), + .name = ITEM_NAME("Everstone"), .price = (I_PRICE >= GEN_7) ? 3000 : 200, .holdEffect = HOLD_EFFECT_PREVENT_EVOLVE, .description = COMPOUND_STRING( @@ -4616,7 +4621,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_NECTAR] = { - .name = _("Red Nectar"), + .name = ITEM_NAME("Red Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, @@ -4631,7 +4636,7 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_NECTAR] = { - .name = _("Yellow Nectar"), + .name = ITEM_NAME("Yellow Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, @@ -4646,7 +4651,7 @@ const struct Item gItemsInfo[] = [ITEM_PINK_NECTAR] = { - .name = _("Pink Nectar"), + .name = ITEM_NAME("Pink Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, @@ -4661,7 +4666,7 @@ const struct Item gItemsInfo[] = [ITEM_PURPLE_NECTAR] = { - .name = _("Purple Nectar"), + .name = ITEM_NAME("Purple Nectar"), .price = 300, .holdEffectParam = 0, .description = sNectarDesc, @@ -4678,7 +4683,7 @@ const struct Item gItemsInfo[] = [ITEM_FLAME_PLATE] = { - .name = _("Flame Plate"), + .name = ITEM_NAME("Flame Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4698,7 +4703,7 @@ const struct Item gItemsInfo[] = [ITEM_SPLASH_PLATE] = { - .name = _("Splash Plate"), + .name = ITEM_NAME("Splash Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4718,7 +4723,7 @@ const struct Item gItemsInfo[] = [ITEM_ZAP_PLATE] = { - .name = _("Zap Plate"), + .name = ITEM_NAME("Zap Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4738,7 +4743,7 @@ const struct Item gItemsInfo[] = [ITEM_MEADOW_PLATE] = { - .name = _("Meadow Plate"), + .name = ITEM_NAME("Meadow Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4758,7 +4763,7 @@ const struct Item gItemsInfo[] = [ITEM_ICICLE_PLATE] = { - .name = _("Icicle Plate"), + .name = ITEM_NAME("Icicle Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4778,7 +4783,7 @@ const struct Item gItemsInfo[] = [ITEM_FIST_PLATE] = { - .name = _("Fist Plate"), + .name = ITEM_NAME("Fist Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4798,7 +4803,7 @@ const struct Item gItemsInfo[] = [ITEM_TOXIC_PLATE] = { - .name = _("Toxic Plate"), + .name = ITEM_NAME("Toxic Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4818,7 +4823,7 @@ const struct Item gItemsInfo[] = [ITEM_EARTH_PLATE] = { - .name = _("Earth Plate"), + .name = ITEM_NAME("Earth Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4838,7 +4843,7 @@ const struct Item gItemsInfo[] = [ITEM_SKY_PLATE] = { - .name = _("Sky Plate"), + .name = ITEM_NAME("Sky Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4858,7 +4863,7 @@ const struct Item gItemsInfo[] = [ITEM_MIND_PLATE] = { - .name = _("Mind Plate"), + .name = ITEM_NAME("Mind Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4878,7 +4883,7 @@ const struct Item gItemsInfo[] = [ITEM_INSECT_PLATE] = { - .name = _("Insect Plate"), + .name = ITEM_NAME("Insect Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4898,7 +4903,7 @@ const struct Item gItemsInfo[] = [ITEM_STONE_PLATE] = { - .name = _("Stone Plate"), + .name = ITEM_NAME("Stone Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4918,7 +4923,7 @@ const struct Item gItemsInfo[] = [ITEM_SPOOKY_PLATE] = { - .name = _("Spooky Plate"), + .name = ITEM_NAME("Spooky Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4938,7 +4943,7 @@ const struct Item gItemsInfo[] = [ITEM_DRACO_PLATE] = { - .name = _("Draco Plate"), + .name = ITEM_NAME("Draco Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4958,7 +4963,7 @@ const struct Item gItemsInfo[] = [ITEM_DREAD_PLATE] = { - .name = _("Dread Plate"), + .name = ITEM_NAME("Dread Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4978,7 +4983,7 @@ const struct Item gItemsInfo[] = [ITEM_IRON_PLATE] = { - .name = _("Iron Plate"), + .name = ITEM_NAME("Iron Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -4998,7 +5003,7 @@ const struct Item gItemsInfo[] = [ITEM_PIXIE_PLATE] = { - .name = _("Pixie Plate"), + .name = ITEM_NAME("Pixie Plate"), .price = 1000, .holdEffect = HOLD_EFFECT_PLATE, .holdEffectParam = 20, @@ -5020,7 +5025,7 @@ const struct Item gItemsInfo[] = [ITEM_DOUSE_DRIVE] = { - .name = _("Douse Drive"), + .name = ITEM_NAME("Douse Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -5038,7 +5043,7 @@ const struct Item gItemsInfo[] = [ITEM_SHOCK_DRIVE] = { - .name = _("Shock Drive"), + .name = ITEM_NAME("Shock Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -5057,7 +5062,7 @@ const struct Item gItemsInfo[] = [ITEM_BURN_DRIVE] = { - .name = _("Burn Drive"), + .name = ITEM_NAME("Burn Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -5076,7 +5081,7 @@ const struct Item gItemsInfo[] = [ITEM_CHILL_DRIVE] = { - .name = _("Chill Drive"), + .name = ITEM_NAME("Chill Drive"), .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING( @@ -5097,8 +5102,8 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_MEMORY] = { - .name = _("Fire Memory"), - .pluralName = _("Fire Memories"), + .name = ITEM_NAME("Fire Memory"), + .pluralName = ITEM_PLURAL_NAME("Fire Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5118,8 +5123,8 @@ const struct Item gItemsInfo[] = [ITEM_WATER_MEMORY] = { - .name = _("Water Memory"), - .pluralName = _("Water Memories"), + .name = ITEM_NAME("Water Memory"), + .pluralName = ITEM_PLURAL_NAME("Water Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5139,8 +5144,8 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_MEMORY] = { - .name = _("Electric Memory"), - .pluralName = _("Electric Memories"), + .name = ITEM_NAME("Electric Memory"), + .pluralName = ITEM_PLURAL_NAME("Electric Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5160,8 +5165,8 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_MEMORY] = { - .name = _("Grass Memory"), - .pluralName = _("Grass Memories"), + .name = ITEM_NAME("Grass Memory"), + .pluralName = ITEM_PLURAL_NAME("Grass Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5181,8 +5186,8 @@ const struct Item gItemsInfo[] = [ITEM_ICE_MEMORY] = { - .name = _("Ice Memory"), - .pluralName = _("Ice Memories"), + .name = ITEM_NAME("Ice Memory"), + .pluralName = ITEM_PLURAL_NAME("Ice Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5202,8 +5207,8 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_MEMORY] = { - .name = _("Fighting Memory"), - .pluralName = _("Fighting Memories"), + .name = ITEM_NAME("Fighting Memory"), + .pluralName = ITEM_PLURAL_NAME("Fighting Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5223,8 +5228,8 @@ const struct Item gItemsInfo[] = [ITEM_POISON_MEMORY] = { - .name = _("Poison Memory"), - .pluralName = _("Poison Memories"), + .name = ITEM_NAME("Poison Memory"), + .pluralName = ITEM_PLURAL_NAME("Poison Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5244,8 +5249,8 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_MEMORY] = { - .name = _("Ground Memory"), - .pluralName = _("Ground Memories"), + .name = ITEM_NAME("Ground Memory"), + .pluralName = ITEM_PLURAL_NAME("Ground Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5265,8 +5270,8 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_MEMORY] = { - .name = _("Flying Memory"), - .pluralName = _("Flying Memories"), + .name = ITEM_NAME("Flying Memory"), + .pluralName = ITEM_PLURAL_NAME("Flying Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5286,8 +5291,8 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_MEMORY] = { - .name = _("Psychic Memory"), - .pluralName = _("Psychic Memories"), + .name = ITEM_NAME("Psychic Memory"), + .pluralName = ITEM_PLURAL_NAME("Psychic Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5307,8 +5312,8 @@ const struct Item gItemsInfo[] = [ITEM_BUG_MEMORY] = { - .name = _("Bug Memory"), - .pluralName = _("Bug Memories"), + .name = ITEM_NAME("Bug Memory"), + .pluralName = ITEM_PLURAL_NAME("Bug Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5328,8 +5333,8 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_MEMORY] = { - .name = _("Rock Memory"), - .pluralName = _("Rock Memories"), + .name = ITEM_NAME("Rock Memory"), + .pluralName = ITEM_PLURAL_NAME("Rock Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5349,8 +5354,8 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_MEMORY] = { - .name = _("Ghost Memory"), - .pluralName = _("Ghost Memories"), + .name = ITEM_NAME("Ghost Memory"), + .pluralName = ITEM_PLURAL_NAME("Ghost Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5370,8 +5375,8 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_MEMORY] = { - .name = _("Dragon Memory"), - .pluralName = _("Dragon Memories"), + .name = ITEM_NAME("Dragon Memory"), + .pluralName = ITEM_PLURAL_NAME("Dragon Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5391,8 +5396,8 @@ const struct Item gItemsInfo[] = [ITEM_DARK_MEMORY] = { - .name = _("Dark Memory"), - .pluralName = _("Dark Memories"), + .name = ITEM_NAME("Dark Memory"), + .pluralName = ITEM_PLURAL_NAME("Dark Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5412,8 +5417,8 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_MEMORY] = { - .name = _("Steel Memory"), - .pluralName = _("Steel Memories"), + .name = ITEM_NAME("Steel Memory"), + .pluralName = ITEM_PLURAL_NAME("Steel Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5433,8 +5438,8 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_MEMORY] = { - .name = _("Fairy Memory"), - .pluralName = _("Fairy Memories"), + .name = ITEM_NAME("Fairy Memory"), + .pluralName = ITEM_PLURAL_NAME("Fairy Memories"), .price = 1000, .holdEffect = HOLD_EFFECT_MEMORY, .holdEffectParam = 0, @@ -5454,7 +5459,7 @@ const struct Item gItemsInfo[] = [ITEM_RUSTED_SWORD] = { - .name = _("Rusted Sword"), + .name = ITEM_NAME("Rusted Sword"), .price = 0, .description = COMPOUND_STRING( "A rusty sword. A\n" @@ -5470,7 +5475,7 @@ const struct Item gItemsInfo[] = [ITEM_RUSTED_SHIELD] = { - .name = _("Rusted Shield"), + .name = ITEM_NAME("Rusted Shield"), .price = 0, .description = COMPOUND_STRING( "A rusty shield. A\n" @@ -5488,7 +5493,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_ORB] = { - .name = _("Red Orb"), + .name = ITEM_NAME("Red Orb"), .price = 0, .holdEffect = HOLD_EFFECT_PRIMAL_ORB, .description = COMPOUND_STRING( @@ -5505,7 +5510,7 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_ORB] = { - .name = _("Blue Orb"), + .name = ITEM_NAME("Blue Orb"), .price = 0, .holdEffect = HOLD_EFFECT_PRIMAL_ORB, .description = COMPOUND_STRING( @@ -5524,7 +5529,7 @@ const struct Item gItemsInfo[] = [ITEM_VENUSAURITE] = { - .name = _("Venusaurite"), + .name = ITEM_NAME("Venusaurite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5542,8 +5547,8 @@ const struct Item gItemsInfo[] = [ITEM_CHARIZARDITE_X] = { - .name = _("Charizardite X"), - .pluralName = _("Charizardites X"), + .name = ITEM_NAME("Charizardite X"), + .pluralName = ITEM_PLURAL_NAME("Charizardites X"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, @@ -5558,8 +5563,8 @@ const struct Item gItemsInfo[] = [ITEM_CHARIZARDITE_Y] = { - .name = _("Charizardite Y"), - .pluralName = _("Charizardites Y"), + .name = ITEM_NAME("Charizardite Y"), + .pluralName = ITEM_PLURAL_NAME("Charizardites Y"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sCharizarditeDesc, @@ -5574,7 +5579,7 @@ const struct Item gItemsInfo[] = [ITEM_BLASTOISINITE] = { - .name = _("Blastoisinite"), + .name = ITEM_NAME("Blastoisinite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5592,7 +5597,7 @@ const struct Item gItemsInfo[] = [ITEM_BEEDRILLITE] = { - .name = _("Beedrillite"), + .name = ITEM_NAME("Beedrillite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5610,7 +5615,7 @@ const struct Item gItemsInfo[] = [ITEM_PIDGEOTITE] = { - .name = _("Pidgeotite"), + .name = ITEM_NAME("Pidgeotite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5628,7 +5633,7 @@ const struct Item gItemsInfo[] = [ITEM_ALAKAZITE] = { - .name = _("Alakazite"), + .name = ITEM_NAME("Alakazite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5646,7 +5651,7 @@ const struct Item gItemsInfo[] = [ITEM_SLOWBRONITE] = { - .name = _("Slowbronite"), + .name = ITEM_NAME("Slowbronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5664,7 +5669,7 @@ const struct Item gItemsInfo[] = [ITEM_GENGARITE] = { - .name = _("Gengarite"), + .name = ITEM_NAME("Gengarite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5682,7 +5687,7 @@ const struct Item gItemsInfo[] = [ITEM_KANGASKHANITE] = { - .name = _("Kangaskhanite"), + .name = ITEM_NAME("Kangaskhanite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5700,7 +5705,7 @@ const struct Item gItemsInfo[] = [ITEM_PINSIRITE] = { - .name = _("Pinsirite"), + .name = ITEM_NAME("Pinsirite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5718,7 +5723,7 @@ const struct Item gItemsInfo[] = [ITEM_GYARADOSITE] = { - .name = _("Gyaradosite"), + .name = ITEM_NAME("Gyaradosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5736,7 +5741,7 @@ const struct Item gItemsInfo[] = [ITEM_AERODACTYLITE] = { - .name = _("Aerodactylite"), + .name = ITEM_NAME("Aerodactylite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5754,8 +5759,8 @@ const struct Item gItemsInfo[] = [ITEM_MEWTWONITE_X] = { - .name = _("Mewtwonite X"), - .pluralName = _("Mewtwonites X"), + .name = ITEM_NAME("Mewtwonite X"), + .pluralName = ITEM_PLURAL_NAME("Mewtwonites X"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, @@ -5770,8 +5775,8 @@ const struct Item gItemsInfo[] = [ITEM_MEWTWONITE_Y] = { - .name = _("Mewtwonite Y"), - .pluralName = _("Mewtwonites Y"), + .name = ITEM_NAME("Mewtwonite Y"), + .pluralName = ITEM_PLURAL_NAME("Mewtwonites Y"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = sMewtwoniteDesc, @@ -5786,7 +5791,7 @@ const struct Item gItemsInfo[] = [ITEM_AMPHAROSITE] = { - .name = _("Ampharosite"), + .name = ITEM_NAME("Ampharosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5804,7 +5809,7 @@ const struct Item gItemsInfo[] = [ITEM_STEELIXITE] = { - .name = _("Steelixite"), + .name = ITEM_NAME("Steelixite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5822,7 +5827,7 @@ const struct Item gItemsInfo[] = [ITEM_SCIZORITE] = { - .name = _("Scizorite"), + .name = ITEM_NAME("Scizorite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5840,7 +5845,7 @@ const struct Item gItemsInfo[] = [ITEM_HERACRONITE] = { - .name = _("Heracronite"), + .name = ITEM_NAME("Heracronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5858,7 +5863,7 @@ const struct Item gItemsInfo[] = [ITEM_HOUNDOOMINITE] = { - .name = _("Houndoominite"), + .name = ITEM_NAME("Houndoominite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5876,7 +5881,7 @@ const struct Item gItemsInfo[] = [ITEM_TYRANITARITE] = { - .name = _("Tyranitarite"), + .name = ITEM_NAME("Tyranitarite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5894,7 +5899,7 @@ const struct Item gItemsInfo[] = [ITEM_SCEPTILITE] = { - .name = _("Sceptilite"), + .name = ITEM_NAME("Sceptilite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5912,7 +5917,7 @@ const struct Item gItemsInfo[] = [ITEM_BLAZIKENITE] = { - .name = _("Blazikenite"), + .name = ITEM_NAME("Blazikenite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5930,7 +5935,7 @@ const struct Item gItemsInfo[] = [ITEM_SWAMPERTITE] = { - .name = _("Swampertite"), + .name = ITEM_NAME("Swampertite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5948,7 +5953,7 @@ const struct Item gItemsInfo[] = [ITEM_GARDEVOIRITE] = { - .name = _("Gardevoirite"), + .name = ITEM_NAME("Gardevoirite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5966,7 +5971,7 @@ const struct Item gItemsInfo[] = [ITEM_SABLENITE] = { - .name = _("Sablenite"), + .name = ITEM_NAME("Sablenite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -5984,7 +5989,7 @@ const struct Item gItemsInfo[] = [ITEM_MAWILITE] = { - .name = _("Mawilite"), + .name = ITEM_NAME("Mawilite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6002,7 +6007,7 @@ const struct Item gItemsInfo[] = [ITEM_AGGRONITE] = { - .name = _("Aggronite"), + .name = ITEM_NAME("Aggronite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6020,7 +6025,7 @@ const struct Item gItemsInfo[] = [ITEM_MEDICHAMITE] = { - .name = _("Medichamite"), + .name = ITEM_NAME("Medichamite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6038,7 +6043,7 @@ const struct Item gItemsInfo[] = [ITEM_MANECTITE] = { - .name = _("Manectite"), + .name = ITEM_NAME("Manectite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6056,7 +6061,7 @@ const struct Item gItemsInfo[] = [ITEM_SHARPEDONITE] = { - .name = _("Sharpedonite"), + .name = ITEM_NAME("Sharpedonite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6074,7 +6079,7 @@ const struct Item gItemsInfo[] = [ITEM_CAMERUPTITE] = { - .name = _("Cameruptite"), + .name = ITEM_NAME("Cameruptite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6092,7 +6097,7 @@ const struct Item gItemsInfo[] = [ITEM_ALTARIANITE] = { - .name = _("Altarianite"), + .name = ITEM_NAME("Altarianite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6110,7 +6115,7 @@ const struct Item gItemsInfo[] = [ITEM_BANETTITE] = { - .name = _("Banettite"), + .name = ITEM_NAME("Banettite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6128,7 +6133,7 @@ const struct Item gItemsInfo[] = [ITEM_ABSOLITE] = { - .name = _("Absolite"), + .name = ITEM_NAME("Absolite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6146,7 +6151,7 @@ const struct Item gItemsInfo[] = [ITEM_GLALITITE] = { - .name = _("Glalitite"), + .name = ITEM_NAME("Glalitite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6164,7 +6169,7 @@ const struct Item gItemsInfo[] = [ITEM_SALAMENCITE] = { - .name = _("Salamencite"), + .name = ITEM_NAME("Salamencite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6182,7 +6187,7 @@ const struct Item gItemsInfo[] = [ITEM_METAGROSSITE] = { - .name = _("Metagrossite"), + .name = ITEM_NAME("Metagrossite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6200,7 +6205,7 @@ const struct Item gItemsInfo[] = [ITEM_LATIASITE] = { - .name = _("Latiasite"), + .name = ITEM_NAME("Latiasite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6218,7 +6223,7 @@ const struct Item gItemsInfo[] = [ITEM_LATIOSITE] = { - .name = _("Latiosite"), + .name = ITEM_NAME("Latiosite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6236,7 +6241,7 @@ const struct Item gItemsInfo[] = [ITEM_LOPUNNITE] = { - .name = _("Lopunnite"), + .name = ITEM_NAME("Lopunnite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6254,7 +6259,7 @@ const struct Item gItemsInfo[] = [ITEM_GARCHOMPITE] = { - .name = _("Garchompite"), + .name = ITEM_NAME("Garchompite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6272,7 +6277,7 @@ const struct Item gItemsInfo[] = [ITEM_LUCARIONITE] = { - .name = _("Lucarionite"), + .name = ITEM_NAME("Lucarionite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6290,7 +6295,7 @@ const struct Item gItemsInfo[] = [ITEM_ABOMASITE] = { - .name = _("Abomasite"), + .name = ITEM_NAME("Abomasite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6308,7 +6313,7 @@ const struct Item gItemsInfo[] = [ITEM_GALLADITE] = { - .name = _("Galladite"), + .name = ITEM_NAME("Galladite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6326,7 +6331,7 @@ const struct Item gItemsInfo[] = [ITEM_AUDINITE] = { - .name = _("Audinite"), + .name = ITEM_NAME("Audinite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6344,7 +6349,7 @@ const struct Item gItemsInfo[] = [ITEM_DIANCITE] = { - .name = _("Diancite"), + .name = ITEM_NAME("Diancite"), .price = 0, .holdEffect = HOLD_EFFECT_MEGA_STONE, .description = COMPOUND_STRING( @@ -6364,7 +6369,7 @@ const struct Item gItemsInfo[] = [ITEM_NORMAL_GEM] = { - .name = _("Normal Gem"), + .name = ITEM_NAME("Normal Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6383,7 +6388,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_GEM] = { - .name = _("Fire Gem"), + .name = ITEM_NAME("Fire Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6402,7 +6407,7 @@ const struct Item gItemsInfo[] = [ITEM_WATER_GEM] = { - .name = _("Water Gem"), + .name = ITEM_NAME("Water Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6421,7 +6426,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_GEM] = { - .name = _("Electric Gem"), + .name = ITEM_NAME("Electric Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6440,7 +6445,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_GEM] = { - .name = _("Grass Gem"), + .name = ITEM_NAME("Grass Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6459,7 +6464,7 @@ const struct Item gItemsInfo[] = [ITEM_ICE_GEM] = { - .name = _("Ice Gem"), + .name = ITEM_NAME("Ice Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6478,7 +6483,7 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_GEM] = { - .name = _("Fighting Gem"), + .name = ITEM_NAME("Fighting Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6497,7 +6502,7 @@ const struct Item gItemsInfo[] = [ITEM_POISON_GEM] = { - .name = _("Poison Gem"), + .name = ITEM_NAME("Poison Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6516,7 +6521,7 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_GEM] = { - .name = _("Ground Gem"), + .name = ITEM_NAME("Ground Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6535,7 +6540,7 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_GEM] = { - .name = _("Flying Gem"), + .name = ITEM_NAME("Flying Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6554,7 +6559,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_GEM] = { - .name = _("Psychic Gem"), + .name = ITEM_NAME("Psychic Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6573,7 +6578,7 @@ const struct Item gItemsInfo[] = [ITEM_BUG_GEM] = { - .name = _("Bug Gem"), + .name = ITEM_NAME("Bug Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6592,7 +6597,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_GEM] = { - .name = _("Rock Gem"), + .name = ITEM_NAME("Rock Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6611,7 +6616,7 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_GEM] = { - .name = _("Ghost Gem"), + .name = ITEM_NAME("Ghost Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6630,7 +6635,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_GEM] = { - .name = _("Dragon Gem"), + .name = ITEM_NAME("Dragon Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6649,7 +6654,7 @@ const struct Item gItemsInfo[] = [ITEM_DARK_GEM] = { - .name = _("Dark Gem"), + .name = ITEM_NAME("Dark Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6668,7 +6673,7 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_GEM] = { - .name = _("Steel Gem"), + .name = ITEM_NAME("Steel Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6687,7 +6692,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_GEM] = { - .name = _("Fairy Gem"), + .name = ITEM_NAME("Fairy Gem"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, @@ -6708,7 +6713,7 @@ const struct Item gItemsInfo[] = [ITEM_NORMALIUM_Z] = { - .name = _("Normalium Z"), + .name = ITEM_NAME("Normalium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6726,7 +6731,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRIUM_Z] = { - .name = _("Firium Z"), + .name = ITEM_NAME("Firium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6744,7 +6749,7 @@ const struct Item gItemsInfo[] = [ITEM_WATERIUM_Z] = { - .name = _("Waterium Z"), + .name = ITEM_NAME("Waterium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6762,7 +6767,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIUM_Z] = { - .name = _("Electrium Z"), + .name = ITEM_NAME("Electrium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6780,7 +6785,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASSIUM_Z] = { - .name = _("Grassium Z"), + .name = ITEM_NAME("Grassium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6798,7 +6803,7 @@ const struct Item gItemsInfo[] = [ITEM_ICIUM_Z] = { - .name = _("Icium Z"), + .name = ITEM_NAME("Icium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6816,7 +6821,7 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTINIUM_Z] = { - .name = _("Fightinium Z"), + .name = ITEM_NAME("Fightinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6834,7 +6839,7 @@ const struct Item gItemsInfo[] = [ITEM_POISONIUM_Z] = { - .name = _("Poisonium Z"), + .name = ITEM_NAME("Poisonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6852,7 +6857,7 @@ const struct Item gItemsInfo[] = [ITEM_GROUNDIUM_Z] = { - .name = _("Groundium Z"), + .name = ITEM_NAME("Groundium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6870,7 +6875,7 @@ const struct Item gItemsInfo[] = [ITEM_FLYINIUM_Z] = { - .name = _("Flyinium Z"), + .name = ITEM_NAME("Flyinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6888,7 +6893,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIUM_Z] = { - .name = _("Psychium Z"), + .name = ITEM_NAME("Psychium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6906,7 +6911,7 @@ const struct Item gItemsInfo[] = [ITEM_BUGINIUM_Z] = { - .name = _("Buginium Z"), + .name = ITEM_NAME("Buginium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6924,7 +6929,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCKIUM_Z] = { - .name = _("Rockium Z"), + .name = ITEM_NAME("Rockium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6942,7 +6947,7 @@ const struct Item gItemsInfo[] = [ITEM_GHOSTIUM_Z] = { - .name = _("Ghostium Z"), + .name = ITEM_NAME("Ghostium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6960,7 +6965,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGONIUM_Z] = { - .name = _("Dragonium Z"), + .name = ITEM_NAME("Dragonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6978,7 +6983,7 @@ const struct Item gItemsInfo[] = [ITEM_DARKINIUM_Z] = { - .name = _("Darkinium Z"), + .name = ITEM_NAME("Darkinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -6996,7 +7001,7 @@ const struct Item gItemsInfo[] = [ITEM_STEELIUM_Z] = { - .name = _("Steelium Z"), + .name = ITEM_NAME("Steelium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7014,7 +7019,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRIUM_Z] = { - .name = _("Fairium Z"), + .name = ITEM_NAME("Fairium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7032,7 +7037,7 @@ const struct Item gItemsInfo[] = [ITEM_PIKANIUM_Z] = { - .name = _("Pikanium Z"), + .name = ITEM_NAME("Pikanium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7050,7 +7055,7 @@ const struct Item gItemsInfo[] = [ITEM_EEVIUM_Z] = { - .name = _("Eevium Z"), + .name = ITEM_NAME("Eevium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7068,7 +7073,7 @@ const struct Item gItemsInfo[] = [ITEM_SNORLIUM_Z] = { - .name = _("Snorlium Z"), + .name = ITEM_NAME("Snorlium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7086,7 +7091,7 @@ const struct Item gItemsInfo[] = [ITEM_MEWNIUM_Z] = { - .name = _("Mewnium Z"), + .name = ITEM_NAME("Mewnium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7104,7 +7109,7 @@ const struct Item gItemsInfo[] = [ITEM_DECIDIUM_Z] = { - .name = _("Decidium Z"), + .name = ITEM_NAME("Decidium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7122,7 +7127,7 @@ const struct Item gItemsInfo[] = [ITEM_INCINIUM_Z] = { - .name = _("Incinium Z"), + .name = ITEM_NAME("Incinium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7140,7 +7145,7 @@ const struct Item gItemsInfo[] = [ITEM_PRIMARIUM_Z] = { - .name = _("Primarium Z"), + .name = ITEM_NAME("Primarium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7158,7 +7163,7 @@ const struct Item gItemsInfo[] = [ITEM_LYCANIUM_Z] = { - .name = _("Lycanium Z"), + .name = ITEM_NAME("Lycanium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7176,7 +7181,7 @@ const struct Item gItemsInfo[] = [ITEM_MIMIKIUM_Z] = { - .name = _("Mimikium Z"), + .name = ITEM_NAME("Mimikium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7194,7 +7199,7 @@ const struct Item gItemsInfo[] = [ITEM_KOMMONIUM_Z] = { - .name = _("Kommonium Z"), + .name = ITEM_NAME("Kommonium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7212,7 +7217,7 @@ const struct Item gItemsInfo[] = [ITEM_TAPUNIUM_Z] = { - .name = _("Tapunium Z"), + .name = ITEM_NAME("Tapunium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7230,7 +7235,7 @@ const struct Item gItemsInfo[] = [ITEM_SOLGANIUM_Z] = { - .name = _("Solganium Z"), + .name = ITEM_NAME("Solganium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7248,7 +7253,7 @@ const struct Item gItemsInfo[] = [ITEM_LUNALIUM_Z] = { - .name = _("Lunalium Z"), + .name = ITEM_NAME("Lunalium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7266,7 +7271,7 @@ const struct Item gItemsInfo[] = [ITEM_MARSHADIUM_Z] = { - .name = _("Marshadium Z"), + .name = ITEM_NAME("Marshadium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7284,7 +7289,7 @@ const struct Item gItemsInfo[] = [ITEM_ALORAICHIUM_Z] = { - .name = _("Aloraichium Z"), + .name = ITEM_NAME("Aloraichium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7302,7 +7307,7 @@ const struct Item gItemsInfo[] = [ITEM_PIKASHUNIUM_Z] = { - .name = _("Pikashunium Z"), + .name = ITEM_NAME("Pikashunium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7320,7 +7325,7 @@ const struct Item gItemsInfo[] = [ITEM_ULTRANECROZIUM_Z] = { - .name = _("Ultranecrozium Z"), + .name = ITEM_NAME("Ultranecrozium Z"), .price = 0, .holdEffect = HOLD_EFFECT_Z_CRYSTAL, .description = COMPOUND_STRING( @@ -7340,7 +7345,7 @@ const struct Item gItemsInfo[] = [ITEM_LIGHT_BALL] = { - .name = _("Light Ball"), + .name = ITEM_NAME("Light Ball"), .price = (I_PRICE >= GEN_7) ? 1000 : 100, .holdEffect = HOLD_EFFECT_LIGHT_BALL, .description = COMPOUND_STRING( @@ -7358,7 +7363,7 @@ const struct Item gItemsInfo[] = [ITEM_LEEK] = { - .name = _("Leek"), + .name = ITEM_NAME("Leek"), .price = (I_PRICE >= GEN_7) ? 1000 : 200, .holdEffect = HOLD_EFFECT_LEEK, .description = COMPOUND_STRING( @@ -7376,7 +7381,7 @@ const struct Item gItemsInfo[] = [ITEM_THICK_CLUB] = { - .name = _("Thick Club"), + .name = ITEM_NAME("Thick Club"), .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffect = HOLD_EFFECT_THICK_CLUB, .description = COMPOUND_STRING( @@ -7394,8 +7399,8 @@ const struct Item gItemsInfo[] = [ITEM_LUCKY_PUNCH] = { - .name = _("Lucky Punch"), - .pluralName = _("Lucky Punches"), + .name = ITEM_NAME("Lucky Punch"), + .pluralName = ITEM_PLURAL_NAME("Lucky Punches"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_LUCKY_PUNCH, .description = COMPOUND_STRING( @@ -7413,8 +7418,8 @@ const struct Item gItemsInfo[] = [ITEM_METAL_POWDER] = { - .name = _("Metal Powder"), - .pluralName = _("Metal Powder"), + .name = ITEM_NAME("Metal Powder"), + .pluralName = ITEM_PLURAL_NAME("Metal Powder"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_METAL_POWDER, .description = COMPOUND_STRING( @@ -7432,8 +7437,8 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_POWDER] = { - .name = _("Quick Powder"), - .pluralName = _("Quick Powder"), + .name = ITEM_NAME("Quick Powder"), + .pluralName = ITEM_PLURAL_NAME("Quick Powder"), .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_QUICK_POWDER, .description = COMPOUND_STRING( @@ -7451,7 +7456,7 @@ const struct Item gItemsInfo[] = [ITEM_DEEP_SEA_SCALE] = { - .name = _("Deep Sea Scale"), + .name = ITEM_NAME("Deep Sea Scale"), .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_SCALE, .description = COMPOUND_STRING( @@ -7470,8 +7475,8 @@ const struct Item gItemsInfo[] = [ITEM_DEEP_SEA_TOOTH] = { - .name = _("Deep Sea Tooth"), - .pluralName = _("Deep Sea Teeth"), + .name = ITEM_NAME("Deep Sea Tooth"), + .pluralName = ITEM_PLURAL_NAME("Deep Sea Teeth"), .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_TOOTH, .description = COMPOUND_STRING( @@ -7490,7 +7495,7 @@ const struct Item gItemsInfo[] = [ITEM_SOUL_DEW] = { - .name = _("Soul Dew"), + .name = ITEM_NAME("Soul Dew"), .price = (I_PRICE >= GEN_7) ? 0 : 200, .holdEffect = HOLD_EFFECT_SOUL_DEW, .holdEffectParam = B_SOUL_DEW_BOOST >= GEN_7 ? 20 : 50, @@ -7515,7 +7520,7 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_ORB] = { - .name = _("Adamant Orb"), + .name = ITEM_NAME("Adamant Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, @@ -7534,7 +7539,7 @@ const struct Item gItemsInfo[] = [ITEM_LUSTROUS_ORB] = { - .name = _("Lustrous Orb"), + .name = ITEM_NAME("Lustrous Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, @@ -7553,7 +7558,7 @@ const struct Item gItemsInfo[] = [ITEM_GRISEOUS_ORB] = { - .name = _("Griseous Orb"), + .name = ITEM_NAME("Griseous Orb"), .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, @@ -7574,7 +7579,7 @@ const struct Item gItemsInfo[] = [ITEM_SEA_INCENSE] = { - .name = _("Sea Incense"), + .name = ITEM_NAME("Sea Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, @@ -7591,7 +7596,7 @@ const struct Item gItemsInfo[] = [ITEM_LAX_INCENSE] = { - .name = _("Lax Incense"), + .name = ITEM_NAME("Lax Incense"), .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, @@ -7610,7 +7615,7 @@ const struct Item gItemsInfo[] = [ITEM_ODD_INCENSE] = { - .name = _("Odd Incense"), + .name = ITEM_NAME("Odd Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, @@ -7627,7 +7632,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_INCENSE] = { - .name = _("Rock Incense"), + .name = ITEM_NAME("Rock Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, @@ -7644,7 +7649,7 @@ const struct Item gItemsInfo[] = [ITEM_FULL_INCENSE] = { - .name = _("Full Incense"), + .name = ITEM_NAME("Full Incense"), .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .holdEffectParam = 5, @@ -7660,7 +7665,7 @@ const struct Item gItemsInfo[] = [ITEM_WAVE_INCENSE] = { - .name = _("Wave Incense"), + .name = ITEM_NAME("Wave Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, @@ -7677,7 +7682,7 @@ const struct Item gItemsInfo[] = [ITEM_ROSE_INCENSE] = { - .name = _("Rose Incense"), + .name = ITEM_NAME("Rose Incense"), .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = 20, @@ -7694,7 +7699,7 @@ const struct Item gItemsInfo[] = [ITEM_LUCK_INCENSE] = { - .name = _("Luck Incense"), + .name = ITEM_NAME("Luck Incense"), .price = (I_PRICE >= GEN_7) ? 11000 : 9600, .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, @@ -7709,7 +7714,7 @@ const struct Item gItemsInfo[] = [ITEM_PURE_INCENSE] = { - .name = _("Pure Incense"), + .name = ITEM_NAME("Pure Incense"), .price = (I_PRICE >= GEN_7) ? 6000 : 9600, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, @@ -7726,8 +7731,8 @@ const struct Item gItemsInfo[] = [ITEM_RED_SCARF] = { - .name = _("Red Scarf"), - .pluralName = _("Red Scarves"), + .name = ITEM_NAME("Red Scarf"), + .pluralName = ITEM_PLURAL_NAME("Red Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that\n" @@ -7744,8 +7749,8 @@ const struct Item gItemsInfo[] = [ITEM_BLUE_SCARF] = { - .name = _("Blue Scarf"), - .pluralName = _("Blue Scarves"), + .name = ITEM_NAME("Blue Scarf"), + .pluralName = ITEM_PLURAL_NAME("Blue Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that\n" @@ -7762,8 +7767,8 @@ const struct Item gItemsInfo[] = [ITEM_PINK_SCARF] = { - .name = _("Pink Scarf"), - .pluralName = _("Pink Scarves"), + .name = ITEM_NAME("Pink Scarf"), + .pluralName = ITEM_PLURAL_NAME("Pink Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that\n" @@ -7780,8 +7785,8 @@ const struct Item gItemsInfo[] = [ITEM_GREEN_SCARF] = { - .name = _("Green Scarf"), - .pluralName = _("Green Scarves"), + .name = ITEM_NAME("Green Scarf"), + .pluralName = ITEM_PLURAL_NAME("Green Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that\n" @@ -7798,8 +7803,8 @@ const struct Item gItemsInfo[] = [ITEM_YELLOW_SCARF] = { - .name = _("Yellow Scarf"), - .pluralName = _("Yellow Scarves"), + .name = ITEM_NAME("Yellow Scarf"), + .pluralName = ITEM_PLURAL_NAME("Yellow Scarves"), .price = 100, .description = COMPOUND_STRING( "A hold item that\n" @@ -7818,7 +7823,7 @@ const struct Item gItemsInfo[] = [ITEM_MACHO_BRACE] = { - .name = _("Macho Brace"), + .name = ITEM_NAME("Macho Brace"), .price = 3000, .holdEffect = HOLD_EFFECT_MACHO_BRACE, .description = COMPOUND_STRING( @@ -7836,7 +7841,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_WEIGHT] = { - .name = _("Power Weight"), + .name = ITEM_NAME("Power Weight"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7856,7 +7861,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BRACER] = { - .name = _("Power Bracer"), + .name = ITEM_NAME("Power Bracer"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7876,7 +7881,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BELT] = { - .name = _("Power Belt"), + .name = ITEM_NAME("Power Belt"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7896,8 +7901,8 @@ const struct Item gItemsInfo[] = [ITEM_POWER_LENS] = { - .name = _("Power Lens"), - .pluralName = _("Power Lenses"), + .name = ITEM_NAME("Power Lens"), + .pluralName = ITEM_PLURAL_NAME("Power Lenses"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7917,7 +7922,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_BAND] = { - .name = _("Power Band"), + .name = ITEM_NAME("Power Band"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7937,7 +7942,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_ANKLET] = { - .name = _("Power Anklet"), + .name = ITEM_NAME("Power Anklet"), .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = POWER_ITEM_BOOST, @@ -7959,8 +7964,8 @@ const struct Item gItemsInfo[] = [ITEM_SILK_SCARF] = { - .name = _("Silk Scarf"), - .pluralName = _("Silk Scarves"), + .name = ITEM_NAME("Silk Scarf"), + .pluralName = ITEM_PLURAL_NAME("Silk Scarves"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -7980,7 +7985,7 @@ const struct Item gItemsInfo[] = [ITEM_CHARCOAL] = { - .name = _("Charcoal"), + .name = ITEM_NAME("Charcoal"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 9800), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8000,8 +8005,8 @@ const struct Item gItemsInfo[] = [ITEM_MYSTIC_WATER] = { - .name = _("Mystic Water"), - .pluralName = _("Mystic Water"), + .name = ITEM_NAME("Mystic Water"), + .pluralName = ITEM_PLURAL_NAME("Mystic Water"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8021,7 +8026,7 @@ const struct Item gItemsInfo[] = [ITEM_MAGNET] = { - .name = _("Magnet"), + .name = ITEM_NAME("Magnet"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8041,7 +8046,7 @@ const struct Item gItemsInfo[] = [ITEM_MIRACLE_SEED] = { - .name = _("Miracle Seed"), + .name = ITEM_NAME("Miracle Seed"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8058,8 +8063,8 @@ const struct Item gItemsInfo[] = [ITEM_NEVER_MELT_ICE] = { - .name = _("Never-Melt Ice"), - .pluralName = _("Never-Melt Ice"), + .name = ITEM_NAME("Never-Melt Ice"), + .pluralName = ITEM_PLURAL_NAME("Never-Melt Ice"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8079,7 +8084,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_BELT] = { - .name = _("Black Belt"), + .name = ITEM_NAME("Black Belt"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8099,7 +8104,7 @@ const struct Item gItemsInfo[] = [ITEM_POISON_BARB] = { - .name = _("Poison Barb"), + .name = ITEM_NAME("Poison Barb"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8119,8 +8124,8 @@ const struct Item gItemsInfo[] = [ITEM_SOFT_SAND] = { - .name = _("Soft Sand"), - .pluralName = _("Soft Sand"), + .name = ITEM_NAME("Soft Sand"), + .pluralName = ITEM_PLURAL_NAME("Soft Sand"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8140,7 +8145,7 @@ const struct Item gItemsInfo[] = [ITEM_SHARP_BEAK] = { - .name = _("Sharp Beak"), + .name = ITEM_NAME("Sharp Beak"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8160,7 +8165,7 @@ const struct Item gItemsInfo[] = [ITEM_TWISTED_SPOON] = { - .name = _("Twisted Spoon"), + .name = ITEM_NAME("Twisted Spoon"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8177,8 +8182,8 @@ const struct Item gItemsInfo[] = [ITEM_SILVER_POWDER] = { - .name = _("Silver Powder"), - .pluralName = _("Silver Powder"), + .name = ITEM_NAME("Silver Powder"), + .pluralName = ITEM_PLURAL_NAME("Silver Powder"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8198,7 +8203,7 @@ const struct Item gItemsInfo[] = [ITEM_HARD_STONE] = { - .name = _("Hard Stone"), + .name = ITEM_NAME("Hard Stone"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8215,7 +8220,7 @@ const struct Item gItemsInfo[] = [ITEM_SPELL_TAG] = { - .name = _("Spell Tag"), + .name = ITEM_NAME("Spell Tag"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8235,7 +8240,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_FANG] = { - .name = _("Dragon Fang"), + .name = ITEM_NAME("Dragon Fang"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8255,8 +8260,8 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_GLASSES] = { - .name = _("Black Glasses"), - .pluralName = _("Black Glasses"), + .name = ITEM_NAME("Black Glasses"), + .pluralName = ITEM_PLURAL_NAME("Black Glasses"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8276,7 +8281,7 @@ const struct Item gItemsInfo[] = [ITEM_METAL_COAT] = { - .name = _("Metal Coat"), + .name = ITEM_NAME("Metal Coat"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 100), .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -8299,7 +8304,7 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_BAND] = { - .name = _("Choice Band"), + .name = ITEM_NAME("Choice Band"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_BAND, .description = COMPOUND_STRING( @@ -8317,8 +8322,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_SPECS] = { - .name = _("Choice Specs"), - .pluralName = _("Choice Specs"), + .name = ITEM_NAME("Choice Specs"), + .pluralName = ITEM_PLURAL_NAME("Choice Specs"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SPECS, .description = COMPOUND_STRING( @@ -8336,8 +8341,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_SCARF] = { - .name = _("Choice Scarf"), - .pluralName = _("Choice Scarves"), + .name = ITEM_NAME("Choice Scarf"), + .pluralName = ITEM_PLURAL_NAME("Choice Scarves"), .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SCARF, .description = COMPOUND_STRING( @@ -8357,7 +8362,7 @@ const struct Item gItemsInfo[] = [ITEM_FLAME_ORB] = { - .name = _("Flame Orb"), + .name = ITEM_NAME("Flame Orb"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLAME_ORB, .description = COMPOUND_STRING( @@ -8375,7 +8380,7 @@ const struct Item gItemsInfo[] = [ITEM_TOXIC_ORB] = { - .name = _("Toxic Orb"), + .name = ITEM_NAME("Toxic Orb"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_TOXIC_ORB, .description = COMPOUND_STRING( @@ -8395,7 +8400,7 @@ const struct Item gItemsInfo[] = [ITEM_DAMP_ROCK] = { - .name = _("Damp Rock"), + .name = ITEM_NAME("Damp Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DAMP_ROCK, .description = COMPOUND_STRING( @@ -8413,7 +8418,7 @@ const struct Item gItemsInfo[] = [ITEM_HEAT_ROCK] = { - .name = _("Heat Rock"), + .name = ITEM_NAME("Heat Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_HEAT_ROCK, .description = COMPOUND_STRING( @@ -8431,7 +8436,7 @@ const struct Item gItemsInfo[] = [ITEM_SMOOTH_ROCK] = { - .name = _("Smooth Rock"), + .name = ITEM_NAME("Smooth Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SMOOTH_ROCK, .description = COMPOUND_STRING( @@ -8449,7 +8454,7 @@ const struct Item gItemsInfo[] = [ITEM_ICY_ROCK] = { - .name = _("Icy Rock"), + .name = ITEM_NAME("Icy Rock"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ICY_ROCK, #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_HAIL @@ -8481,7 +8486,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_SEED] = { - .name = _("Electric Seed"), + .name = ITEM_NAME("Electric Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN, @@ -8500,7 +8505,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_SEED] = { - .name = _("Psychic Seed"), + .name = ITEM_NAME("Psychic Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN, @@ -8519,7 +8524,7 @@ const struct Item gItemsInfo[] = [ITEM_MISTY_SEED] = { - .name = _("Misty Seed"), + .name = ITEM_NAME("Misty Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_MISTY_TERRAIN, @@ -8538,7 +8543,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASSY_SEED] = { - .name = _("Grassy Seed"), + .name = ITEM_NAME("Grassy Seed"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_GRASSY_TERRAIN, @@ -8559,7 +8564,7 @@ const struct Item gItemsInfo[] = [ITEM_ABSORB_BULB] = { - .name = _("Absorb Bulb"), + .name = ITEM_NAME("Absorb Bulb"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ABSORB_BULB, .holdEffectParam = 0, @@ -8578,8 +8583,8 @@ const struct Item gItemsInfo[] = [ITEM_CELL_BATTERY] = { - .name = _("Cell Battery"), - .pluralName = _("Cell Batteries"), + .name = ITEM_NAME("Cell Battery"), + .pluralName = ITEM_PLURAL_NAME("Cell Batteries"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CELL_BATTERY, .holdEffectParam = 0, @@ -8598,8 +8603,8 @@ const struct Item gItemsInfo[] = [ITEM_LUMINOUS_MOSS] = { - .name = _("Luminous Moss"), - .pluralName = _("Luminous Moss"), + .name = ITEM_NAME("Luminous Moss"), + .pluralName = ITEM_PLURAL_NAME("Luminous Moss"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_LUMINOUS_MOSS, .holdEffectParam = 0, @@ -8618,7 +8623,7 @@ const struct Item gItemsInfo[] = [ITEM_SNOWBALL] = { - .name = _("Snowball"), + .name = ITEM_NAME("Snowball"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SNOWBALL, .holdEffectParam = 0, @@ -8639,8 +8644,8 @@ const struct Item gItemsInfo[] = [ITEM_BRIGHT_POWDER] = { - .name = _("Bright Powder"), - .pluralName = _("Bright Powder"), + .name = ITEM_NAME("Bright Powder"), + .pluralName = ITEM_PLURAL_NAME("Bright Powder"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 10), .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, @@ -8659,7 +8664,7 @@ const struct Item gItemsInfo[] = [ITEM_WHITE_HERB] = { - .name = _("White Herb"), + .name = ITEM_NAME("White Herb"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_WHITE_HERB, .description = COMPOUND_STRING( @@ -8677,7 +8682,7 @@ const struct Item gItemsInfo[] = [ITEM_EXP_SHARE] = { - .name = _("Exp. Share"), + .name = ITEM_NAME("Exp. Share"), .holdEffect = HOLD_EFFECT_EXP_SHARE, #if I_EXP_SHARE_ITEM >= GEN_6 .price = 0, @@ -8703,7 +8708,7 @@ const struct Item gItemsInfo[] = [ITEM_QUICK_CLAW] = { - .name = _("Quick Claw"), + .name = ITEM_NAME("Quick Claw"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_QUICK_CLAW, .holdEffectParam = 20, @@ -8722,7 +8727,7 @@ const struct Item gItemsInfo[] = [ITEM_SOOTHE_BELL] = { - .name = _("Soothe Bell"), + .name = ITEM_NAME("Soothe Bell"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_FRIENDSHIP_UP, .description = COMPOUND_STRING( @@ -8740,7 +8745,7 @@ const struct Item gItemsInfo[] = [ITEM_MENTAL_HERB] = { - .name = _("Mental Herb"), + .name = ITEM_NAME("Mental Herb"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_MENTAL_HERB, .description = COMPOUND_STRING( @@ -8764,7 +8769,7 @@ const struct Item gItemsInfo[] = [ITEM_KINGS_ROCK] = { - .name = _("King's Rock"), + .name = ITEM_NAME("King's Rock"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 5000 : 100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, @@ -8781,7 +8786,7 @@ const struct Item gItemsInfo[] = [ITEM_AMULET_COIN] = { - .name = _("Amulet Coin"), + .name = ITEM_NAME("Amulet Coin"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 10000 : 100), .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, @@ -8796,7 +8801,7 @@ const struct Item gItemsInfo[] = [ITEM_CLEANSE_TAG] = { - .name = _("Cleanse Tag"), + .name = ITEM_NAME("Cleanse Tag"), .price = (I_PRICE >= GEN_7) ? 5000 : 200, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, @@ -8811,7 +8816,7 @@ const struct Item gItemsInfo[] = [ITEM_SMOKE_BALL] = { - .name = _("Smoke Ball"), + .name = ITEM_NAME("Smoke Ball"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CAN_ALWAYS_RUN, .description = COMPOUND_STRING( @@ -8829,7 +8834,7 @@ const struct Item gItemsInfo[] = [ITEM_FOCUS_BAND] = { - .name = _("Focus Band"), + .name = ITEM_NAME("Focus Band"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_BAND, .holdEffectParam = 10, @@ -8848,7 +8853,7 @@ const struct Item gItemsInfo[] = [ITEM_LUCKY_EGG] = { - .name = _("Lucky Egg"), + .name = ITEM_NAME("Lucky Egg"), .price = (I_PRICE >= GEN_7) ? 10000 : 200, .holdEffect = HOLD_EFFECT_LUCKY_EGG, .description = COMPOUND_STRING( @@ -8866,8 +8871,8 @@ const struct Item gItemsInfo[] = [ITEM_SCOPE_LENS] = { - .name = _("Scope Lens"), - .pluralName = _("Scope Lenses"), + .name = ITEM_NAME("Scope Lens"), + .pluralName = ITEM_PLURAL_NAME("Scope Lenses"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING( @@ -8885,8 +8890,8 @@ const struct Item gItemsInfo[] = [ITEM_LEFTOVERS] = { - .name = _("Leftovers"), - .pluralName = _("Leftovers"), + .name = ITEM_NAME("Leftovers"), + .pluralName = ITEM_PLURAL_NAME("Leftovers"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LEFTOVERS, .holdEffectParam = 10, @@ -8905,7 +8910,7 @@ const struct Item gItemsInfo[] = [ITEM_SHELL_BELL] = { - .name = _("Shell Bell"), + .name = ITEM_NAME("Shell Bell"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SHELL_BELL, .holdEffectParam = 8, @@ -8924,8 +8929,8 @@ const struct Item gItemsInfo[] = [ITEM_WIDE_LENS] = { - .name = _("Wide Lens"), - .pluralName = _("Wide Lenses"), + .name = ITEM_NAME("Wide Lens"), + .pluralName = ITEM_PLURAL_NAME("Wide Lenses"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WIDE_LENS, .holdEffectParam = 10, @@ -8944,7 +8949,7 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_BAND] = { - .name = _("Muscle Band"), + .name = ITEM_NAME("Muscle Band"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_MUSCLE_BAND, .holdEffectParam = 10, @@ -8963,8 +8968,8 @@ const struct Item gItemsInfo[] = [ITEM_WISE_GLASSES] = { - .name = _("Wise Glasses"), - .pluralName = _("Wise Glasses"), + .name = ITEM_NAME("Wise Glasses"), + .pluralName = ITEM_PLURAL_NAME("Wise Glasses"), .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WISE_GLASSES, .holdEffectParam = 10, @@ -8983,7 +8988,7 @@ const struct Item gItemsInfo[] = [ITEM_EXPERT_BELT] = { - .name = _("Expert Belt"), + .name = ITEM_NAME("Expert Belt"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EXPERT_BELT, .holdEffectParam = 20, @@ -9002,8 +9007,8 @@ const struct Item gItemsInfo[] = [ITEM_LIGHT_CLAY] = { - .name = _("Light Clay"), - .pluralName = _("Light Clay"), + .name = ITEM_NAME("Light Clay"), + .pluralName = ITEM_PLURAL_NAME("Light Clay"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIGHT_CLAY, .description = COMPOUND_STRING( @@ -9021,7 +9026,7 @@ const struct Item gItemsInfo[] = [ITEM_LIFE_ORB] = { - .name = _("Life Orb"), + .name = ITEM_NAME("Life Orb"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIFE_ORB, .description = COMPOUND_STRING( @@ -9039,7 +9044,7 @@ const struct Item gItemsInfo[] = [ITEM_POWER_HERB] = { - .name = _("Power Herb"), + .name = ITEM_NAME("Power Herb"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_POWER_HERB, .description = COMPOUND_STRING( @@ -9057,8 +9062,8 @@ const struct Item gItemsInfo[] = [ITEM_FOCUS_SASH] = { - .name = _("Focus Sash"), - .pluralName = _("Focus Sashes"), + .name = ITEM_NAME("Focus Sash"), + .pluralName = ITEM_PLURAL_NAME("Focus Sashes"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_SASH, .description = COMPOUND_STRING( @@ -9076,8 +9081,8 @@ const struct Item gItemsInfo[] = [ITEM_ZOOM_LENS] = { - .name = _("Zoom Lens"), - .pluralName = _("Zoom Lenses"), + .name = ITEM_NAME("Zoom Lens"), + .pluralName = ITEM_PLURAL_NAME("Zoom Lenses"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ZOOM_LENS, .holdEffectParam = 20, @@ -9096,7 +9101,7 @@ const struct Item gItemsInfo[] = [ITEM_METRONOME] = { - .name = _("Metronome"), + .name = ITEM_NAME("Metronome"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_METRONOME, .holdEffectParam = 20, @@ -9115,7 +9120,7 @@ const struct Item gItemsInfo[] = [ITEM_IRON_BALL] = { - .name = _("Iron Ball"), + .name = ITEM_NAME("Iron Ball"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_IRON_BALL, .description = COMPOUND_STRING( @@ -9133,7 +9138,7 @@ const struct Item gItemsInfo[] = [ITEM_LAGGING_TAIL] = { - .name = _("Lagging Tail"), + .name = ITEM_NAME("Lagging Tail"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .description = sFullIncenseDesc, @@ -9148,7 +9153,7 @@ const struct Item gItemsInfo[] = [ITEM_DESTINY_KNOT] = { - .name = _("Destiny Knot"), + .name = ITEM_NAME("Destiny Knot"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DESTINY_KNOT, .description = COMPOUND_STRING( @@ -9166,8 +9171,8 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_SLUDGE] = { - .name = _("Black Sludge"), - .pluralName = _("Black Sludge"), + .name = ITEM_NAME("Black Sludge"), + .pluralName = ITEM_PLURAL_NAME("Black Sludge"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BLACK_SLUDGE, .description = COMPOUND_STRING( @@ -9185,7 +9190,7 @@ const struct Item gItemsInfo[] = [ITEM_GRIP_CLAW] = { - .name = _("Grip Claw"), + .name = ITEM_NAME("Grip Claw"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GRIP_CLAW, .description = COMPOUND_STRING( @@ -9203,7 +9208,7 @@ const struct Item gItemsInfo[] = [ITEM_STICKY_BARB] = { - .name = _("Sticky Barb"), + .name = ITEM_NAME("Sticky Barb"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_STICKY_BARB, .description = COMPOUND_STRING( @@ -9221,7 +9226,7 @@ const struct Item gItemsInfo[] = [ITEM_SHED_SHELL] = { - .name = _("Shed Shell"), + .name = ITEM_NAME("Shed Shell"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SHED_SHELL, .description = COMPOUND_STRING( @@ -9239,7 +9244,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_ROOT] = { - .name = _("Big Root"), + .name = ITEM_NAME("Big Root"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BIG_ROOT, .holdEffectParam = 30, @@ -9258,7 +9263,7 @@ const struct Item gItemsInfo[] = [ITEM_RAZOR_CLAW] = { - .name = _("Razor Claw"), + .name = ITEM_NAME("Razor Claw"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING( @@ -9277,7 +9282,7 @@ const struct Item gItemsInfo[] = [ITEM_RAZOR_FANG] = { - .name = _("Razor Fang"), + .name = ITEM_NAME("Razor Fang"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, @@ -9294,7 +9299,7 @@ const struct Item gItemsInfo[] = [ITEM_EVIOLITE] = { - .name = _("Eviolite"), + .name = ITEM_NAME("Eviolite"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EVIOLITE, .holdEffectParam = 50, @@ -9313,7 +9318,7 @@ const struct Item gItemsInfo[] = [ITEM_FLOAT_STONE] = { - .name = _("Float Stone"), + .name = ITEM_NAME("Float Stone"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLOAT_STONE, .description = COMPOUND_STRING( @@ -9331,7 +9336,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCKY_HELMET] = { - .name = _("Rocky Helmet"), + .name = ITEM_NAME("Rocky Helmet"), .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ROCKY_HELMET, .holdEffectParam = 0, @@ -9350,7 +9355,7 @@ const struct Item gItemsInfo[] = [ITEM_AIR_BALLOON] = { - .name = _("Air Balloon"), + .name = ITEM_NAME("Air Balloon"), .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_AIR_BALLOON, .holdEffectParam = 0, @@ -9369,7 +9374,7 @@ const struct Item gItemsInfo[] = [ITEM_RED_CARD] = { - .name = _("Red Card"), + .name = ITEM_NAME("Red Card"), .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RED_CARD, .holdEffectParam = 0, @@ -9388,7 +9393,7 @@ const struct Item gItemsInfo[] = [ITEM_RING_TARGET] = { - .name = _("Ring Target"), + .name = ITEM_NAME("Ring Target"), .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RING_TARGET, .holdEffectParam = 0, @@ -9407,7 +9412,7 @@ const struct Item gItemsInfo[] = [ITEM_BINDING_BAND] = { - .name = _("Binding Band"), + .name = ITEM_NAME("Binding Band"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BINDING_BAND, .description = COMPOUND_STRING( @@ -9425,7 +9430,7 @@ const struct Item gItemsInfo[] = [ITEM_EJECT_BUTTON] = { - .name = _("Eject Button"), + .name = ITEM_NAME("Eject Button"), .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EJECT_BUTTON, .holdEffectParam = 0, @@ -9444,8 +9449,8 @@ const struct Item gItemsInfo[] = [ITEM_WEAKNESS_POLICY] = { - .name = _("Weakness Policy"), - .pluralName = _("Weakness Policies"), + .name = ITEM_NAME("Weakness Policy"), + .pluralName = ITEM_PLURAL_NAME("Weakness Policies"), .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_WEAKNESS_POLICY, .holdEffectParam = 0, @@ -9464,7 +9469,7 @@ const struct Item gItemsInfo[] = [ITEM_ASSAULT_VEST] = { - .name = _("Assault Vest"), + .name = ITEM_NAME("Assault Vest"), .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_ASSAULT_VEST, .holdEffectParam = 50, @@ -9483,8 +9488,8 @@ const struct Item gItemsInfo[] = [ITEM_SAFETY_GOGGLES] = { - .name = _("Safety Goggles"), - .pluralName = _("Safety Goggles"), + .name = ITEM_NAME("Safety Goggles"), + .pluralName = ITEM_PLURAL_NAME("Safety Goggles"), .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_SAFETY_GOGGLES, .description = COMPOUND_STRING( @@ -9502,7 +9507,7 @@ const struct Item gItemsInfo[] = [ITEM_ADRENALINE_ORB] = { - .name = _("Adrenaline Orb"), + .name = ITEM_NAME("Adrenaline Orb"), .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_8) ? 4000 : 300), .holdEffect = HOLD_EFFECT_ADRENALINE_ORB, .description = COMPOUND_STRING( @@ -9520,7 +9525,7 @@ const struct Item gItemsInfo[] = [ITEM_TERRAIN_EXTENDER] = { - .name = _("Terrain Extender"), + .name = ITEM_NAME("Terrain Extender"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_TERRAIN_EXTENDER, .description = COMPOUND_STRING( @@ -9538,8 +9543,8 @@ const struct Item gItemsInfo[] = [ITEM_PROTECTIVE_PADS] = { - .name = _("Protective Pads"), - .pluralName = _("Protective Pads"), + .name = ITEM_NAME("Protective Pads"), + .pluralName = ITEM_PLURAL_NAME("Protective Pads"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_PROTECTIVE_PADS, .description = COMPOUND_STRING( @@ -9557,7 +9562,7 @@ const struct Item gItemsInfo[] = [ITEM_THROAT_SPRAY] = { - .name = _("Throat Spray"), + .name = ITEM_NAME("Throat Spray"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_THROAT_SPRAY, .description = COMPOUND_STRING( @@ -9575,7 +9580,7 @@ const struct Item gItemsInfo[] = [ITEM_EJECT_PACK] = { - .name = _("Eject Pack"), + .name = ITEM_NAME("Eject Pack"), .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_EJECT_PACK, .description = COMPOUND_STRING( @@ -9593,8 +9598,8 @@ const struct Item gItemsInfo[] = [ITEM_HEAVY_DUTY_BOOTS] = { - .name = _("Heavy-Duty Boots"), - .pluralName = _("Heavy-Duty Boots"), + .name = ITEM_NAME("Heavy-Duty Boots"), + .pluralName = ITEM_PLURAL_NAME("Heavy-Duty Boots"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_HEAVY_DUTY_BOOTS, .description = COMPOUND_STRING( @@ -9612,8 +9617,8 @@ const struct Item gItemsInfo[] = [ITEM_BLUNDER_POLICY] = { - .name = _("Blunder Policy"), - .pluralName = _("Blunder Policies"), + .name = ITEM_NAME("Blunder Policy"), + .pluralName = ITEM_PLURAL_NAME("Blunder Policies"), .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_BLUNDER_POLICY, .description = COMPOUND_STRING( @@ -9631,7 +9636,7 @@ const struct Item gItemsInfo[] = [ITEM_ROOM_SERVICE] = { - .name = _("Room Service"), + .name = ITEM_NAME("Room Service"), .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_ROOM_SERVICE, .description = COMPOUND_STRING( @@ -9649,7 +9654,7 @@ const struct Item gItemsInfo[] = [ITEM_UTILITY_UMBRELLA] = { - .name = _("Utility Umbrella"), + .name = ITEM_NAME("Utility Umbrella"), .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_UTILITY_UMBRELLA, .description = COMPOUND_STRING( @@ -9669,8 +9674,8 @@ const struct Item gItemsInfo[] = [ITEM_CHERI_BERRY] = { - .name = _("Cheri Berry"), - .pluralName = _("Cheri Berries"), + .name = ITEM_NAME("Cheri Berry"), + .pluralName = ITEM_PLURAL_NAME("Cheri Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PAR, .description = COMPOUND_STRING( @@ -9689,8 +9694,8 @@ const struct Item gItemsInfo[] = [ITEM_CHESTO_BERRY] = { - .name = _("Chesto Berry"), - .pluralName = _("Chesto Berries"), + .name = ITEM_NAME("Chesto Berry"), + .pluralName = ITEM_PLURAL_NAME("Chesto Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_SLP, .description = COMPOUND_STRING( @@ -9709,8 +9714,8 @@ const struct Item gItemsInfo[] = [ITEM_PECHA_BERRY] = { - .name = _("Pecha Berry"), - .pluralName = _("Pecha Berries"), + .name = ITEM_NAME("Pecha Berry"), + .pluralName = ITEM_PLURAL_NAME("Pecha Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PSN, .description = COMPOUND_STRING( @@ -9729,8 +9734,8 @@ const struct Item gItemsInfo[] = [ITEM_RAWST_BERRY] = { - .name = _("Rawst Berry"), - .pluralName = _("Rawst Berries"), + .name = ITEM_NAME("Rawst Berry"), + .pluralName = ITEM_PLURAL_NAME("Rawst Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_BRN, .description = COMPOUND_STRING( @@ -9749,8 +9754,8 @@ const struct Item gItemsInfo[] = [ITEM_ASPEAR_BERRY] = { - .name = _("Aspear Berry"), - .pluralName = _("Aspear Berries"), + .name = ITEM_NAME("Aspear Berry"), + .pluralName = ITEM_PLURAL_NAME("Aspear Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_FRZ, .description = COMPOUND_STRING( @@ -9769,8 +9774,8 @@ const struct Item gItemsInfo[] = [ITEM_LEPPA_BERRY] = { - .name = _("Leppa Berry"), - .pluralName = _("Leppa Berries"), + .name = ITEM_NAME("Leppa Berry"), + .pluralName = ITEM_PLURAL_NAME("Leppa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_PP, .holdEffectParam = 10, @@ -9790,8 +9795,8 @@ const struct Item gItemsInfo[] = [ITEM_ORAN_BERRY] = { - .name = _("Oran Berry"), - .pluralName = _("Oran Berries"), + .name = ITEM_NAME("Oran Berry"), + .pluralName = ITEM_PLURAL_NAME("Oran Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 10, @@ -9811,8 +9816,8 @@ const struct Item gItemsInfo[] = [ITEM_PERSIM_BERRY] = { - .name = _("Persim Berry"), - .pluralName = _("Persim Berries"), + .name = ITEM_NAME("Persim Berry"), + .pluralName = ITEM_PLURAL_NAME("Persim Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_CONFUSION, .description = COMPOUND_STRING( @@ -9831,8 +9836,8 @@ const struct Item gItemsInfo[] = [ITEM_LUM_BERRY] = { - .name = _("Lum Berry"), - .pluralName = _("Lum Berries"), + .name = ITEM_NAME("Lum Berry"), + .pluralName = ITEM_PLURAL_NAME("Lum Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_STATUS, .description = COMPOUND_STRING( @@ -9851,8 +9856,8 @@ const struct Item gItemsInfo[] = [ITEM_SITRUS_BERRY] = { - .name = _("Sitrus Berry"), - .pluralName = _("Sitrus Berries"), + .name = ITEM_NAME("Sitrus Berry"), + .pluralName = ITEM_PLURAL_NAME("Sitrus Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, #if I_SITRUS_BERRY_HEAL >= GEN_4 .holdEffect = HOLD_EFFECT_RESTORE_PCT_HP, @@ -9881,8 +9886,8 @@ const struct Item gItemsInfo[] = [ITEM_FIGY_BERRY] = { - .name = _("Figy Berry"), - .pluralName = _("Figy Berries"), + .name = ITEM_NAME("Figy Berry"), + .pluralName = ITEM_PLURAL_NAME("Figy Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SPICY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9897,8 +9902,8 @@ const struct Item gItemsInfo[] = [ITEM_WIKI_BERRY] = { - .name = _("Wiki Berry"), - .pluralName = _("Wiki Berries"), + .name = ITEM_NAME("Wiki Berry"), + .pluralName = ITEM_PLURAL_NAME("Wiki Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_DRY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9913,8 +9918,8 @@ const struct Item gItemsInfo[] = [ITEM_MAGO_BERRY] = { - .name = _("Mago Berry"), - .pluralName = _("Mago Berries"), + .name = ITEM_NAME("Mago Berry"), + .pluralName = ITEM_PLURAL_NAME("Mago Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SWEET, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9929,8 +9934,8 @@ const struct Item gItemsInfo[] = [ITEM_AGUAV_BERRY] = { - .name = _("Aguav Berry"), - .pluralName = _("Aguav Berries"), + .name = ITEM_NAME("Aguav Berry"), + .pluralName = ITEM_PLURAL_NAME("Aguav Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_BITTER, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9945,8 +9950,8 @@ const struct Item gItemsInfo[] = [ITEM_IAPAPA_BERRY] = { - .name = _("Iapapa Berry"), - .pluralName = _("Iapapa Berries"), + .name = ITEM_NAME("Iapapa Berry"), + .pluralName = ITEM_PLURAL_NAME("Iapapa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SOUR, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, @@ -9961,8 +9966,8 @@ const struct Item gItemsInfo[] = [ITEM_RAZZ_BERRY] = { - .name = _("Razz Berry"), - .pluralName = _("Razz Berries"), + .name = ITEM_NAME("Razz Berry"), + .pluralName = ITEM_PLURAL_NAME("Razz Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -9978,8 +9983,8 @@ const struct Item gItemsInfo[] = [ITEM_BLUK_BERRY] = { - .name = _("Bluk Berry"), - .pluralName = _("Bluk Berries"), + .name = ITEM_NAME("Bluk Berry"), + .pluralName = ITEM_PLURAL_NAME("Bluk Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -9995,8 +10000,8 @@ const struct Item gItemsInfo[] = [ITEM_NANAB_BERRY] = { - .name = _("Nanab Berry"), - .pluralName = _("Nanab Berries"), + .name = ITEM_NAME("Nanab Berry"), + .pluralName = ITEM_PLURAL_NAME("Nanab Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10012,8 +10017,8 @@ const struct Item gItemsInfo[] = [ITEM_WEPEAR_BERRY] = { - .name = _("Wepear Berry"), - .pluralName = _("Wepear Berries"), + .name = ITEM_NAME("Wepear Berry"), + .pluralName = ITEM_PLURAL_NAME("Wepear Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10029,8 +10034,8 @@ const struct Item gItemsInfo[] = [ITEM_PINAP_BERRY] = { - .name = _("Pinap Berry"), - .pluralName = _("Pinap Berries"), + .name = ITEM_NAME("Pinap Berry"), + .pluralName = ITEM_PLURAL_NAME("Pinap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10046,8 +10051,8 @@ const struct Item gItemsInfo[] = [ITEM_POMEG_BERRY] = { - .name = _("Pomeg Berry"), - .pluralName = _("Pomeg Berries"), + .name = ITEM_NAME("Pomeg Berry"), + .pluralName = ITEM_PLURAL_NAME("Pomeg Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10064,8 +10069,8 @@ const struct Item gItemsInfo[] = [ITEM_KELPSY_BERRY] = { - .name = _("Kelpsy Berry"), - .pluralName = _("Kelpsy Berries"), + .name = ITEM_NAME("Kelpsy Berry"), + .pluralName = ITEM_PLURAL_NAME("Kelpsy Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10082,8 +10087,8 @@ const struct Item gItemsInfo[] = [ITEM_QUALOT_BERRY] = { - .name = _("Qualot Berry"), - .pluralName = _("Qualot Berries"), + .name = ITEM_NAME("Qualot Berry"), + .pluralName = ITEM_PLURAL_NAME("Qualot Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10100,8 +10105,8 @@ const struct Item gItemsInfo[] = [ITEM_HONDEW_BERRY] = { - .name = _("Hondew Berry"), - .pluralName = _("Hondew Berries"), + .name = ITEM_NAME("Hondew Berry"), + .pluralName = ITEM_PLURAL_NAME("Hondew Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10118,8 +10123,8 @@ const struct Item gItemsInfo[] = [ITEM_GREPA_BERRY] = { - .name = _("Grepa Berry"), - .pluralName = _("Grepa Berries"), + .name = ITEM_NAME("Grepa Berry"), + .pluralName = ITEM_PLURAL_NAME("Grepa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10136,8 +10141,8 @@ const struct Item gItemsInfo[] = [ITEM_TAMATO_BERRY] = { - .name = _("Tamato Berry"), - .pluralName = _("Tamato Berries"), + .name = ITEM_NAME("Tamato Berry"), + .pluralName = ITEM_PLURAL_NAME("Tamato Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "Makes a Pokémon\n" @@ -10154,8 +10159,8 @@ const struct Item gItemsInfo[] = [ITEM_CORNN_BERRY] = { - .name = _("Cornn Berry"), - .pluralName = _("Cornn Berries"), + .name = ITEM_NAME("Cornn Berry"), + .pluralName = ITEM_PLURAL_NAME("Cornn Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10171,8 +10176,8 @@ const struct Item gItemsInfo[] = [ITEM_MAGOST_BERRY] = { - .name = _("Magost Berry"), - .pluralName = _("Magost Berries"), + .name = ITEM_NAME("Magost Berry"), + .pluralName = ITEM_PLURAL_NAME("Magost Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10188,8 +10193,8 @@ const struct Item gItemsInfo[] = [ITEM_RABUTA_BERRY] = { - .name = _("Rabuta Berry"), - .pluralName = _("Rabuta Berries"), + .name = ITEM_NAME("Rabuta Berry"), + .pluralName = ITEM_PLURAL_NAME("Rabuta Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10205,8 +10210,8 @@ const struct Item gItemsInfo[] = [ITEM_NOMEL_BERRY] = { - .name = _("Nomel Berry"), - .pluralName = _("Nomel Berries"), + .name = ITEM_NAME("Nomel Berry"), + .pluralName = ITEM_PLURAL_NAME("Nomel Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10222,8 +10227,8 @@ const struct Item gItemsInfo[] = [ITEM_SPELON_BERRY] = { - .name = _("Spelon Berry"), - .pluralName = _("Spelon Berries"), + .name = ITEM_NAME("Spelon Berry"), + .pluralName = ITEM_PLURAL_NAME("Spelon Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10239,8 +10244,8 @@ const struct Item gItemsInfo[] = [ITEM_PAMTRE_BERRY] = { - .name = _("Pamtre Berry"), - .pluralName = _("Pamtre Berries"), + .name = ITEM_NAME("Pamtre Berry"), + .pluralName = ITEM_PLURAL_NAME("Pamtre Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10256,8 +10261,8 @@ const struct Item gItemsInfo[] = [ITEM_WATMEL_BERRY] = { - .name = _("Watmel Berry"), - .pluralName = _("Watmel Berries"), + .name = ITEM_NAME("Watmel Berry"), + .pluralName = ITEM_PLURAL_NAME("Watmel Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10273,8 +10278,8 @@ const struct Item gItemsInfo[] = [ITEM_DURIN_BERRY] = { - .name = _("Durin Berry"), - .pluralName = _("Durin Berries"), + .name = ITEM_NAME("Durin Berry"), + .pluralName = ITEM_PLURAL_NAME("Durin Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10290,8 +10295,8 @@ const struct Item gItemsInfo[] = [ITEM_BELUE_BERRY] = { - .name = _("Belue Berry"), - .pluralName = _("Belue Berries"), + .name = ITEM_NAME("Belue Berry"), + .pluralName = ITEM_PLURAL_NAME("Belue Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10307,8 +10312,8 @@ const struct Item gItemsInfo[] = [ITEM_CHILAN_BERRY] = { - .name = _("Chilan Berry"), - .pluralName = _("Chilan Berries"), + .name = ITEM_NAME("Chilan Berry"), + .pluralName = ITEM_PLURAL_NAME("Chilan Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_NORMAL, @@ -10326,8 +10331,8 @@ const struct Item gItemsInfo[] = [ITEM_OCCA_BERRY] = { - .name = _("Occa Berry"), - .pluralName = _("Occa Berries"), + .name = ITEM_NAME("Occa Berry"), + .pluralName = ITEM_PLURAL_NAME("Occa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIRE, @@ -10345,8 +10350,8 @@ const struct Item gItemsInfo[] = [ITEM_PASSHO_BERRY] = { - .name = _("Passho Berry"), - .pluralName = _("Passho Berries"), + .name = ITEM_NAME("Passho Berry"), + .pluralName = ITEM_PLURAL_NAME("Passho Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_WATER, @@ -10364,8 +10369,8 @@ const struct Item gItemsInfo[] = [ITEM_WACAN_BERRY] = { - .name = _("Wacan Berry"), - .pluralName = _("Wacan Berries"), + .name = ITEM_NAME("Wacan Berry"), + .pluralName = ITEM_PLURAL_NAME("Wacan Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ELECTRIC, @@ -10383,8 +10388,8 @@ const struct Item gItemsInfo[] = [ITEM_RINDO_BERRY] = { - .name = _("Rindo Berry"), - .pluralName = _("Rindo Berries"), + .name = ITEM_NAME("Rindo Berry"), + .pluralName = ITEM_PLURAL_NAME("Rindo Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GRASS, @@ -10402,8 +10407,8 @@ const struct Item gItemsInfo[] = [ITEM_YACHE_BERRY] = { - .name = _("Yache Berry"), - .pluralName = _("Yache Berries"), + .name = ITEM_NAME("Yache Berry"), + .pluralName = ITEM_PLURAL_NAME("Yache Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ICE, @@ -10421,8 +10426,8 @@ const struct Item gItemsInfo[] = [ITEM_CHOPLE_BERRY] = { - .name = _("Chople Berry"), - .pluralName = _("Chople Berries"), + .name = ITEM_NAME("Chople Berry"), + .pluralName = ITEM_PLURAL_NAME("Chople Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIGHTING, @@ -10440,8 +10445,8 @@ const struct Item gItemsInfo[] = [ITEM_KEBIA_BERRY] = { - .name = _("Kebia Berry"), - .pluralName = _("Kebia Berries"), + .name = ITEM_NAME("Kebia Berry"), + .pluralName = ITEM_PLURAL_NAME("Kebia Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_POISON, @@ -10459,8 +10464,8 @@ const struct Item gItemsInfo[] = [ITEM_SHUCA_BERRY] = { - .name = _("Shuca Berry"), - .pluralName = _("Shuca Berries"), + .name = ITEM_NAME("Shuca Berry"), + .pluralName = ITEM_PLURAL_NAME("Shuca Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GROUND, @@ -10478,8 +10483,8 @@ const struct Item gItemsInfo[] = [ITEM_COBA_BERRY] = { - .name = _("Coba Berry"), - .pluralName = _("Coba Berries"), + .name = ITEM_NAME("Coba Berry"), + .pluralName = ITEM_PLURAL_NAME("Coba Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FLYING, @@ -10497,8 +10502,8 @@ const struct Item gItemsInfo[] = [ITEM_PAYAPA_BERRY] = { - .name = _("Payapa Berry"), - .pluralName = _("Payapa Berries"), + .name = ITEM_NAME("Payapa Berry"), + .pluralName = ITEM_PLURAL_NAME("Payapa Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_PSYCHIC, @@ -10516,8 +10521,8 @@ const struct Item gItemsInfo[] = [ITEM_TANGA_BERRY] = { - .name = _("Tanga Berry"), - .pluralName = _("Tanga Berries"), + .name = ITEM_NAME("Tanga Berry"), + .pluralName = ITEM_PLURAL_NAME("Tanga Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_BUG, @@ -10535,8 +10540,8 @@ const struct Item gItemsInfo[] = [ITEM_CHARTI_BERRY] = { - .name = _("Charti Berry"), - .pluralName = _("Charti Berries"), + .name = ITEM_NAME("Charti Berry"), + .pluralName = ITEM_PLURAL_NAME("Charti Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ROCK, @@ -10554,8 +10559,8 @@ const struct Item gItemsInfo[] = [ITEM_KASIB_BERRY] = { - .name = _("Kasib Berry"), - .pluralName = _("Kasib Berries"), + .name = ITEM_NAME("Kasib Berry"), + .pluralName = ITEM_PLURAL_NAME("Kasib Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GHOST, @@ -10573,8 +10578,8 @@ const struct Item gItemsInfo[] = [ITEM_HABAN_BERRY] = { - .name = _("Haban Berry"), - .pluralName = _("Haban Berries"), + .name = ITEM_NAME("Haban Berry"), + .pluralName = ITEM_PLURAL_NAME("Haban Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DRAGON, @@ -10592,8 +10597,8 @@ const struct Item gItemsInfo[] = [ITEM_COLBUR_BERRY] = { - .name = _("Colbur Berry"), - .pluralName = _("Colbur Berries"), + .name = ITEM_NAME("Colbur Berry"), + .pluralName = ITEM_PLURAL_NAME("Colbur Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DARK, @@ -10611,8 +10616,8 @@ const struct Item gItemsInfo[] = [ITEM_BABIRI_BERRY] = { - .name = _("Babiri Berry"), - .pluralName = _("Babiri Berries"), + .name = ITEM_NAME("Babiri Berry"), + .pluralName = ITEM_PLURAL_NAME("Babiri Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_STEEL, @@ -10630,8 +10635,8 @@ const struct Item gItemsInfo[] = [ITEM_ROSELI_BERRY] = { - .name = _("Roseli Berry"), - .pluralName = _("Roseli Berries"), + .name = ITEM_NAME("Roseli Berry"), + .pluralName = ITEM_PLURAL_NAME("Roseli Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FAIRY, @@ -10649,8 +10654,8 @@ const struct Item gItemsInfo[] = [ITEM_LIECHI_BERRY] = { - .name = _("Liechi Berry"), - .pluralName = _("Liechi Berries"), + .name = ITEM_NAME("Liechi Berry"), + .pluralName = ITEM_PLURAL_NAME("Liechi Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ATTACK_UP, .holdEffectParam = 4, @@ -10668,8 +10673,8 @@ const struct Item gItemsInfo[] = [ITEM_GANLON_BERRY] = { - .name = _("Ganlon Berry"), - .pluralName = _("Ganlon Berries"), + .name = ITEM_NAME("Ganlon Berry"), + .pluralName = ITEM_PLURAL_NAME("Ganlon Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_DEFENSE_UP, .holdEffectParam = 4, @@ -10687,8 +10692,8 @@ const struct Item gItemsInfo[] = [ITEM_SALAC_BERRY] = { - .name = _("Salac Berry"), - .pluralName = _("Salac Berries"), + .name = ITEM_NAME("Salac Berry"), + .pluralName = ITEM_PLURAL_NAME("Salac Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SPEED_UP, .holdEffectParam = 4, @@ -10706,8 +10711,8 @@ const struct Item gItemsInfo[] = [ITEM_PETAYA_BERRY] = { - .name = _("Petaya Berry"), - .pluralName = _("Petaya Berries"), + .name = ITEM_NAME("Petaya Berry"), + .pluralName = ITEM_PLURAL_NAME("Petaya Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_ATTACK_UP, .holdEffectParam = 4, @@ -10725,8 +10730,8 @@ const struct Item gItemsInfo[] = [ITEM_APICOT_BERRY] = { - .name = _("Apicot Berry"), - .pluralName = _("Apicot Berries"), + .name = ITEM_NAME("Apicot Berry"), + .pluralName = ITEM_PLURAL_NAME("Apicot Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_DEFENSE_UP, .holdEffectParam = 4, @@ -10744,8 +10749,8 @@ const struct Item gItemsInfo[] = [ITEM_LANSAT_BERRY] = { - .name = _("Lansat Berry"), - .pluralName = _("Lansat Berries"), + .name = ITEM_NAME("Lansat Berry"), + .pluralName = ITEM_PLURAL_NAME("Lansat Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CRITICAL_UP, .holdEffectParam = 4, @@ -10763,8 +10768,8 @@ const struct Item gItemsInfo[] = [ITEM_STARF_BERRY] = { - .name = _("Starf Berry"), - .pluralName = _("Starf Berries"), + .name = ITEM_NAME("Starf Berry"), + .pluralName = ITEM_PLURAL_NAME("Starf Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RANDOM_STAT_UP, .holdEffectParam = 4, @@ -10782,8 +10787,8 @@ const struct Item gItemsInfo[] = [ITEM_ENIGMA_BERRY] = { - .name = _("Enigma Berry"), - .pluralName = _("Enigma Berries"), + .name = ITEM_NAME("Enigma Berry"), + .pluralName = ITEM_PLURAL_NAME("Enigma Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ENIGMA_BERRY, .description = COMPOUND_STRING( @@ -10800,8 +10805,8 @@ const struct Item gItemsInfo[] = [ITEM_MICLE_BERRY] = { - .name = _("Micle Berry"), - .pluralName = _("Micle Berries"), + .name = ITEM_NAME("Micle Berry"), + .pluralName = ITEM_PLURAL_NAME("Micle Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MICLE_BERRY, .holdEffectParam = 4, @@ -10819,8 +10824,8 @@ const struct Item gItemsInfo[] = [ITEM_CUSTAP_BERRY] = { - .name = _("Custap Berry"), - .pluralName = _("Custap Berries"), + .name = ITEM_NAME("Custap Berry"), + .pluralName = ITEM_PLURAL_NAME("Custap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CUSTAP_BERRY, .holdEffectParam = 4, @@ -10838,8 +10843,8 @@ const struct Item gItemsInfo[] = [ITEM_JABOCA_BERRY] = { - .name = _("Jaboca Berry"), - .pluralName = _("Jaboca Berries"), + .name = ITEM_NAME("Jaboca Berry"), + .pluralName = ITEM_PLURAL_NAME("Jaboca Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_JABOCA_BERRY, .description = COMPOUND_STRING( @@ -10856,8 +10861,8 @@ const struct Item gItemsInfo[] = [ITEM_ROWAP_BERRY] = { - .name = _("Rowap Berry"), - .pluralName = _("Rowap Berries"), + .name = ITEM_NAME("Rowap Berry"), + .pluralName = ITEM_PLURAL_NAME("Rowap Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ROWAP_BERRY, .description = COMPOUND_STRING( @@ -10874,8 +10879,8 @@ const struct Item gItemsInfo[] = [ITEM_KEE_BERRY] = { - .name = _("Kee Berry"), - .pluralName = _("Kee Berries"), + .name = ITEM_NAME("Kee Berry"), + .pluralName = ITEM_PLURAL_NAME("Kee Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_KEE_BERRY, .description = COMPOUND_STRING( @@ -10892,8 +10897,8 @@ const struct Item gItemsInfo[] = [ITEM_MARANGA_BERRY] = { - .name = _("Maranga Berry"), - .pluralName = _("Maranga Berries"), + .name = ITEM_NAME("Maranga Berry"), + .pluralName = ITEM_PLURAL_NAME("Maranga Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MARANGA_BERRY, .description = COMPOUND_STRING( @@ -10910,8 +10915,8 @@ const struct Item gItemsInfo[] = [ITEM_ENIGMA_BERRY_E_READER] = { - .name = _("Enigma Berry"), - .pluralName = _("Enigma Berries"), + .name = ITEM_NAME("Enigma Berry"), + .pluralName = ITEM_PLURAL_NAME("Enigma Berries"), .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING( "{POKEBLOCK} ingredient.\n" @@ -10930,7 +10935,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FOCUS_PUNCH] = { - .name = _("TM01"), + .name = ITEM_NAME("TM01"), .price = 3000, .description = COMPOUND_STRING( "Powerful, but makes\n" @@ -10944,7 +10949,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_DRAGON_CLAW] = { - .name = _("TM02"), + .name = ITEM_NAME("TM02"), .price = 3000, .description = COMPOUND_STRING( "Hooks and slashes\n" @@ -10958,7 +10963,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_WATER_PULSE] = { - .name = _("TM03"), + .name = ITEM_NAME("TM03"), .price = 3000, .description = COMPOUND_STRING( "Generates an\n" @@ -10972,7 +10977,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_CALM_MIND] = { - .name = _("TM04"), + .name = ITEM_NAME("TM04"), .price = 3000, .description = COMPOUND_STRING( "Raises Sp. Atk and\n" @@ -10986,7 +10991,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_ROAR] = { - .name = _("TM05"), + .name = ITEM_NAME("TM05"), .price = 1000, .description = COMPOUND_STRING( "A savage roar that\n" @@ -11000,7 +11005,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_TOXIC] = { - .name = _("TM06"), + .name = ITEM_NAME("TM06"), .price = 3000, .description = COMPOUND_STRING( "Poisons the foe\n" @@ -11014,7 +11019,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_HAIL] = { - .name = _("TM07"), + .name = ITEM_NAME("TM07"), .price = 3000, #if B_PREFERRED_ICE_WEATHER == B_ICE_WEATHER_SNOW .description = COMPOUND_STRING( @@ -11035,7 +11040,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_BULK_UP] = { - .name = _("TM08"), + .name = ITEM_NAME("TM08"), .price = 3000, .description = COMPOUND_STRING( "Bulks up the body\n" @@ -11049,7 +11054,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_BULLET_SEED] = { - .name = _("TM09"), + .name = ITEM_NAME("TM09"), .price = 3000, .description = COMPOUND_STRING( "Shoots 2 to 5 seeds\n" @@ -11063,7 +11068,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_HIDDEN_POWER] = { - .name = _("TM10"), + .name = ITEM_NAME("TM10"), .price = 3000, .description = COMPOUND_STRING( "The attack power\n" @@ -11077,7 +11082,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SUNNY_DAY] = { - .name = _("TM11"), + .name = ITEM_NAME("TM11"), .price = 2000, .description = COMPOUND_STRING( "Raises the power of\n" @@ -11091,7 +11096,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_TAUNT] = { - .name = _("TM12"), + .name = ITEM_NAME("TM12"), .price = 3000, .description = COMPOUND_STRING( "Enrages the foe so\n" @@ -11105,7 +11110,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_ICE_BEAM] = { - .name = _("TM13"), + .name = ITEM_NAME("TM13"), .price = 3000, .description = COMPOUND_STRING( "Fires an icy cold\n" @@ -11123,7 +11128,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_BLIZZARD] = { - .name = _("TM14"), + .name = ITEM_NAME("TM14"), .price = 5500, .description = COMPOUND_STRING( #if B_USE_FROSTBITE == TRUE @@ -11143,7 +11148,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_HYPER_BEAM] = { - .name = _("TM15"), + .name = ITEM_NAME("TM15"), .price = 7500, .description = COMPOUND_STRING( "Powerful, but needs\n" @@ -11157,7 +11162,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_LIGHT_SCREEN] = { - .name = _("TM16"), + .name = ITEM_NAME("TM16"), .price = 3000, .description = COMPOUND_STRING( "Creates a wall of\n" @@ -11171,7 +11176,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_PROTECT] = { - .name = _("TM17"), + .name = ITEM_NAME("TM17"), .price = 3000, .description = COMPOUND_STRING( "Negates all damage,\n" @@ -11185,7 +11190,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_RAIN_DANCE] = { - .name = _("TM18"), + .name = ITEM_NAME("TM18"), .price = 2000, .description = COMPOUND_STRING( "Raises the power of\n" @@ -11199,7 +11204,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_GIGA_DRAIN] = { - .name = _("TM19"), + .name = ITEM_NAME("TM19"), .price = 3000, .description = COMPOUND_STRING( "Recovers half the\n" @@ -11213,7 +11218,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SAFEGUARD] = { - .name = _("TM20"), + .name = ITEM_NAME("TM20"), .price = 3000, .description = COMPOUND_STRING( "Prevents status\n" @@ -11227,7 +11232,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FRUSTRATION] = { - .name = _("TM21"), + .name = ITEM_NAME("TM21"), .price = 1000, .description = COMPOUND_STRING( "The less the user\n" @@ -11241,7 +11246,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SOLAR_BEAM] = { - .name = _("TM22"), + .name = ITEM_NAME("TM22"), .price = 3000, .description = COMPOUND_STRING( "Absorbs sunlight in\n" @@ -11255,7 +11260,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_IRON_TAIL] = { - .name = _("TM23"), + .name = ITEM_NAME("TM23"), .price = 3000, .description = COMPOUND_STRING( "Slams the foe with\n" @@ -11269,7 +11274,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_THUNDERBOLT] = { - .name = _("TM24"), + .name = ITEM_NAME("TM24"), .price = 3000, .description = COMPOUND_STRING( "A powerful electric\n" @@ -11283,7 +11288,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_THUNDER] = { - .name = _("TM25"), + .name = ITEM_NAME("TM25"), .price = 5500, .description = COMPOUND_STRING( "Strikes the foe\n" @@ -11297,7 +11302,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_EARTHQUAKE] = { - .name = _("TM26"), + .name = ITEM_NAME("TM26"), .price = 3000, .description = COMPOUND_STRING( "Causes a quake\n" @@ -11311,7 +11316,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_RETURN] = { - .name = _("TM27"), + .name = ITEM_NAME("TM27"), .price = 1000, .description = COMPOUND_STRING( "The more the user\n" @@ -11325,7 +11330,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_DIG] = { - .name = _("TM28"), + .name = ITEM_NAME("TM28"), .price = 2000, .description = COMPOUND_STRING( "Digs underground\n" @@ -11339,7 +11344,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_PSYCHIC] = { - .name = _("TM29"), + .name = ITEM_NAME("TM29"), .price = 2000, .description = COMPOUND_STRING( "A powerful psychic\n" @@ -11353,7 +11358,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SHADOW_BALL] = { - .name = _("TM30"), + .name = ITEM_NAME("TM30"), .price = 3000, .description = COMPOUND_STRING( "Hurls a dark lump\n" @@ -11367,7 +11372,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_BRICK_BREAK] = { - .name = _("TM31"), + .name = ITEM_NAME("TM31"), .price = 3000, .description = COMPOUND_STRING( "Destroys barriers\n" @@ -11381,7 +11386,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_DOUBLE_TEAM] = { - .name = _("TM32"), + .name = ITEM_NAME("TM32"), .price = 2000, .description = COMPOUND_STRING( "Creates illusory\n" @@ -11395,7 +11400,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_REFLECT] = { - .name = _("TM33"), + .name = ITEM_NAME("TM33"), .price = 3000, .description = COMPOUND_STRING( "Creates a wall of\n" @@ -11409,7 +11414,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SHOCK_WAVE] = { - .name = _("TM34"), + .name = ITEM_NAME("TM34"), .price = 3000, .description = COMPOUND_STRING( "Zaps the foe with a\n" @@ -11423,7 +11428,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FLAMETHROWER] = { - .name = _("TM35"), + .name = ITEM_NAME("TM35"), .price = 3000, .description = COMPOUND_STRING( "Looses a stream of\n" @@ -11437,7 +11442,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SLUDGE_BOMB] = { - .name = _("TM36"), + .name = ITEM_NAME("TM36"), .price = 1000, .description = COMPOUND_STRING( "Hurls sludge at the\n" @@ -11451,7 +11456,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SANDSTORM] = { - .name = _("TM37"), + .name = ITEM_NAME("TM37"), .price = 2000, .description = COMPOUND_STRING( "Causes a sandstorm\n" @@ -11465,7 +11470,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FIRE_BLAST] = { - .name = _("TM38"), + .name = ITEM_NAME("TM38"), .price = 5500, .description = COMPOUND_STRING( "A powerful fire\n" @@ -11479,7 +11484,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_ROCK_TOMB] = { - .name = _("TM39"), + .name = ITEM_NAME("TM39"), .price = 3000, .description = COMPOUND_STRING( "Stops the foe from\n" @@ -11493,7 +11498,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_AERIAL_ACE] = { - .name = _("TM40"), + .name = ITEM_NAME("TM40"), .price = 3000, .description = COMPOUND_STRING( "An extremely fast\n" @@ -11507,7 +11512,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_TORMENT] = { - .name = _("TM41"), + .name = ITEM_NAME("TM41"), .price = 3000, .description = COMPOUND_STRING( "Prevents the foe\n" @@ -11521,7 +11526,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_FACADE] = { - .name = _("TM42"), + .name = ITEM_NAME("TM42"), .price = 3000, .description = COMPOUND_STRING( "Raises Attack when\n" @@ -11535,7 +11540,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SECRET_POWER] = { - .name = _("TM43"), + .name = ITEM_NAME("TM43"), .price = 3000, .description = COMPOUND_STRING( "Adds an effect to\n" @@ -11549,7 +11554,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_REST] = { - .name = _("TM44"), + .name = ITEM_NAME("TM44"), .price = 3000, .description = COMPOUND_STRING( "The user sleeps for\n" @@ -11563,7 +11568,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_ATTRACT] = { - .name = _("TM45"), + .name = ITEM_NAME("TM45"), .price = 3000, .description = COMPOUND_STRING( "Makes it tough to\n" @@ -11577,7 +11582,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_THIEF] = { - .name = _("TM46"), + .name = ITEM_NAME("TM46"), .price = 3000, .description = COMPOUND_STRING( "While attacking,\n" @@ -11591,7 +11596,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_STEEL_WING] = { - .name = _("TM47"), + .name = ITEM_NAME("TM47"), .price = 3000, .description = COMPOUND_STRING( "Spreads hard-\n" @@ -11605,7 +11610,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SKILL_SWAP] = { - .name = _("TM48"), + .name = ITEM_NAME("TM48"), .price = 3000, .description = COMPOUND_STRING( "Switches abilities\n" @@ -11619,7 +11624,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_SNATCH] = { - .name = _("TM49"), + .name = ITEM_NAME("TM49"), .price = 3000, .description = COMPOUND_STRING( "Steals the effects\n" @@ -11633,7 +11638,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_OVERHEAT] = { - .name = _("TM50"), + .name = ITEM_NAME("TM50"), .price = 3000, .description = COMPOUND_STRING( "Enables full-power\n" @@ -11647,7 +11652,7 @@ const struct Item gItemsInfo[] = [ITEM_TM51] = { - .name = _("TM51"), + .name = ITEM_NAME("TM51"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11658,7 +11663,7 @@ const struct Item gItemsInfo[] = [ITEM_TM52] = { - .name = _("TM52"), + .name = ITEM_NAME("TM52"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11669,7 +11674,7 @@ const struct Item gItemsInfo[] = [ITEM_TM53] = { - .name = _("TM53"), + .name = ITEM_NAME("TM53"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11680,7 +11685,7 @@ const struct Item gItemsInfo[] = [ITEM_TM54] = { - .name = _("TM54"), + .name = ITEM_NAME("TM54"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11691,7 +11696,7 @@ const struct Item gItemsInfo[] = [ITEM_TM55] = { - .name = _("TM55"), + .name = ITEM_NAME("TM55"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11702,7 +11707,7 @@ const struct Item gItemsInfo[] = [ITEM_TM56] = { - .name = _("TM56"), + .name = ITEM_NAME("TM56"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11713,7 +11718,7 @@ const struct Item gItemsInfo[] = [ITEM_TM57] = { - .name = _("TM57"), + .name = ITEM_NAME("TM57"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11724,7 +11729,7 @@ const struct Item gItemsInfo[] = [ITEM_TM58] = { - .name = _("TM58"), + .name = ITEM_NAME("TM58"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11735,7 +11740,7 @@ const struct Item gItemsInfo[] = [ITEM_TM59] = { - .name = _("TM59"), + .name = ITEM_NAME("TM59"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11746,7 +11751,7 @@ const struct Item gItemsInfo[] = [ITEM_TM60] = { - .name = _("TM60"), + .name = ITEM_NAME("TM60"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11757,7 +11762,7 @@ const struct Item gItemsInfo[] = [ITEM_TM61] = { - .name = _("TM61"), + .name = ITEM_NAME("TM61"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11768,7 +11773,7 @@ const struct Item gItemsInfo[] = [ITEM_TM62] = { - .name = _("TM62"), + .name = ITEM_NAME("TM62"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11779,7 +11784,7 @@ const struct Item gItemsInfo[] = [ITEM_TM63] = { - .name = _("TM63"), + .name = ITEM_NAME("TM63"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11790,7 +11795,7 @@ const struct Item gItemsInfo[] = [ITEM_TM64] = { - .name = _("TM64"), + .name = ITEM_NAME("TM64"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11801,7 +11806,7 @@ const struct Item gItemsInfo[] = [ITEM_TM65] = { - .name = _("TM65"), + .name = ITEM_NAME("TM65"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11812,7 +11817,7 @@ const struct Item gItemsInfo[] = [ITEM_TM66] = { - .name = _("TM66"), + .name = ITEM_NAME("TM66"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11823,7 +11828,7 @@ const struct Item gItemsInfo[] = [ITEM_TM67] = { - .name = _("TM67"), + .name = ITEM_NAME("TM67"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11834,7 +11839,7 @@ const struct Item gItemsInfo[] = [ITEM_TM68] = { - .name = _("TM68"), + .name = ITEM_NAME("TM68"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11845,7 +11850,7 @@ const struct Item gItemsInfo[] = [ITEM_TM69] = { - .name = _("TM69"), + .name = ITEM_NAME("TM69"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11856,7 +11861,7 @@ const struct Item gItemsInfo[] = [ITEM_TM70] = { - .name = _("TM70"), + .name = ITEM_NAME("TM70"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11867,7 +11872,7 @@ const struct Item gItemsInfo[] = [ITEM_TM71] = { - .name = _("TM71"), + .name = ITEM_NAME("TM71"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11878,7 +11883,7 @@ const struct Item gItemsInfo[] = [ITEM_TM72] = { - .name = _("TM72"), + .name = ITEM_NAME("TM72"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11889,7 +11894,7 @@ const struct Item gItemsInfo[] = [ITEM_TM73] = { - .name = _("TM73"), + .name = ITEM_NAME("TM73"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11900,7 +11905,7 @@ const struct Item gItemsInfo[] = [ITEM_TM74] = { - .name = _("TM74"), + .name = ITEM_NAME("TM74"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11911,7 +11916,7 @@ const struct Item gItemsInfo[] = [ITEM_TM75] = { - .name = _("TM75"), + .name = ITEM_NAME("TM75"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11922,7 +11927,7 @@ const struct Item gItemsInfo[] = [ITEM_TM76] = { - .name = _("TM76"), + .name = ITEM_NAME("TM76"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11933,7 +11938,7 @@ const struct Item gItemsInfo[] = [ITEM_TM77] = { - .name = _("TM77"), + .name = ITEM_NAME("TM77"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11944,7 +11949,7 @@ const struct Item gItemsInfo[] = [ITEM_TM78] = { - .name = _("TM78"), + .name = ITEM_NAME("TM78"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11955,7 +11960,7 @@ const struct Item gItemsInfo[] = [ITEM_TM79] = { - .name = _("TM79"), + .name = ITEM_NAME("TM79"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11966,7 +11971,7 @@ const struct Item gItemsInfo[] = [ITEM_TM80] = { - .name = _("TM80"), + .name = ITEM_NAME("TM80"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11977,7 +11982,7 @@ const struct Item gItemsInfo[] = [ITEM_TM81] = { - .name = _("TM81"), + .name = ITEM_NAME("TM81"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11988,7 +11993,7 @@ const struct Item gItemsInfo[] = [ITEM_TM82] = { - .name = _("TM82"), + .name = ITEM_NAME("TM82"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -11999,7 +12004,7 @@ const struct Item gItemsInfo[] = [ITEM_TM83] = { - .name = _("TM83"), + .name = ITEM_NAME("TM83"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12010,7 +12015,7 @@ const struct Item gItemsInfo[] = [ITEM_TM84] = { - .name = _("TM84"), + .name = ITEM_NAME("TM84"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12021,7 +12026,7 @@ const struct Item gItemsInfo[] = [ITEM_TM85] = { - .name = _("TM85"), + .name = ITEM_NAME("TM85"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12032,7 +12037,7 @@ const struct Item gItemsInfo[] = [ITEM_TM86] = { - .name = _("TM86"), + .name = ITEM_NAME("TM86"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12043,7 +12048,7 @@ const struct Item gItemsInfo[] = [ITEM_TM87] = { - .name = _("TM87"), + .name = ITEM_NAME("TM87"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12054,7 +12059,7 @@ const struct Item gItemsInfo[] = [ITEM_TM88] = { - .name = _("TM88"), + .name = ITEM_NAME("TM88"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12065,7 +12070,7 @@ const struct Item gItemsInfo[] = [ITEM_TM89] = { - .name = _("TM89"), + .name = ITEM_NAME("TM89"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12076,7 +12081,7 @@ const struct Item gItemsInfo[] = [ITEM_TM90] = { - .name = _("TM90"), + .name = ITEM_NAME("TM90"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12087,7 +12092,7 @@ const struct Item gItemsInfo[] = [ITEM_TM91] = { - .name = _("TM91"), + .name = ITEM_NAME("TM91"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12098,7 +12103,7 @@ const struct Item gItemsInfo[] = [ITEM_TM92] = { - .name = _("TM92"), + .name = ITEM_NAME("TM92"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12109,7 +12114,7 @@ const struct Item gItemsInfo[] = [ITEM_TM93] = { - .name = _("TM93"), + .name = ITEM_NAME("TM93"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12120,7 +12125,7 @@ const struct Item gItemsInfo[] = [ITEM_TM94] = { - .name = _("TM94"), + .name = ITEM_NAME("TM94"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12131,7 +12136,7 @@ const struct Item gItemsInfo[] = [ITEM_TM95] = { - .name = _("TM95"), + .name = ITEM_NAME("TM95"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12142,7 +12147,7 @@ const struct Item gItemsInfo[] = [ITEM_TM96] = { - .name = _("TM96"), + .name = ITEM_NAME("TM96"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12153,7 +12158,7 @@ const struct Item gItemsInfo[] = [ITEM_TM97] = { - .name = _("TM97"), + .name = ITEM_NAME("TM97"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12164,7 +12169,7 @@ const struct Item gItemsInfo[] = [ITEM_TM98] = { - .name = _("TM98"), + .name = ITEM_NAME("TM98"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12175,7 +12180,7 @@ const struct Item gItemsInfo[] = [ITEM_TM99] = { - .name = _("TM99"), + .name = ITEM_NAME("TM99"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12186,7 +12191,7 @@ const struct Item gItemsInfo[] = [ITEM_TM100] = { - .name = _("TM100"), + .name = ITEM_NAME("TM100"), .price = 3000, .description = sQuestionMarksDesc, // Todo .importance = I_REUSABLE_TMS, @@ -12197,7 +12202,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_CUT] = { - .name = _("HM01"), + .name = ITEM_NAME("HM01"), .price = 0, .description = COMPOUND_STRING( "Attacks the foe\n" @@ -12211,7 +12216,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_FLY] = { - .name = _("HM02"), + .name = ITEM_NAME("HM02"), .price = 0, .description = COMPOUND_STRING( "Flies up on the\n" @@ -12225,7 +12230,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_SURF] = { - .name = _("HM03"), + .name = ITEM_NAME("HM03"), .price = 0, .description = COMPOUND_STRING( "Creates a huge\n" @@ -12239,7 +12244,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_STRENGTH] = { - .name = _("HM04"), + .name = ITEM_NAME("HM04"), .price = 0, .description = COMPOUND_STRING( "Builds enormous\n" @@ -12253,7 +12258,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_FLASH] = { - .name = _("HM05"), + .name = ITEM_NAME("HM05"), .price = 0, .description = COMPOUND_STRING( "Looses a powerful\n" @@ -12267,7 +12272,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_ROCK_SMASH] = { - .name = _("HM06"), + .name = ITEM_NAME("HM06"), .price = 0, .description = COMPOUND_STRING( "A rock-crushingly\n" @@ -12281,7 +12286,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_WATERFALL] = { - .name = _("HM07"), + .name = ITEM_NAME("HM07"), .price = 0, .description = COMPOUND_STRING( "Attacks the foe\n" @@ -12295,7 +12300,7 @@ const struct Item gItemsInfo[] = [ITEM_HM_DIVE] = { - .name = _("HM08"), + .name = ITEM_NAME("HM08"), .price = 0, .description = COMPOUND_STRING( "Dives underwater\n" @@ -12312,7 +12317,7 @@ const struct Item gItemsInfo[] = [ITEM_OVAL_CHARM] = { - .name = _("Oval Charm"), + .name = ITEM_NAME("Oval Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12328,7 +12333,7 @@ const struct Item gItemsInfo[] = [ITEM_SHINY_CHARM] = { - .name = _("Shiny Charm"), + .name = ITEM_NAME("Shiny Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12344,7 +12349,7 @@ const struct Item gItemsInfo[] = [ITEM_CATCHING_CHARM] = { - .name = _("Catching Charm"), + .name = ITEM_NAME("Catching Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12360,7 +12365,7 @@ const struct Item gItemsInfo[] = [ITEM_EXP_CHARM] = { - .name = _("Exp. Charm"), + .name = ITEM_NAME("Exp. Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12378,7 +12383,7 @@ const struct Item gItemsInfo[] = [ITEM_ROTOM_CATALOG] = { - .name = _("Rotom Catalog"), + .name = ITEM_NAME("Rotom Catalog"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12394,7 +12399,7 @@ const struct Item gItemsInfo[] = [ITEM_GRACIDEA] = { - .name = _("Gracidea"), + .name = ITEM_NAME("Gracidea"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12410,8 +12415,8 @@ const struct Item gItemsInfo[] = [ITEM_REVEAL_GLASS] = { - .name = _("Reveal Glass"), - .pluralName = _("Reveal Glasses"), + .name = ITEM_NAME("Reveal Glass"), + .pluralName = ITEM_PLURAL_NAME("Reveal Glasses"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12427,8 +12432,8 @@ const struct Item gItemsInfo[] = [ITEM_DNA_SPLICERS] = { - .name = _("DNA Splicers"), - .pluralName = _("DNA Splicers"), + .name = ITEM_NAME("DNA Splicers"), + .pluralName = ITEM_PLURAL_NAME("DNA Splicers"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12444,7 +12449,7 @@ const struct Item gItemsInfo[] = [ITEM_ZYGARDE_CUBE] = { - .name = _("Zygarde Cube"), + .name = ITEM_NAME("Zygarde Cube"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12460,7 +12465,7 @@ const struct Item gItemsInfo[] = [ITEM_PRISON_BOTTLE] = { - .name = _("Prison Bottle"), + .name = ITEM_NAME("Prison Bottle"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12476,7 +12481,7 @@ const struct Item gItemsInfo[] = [ITEM_N_SOLARIZER] = { - .name = _("N-Solarizer"), + .name = ITEM_NAME("N-Solarizer"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12492,7 +12497,7 @@ const struct Item gItemsInfo[] = [ITEM_N_LUNARIZER] = { - .name = _("N-Lunarizer"), + .name = ITEM_NAME("N-Lunarizer"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12508,8 +12513,8 @@ const struct Item gItemsInfo[] = [ITEM_REINS_OF_UNITY] = { - .name = _("Reins of Unity"), - .pluralName = _("Reins of Unity"), + .name = ITEM_NAME("Reins of Unity"), + .pluralName = ITEM_PLURAL_NAME("Reins of Unity"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12527,7 +12532,7 @@ const struct Item gItemsInfo[] = [ITEM_MEGA_RING] = { - .name = _("Mega Ring"), + .name = ITEM_NAME("Mega Ring"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12543,7 +12548,7 @@ const struct Item gItemsInfo[] = [ITEM_Z_POWER_RING] = { - .name = _("Z-Power Ring"), + .name = ITEM_NAME("Z-Power Ring"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -12559,7 +12564,7 @@ const struct Item gItemsInfo[] = [ITEM_DYNAMAX_BAND] = { - .name = _("Dynamax Band"), + .name = ITEM_NAME("Dynamax Band"), .price = 0, .description = COMPOUND_STRING( "A band carrying a\n" @@ -12576,7 +12581,7 @@ const struct Item gItemsInfo[] = [ITEM_BICYCLE] = { - .name = _("Bicycle"), + .name = ITEM_NAME("Bicycle"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle\n" @@ -12592,7 +12597,7 @@ const struct Item gItemsInfo[] = [ITEM_MACH_BIKE] = { - .name = _("Mach Bike"), + .name = ITEM_NAME("Mach Bike"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle\n" @@ -12609,7 +12614,7 @@ const struct Item gItemsInfo[] = [ITEM_ACRO_BIKE] = { - .name = _("Acro Bike"), + .name = ITEM_NAME("Acro Bike"), .price = 0, .description = COMPOUND_STRING( "A folding bicycle\n" @@ -12626,7 +12631,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_ROD] = { - .name = _("Old Rod"), + .name = ITEM_NAME("Old Rod"), .price = 0, .description = COMPOUND_STRING( "Use by any body of\n" @@ -12643,7 +12648,7 @@ const struct Item gItemsInfo[] = [ITEM_GOOD_ROD] = { - .name = _("Good Rod"), + .name = ITEM_NAME("Good Rod"), .price = 0, .description = COMPOUND_STRING( "A decent fishing\n" @@ -12660,7 +12665,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPER_ROD] = { - .name = _("Super Rod"), + .name = ITEM_NAME("Super Rod"), .price = 0, .description = COMPOUND_STRING( "The best fishing\n" @@ -12677,7 +12682,7 @@ const struct Item gItemsInfo[] = [ITEM_DOWSING_MACHINE] = { - .name = _("Dowsing Machine"), + .name = ITEM_NAME("Dowsing Machine"), .price = 0, .description = COMPOUND_STRING( "A device that\n" @@ -12693,7 +12698,7 @@ const struct Item gItemsInfo[] = [ITEM_TOWN_MAP] = { - .name = _("Town Map"), + .name = ITEM_NAME("Town Map"), .price = 0, .description = COMPOUND_STRING( "Can be viewed\n" @@ -12709,7 +12714,7 @@ const struct Item gItemsInfo[] = [ITEM_VS_SEEKER] = { - .name = _("Vs. Seeker"), + .name = ITEM_NAME("Vs. Seeker"), .price = 0, .description = COMPOUND_STRING( "A rechargeable unit\n" @@ -12729,7 +12734,7 @@ const struct Item gItemsInfo[] = [ITEM_TM_CASE] = { - .name = _("TM Case"), + .name = ITEM_NAME("TM Case"), .price = 0, .description = COMPOUND_STRING( "A convenient case\n" @@ -12745,8 +12750,8 @@ const struct Item gItemsInfo[] = [ITEM_BERRY_POUCH] = { - .name = _("Berry Pouch"), - .pluralName = _("Berry Pouches"), + .name = ITEM_NAME("Berry Pouch"), + .pluralName = ITEM_PLURAL_NAME("Berry Pouches"), .price = 0, .description = COMPOUND_STRING( "A convenient\n" @@ -12762,7 +12767,7 @@ const struct Item gItemsInfo[] = [ITEM_POKEMON_BOX_LINK] = { - .name = _("{PKMN} Box Link"), + .name = ITEM_NAME("{PKMN} Box Link"), .price = 0, .description = COMPOUND_STRING( "This device grants\n" @@ -12778,7 +12783,7 @@ const struct Item gItemsInfo[] = [ITEM_COIN_CASE] = { - .name = _("Coin Case"), + .name = ITEM_NAME("Coin Case"), .price = 0, .description = COMPOUND_STRING( "A case that holds\n" @@ -12793,7 +12798,7 @@ const struct Item gItemsInfo[] = [ITEM_POWDER_JAR] = { - .name = _("Powder Jar"), + .name = ITEM_NAME("Powder Jar"), .price = 0, .description = COMPOUND_STRING( "Stores Berry\n" @@ -12809,7 +12814,7 @@ const struct Item gItemsInfo[] = [ITEM_WAILMER_PAIL] = { - .name = _("Wailmer Pail"), + .name = ITEM_NAME("Wailmer Pail"), .price = 0, .description = COMPOUND_STRING( "A tool used for\n" @@ -12825,7 +12830,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_RADAR] = { - .name = _("Poké Radar"), + .name = ITEM_NAME("Poké Radar"), .price = 0, .description = COMPOUND_STRING( "A tool used to\n" @@ -12841,7 +12846,7 @@ const struct Item gItemsInfo[] = [ITEM_POKEBLOCK_CASE] = { - .name = _("{POKEBLOCK} Case"), + .name = ITEM_NAME("{POKEBLOCK} Case"), .price = 0, .description = COMPOUND_STRING( "A case for holding\n" @@ -12857,7 +12862,7 @@ const struct Item gItemsInfo[] = [ITEM_SOOT_SACK] = { - .name = _("Soot Sack"), + .name = ITEM_NAME("Soot Sack"), .price = 0, .description = COMPOUND_STRING( "A sack used to\n" @@ -12873,7 +12878,7 @@ const struct Item gItemsInfo[] = [ITEM_POKE_FLUTE] = { - .name = _("Poké Flute"), + .name = ITEM_NAME("Poké Flute"), .price = 0, .description = COMPOUND_STRING( "A sweet-sounding\n" @@ -12890,7 +12895,7 @@ const struct Item gItemsInfo[] = [ITEM_FAME_CHECKER] = { - .name = _("Fame Checker"), + .name = ITEM_NAME("Fame Checker"), .price = 0, .description = COMPOUND_STRING( "Stores information\n" @@ -12906,7 +12911,7 @@ const struct Item gItemsInfo[] = [ITEM_TEACHY_TV] = { - .name = _("Teachy TV"), + .name = ITEM_NAME("Teachy TV"), .price = 0, .description = COMPOUND_STRING( "A TV set tuned to\n" @@ -12924,7 +12929,7 @@ const struct Item gItemsInfo[] = [ITEM_SS_TICKET] = { - .name = _("S.S. Ticket"), + .name = ITEM_NAME("S.S. Ticket"), .price = 0, .description = COMPOUND_STRING( "The ticket required\n" @@ -12940,7 +12945,7 @@ const struct Item gItemsInfo[] = [ITEM_EON_TICKET] = { - .name = _("Eon Ticket"), + .name = ITEM_NAME("Eon Ticket"), .price = 0, .description = COMPOUND_STRING( "The ticket for a\n" @@ -12957,7 +12962,7 @@ const struct Item gItemsInfo[] = [ITEM_MYSTIC_TICKET] = { - .name = _("Mystic Ticket"), + .name = ITEM_NAME("Mystic Ticket"), .price = 0, .description = COMPOUND_STRING( "A ticket required\n" @@ -12973,7 +12978,7 @@ const struct Item gItemsInfo[] = [ITEM_AURORA_TICKET] = { - .name = _("Aurora Ticket"), + .name = ITEM_NAME("Aurora Ticket"), .price = 0, .description = COMPOUND_STRING( "A ticket required\n" @@ -12989,7 +12994,7 @@ const struct Item gItemsInfo[] = [ITEM_OLD_SEA_MAP] = { - .name = _("Old Sea Map"), + .name = ITEM_NAME("Old Sea Map"), .price = 0, .description = COMPOUND_STRING( "A faded sea chart\n" @@ -13005,7 +13010,7 @@ const struct Item gItemsInfo[] = [ITEM_LETTER] = { - .name = _("Letter"), + .name = ITEM_NAME("Letter"), .price = 0, .description = COMPOUND_STRING( "A letter to Steven\n" @@ -13021,8 +13026,8 @@ const struct Item gItemsInfo[] = [ITEM_DEVON_PARTS] = { - .name = _("Devon Parts"), - .pluralName = _("Devon Parts"), + .name = ITEM_NAME("Devon Parts"), + .pluralName = ITEM_PLURAL_NAME("Devon Parts"), .price = 0, .description = COMPOUND_STRING( "A package that\n" @@ -13038,8 +13043,8 @@ const struct Item gItemsInfo[] = [ITEM_GO_GOGGLES] = { - .name = _("Go-Goggles"), - .pluralName = _("Go-Goggles"), + .name = ITEM_NAME("Go-Goggles"), + .pluralName = ITEM_PLURAL_NAME("Go-Goggles"), .price = 0, .description = COMPOUND_STRING( "Nifty goggles that\n" @@ -13055,7 +13060,7 @@ const struct Item gItemsInfo[] = [ITEM_DEVON_SCOPE] = { - .name = _("Devon Scope"), + .name = ITEM_NAME("Devon Scope"), .price = 0, .description = COMPOUND_STRING( "A device by Devon\n" @@ -13071,7 +13076,7 @@ const struct Item gItemsInfo[] = [ITEM_BASEMENT_KEY] = { - .name = _("Basement Key"), + .name = ITEM_NAME("Basement Key"), .price = 0, .description = COMPOUND_STRING( "The key for New\n" @@ -13087,7 +13092,7 @@ const struct Item gItemsInfo[] = [ITEM_SCANNER] = { - .name = _("Scanner"), + .name = ITEM_NAME("Scanner"), .price = 0, .description = COMPOUND_STRING( "A device found\n" @@ -13103,7 +13108,7 @@ const struct Item gItemsInfo[] = [ITEM_STORAGE_KEY] = { - .name = _("Storage Key"), + .name = ITEM_NAME("Storage Key"), .price = 0, .description = COMPOUND_STRING( "The key to the\n" @@ -13119,8 +13124,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_1] = { - .name = _("Key to Room 1"), - .pluralName = _("Keys to Room 1"), + .name = ITEM_NAME("Key to Room 1"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 1"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -13133,8 +13138,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_2] = { - .name = _("Key to Room 2"), - .pluralName = _("Keys to Room 2"), + .name = ITEM_NAME("Key to Room 2"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 2"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -13147,8 +13152,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_4] = { - .name = _("Key to Room 4"), - .pluralName = _("Keys to Room 4"), + .name = ITEM_NAME("Key to Room 4"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 4"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -13161,8 +13166,8 @@ const struct Item gItemsInfo[] = [ITEM_KEY_TO_ROOM_6] = { - .name = _("Key to Room 6"), - .pluralName = _("Keys to Room 6"), + .name = ITEM_NAME("Key to Room 6"), + .pluralName = ITEM_PLURAL_NAME("Keys to Room 6"), .price = 0, .description = sKeyToRoomDesc, .importance = 1, @@ -13175,7 +13180,7 @@ const struct Item gItemsInfo[] = [ITEM_METEORITE] = { - .name = _("Meteorite"), + .name = ITEM_NAME("Meteorite"), .price = 0, .description = COMPOUND_STRING( "A meteorite found\n" @@ -13190,7 +13195,7 @@ const struct Item gItemsInfo[] = [ITEM_MAGMA_EMBLEM] = { - .name = _("Magma Emblem"), + .name = ITEM_NAME("Magma Emblem"), .price = 0, .description = COMPOUND_STRING( "A medal-like item in\n" @@ -13206,8 +13211,8 @@ const struct Item gItemsInfo[] = [ITEM_CONTEST_PASS] = { - .name = _("Contest Pass"), - .pluralName = _("Contest Passes"), + .name = ITEM_NAME("Contest Pass"), + .pluralName = ITEM_PLURAL_NAME("Contest Passes"), .price = 0, .description = COMPOUND_STRING( "The pass required\n" @@ -13223,7 +13228,7 @@ const struct Item gItemsInfo[] = [ITEM_PARCEL] = { - .name = _("Parcel"), + .name = ITEM_NAME("Parcel"), .price = 0, .description = COMPOUND_STRING( "A parcel for Prof.\n" @@ -13239,7 +13244,7 @@ const struct Item gItemsInfo[] = [ITEM_SECRET_KEY] = { - .name = _("Secret Key"), + .name = ITEM_NAME("Secret Key"), .price = 0, .description = COMPOUND_STRING( "The key to the\n" @@ -13255,7 +13260,7 @@ const struct Item gItemsInfo[] = [ITEM_BIKE_VOUCHER] = { - .name = _("Bike Voucher"), + .name = ITEM_NAME("Bike Voucher"), .price = 0, .description = COMPOUND_STRING( "A voucher for\n" @@ -13271,8 +13276,8 @@ const struct Item gItemsInfo[] = [ITEM_GOLD_TEETH] = { - .name = _("Gold Teeth"), - .pluralName = _("Gold Teeth"), + .name = ITEM_NAME("Gold Teeth"), + .pluralName = ITEM_PLURAL_NAME("Gold Teeth"), .price = 0, .description = COMPOUND_STRING( "Gold dentures lost\n" @@ -13288,7 +13293,7 @@ const struct Item gItemsInfo[] = [ITEM_CARD_KEY] = { - .name = _("Card Key"), + .name = ITEM_NAME("Card Key"), .price = 0, .description = COMPOUND_STRING( "A card-type door\n" @@ -13304,7 +13309,7 @@ const struct Item gItemsInfo[] = [ITEM_LIFT_KEY] = { - .name = _("Lift Key"), + .name = ITEM_NAME("Lift Key"), .price = 0, .description = COMPOUND_STRING( "An elevator key\n" @@ -13320,7 +13325,7 @@ const struct Item gItemsInfo[] = [ITEM_SILPH_SCOPE] = { - .name = _("Silph Scope"), + .name = ITEM_NAME("Silph Scope"), .price = 0, .description = COMPOUND_STRING( "Silph Co's scope\n" @@ -13336,8 +13341,8 @@ const struct Item gItemsInfo[] = [ITEM_TRI_PASS] = { - .name = _("Tri-Pass"), - .pluralName = _("Tri-Passes"), + .name = ITEM_NAME("Tri-Pass"), + .pluralName = ITEM_PLURAL_NAME("Tri-Passes"), .price = 0, .description = COMPOUND_STRING( "A pass for ferries\n" @@ -13353,8 +13358,8 @@ const struct Item gItemsInfo[] = [ITEM_RAINBOW_PASS] = { - .name = _("Rainbow Pass"), - .pluralName = _("Rainbow Passes"), + .name = ITEM_NAME("Rainbow Pass"), + .pluralName = ITEM_PLURAL_NAME("Rainbow Passes"), .price = 0, .description = COMPOUND_STRING( "For ferries serving\n" @@ -13370,8 +13375,8 @@ const struct Item gItemsInfo[] = [ITEM_TEA] = { - .name = _("Tea"), - .pluralName = _("Tea"), + .name = ITEM_NAME("Tea"), + .pluralName = ITEM_PLURAL_NAME("Tea"), .price = 0, .description = COMPOUND_STRING( "A thirst-quenching\n" @@ -13387,8 +13392,8 @@ const struct Item gItemsInfo[] = [ITEM_RUBY] = { - .name = _("Ruby"), - .pluralName = _("Rubies"), + .name = ITEM_NAME("Ruby"), + .pluralName = ITEM_PLURAL_NAME("Rubies"), .price = 0, .description = COMPOUND_STRING( "An exquisite, red-\n" @@ -13404,7 +13409,7 @@ const struct Item gItemsInfo[] = [ITEM_SAPPHIRE] = { - .name = _("Sapphire"), + .name = ITEM_NAME("Sapphire"), .price = 0, .description = COMPOUND_STRING( "A brilliant blue gem\n" @@ -13420,7 +13425,7 @@ const struct Item gItemsInfo[] = [ITEM_ABILITY_SHIELD] = { - .name = _("Ability Shield"), + .name = ITEM_NAME("Ability Shield"), .price = 20000, .holdEffect = HOLD_EFFECT_ABILITY_SHIELD, .description = COMPOUND_STRING( @@ -13439,7 +13444,7 @@ const struct Item gItemsInfo[] = [ITEM_CLEAR_AMULET] = { - .name = _("Clear Amulet"), + .name = ITEM_NAME("Clear Amulet"), .price = 30000, .holdEffect = HOLD_EFFECT_CLEAR_AMULET, .description = COMPOUND_STRING( @@ -13457,7 +13462,7 @@ const struct Item gItemsInfo[] = [ITEM_PUNCHING_GLOVE] = { - .name = _("Punching Glove"), + .name = ITEM_NAME("Punching Glove"), .price = 15000, .holdEffect = HOLD_EFFECT_PUNCHING_GLOVE, .description = COMPOUND_STRING( @@ -13475,7 +13480,7 @@ const struct Item gItemsInfo[] = [ITEM_COVERT_CLOAK] = { - .name = _("Covert Cloak"), + .name = ITEM_NAME("Covert Cloak"), .price = 20000, .holdEffect = HOLD_EFFECT_COVERT_CLOAK, .description = COMPOUND_STRING( @@ -13493,8 +13498,8 @@ const struct Item gItemsInfo[] = [ITEM_LOADED_DICE] = { - .name = _("Loaded Dice"), - .pluralName = _("Loaded Dice"), + .name = ITEM_NAME("Loaded Dice"), + .pluralName = ITEM_PLURAL_NAME("Loaded Dice"), .price = 20000, .holdEffect = HOLD_EFFECT_LOADED_DICE, .description = COMPOUND_STRING( @@ -13512,7 +13517,7 @@ const struct Item gItemsInfo[] = [ITEM_AUSPICIOUS_ARMOR] = { - .name = _("Auspicious Armor"), + .name = ITEM_NAME("Auspicious Armor"), .price = 3000, .description = COMPOUND_STRING( "Armor inhabited by\n" @@ -13530,8 +13535,8 @@ const struct Item gItemsInfo[] = [ITEM_BOOSTER_ENERGY] = { - .name = _("Booster Energy"), - .pluralName = _("Booster Energies"), + .name = ITEM_NAME("Booster Energy"), + .pluralName = ITEM_PLURAL_NAME("Booster Energies"), .price = 0, .holdEffect = HOLD_EFFECT_BOOSTER_ENERGY, .description = COMPOUND_STRING( @@ -13549,7 +13554,7 @@ const struct Item gItemsInfo[] = [ITEM_BIG_BAMBOO_SHOOT] = { - .name = _("Big Bamboo Shoot"), + .name = ITEM_NAME("Big Bamboo Shoot"), .price = 3000, .description = COMPOUND_STRING( "A large and rare\n" @@ -13566,7 +13571,7 @@ const struct Item gItemsInfo[] = [ITEM_GIMMIGHOUL_COIN] = { - .name = _("Gimmighoul Coin"), + .name = ITEM_NAME("Gimmighoul Coin"), .price = 400, .description = COMPOUND_STRING( "Gimmighoul hoard\n" @@ -13582,7 +13587,7 @@ const struct Item gItemsInfo[] = [ITEM_LEADERS_CREST] = { - .name = _("Leader's Crest"), + .name = ITEM_NAME("Leader's Crest"), .price = 3000, .description = COMPOUND_STRING( "A shard of an old\n" @@ -13598,7 +13603,7 @@ const struct Item gItemsInfo[] = [ITEM_MALICIOUS_ARMOR] = { - .name = _("Malicious Armor"), + .name = ITEM_NAME("Malicious Armor"), .price = 3000, .description = COMPOUND_STRING( "Armor inhabited by\n" @@ -13616,7 +13621,7 @@ const struct Item gItemsInfo[] = [ITEM_MIRROR_HERB] = { - .name = _("Mirror Herb"), + .name = ITEM_NAME("Mirror Herb"), .price = 30000, .holdEffect = HOLD_EFFECT_MIRROR_HERB, .description = COMPOUND_STRING( @@ -13634,8 +13639,8 @@ const struct Item gItemsInfo[] = [ITEM_SCROLL_OF_DARKNESS] = { - .name = _("Scroll of Darkness"), - .pluralName = _("Scrolls of Darkness"), + .name = ITEM_NAME("Scroll of Darkness"), + .pluralName = ITEM_PLURAL_NAME("Scrolls of Darkness"), .price = 0, .description = COMPOUND_STRING( "A peculiar scroll\n" @@ -13653,8 +13658,8 @@ const struct Item gItemsInfo[] = [ITEM_SCROLL_OF_WATERS] = { - .name = _("Scroll of Waters"), - .pluralName = _("Scrolls of Waters"), + .name = ITEM_NAME("Scroll of Waters"), + .pluralName = ITEM_PLURAL_NAME("Scrolls of Waters"), .price = 0, .description = COMPOUND_STRING( "A peculiar scroll\n" @@ -13672,7 +13677,7 @@ const struct Item gItemsInfo[] = [ITEM_TERA_ORB] = { - .name = _("Tera Orb"), + .name = ITEM_NAME("Tera Orb"), .price = 0, .description = COMPOUND_STRING( "Energy charges can\n" @@ -13688,7 +13693,7 @@ const struct Item gItemsInfo[] = [ITEM_TINY_BAMBOO_SHOOT] = { - .name = _("Tiny Bamboo Shoot"), + .name = ITEM_NAME("Tiny Bamboo Shoot"), .price = 750, .description = COMPOUND_STRING( "A small and rare\n" @@ -13705,7 +13710,7 @@ const struct Item gItemsInfo[] = [ITEM_BUG_TERA_SHARD] = { - .name = _("Bug Tera Shard"), + .name = ITEM_NAME("Bug Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13718,7 +13723,7 @@ const struct Item gItemsInfo[] = [ITEM_DARK_TERA_SHARD] = { - .name = _("Dark Tera Shard"), + .name = ITEM_NAME("Dark Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13731,7 +13736,7 @@ const struct Item gItemsInfo[] = [ITEM_DRAGON_TERA_SHARD] = { - .name = _("Dragon Tera Shard"), + .name = ITEM_NAME("Dragon Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13744,7 +13749,7 @@ const struct Item gItemsInfo[] = [ITEM_ELECTRIC_TERA_SHARD] = { - .name = _("Electric Tera Shard"), + .name = ITEM_NAME("Electric Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13757,7 +13762,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_TERA_SHARD] = { - .name = _("Fairy Tera Shard"), + .name = ITEM_NAME("Fairy Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13770,7 +13775,7 @@ const struct Item gItemsInfo[] = [ITEM_FIGHTING_TERA_SHARD] = { - .name = _("Fighting Tera Shard"), + .name = ITEM_NAME("Fighting Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13783,7 +13788,7 @@ const struct Item gItemsInfo[] = [ITEM_FIRE_TERA_SHARD] = { - .name = _("Fire Tera Shard"), + .name = ITEM_NAME("Fire Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13796,7 +13801,7 @@ const struct Item gItemsInfo[] = [ITEM_FLYING_TERA_SHARD] = { - .name = _("Flying Tera Shard"), + .name = ITEM_NAME("Flying Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13809,7 +13814,7 @@ const struct Item gItemsInfo[] = [ITEM_GHOST_TERA_SHARD] = { - .name = _("Ghost Tera Shard"), + .name = ITEM_NAME("Ghost Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13822,7 +13827,7 @@ const struct Item gItemsInfo[] = [ITEM_GRASS_TERA_SHARD] = { - .name = _("Grass Tera Shard"), + .name = ITEM_NAME("Grass Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13835,7 +13840,7 @@ const struct Item gItemsInfo[] = [ITEM_GROUND_TERA_SHARD] = { - .name = _("Ground Tera Shard"), + .name = ITEM_NAME("Ground Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13848,7 +13853,7 @@ const struct Item gItemsInfo[] = [ITEM_ICE_TERA_SHARD] = { - .name = _("Ice Tera Shard"), + .name = ITEM_NAME("Ice Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13861,7 +13866,7 @@ const struct Item gItemsInfo[] = [ITEM_NORMAL_TERA_SHARD] = { - .name = _("Normal Tera Shard"), + .name = ITEM_NAME("Normal Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13874,7 +13879,7 @@ const struct Item gItemsInfo[] = [ITEM_POISON_TERA_SHARD] = { - .name = _("Poison Tera Shard"), + .name = ITEM_NAME("Poison Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13887,7 +13892,7 @@ const struct Item gItemsInfo[] = [ITEM_PSYCHIC_TERA_SHARD] = { - .name = _("Psychic Tera Shard"), + .name = ITEM_NAME("Psychic Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13900,7 +13905,7 @@ const struct Item gItemsInfo[] = [ITEM_ROCK_TERA_SHARD] = { - .name = _("Rock Tera Shard"), + .name = ITEM_NAME("Rock Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13913,7 +13918,7 @@ const struct Item gItemsInfo[] = [ITEM_STEEL_TERA_SHARD] = { - .name = _("Steel Tera Shard"), + .name = ITEM_NAME("Steel Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13926,7 +13931,7 @@ const struct Item gItemsInfo[] = [ITEM_WATER_TERA_SHARD] = { - .name = _("Water Tera Shard"), + .name = ITEM_NAME("Water Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -13939,7 +13944,7 @@ const struct Item gItemsInfo[] = [ITEM_ADAMANT_CRYSTAL] = { - .name = _("Adamant Crystal"), + .name = ITEM_NAME("Adamant Crystal"), .price = 0, .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, @@ -13958,7 +13963,7 @@ const struct Item gItemsInfo[] = [ITEM_GRISEOUS_CORE] = { - .name = _("Griseous Core"), + .name = ITEM_NAME("Griseous Core"), .price = 0, .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, @@ -13977,7 +13982,7 @@ const struct Item gItemsInfo[] = [ITEM_LUSTROUS_GLOBE] = { - .name = _("Lustrous Globe"), + .name = ITEM_NAME("Lustrous Globe"), .price = 0, .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, @@ -13996,7 +14001,7 @@ const struct Item gItemsInfo[] = [ITEM_BLACK_AUGURITE] = { - .name = _("Black Augurite"), + .name = ITEM_NAME("Black Augurite"), .price = 8000, .description = COMPOUND_STRING( "A black stone that\n" @@ -14014,7 +14019,7 @@ const struct Item gItemsInfo[] = [ITEM_LINKING_CORD] = { - .name = _("Linking Cord"), + .name = ITEM_NAME("Linking Cord"), .price = 8000, .description = COMPOUND_STRING( "A mysterious string\n" @@ -14032,7 +14037,7 @@ const struct Item gItemsInfo[] = [ITEM_PEAT_BLOCK] = { - .name = _("Peat Block"), + .name = ITEM_NAME("Peat Block"), .price = 10000, .description = COMPOUND_STRING( "A block of material\n" @@ -14050,7 +14055,7 @@ const struct Item gItemsInfo[] = [ITEM_BERSERK_GENE] = { - .name = _("Berserk Gene"), + .name = ITEM_NAME("Berserk Gene"), .price = 20, .holdEffect = HOLD_EFFECT_BERSERK_GENE, .description = COMPOUND_STRING( @@ -14068,7 +14073,7 @@ const struct Item gItemsInfo[] = [ITEM_FAIRY_FEATHER] = { - .name = _("Fairy Feather"), + .name = ITEM_NAME("Fairy Feather"), .price = 1000, .holdEffect = HOLD_EFFECT_TYPE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, @@ -14088,7 +14093,7 @@ const struct Item gItemsInfo[] = [ITEM_SYRUPY_APPLE] = { - .name = _("Syrupy Apple"), + .name = ITEM_NAME("Syrupy Apple"), .price = 2200, .description = COMPOUND_STRING( "A very syrupy apple\n" @@ -14106,7 +14111,7 @@ const struct Item gItemsInfo[] = [ITEM_UNREMARKABLE_TEACUP] = { - .name = _("Unremarkable Teacup"), + .name = ITEM_NAME("Unremarkable Teacup"), .price = 1600, .description = COMPOUND_STRING( "A cracked teacup\n" @@ -14124,7 +14129,7 @@ const struct Item gItemsInfo[] = [ITEM_MASTERPIECE_TEACUP] = { - .name = _("Masterpiece Teacup"), + .name = ITEM_NAME("Masterpiece Teacup"), .price = 38000, .description = COMPOUND_STRING( "A chipped teacup\n" @@ -14142,7 +14147,7 @@ const struct Item gItemsInfo[] = [ITEM_CORNERSTONE_MASK] = { - .name = _("Cornerstone Mask"), + .name = ITEM_NAME("Cornerstone Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -14160,7 +14165,7 @@ const struct Item gItemsInfo[] = [ITEM_WELLSPRING_MASK] = { - .name = _("Wellspring Mask"), + .name = ITEM_NAME("Wellspring Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -14178,7 +14183,7 @@ const struct Item gItemsInfo[] = [ITEM_HEARTHFLAME_MASK] = { - .name = _("Hearthflame Mask"), + .name = ITEM_NAME("Hearthflame Mask"), .price = 0, .holdEffect = HOLD_EFFECT_OGERPON_MASK, .holdEffectParam = 20, @@ -14196,8 +14201,8 @@ const struct Item gItemsInfo[] = [ITEM_HEALTH_MOCHI] = { - .name = _("Health Mochi"), - .pluralName = _("Health Mochi"), + .name = ITEM_NAME("Health Mochi"), + .pluralName = ITEM_PLURAL_NAME("Health Mochi"), .price = 500, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, @@ -14212,8 +14217,8 @@ const struct Item gItemsInfo[] = [ITEM_MUSCLE_MOCHI] = { - .name = _("Muscle Mochi"), - .pluralName = _("Muscle Mochi"), + .name = ITEM_NAME("Muscle Mochi"), + .pluralName = ITEM_PLURAL_NAME("Muscle Mochi"), .price = 500, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, @@ -14228,8 +14233,8 @@ const struct Item gItemsInfo[] = [ITEM_RESIST_MOCHI] = { - .name = _("Resist Mochi"), - .pluralName = _("Resist Mochi"), + .name = ITEM_NAME("Resist Mochi"), + .pluralName = ITEM_PLURAL_NAME("Resist Mochi"), .price = 500, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, @@ -14244,8 +14249,8 @@ const struct Item gItemsInfo[] = [ITEM_GENIUS_MOCHI] = { - .name = _("Genius Mochi"), - .pluralName = _("Genius Mochi"), + .name = ITEM_NAME("Genius Mochi"), + .pluralName = ITEM_PLURAL_NAME("Genius Mochi"), .price = 500, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, @@ -14260,8 +14265,8 @@ const struct Item gItemsInfo[] = [ITEM_CLEVER_MOCHI] = { - .name = _("Clever Mochi"), - .pluralName = _("Clever Mochi"), + .name = ITEM_NAME("Clever Mochi"), + .pluralName = ITEM_PLURAL_NAME("Clever Mochi"), .price = 500, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, @@ -14276,8 +14281,8 @@ const struct Item gItemsInfo[] = [ITEM_SWIFT_MOCHI] = { - .name = _("Swift Mochi"), - .pluralName = _("Swift Mochi"), + .name = ITEM_NAME("Swift Mochi"), + .pluralName = ITEM_PLURAL_NAME("Swift Mochi"), .price = 500, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, @@ -14292,8 +14297,8 @@ const struct Item gItemsInfo[] = [ITEM_FRESH_START_MOCHI] = { - .name = _("Fresh Start Mochi"), - .pluralName = _("Fresh Start Mochi"), + .name = ITEM_NAME("Fresh Start Mochi"), + .pluralName = ITEM_PLURAL_NAME("Fresh Start Mochi"), .price = 300, .description = COMPOUND_STRING( "An item that resets\n" @@ -14311,7 +14316,7 @@ const struct Item gItemsInfo[] = [ITEM_GLIMMERING_CHARM] = { - .name = _("Glimmering Charm"), + .name = ITEM_NAME("Glimmering Charm"), .price = 0, .importance = 1, .description = COMPOUND_STRING( @@ -14327,7 +14332,7 @@ const struct Item gItemsInfo[] = [ITEM_METAL_ALLOY] = { - .name = _("Metal Alloy"), + .name = ITEM_NAME("Metal Alloy"), .price = 6000, .description = COMPOUND_STRING( "A peculiar metal\n" @@ -14344,7 +14349,7 @@ const struct Item gItemsInfo[] = [ITEM_STELLAR_TERA_SHARD] = { - .name = _("Stellar Tera Shard"), + .name = ITEM_NAME("Stellar Tera Shard"), .price = 0, .description = sTeraShardDesc, .pocket = POCKET_ITEMS, @@ -14357,7 +14362,7 @@ const struct Item gItemsInfo[] = [ITEM_JUBILIFE_MUFFIN] = { - .name = _("Jubilife Muffin"), + .name = ITEM_NAME("Jubilife Muffin"), .price = 250, .description = sFullHealDesc, .pocket = POCKET_ITEMS, @@ -14373,7 +14378,7 @@ const struct Item gItemsInfo[] = [ITEM_REMEDY] = { - .name = _("Remedy"), + .name = ITEM_NAME("Remedy"), .price = 150, .description = COMPOUND_STRING( "A bitter powder\n" @@ -14392,7 +14397,7 @@ const struct Item gItemsInfo[] = [ITEM_FINE_REMEDY] = { - .name = _("Fine Remedy"), + .name = ITEM_NAME("Fine Remedy"), .price = 150, .description = COMPOUND_STRING( "A bitter powder\n" @@ -14415,7 +14420,7 @@ const struct Item gItemsInfo[] = [ITEM_SUPERB_REMEDY] = { - .name = _("Superb Remedy"), + .name = ITEM_NAME("Superb Remedy"), .price = 750, .description = COMPOUND_STRING( "A bitter powder\n" @@ -14438,7 +14443,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_EVASION] = { - .name = _("Aux Evasion"), + .name = ITEM_NAME("Aux Evasion"), .price = 800, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14461,7 +14466,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_GUARD] = { - .name = _("Aux Guard"), + .name = ITEM_NAME("Aux Guard"), .price = 400, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14484,7 +14489,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_POWER] = { - .name = _("Aux Power"), + .name = ITEM_NAME("Aux Power"), .price = 400, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14507,7 +14512,7 @@ const struct Item gItemsInfo[] = [ITEM_AUX_POWERGUARD] = { - .name = _("Aux Powerguard"), + .name = ITEM_NAME("Aux Powerguard"), .price = 1200, .holdEffectParam = X_ITEM_STAGES, .description = COMPOUND_STRING( @@ -14531,7 +14536,7 @@ const struct Item gItemsInfo[] = [ITEM_CHOICE_DUMPLING] = { - .name = _("Choice Dumpling"), + .name = ITEM_NAME("Choice Dumpling"), .price = 1200, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14544,7 +14549,7 @@ const struct Item gItemsInfo[] = [ITEM_SWAP_SNACK] = { - .name = _("Swap Snack"), + .name = ITEM_NAME("Swap Snack"), .price = 1200, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14557,7 +14562,7 @@ const struct Item gItemsInfo[] = [ITEM_TWICE_SPICED_RADISH] = { - .name = _("Twice-Spiced Radish"), + .name = ITEM_NAME("Twice-Spiced Radish"), .price = 1600, .description = sQuestionMarksDesc, .pocket = POCKET_ITEMS, @@ -14570,7 +14575,7 @@ const struct Item gItemsInfo[] = [ITEM_POKESHI_DOLL] = { - .name = _("Pokéshi Doll"), + .name = ITEM_NAME("Pokéshi Doll"), .price = 2000, .description = COMPOUND_STRING( "A wooden toy\n" @@ -14584,3 +14589,6 @@ const struct Item gItemsInfo[] = .iconPalette = gItemIconPalette_PokeshiDoll, }, }; + +#undef ITEM_NAME +#undef ITEM_PLURAL_NAME diff --git a/src/item.c b/src/item.c index 7ca2b90399..6802b2272c 100644 --- a/src/item.c +++ b/src/item.c @@ -776,7 +776,9 @@ static u16 SanitizeItemId(u16 itemId) const u8 *GetItemName(u16 itemId) { - return gItemsInfo[SanitizeItemId(itemId)].name; + const u8 *name = gItemsInfo[SanitizeItemId(itemId)].name; + + return name == NULL ? gQuestionMarksItemName : name; } u32 GetItemPrice(u16 itemId) @@ -786,7 +788,7 @@ u32 GetItemPrice(u16 itemId) static bool32 DoesItemHavePluralName(u16 itemId) { - return (gItemsInfo[SanitizeItemId(itemId)].pluralName[0] != '\0'); + return gItemsInfo[SanitizeItemId(itemId)].pluralName != NULL; } static const u8 *GetItemPluralName(u16 itemId) From 90601792b9dd6a022f3be9df2d9956cba5ca19e8 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:06:01 +0200 Subject: [PATCH 196/283] Split Sheer Force tests by gen instead of by four (#7260) --- test/battle/ability/sheer_force.c | 441 +++++++++++++++++++++++++++++- 1 file changed, 432 insertions(+), 9 deletions(-) diff --git a/test/battle/ability/sheer_force.c b/test/battle/ability/sheer_force.c index 076597d49b..8e99361296 100644 --- a/test/battle/ability/sheer_force.c +++ b/test/battle/ability/sheer_force.c @@ -609,12 +609,12 @@ static inline bool32 IsMoveSheerForceBoosted(u32 move) return FALSE; } -// Test split into four parts that handles ~1/4 of all moves each -DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 1") +// Tests split by generation +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen1)") { s16 damage1, damage2; u32 move = 0; - for (u32 j = 1; j < MOVES_COUNT; j += 4) + for (u32 j = MOVE_POUND; j < MOVES_COUNT_GEN1; j++) { if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) PARAMETRIZE { move = j; } @@ -692,13 +692,348 @@ DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to EXPECT_EQ(damage2, damage1); } } -DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 2") + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen2)") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = MOVE_SKETCH; j < MOVES_COUNT_GEN2; j++) + { + if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + switch (GetMoveEffect(move)) + { + case EFFECT_TWO_TURNS_ATTACK: + case EFFECT_SEMI_INVULNERABLE: + case EFFECT_SOLAR_BEAM: + case EFFECT_SKY_DROP: + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + break; + case EFFECT_FUTURE_SIGHT: + TURN { ; } + TURN { ; } + break; + case EFFECT_BIDE: + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + break; + default: + break; + } + } SCENE { + if (GetMoveEffect(move) != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen3)") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = MOVE_FAKE_OUT; j < MOVES_COUNT_GEN3; j++) + { + if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + switch (GetMoveEffect(move)) + { + case EFFECT_TWO_TURNS_ATTACK: + case EFFECT_SEMI_INVULNERABLE: + case EFFECT_SOLAR_BEAM: + case EFFECT_SKY_DROP: + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + break; + case EFFECT_FUTURE_SIGHT: + TURN { ; } + TURN { ; } + break; + case EFFECT_BIDE: + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + break; + default: + break; + } + } SCENE { + if (GetMoveEffect(move) != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen4)") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = MOVE_ROOST; j < MOVES_COUNT_GEN4; j++) + { + if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + switch (GetMoveEffect(move)) + { + case EFFECT_TWO_TURNS_ATTACK: + case EFFECT_SEMI_INVULNERABLE: + case EFFECT_SOLAR_BEAM: + case EFFECT_SKY_DROP: + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + break; + case EFFECT_FUTURE_SIGHT: + TURN { ; } + TURN { ; } + break; + case EFFECT_BIDE: + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + break; + default: + break; + } + } SCENE { + if (GetMoveEffect(move) != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen5)") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = MOVE_HONE_CLAWS; j < MOVES_COUNT_GEN5; j++) + { + if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + switch (GetMoveEffect(move)) + { + case EFFECT_TWO_TURNS_ATTACK: + case EFFECT_SEMI_INVULNERABLE: + case EFFECT_SOLAR_BEAM: + case EFFECT_SKY_DROP: + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + break; + case EFFECT_FUTURE_SIGHT: + TURN { ; } + TURN { ; } + break; + case EFFECT_BIDE: + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + break; + default: + break; + } + } SCENE { + if (GetMoveEffect(move) != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen6)") { s16 damage1, damage2; u32 move = 0; - for (u32 j = 2; j < MOVES_COUNT; j += 4) + for (u32 j = MOVE_FLYING_PRESS; j < MOVES_COUNT_GEN6; j++) + { if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) PARAMETRIZE { move = j; } + } GIVEN { PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } @@ -772,13 +1107,16 @@ DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to EXPECT_EQ(damage2, damage1); } } -DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 3") + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen7)") { s16 damage1, damage2; u32 move = 0; - for (u32 j = 3; j < MOVES_COUNT; j += 4) + for (u32 j = MOVE_SHORE_UP; j < MOVES_COUNT_GEN7; j++) + { if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) PARAMETRIZE { move = j; } + } GIVEN { PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } @@ -852,11 +1190,96 @@ DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to EXPECT_EQ(damage2, damage1); } } -DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost 4") + +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen8)") +{ + s16 damage1, damage2; + u32 move = 0; + for (u32 j = MOVE_DYNAMAX_CANNON; j < MOVES_COUNT_GEN8; j++) + { + if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) + PARAMETRIZE { move = j; } + } + GIVEN { + PLAYER(SPECIES_STEELIX) { Ability(ABILITY_SHEER_FORCE); Item(ITEM_BLUK_BERRY); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_STEELIX) { Ability(ABILITY_STURDY); Item(ITEM_BLUK_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); Level(100); Item(ITEM_BLUK_BERRY); } + } WHEN { + if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect + TURN { MOVE(opponentRight, MOVE_AGILITY); MOVE(playerRight, MOVE_AGILITY); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_UPPER_HAND) // Upper Hand requires the target to be using a damaging priority move + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); MOVE(playerRight, move, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_COUNTER || move == MOVE_UPPER_HAND) + TURN { MOVE(opponentRight, MOVE_QUICK_ATTACK, target: playerLeft); + MOVE(playerRight, MOVE_QUICK_ATTACK, target: opponentLeft); + MOVE(playerLeft, move, target: opponentRight); + MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_MIRROR_COAT || move == MOVE_METAL_BURST) + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_SUCKER_PUNCH || move == MOVE_THUNDERCLAP) + TURN { MOVE(opponentRight, MOVE_SCRATCH, target: playerLeft); MOVE(playerRight, MOVE_SCRATCH, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + else if (move == MOVE_DREAM_EATER) + { + TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); MOVE(opponentLeft, MOVE_HYPNOSIS, target: playerRight); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SNORE) + { + TURN { MOVE(opponentRight, MOVE_HYPNOSIS, target: playerLeft); MOVE(playerRight, MOVE_HYPNOSIS, target: opponentLeft); MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else if (move == MOVE_SPIT_UP || move == MOVE_LAST_RESORT) + { + TURN { MOVE(playerLeft, MOVE_STOCKPILE); MOVE(opponentLeft, MOVE_STOCKPILE); } + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + } + else + TURN { MOVE(playerLeft, move, target: opponentRight); MOVE(opponentLeft, move, target: playerRight); } + switch (GetMoveEffect(move)) + { + case EFFECT_TWO_TURNS_ATTACK: + case EFFECT_SEMI_INVULNERABLE: + case EFFECT_SOLAR_BEAM: + case EFFECT_SKY_DROP: + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { ; } + break; + case EFFECT_FUTURE_SIGHT: + TURN { ; } + TURN { ; } + break; + case EFFECT_BIDE: + TURN { MOVE(opponentRight, MOVE_WATER_GUN, target: playerLeft); MOVE(playerRight, MOVE_WATER_GUN, target: opponentLeft); SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + TURN { SKIP_TURN(playerLeft); SKIP_TURN(opponentLeft); } + break; + default: + break; + } + } SCENE { + if (GetMoveEffect(move) != EFFECT_FUTURE_SIGHT) + { + HP_BAR(opponentRight, captureDamage: &damage1); + HP_BAR(playerRight, captureDamage: &damage2); + } + else + { + HP_BAR(playerRight, captureDamage: &damage2); + HP_BAR(opponentRight, captureDamage: &damage1); + } + } THEN { + if (IsMoveSheerForceBoosted(move)) + EXPECT_GT(damage1, damage2); + else + EXPECT_EQ(damage2, damage1); + } +} + +// Last test should always go up to MOVES_COUNT to catch users moves +DOUBLE_BATTLE_TEST("Sheer Force only boosts the damage of moves it's supposed to boost (Gen9)") { s16 damage1, damage2; u32 move = 0; - for (u32 j = 4; j < MOVES_COUNT; j += 4) + for (u32 j = MOVE_TERA_BLAST; j < MOVES_COUNT; j++) { if (GetMoveCategory(j) != DAMAGE_CATEGORY_STATUS && !IgnoreMoveForSheerForceBoost(j)) PARAMETRIZE { move = j; } From fda783b394ef430559768bf9f9420f6b2c2f084c Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 8 Aug 2025 16:54:07 -0400 Subject: [PATCH 197/283] AI handling for similar utility moves (#7513) --- include/battle_ai_util.h | 27 ++- src/battle_ai_field_statuses.c | 7 +- src/battle_ai_main.c | 93 +++++----- src/battle_ai_util.c | 311 +++++++++++++++++++++++---------- test/battle/ai/ai_doubles.c | 2 +- 5 files changed, 290 insertions(+), 150 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 62cba4949e..448fbf71c5 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -168,14 +168,15 @@ bool32 HasMove(u32 battlerId, u32 move); bool32 HasOnlyMovesWithCategory(u32 battlerId, enum DamageCategory category, bool32 onlyOffensive); bool32 HasMoveWithCategory(u32 battler, enum DamageCategory category); bool32 HasMoveWithType(u32 battler, u32 type); -bool32 HasMoveWithEffect(u32 battlerId, enum BattleMoveEffects moveEffect); +bool32 HasMoveWithEffect(u32 battler, enum BattleMoveEffects moveEffect); +bool32 HasMoveWithAIEffect(u32 battler, u32 aiEffect); bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect); +bool32 HasBattlerSideMoveWithAIEffect(u32 battler, u32 effect); bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect); bool32 HasNonVolatileMoveEffect(u32 battlerId, u32 effect); bool32 IsPowerBasedOnStatus(u32 battlerId, enum BattleMoveEffects effect, u32 argument); bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect); bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect); -bool32 HasBattlerSideUsedMoveWithAdditionalEffect(u32 battler, u32 moveEffect); bool32 HasMoveWithCriticalHitChance(u32 battlerId); bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, enum BattleMoveEffects exception); bool32 HasMoveThatLowersOwnStats(u32 battlerId); @@ -252,11 +253,9 @@ bool32 HasTwoOpponents(u32 battler); bool32 HasPartner(u32 battler); bool32 HasPartnerIgnoreFlags(u32 battler); // HasPartner respects the Attacks Partner AI flag; HasPartnerIgnoreFlags checks only if a live pokemon is adjacent. +bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 partnerMove); bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); -bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove); bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove); -bool32 IsMoveEffectWeather(u32 move); -bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove); bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMoveEffects effectCheck); bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck); bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); @@ -301,4 +300,22 @@ bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *ai u32 GetThinkingBattler(u32 battler); bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); +// These are for the purpose of not doubling up on moves during double battles. +// Used in GetAIEffectGroup for move effects and GetAIEffectGroupFromMove for additional effects +#define AI_EFFECT_NONE 0 +#define AI_EFFECT_WEATHER (1 << 0) +#define AI_EFFECT_TERRAIN (1 << 1) +#define AI_EFFECT_CLEAR_HAZARDS (1 << 2) +#define AI_EFFECT_BREAK_SCREENS (1 << 3) +#define AI_EFFECT_RESET_STATS (1 << 4) +#define AI_EFFECT_FORCE_SWITCH (1 << 5) +#define AI_EFFECT_TORMENT (1 << 6) +#define AI_EFFECT_LIGHT_SCREEN (1 << 7) +#define AI_EFFECT_REFLECT (1 << 8) +#define AI_EFFECT_GRAVITY (1 << 9) +#define AI_EFFECT_CHANGE_ABILITY (1 << 10) + +// As Aurora Veil should almost never be used alongside the other screens, we save the bit. +#define AI_EFFECT_AURORA_VEIL (AI_EFFECT_LIGHT_SCREEN | AI_EFFECT_REFLECT) + #endif //GUARD_BATTLE_AI_UTIL_H diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c index d04f00d4b5..d85df3e74a 100644 --- a/src/battle_ai_field_statuses.c +++ b/src/battle_ai_field_statuses.c @@ -375,14 +375,15 @@ static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) // harass dragons if ((grounded || allyGrounded) - && (HasDamagingMoveOfType(FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(BATTLE_PARTNER(FOE(battler)), TYPE_DRAGON))) + && (HasDamagingMoveOfType(FOE(battler), TYPE_DRAGON) || HasDamagingMoveOfType(BATTLE_PARTNER(FOE(battler)), TYPE_DRAGON))) return FIELD_EFFECT_POSITIVE; - if ((grounded || allyGrounded) && HasBattlerSideUsedMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) + if ((grounded || allyGrounded) + && (HasNonVolatileMoveEffect(FOE(battler), MOVE_EFFECT_SLEEP) || HasNonVolatileMoveEffect(BATTLE_PARTNER(FOE(battler)), MOVE_EFFECT_SLEEP))) return FIELD_EFFECT_POSITIVE; if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) - || (gStatuses3[battler] & STATUS3_YAWN))) + || (gStatuses3[battler] & STATUS3_YAWN))) return FIELD_EFFECT_POSITIVE; return FIELD_EFFECT_NEUTRAL; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 528bcbd859..5e75f1dfb3 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1648,7 +1648,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; // other case EFFECT_HAZE: - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); // partner already using haze } @@ -1707,19 +1707,19 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-1); // may still want to just poison //fallthrough case EFFECT_LIGHT_SCREEN: - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_LIGHTSCREEN - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_REFLECT: - if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_REFLECT - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_REFLECT | SIDE_STATUS_AURORA_VEIL) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_AURORA_VEIL: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_AURORA_VEIL - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) - || !(weather & (B_WEATHER_ICY_ANY))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || !(weather & (B_WEATHER_ICY_ANY))) ADJUST_SCORE(-10); break; case EFFECT_SHEER_COLD: @@ -1734,7 +1734,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MIST: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_MIST - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_FOCUS_ENERGY: @@ -1742,19 +1742,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NON_VOLATILE_STATUS: - if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY - && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) - ADJUST_SCORE(-10); if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_CONFUSE: - if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY - && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) - ADJUST_SCORE(-10); case EFFECT_SWAGGER: case EFFECT_FLATTER: - if (!AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) + || !AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_SUBSTITUTE: @@ -1788,7 +1783,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (gDisableStructs[battlerDef].disableTimer == 0 && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) - && !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first { @@ -1884,7 +1879,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_STICKY_WEB: if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: @@ -1912,7 +1907,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(-10); //Both enemies are perish songed } - else if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + else if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { ADJUST_SCORE(-10); } @@ -1929,23 +1924,23 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SANDSTORM: if (weather & (B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) - || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_SUNNY_DAY: if (weather & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) - || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_RAIN_DANCE: if (weather & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) - || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_HAIL: case EFFECT_SNOWSCAPE: if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) - || (HasPartner(battlerAtk) && IsMoveEffectWeather(aiData->partnerMove))) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_ATTRACT: @@ -1954,7 +1949,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SAFEGUARD: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_SAFEGUARD - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_MAGNITUDE: @@ -1980,7 +1975,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CHILLY_RECEPTION: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) || IsMoveEffectWeather(aiData->partnerMove)) + else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; case EFFECT_BELLY_DRUM: @@ -2046,7 +2042,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_FOLLOW_ME: case EFFECT_HELPING_HAND: if (!hasPartner - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove)) || gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battlerAtk)] != PARTY_SIZE) //Partner is switching out. ADJUST_SCORE(-10); @@ -2096,13 +2092,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MUD_SPORT: if (gFieldStatuses & STATUS_FIELD_MUDSPORT || gBattleMons[battlerAtk].volatiles.mudSport - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_WATER_SPORT: if (gFieldStatuses & STATUS_FIELD_WATERSPORT || gBattleMons[battlerAtk].volatiles.waterSport - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_ABSORB: @@ -2239,7 +2235,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_HEAL_BELL: - if (!AnyPartyMemberStatused(battlerAtk, IsSoundMove(move)) || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (!AnyPartyMemberStatused(battlerAtk, IsSoundMove(move)) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_ENDURE: @@ -2336,7 +2332,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) || AreAnyHazardsOnSide(GetBattlerSide(battlerAtk))) { - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); //Only need one hazards removal break; @@ -2440,12 +2436,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_SIMPLE_BEAM: case EFFECT_SKILL_SWAP: case EFFECT_WORRY_SEED: - if (!CanEffectChangeAbility(battlerAtk, battlerDef, moveEffect, aiData)) + if (!CanEffectChangeAbility(battlerAtk, battlerDef, moveEffect, aiData) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_AND_RETURN_SCORE(NO_DAMAGE_OR_FAILS); break; case EFFECT_SNATCH: if (!HasMoveWithFlag(battlerDef, MoveCanBeSnatched) - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_POWER_TRICK: @@ -2542,23 +2539,28 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_GRASSY_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_ELECTRIC_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_PSYCHIC_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_MISTY_TERRAIN: - if (PartnerMoveEffectIsTerrain(BATTLE_PARTNER(battlerAtk), aiData->partnerMove) || gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_STEEL_ROLLER: - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-10); break; case EFFECT_PLEDGE: @@ -2888,7 +2890,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_COURT_CHANGE: case EFFECT_TEATIME: - if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_PLACEHOLDER: @@ -3009,6 +3011,10 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // check what effect partner is using if (aiData->partnerMove != 0 && hasPartner) { + // This catches weather, terrain, screens, etc + if (AreMovesEquivalent(battlerAtk, battlerAtkPartner, move, aiData->partnerMove)) + ADJUST_SCORE(-10); + switch (partnerEffect) { case EFFECT_HELPING_HAND: @@ -3022,16 +3028,6 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(WEAK_EFFECT); } break; - // Don't change weather if ally already decided to do so. - case EFFECT_SUNNY_DAY: - case EFFECT_HAIL: - case EFFECT_SNOWSCAPE: - case EFFECT_RAIN_DANCE: - case EFFECT_SANDSTORM: - case EFFECT_CHILLY_RECEPTION: - if (IsMoveEffectWeather(move)) - ADJUST_SCORE(-10); - break; case EFFECT_AFTER_YOU: if (effect == EFFECT_TRICK_ROOM && !(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); @@ -4110,7 +4106,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_HAZE: if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk)) - || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) break; score += AI_TryToClearStats(battlerAtk, battlerDef, moveTargetsBothOpponents); break; @@ -5243,6 +5239,7 @@ case EFFECT_GUARD_SPLIT: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].volatiles.wrapped)) ADJUST_SCORE(GOOD_EFFECT); + break; case EFFECT_SPECTRAL_THIEF: ADJUST_SCORE(AI_ShouldCopyStatChanges(battlerAtk, battlerDef)); break; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 8e6f0d79a2..9e4f4e35fd 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -24,6 +24,9 @@ #include "constants/moves.h" #include "constants/items.h" +static u32 GetAIEffectGroup(enum BattleMoveEffects effect); +static u32 GetAIEffectGroupFromMove(u32 battler, u32 move); + // Functions static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move) { @@ -2222,21 +2225,37 @@ bool32 HasMoveWithType(u32 battler, u32 type) return FALSE; } -bool32 HasMoveWithEffect(u32 battlerId, enum BattleMoveEffects effect) +bool32 HasMoveWithEffect(u32 battler, enum BattleMoveEffects effect) { s32 i; - u16 *moves = GetMovesArray(battlerId); + u16 *moves = GetMovesArray(battler); for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE - && GetMoveEffect(moves[i]) == effect) + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && GetMoveEffect(moves[i]) == effect) return TRUE; } return FALSE; } +bool32 HasMoveWithAIEffect(u32 battler, u32 aiEffect) +{ + s32 i; + u16 *moves = GetMovesArray(battler); + + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE) + { + if (GetAIEffectGroupFromMove(battler, moves[i]) & aiEffect) + return TRUE; + } + } + + return FALSE; +} + bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect) { if (HasMoveWithEffect(battler, effect)) @@ -2246,18 +2265,44 @@ bool32 HasBattlerSideMoveWithEffect(u32 battler, u32 effect) return FALSE; } +bool32 HasBattlerSideMoveWithAIEffect(u32 battler, u32 aiEffect) +{ + if (HasMoveWithAIEffect(battler, aiEffect)) + return TRUE; + if (HasPartnerIgnoreFlags(battler) && HasMoveWithAIEffect(BATTLE_PARTNER(battler), aiEffect)) + return TRUE; + return FALSE; +} + // HasBattlerSideMoveWithEffect checks if the AI knows a side has a move effect, -// while HasBattlerSideUsedMoveWithEffect checks if the side has ever used a move effect. -// The former acts the same way as the latter if AI_FLAG_OMNISCIENT isn't used. +// while HasBattlerSideUsedMoveWithEffect checks if the side has actively USED the move effect. +// It matches both on move effect and on AI move effect; eg, EFFECT_HAZE will also bring up Freezy Frost or Clear Smog, anything with AI_EFFECT_RESET_STATS. bool32 HasBattlerSideUsedMoveWithEffect(u32 battler, u32 effect) { + u32 aiEffect = GetAIEffectGroup(effect); u32 i; for (i = 0; i < MAX_MON_MOVES; i++) { if (GetMoveEffect(gBattleHistory->usedMoves[battler][i]) == effect) return TRUE; - if (HasPartnerIgnoreFlags(battler) && GetMoveEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) == effect) - return TRUE; + + if (aiEffect != AI_EFFECT_NONE) + { + if (GetAIEffectGroupFromMove(battler, gBattleHistory->usedMoves[battler][i]) & aiEffect) + return TRUE; + } + + if (HasPartnerIgnoreFlags(battler)) + { + if (GetMoveEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) == effect) + return TRUE; + + if (aiEffect != AI_EFFECT_NONE) + { + if (GetAIEffectGroupFromMove(battler, gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i]) & aiEffect) + return TRUE; + } + } } return FALSE; } @@ -2316,22 +2361,6 @@ bool32 HasBattlerSideMoveWithAdditionalEffect(u32 battler, u32 moveEffect) return FALSE; } -// HasBattlerSideMoveWithAdditionalEffect checks if the AI knows a side has a move effect, -// while HasBattlerSideUsedMoveWithAdditionalEffect checks if the side has ever used a move effect. -// The former acts the same way as the latter if AI_FLAG_OMNISCIENT isn't used. -bool32 HasBattlerSideUsedMoveWithAdditionalEffect(u32 battler, u32 moveEffect) -{ - u32 i; - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (MoveHasAdditionalEffect(gBattleHistory->usedMoves[battler][i], moveEffect)) - return TRUE; - if (HasPartnerIgnoreFlags(battler) && MoveHasAdditionalEffect(gBattleHistory->usedMoves[BATTLE_PARTNER(battler)][i], moveEffect)) - return TRUE; - } - return FALSE; -} - bool32 HasMoveWithCriticalHitChance(u32 battlerId) { s32 i; @@ -3732,8 +3761,7 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo u32 atkSide = GetBattlerSide(battlerAtk); // Don't waste a turn if screens will be broken - if (HasMoveWithEffect(battlerDef, EFFECT_BRICK_BREAK) - || HasMoveWithEffect(battlerDef, EFFECT_RAGING_BULL)) + if (HasMoveWithAIEffect(battlerDef, AI_EFFECT_BREAK_SCREENS)) return FALSE; switch (moveEffect) @@ -3747,13 +3775,13 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo case EFFECT_REFLECT: // Use only if the player has a physical move and AI doesn't already have Reflect itself active. if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_PHYSICAL) - && !(gSideStatuses[atkSide] & SIDE_STATUS_REFLECT)) + && !(gSideStatuses[atkSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; case EFFECT_LIGHT_SCREEN: // Use only if the player has a special move and AI doesn't already have Light Screen itself active. if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL) - && !(gSideStatuses[atkSide] & SIDE_STATUS_LIGHTSCREEN)) + && !(gSideStatuses[atkSide] & (SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))) return TRUE; break; default: @@ -3821,30 +3849,175 @@ u32 GetAllyChosenMove(u32 battlerId) return gBattleMons[partnerBattler].moves[gBattleStruct->chosenMovePositions[partnerBattler]]; } -//PARTNER_MOVE_EFFECT_IS_SAME -bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) +bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 partnerMove) { - if (!HasPartner(battlerAtkPartner)) + if (!IsBattlerAlive(battlerAtkPartner) || partnerMove == MOVE_NONE) return FALSE; - if (GetMoveEffect(move) == GetMoveEffect(partnerMove) - && partnerMove != MOVE_NONE - && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef) + u32 battlerDef = gBattleStruct->moveTarget[battlerAtk]; + + // We don't care the effect is basically the same; we would use this move anyway. + if (GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) + return FALSE; + + u32 atkEffect = GetAIEffectGroupFromMove(battlerAtk, move); + u32 partnerEffect = GetAIEffectGroupFromMove(battlerAtkPartner, partnerMove); + + // shared bits indicate they're meaningfully the same in some way + if (atkEffect & partnerEffect) { + if (gMovesInfo[move].target == MOVE_TARGET_SELECTED && gMovesInfo[partnerMove].target == MOVE_TARGET_SELECTED) + { + if (battlerDef == gBattleStruct->moveTarget[battlerAtkPartner]) + return TRUE; + else + return FALSE; + } return TRUE; } return FALSE; } -//PARTNER_MOVE_EFFECT_IS_SAME_NO_TARGET -bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove) +static u32 GetAIEffectGroup(enum BattleMoveEffects effect) +{ + u32 aiEffect = AI_EFFECT_NONE; + + switch (effect) + { + case EFFECT_SUNNY_DAY: + case EFFECT_RAIN_DANCE: + case EFFECT_SANDSTORM: + case EFFECT_HAIL: + case EFFECT_SNOWSCAPE: + case EFFECT_CHILLY_RECEPTION: + aiEffect |= AI_EFFECT_WEATHER; + break; + case EFFECT_ELECTRIC_TERRAIN: + case EFFECT_GRASSY_TERRAIN: + case EFFECT_MISTY_TERRAIN: + case EFFECT_PSYCHIC_TERRAIN: + case EFFECT_STEEL_ROLLER: + case EFFECT_ICE_SPINNER: + aiEffect |= AI_EFFECT_TERRAIN; + break; + case EFFECT_COURT_CHANGE: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_AURORA_VEIL | AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_DEFOG: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_RAPID_SPIN: + case EFFECT_TIDY_UP: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS; + break; + case EFFECT_BRICK_BREAK: + case EFFECT_RAGING_BULL: + aiEffect |= AI_EFFECT_BREAK_SCREENS; + break; + case EFFECT_HAZE: + aiEffect |= AI_EFFECT_RESET_STATS; + break; + case EFFECT_HIT_SWITCH_TARGET: + case EFFECT_ROAR: + aiEffect |= AI_EFFECT_FORCE_SWITCH; + break; + case EFFECT_TORMENT: + aiEffect |= AI_EFFECT_TORMENT; + break; + case EFFECT_AURORA_VEIL: + aiEffect |= AI_EFFECT_AURORA_VEIL; + break; + case EFFECT_LIGHT_SCREEN: + aiEffect |= AI_EFFECT_LIGHT_SCREEN; + break; + case EFFECT_REFLECT: + aiEffect |= AI_EFFECT_REFLECT; + break; + case EFFECT_GRAVITY: + aiEffect |= AI_EFFECT_GRAVITY; + break; + case EFFECT_DOODLE: + case EFFECT_ENTRAINMENT: + case EFFECT_GASTRO_ACID: + case EFFECT_ROLE_PLAY: + case EFFECT_SIMPLE_BEAM: + case EFFECT_SKILL_SWAP: + case EFFECT_WORRY_SEED: + aiEffect |= AI_EFFECT_CHANGE_ABILITY; + break; + default: + break; + } + return aiEffect; +} + +static u32 GetAIEffectGroupFromMove(u32 battler, u32 move) +{ + u32 aiEffect = GetAIEffectGroup(GetMoveEffect(move)); + + u32 i; + u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + for (i = 0; i < additionalEffectCount; i++) + { + switch (GetMoveAdditionalEffectById(move, i)->moveEffect) + { + case MOVE_EFFECT_SUN: + case MOVE_EFFECT_RAIN: + case MOVE_EFFECT_SANDSTORM: + case MOVE_EFFECT_HAIL: + aiEffect |= AI_EFFECT_WEATHER; + break; + case MOVE_EFFECT_ELECTRIC_TERRAIN: + case MOVE_EFFECT_GRASSY_TERRAIN: + case MOVE_EFFECT_MISTY_TERRAIN: + case MOVE_EFFECT_PSYCHIC_TERRAIN: + aiEffect |= AI_EFFECT_TERRAIN; + break; + case MOVE_EFFECT_DEFOG: + aiEffect |= AI_EFFECT_CLEAR_HAZARDS | AI_EFFECT_BREAK_SCREENS; + break; + case MOVE_EFFECT_CLEAR_SMOG: + case MOVE_EFFECT_HAZE: + aiEffect |= AI_EFFECT_RESET_STATS; + break; + case MOVE_EFFECT_TORMENT_SIDE: + aiEffect |= AI_EFFECT_TORMENT; + break; + case MOVE_EFFECT_LIGHT_SCREEN: + aiEffect |= AI_EFFECT_LIGHT_SCREEN; + break; + case MOVE_EFFECT_REFLECT: + aiEffect |= AI_EFFECT_REFLECT; + break; + case MOVE_EFFECT_AURORA_VEIL: + aiEffect |= AI_EFFECT_AURORA_VEIL; + break; + case MOVE_EFFECT_GRAVITY: + aiEffect |= AI_EFFECT_GRAVITY; + break; + default: + break; + } + } + + return aiEffect; +} + +// It matches both on move effect and on AI move effect; eg, EFFECT_HAZE will also bring up Freezy Frost or Clear Smog, anything with AI_EFFECT_RESET_STATS. +bool32 DoesPartnerHaveSameMoveEffect(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove) { if (!HasPartner(battlerAtkPartner)) return FALSE; if (GetMoveEffect(move) == GetMoveEffect(partnerMove) && partnerMove != MOVE_NONE) + { + if (gMovesInfo[move].target == MOVE_TARGET_SELECTED && gMovesInfo[partnerMove].target == MOVE_TARGET_SELECTED) + { + return gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef; + } return TRUE; + } return FALSE; } @@ -3868,37 +4041,6 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef return FALSE; } -bool32 IsMoveEffectWeather(u32 move) -{ - enum BattleMoveEffects effect = GetMoveEffect(move); - if (move != MOVE_NONE - && (effect == EFFECT_SUNNY_DAY - || effect == EFFECT_RAIN_DANCE - || effect == EFFECT_SANDSTORM - || effect == EFFECT_HAIL - || effect == EFFECT_SNOWSCAPE - || effect == EFFECT_CHILLY_RECEPTION)) - return TRUE; - return FALSE; -} - -//PARTNER_MOVE_EFFECT_IS_TERRAIN -bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove) -{ - if (!HasPartner(battlerAtkPartner)) - return FALSE; - - enum BattleMoveEffects partnerEffect = GetMoveEffect(partnerMove); - if (partnerMove != MOVE_NONE - && (partnerEffect == EFFECT_GRASSY_TERRAIN - || partnerEffect == EFFECT_MISTY_TERRAIN - || partnerEffect == EFFECT_ELECTRIC_TERRAIN - || partnerEffect == EFFECT_PSYCHIC_TERRAIN)) - return TRUE; - - return FALSE; -} - //PARTNER_MOVE_EFFECT_IS bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, enum BattleMoveEffects effectCheck) { @@ -4363,17 +4505,14 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, if (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_ENCORE)) return NO_INCREASE; - // Don't increase stats if opposing battler has used Haze effect - if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) && - (HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE) - || HasBattlerSideUsedMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_CLEAR_SMOG) - || HasBattlerSideUsedMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_HAZE))) + // Don't increase stats if opposing battler has used Haze effect or AI effect + if (!RandomPercentage(RNG_AI_BOOST_INTO_HAZE, BOOST_INTO_HAZE_CHANCE) + && HasBattlerSideUsedMoveWithEffect(battlerDef, EFFECT_HAZE)) return NO_INCREASE; // Don't increase if AI is at +1 and opponent has Haze effect - if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 5 && (HasBattlerSideMoveWithEffect(battlerDef, EFFECT_HAZE) - || HasBattlerSideMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_CLEAR_SMOG) - || HasBattlerSideMoveWithAdditionalEffect(battlerDef, MOVE_EFFECT_HAZE))) + if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 5 + && HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_RESET_STATS)) return NO_INCREASE; // Don't increase stats if AI could KO target through Sturdy effect, as otherwise it always 2HKOs @@ -4976,11 +5115,7 @@ bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef) bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, u32 move, struct AiLogicData *aiData) { if (CountUsablePartyMons(battlerDef) == 0 - || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_COURT_CHANGE) - || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_DEFOG) - || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) - || HasBattlerSideMoveWithEffect(battlerDef, EFFECT_TIDY_UP) - || HasBattlerSideMoveWithEffect(battlerDef, MOVE_EFFECT_DEFOG)) + || HasBattlerSideMoveWithAIEffect(battlerDef, AI_EFFECT_CLEAR_HAZARDS)) return FALSE; if (IsBattleMoveStatus(move)) @@ -5023,27 +5158,17 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData) { u32 preventsStatLoss; - u32 partnerAbility; - u32 partnerHoldEffect = aiData->holdEffects[battlerAtkPartner]; + u32 partnerAbility = aiData->abilities[battlerAtkPartner]; u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battlerAtk)); u32 opposingBattler = GetBattlerAtPosition(opposingPosition); - if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move)) - partnerAbility = ABILITY_NONE; - else - partnerAbility = aiData->abilities[battlerAtkPartner]; - if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] == MAX_STAT_STAGE || partnerAbility == ABILITY_CONTRARY || partnerAbility == ABILITY_GOOD_AS_GOLD - || HasMoveWithEffect(BATTLE_OPPOSITE(battlerAtk), EFFECT_FOUL_PLAY) - || HasMoveWithEffect(BATTLE_OPPOSITE(battlerAtkPartner), EFFECT_FOUL_PLAY)) + || HasBattlerSideMoveWithEffect(FOE(battlerAtk), EFFECT_FOUL_PLAY)) return FALSE; - preventsStatLoss = (partnerAbility == ABILITY_CLEAR_BODY - || partnerAbility == ABILITY_FULL_METAL_BODY - || partnerAbility == ABILITY_WHITE_SMOKE - || partnerHoldEffect == HOLD_EFFECT_CLEAR_AMULET); + preventsStatLoss = !CanLowerStat(battlerAtk, battlerAtkPartner, aiData, STAT_DEF); switch (GetMoveEffect(aiData->partnerMove)) { diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index e0eac1eeed..ab6b4a4425 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -90,7 +90,7 @@ TO_DO_BATTLE_TEST("AI understands Instruct") TO_DO_BATTLE_TEST("AI understands Quick Guard") TO_DO_BATTLE_TEST("AI understands Wide Guard") -AI_DOUBLE_BATTLE_TEST("AI will not use the same nondamaging move as its partner for no reason") +AI_DOUBLE_BATTLE_TEST("AI won't use the same nondamaging move as its partner for no reason") { u32 move; PARAMETRIZE { move = MOVE_AROMATHERAPY; } From 89b179e4c43650992ccffa9f73b5942117a7c1d7 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Sat, 9 Aug 2025 18:27:47 -0400 Subject: [PATCH 198/283] Fixes draining moves recovering 1 HP when dealing 0 damage (#7523) Co-authored-by: root Co-authored-by: LinathanZel --- src/battle_script_commands.c | 5 ++++- test/battle/move_effect/absorb.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) mode change 100644 => 100755 src/battle_script_commands.c diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c old mode 100644 new mode 100755 index 965745608c..943e7db979 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6061,10 +6061,13 @@ static void Cmd_moveend(void) switch (moveEffect) { case EFFECT_ABSORB: - if (!(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK) && IsBattlerAlive(gBattlerAttacker)) + if (!(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK) + && gBattleStruct->moveDamage[gBattlerTarget] > 0 + && IsBattlerAlive(gBattlerAttacker)) { gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100)); gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE; effect = TRUE; if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIQUID_OOZE) diff --git a/test/battle/move_effect/absorb.c b/test/battle/move_effect/absorb.c index 456c888cd4..d497bc3f04 100644 --- a/test/battle/move_effect/absorb.c +++ b/test/battle/move_effect/absorb.c @@ -104,3 +104,17 @@ SINGLE_BATTLE_TEST("Absorb does not drain any HP if user flinched") } TO_DO_BATTLE_TEST("Absorb recovers 50% of the damage dealt to a Substitute"); + +SINGLE_BATTLE_TEST("Absorb does not drain any HP if user does 0 damage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(opponent, MOVE_ENDURE); MOVE(player, MOVE_ABSORB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); + NOT MESSAGE("The opposing Wobbuffet had its energy drained!"); + } +} From 7de3663f383125c9288e87e9b8eda422705c5441 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 10 Aug 2025 16:58:36 +0200 Subject: [PATCH 199/283] Fixes Life Orb still activating if move was absorbed (#7521) --- include/battle.h | 3 +- src/battle_script_commands.c | 7 ++- src/battle_util.c | 6 +-- test/battle/hold_effect/life_orb.c | 50 +++++++++++++++++++ test/battle/move_effect/assurance.c | 27 ++++++++++ .../battle/move_effect_secondary/clear_smog.c | 19 +++++++ 6 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 test/battle/move_effect_secondary/clear_smog.c diff --git a/include/battle.h b/include/battle.h index 79cc591980..cd3126ba6b 100644 --- a/include/battle.h +++ b/include/battle.h @@ -169,7 +169,8 @@ struct ProtectStruct u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u16 usedAllySwitch:1; u16 lashOutAffected:1; - u16 padding:4; + u16 assuranceDoubled:1; + u16 padding:3; // End of 16-bit bitfield u16 physicalDmg; u16 specialDmg; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0f3fbdba61..870f21d7a8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2272,6 +2272,9 @@ static void Cmd_adjustdamage(void) gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; gSpecialStatuses[battlerDef].enduredDamage = TRUE; } + + if (gSpecialStatuses[battlerDef].enduredDamage) + gProtectStructs[battlerDef].assuranceDoubled = TRUE; } if (calcSpreadMoveDamage) @@ -2726,6 +2729,7 @@ static void Cmd_datahpupdate(void) gProtectStructs[battler].physicalBattlerId = gBattlerAttacker; else gProtectStructs[battler].physicalBattlerId = gBattlerTarget; + gProtectStructs[battler].assuranceDoubled = TRUE; } else if (!IsBattleMovePhysical(gCurrentMove) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && effect != EFFECT_PAIN_SPLIT) { @@ -2736,6 +2740,7 @@ static void Cmd_datahpupdate(void) gProtectStructs[battler].specialBattlerId = gBattlerAttacker; else gProtectStructs[battler].specialBattlerId = gBattlerTarget; + gProtectStructs[battler].assuranceDoubled = TRUE; } } gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; @@ -3722,7 +3727,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) if (gBattleMons[gEffectBattler].statStages[i] != DEFAULT_STAT_STAGE) break; } - if ((gSpecialStatuses[gEffectBattler].physicalDmg || gSpecialStatuses[gEffectBattler].specialDmg) && i != NUM_BATTLE_STATS) + if (IsBattlerTurnDamaged(gEffectBattler) && i != NUM_BATTLE_STATS) { for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[gEffectBattler].statStages[i] = DEFAULT_STAT_STAGE; diff --git a/src/battle_util.c b/src/battle_util.c index 31c5229d0f..f8fb5faa86 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7155,10 +7155,8 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) case HOLD_EFFECT_LIFE_ORB: if (IsBattlerAlive(gBattlerAttacker) && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && !IsBattleMoveStatus(gCurrentMove) - && (IsBattlerTurnDamaged(gBattlerTarget) || !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Needs the second check in case of Substitute + && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleScripting.savedDmg > 0) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10; @@ -8157,7 +8155,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower = gBattleMons[battlerDef].hp * basePower / gBattleMons[battlerDef].maxHP; break; case EFFECT_ASSURANCE: - if (gProtectStructs[battlerDef].physicalDmg != 0 || gProtectStructs[battlerDef].specialDmg != 0 || gProtectStructs[battlerDef].confusionSelfDmg) + if (gProtectStructs[battlerDef].assuranceDoubled) basePower *= 2; break; case EFFECT_TRUMP_CARD: diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c index 92c545dfad..2f1514538c 100644 --- a/test/battle/hold_effect/life_orb.c +++ b/test/battle/hold_effect/life_orb.c @@ -81,3 +81,53 @@ SINGLE_BATTLE_TEST("Life Orb doesn't cause any HP loss if user is unable to atta } } } + +SINGLE_BATTLE_TEST("Life Orb does not activate if on a confusion hit") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + 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); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, player); + HP_BAR(opponent); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + } + } +} + +SINGLE_BATTLE_TEST("Life Orb does not activate if move was absorbed by target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); } + } WHEN { + TURN { MOVE(player, MOVE_SHOCK_WAVE); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHOCK_WAVE, player); + HP_BAR(opponent); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + } + } +} + +SINGLE_BATTLE_TEST("Life Orb activates if move connected but no damage was dealt") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_FALSE_SWIPE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, player); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + } +} diff --git a/test/battle/move_effect/assurance.c b/test/battle/move_effect/assurance.c index e6cbf72b9f..6eccb48f3f 100644 --- a/test/battle/move_effect/assurance.c +++ b/test/battle/move_effect/assurance.c @@ -6,3 +6,30 @@ TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Crash"); TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Confusion"); TO_DO_BATTLE_TEST("Assurance doubles in power if the target has been damaged in the same turn - Rocky Helmet"); + +DOUBLE_BATTLE_TEST("Assurance doubles in power if False Swipe connected but didn't do any damage") +{ + s16 hits[2]; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ASSURANCE, target: playerRight); } + TURN { + MOVE(opponentLeft, MOVE_FALSE_SWIPE, target: playerLeft); + MOVE(playerLeft, MOVE_RECOVER); + MOVE(opponentRight, MOVE_ASSURANCE, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponentLeft); + HP_BAR(playerRight, captureDamage: &hits[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSURANCE, opponentRight); + HP_BAR(playerLeft, captureDamage: &hits[1]); + } THEN { + EXPECT_MUL_EQ(hits[0], Q_4_12(2.0), hits[1]); + } +} diff --git a/test/battle/move_effect_secondary/clear_smog.c b/test/battle/move_effect_secondary/clear_smog.c new file mode 100644 index 0000000000..f8d7b0eb2f --- /dev/null +++ b/test/battle/move_effect_secondary/clear_smog.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Clear Smog removes stat changes even if it did no damage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_ENDURE); MOVE(opponent, MOVE_CLEAR_SMOG); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CLEAR_SMOG, opponent); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} From cc736c423314c297dda2459f7f135db4146ddc02 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 10 Aug 2025 16:56:42 -0400 Subject: [PATCH 200/283] Corrected Liquid Ooze test (#7527) --- test/battle/ability/liquid_ooze.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index fa8ca8e3b2..1bd3cbbdf8 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of } /* * https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(Ability)#In_battle: - * If the recipient of Leech Seed's effect were to faint due to Liquid Ooze on the same turn as the victim of Leech Seed, then the victim faints before the recipient. This means that the victim's team loses the battle if both teams had their final Pokémon sent out. + * If the recipient of Leech Seed's effect were to faint due to Liquid Ooze on the same turn as the victim of Leech Seed, then the victim faints before the recipient. This means that the victim's team loses the battle if both teams had their final Pokémon sent out. */ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder") { @@ -140,6 +140,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder" SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+)") { + KNOWN_FAILING; s16 damage; GIVEN { ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); @@ -158,8 +159,30 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of h HP_BAR(opponent); HP_BAR(player, captureDamage: &damage); } THEN { - EXPECT_LT(damage, 0); + EXPECT_GT(damage, 0); // Positive damage } } -TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4") +SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4") +{ + s16 damage; + GIVEN { + ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); + ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TENTACRUEL) { Ability(ABILITY_LIQUID_OOZE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_DREAM_EATER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DREAM_EATER, player); + HP_BAR(opponent); + HP_BAR(player, captureDamage: &damage); + } THEN { + EXPECT_LT(damage, 0); // Negative damage = Heal + } +} From de6c9c617692d6b6298fbfc8e722f1948ad8df23 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 11 Aug 2025 09:06:23 +0100 Subject: [PATCH 201/283] Hacky support for enums in C asm statements (#7494) --- include/test/overworld_script.h | 1 - tools/preproc/asm_file.cpp | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/test/overworld_script.h b/include/test/overworld_script.h index e849f87e0c..a5bee797b2 100644 --- a/include/test/overworld_script.h +++ b/include/test/overworld_script.h @@ -51,7 +51,6 @@ asm(".set FALSE, 0\n" ".set VARS_END, " STR(VARS_END) "\n" ".set SPECIAL_VARS_START, " STR(SPECIAL_VARS_START) "\n" ".set SPECIAL_VARS_END, " STR(SPECIAL_VARS_END) "\n"); -asm(".include \"constants/gba_constants.inc\"\n"); // Make overworld script macros available. asm(".include \"constants/gba_constants.inc\"\n" diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index 83e84a6fde..10330f1774 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -620,6 +620,10 @@ bool AsmFile::ParseEnum() } enumCounter = 0; } + // HACK(#7394): Make the definitions global so that C 'asm' + // statements are able to reference them (if they happen to + // be available in an assembled object file). + std::printf(".global %s; ", currentIdentName.c_str()); std::printf(".equiv %s, (%s) + %ld\n", currentIdentName.c_str(), enumBase.c_str(), enumCounter); enumCounter++; symbolCount++; From a9d5c2cd289e6ad4aca2f541982da5fb940a7e6f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 11 Aug 2025 10:06:58 -0400 Subject: [PATCH 202/283] Updated Dream Eater/Liquid Ooze's interaction to Gen 5 standards (#7528) --- data/battle_scripts_1.s | 51 +++--------------------- docs/tutorials/how_to_testing_system.md | 2 +- include/battle_scripts.h | 2 +- include/config/battle.h | 3 +- include/constants/battle_move_effects.h | 2 +- include/constants/battle_string_ids.h | 1 - include/constants/generational_changes.h | 1 + include/generational_changes.h | 1 + include/test/battle.h | 2 +- src/battle_message.c | 1 - src/battle_script_commands.c | 14 ++++--- src/battle_util.c | 4 +- test/battle/ability/liquid_ooze.c | 3 +- test/battle/move_effect/dream_eater.c | 4 +- 14 files changed, 27 insertions(+), 64 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 53f6697aef..248d79714d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2835,13 +2835,6 @@ BattleScript_AlreadyAsleep:: setmoveresultflags MOVE_RESULT_FAILED goto BattleScript_MoveEnd -BattleScript_WasntAffected:: - pause B_WAIT_TIME_SHORT - printstring STRINGID_PKMNWASNTAFFECTED - waitmessage B_WAIT_TIME_LONG - setmoveresultflags MOVE_RESULT_FAILED - goto BattleScript_MoveEnd - BattleScript_CantMakeAsleep:: pause B_WAIT_TIME_SHORT printfromtable gUproarAwakeStringIds @@ -2886,44 +2879,10 @@ BattleScript_MaxHp50Recoil:: BattleScript_EffectDreamEater:: attackcanceler - jumpifsubstituteblocks BattleScript_DreamEaterNoEffect - jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_DreamEaterWorked - jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_DreamEaterWorked -BattleScript_DreamEaterNoEffect: - attackstring - ppreduce - waitmessage B_WAIT_TIME_LONG - goto BattleScript_WasntAffected -BattleScript_DreamEaterWorked: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_DreamEaterTryFaintEnd - setdrainedhp - manipulatedamage DMG_BIG_ROOT - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER - jumpifmovehadnoeffect BattleScript_DreamEaterTryFaintEnd - printstring STRINGID_PKMNENERGYDRAINED - waitmessage B_WAIT_TIME_LONG -BattleScript_DreamEaterTryFaintEnd: - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + jumpifsubstituteblocks BattleScript_DoesntAffectTargetAtkString + jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_HitFromAccCheck + jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_HitFromAccCheck + goto BattleScript_DoesntAffectTargetAtkString BattleScript_EffectMirrorMove:: attackcanceler @@ -9168,7 +9127,7 @@ BattleScript_EjectPackActivates:: jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd goto BattleScript_EjectPackActivate_Ret -BattleScript_DarkTypePreventsPrankster:: +BattleScript_DoesntAffectTargetAtkString:: attackstring ppreduce pause B_WAIT_TIME_SHORT diff --git a/docs/tutorials/how_to_testing_system.md b/docs/tutorials/how_to_testing_system.md index c5fbb945aa..b663ad54b4 100644 --- a/docs/tutorials/how_to_testing_system.md +++ b/docs/tutorials/how_to_testing_system.md @@ -428,7 +428,7 @@ Spaces in pattern match newlines (\n, \l, and \p) in the message. Often used to check that a battler took its turn but it failed, e.g.: ``` MESSAGE("Wobbuffet used Dream Eater!"); - MESSAGE("The opposing Wobbuffet wasn't affected!"); + MESSAGE("It doesn't affect the opposing Wobbuffet…"); ``` ### `STATUS_ICON` diff --git a/include/battle_scripts.h b/include/battle_scripts.h index ef6206cf45..46326a42df 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -426,7 +426,7 @@ extern const u8 BattleScript_MentalHerbCureEnd2[]; extern const u8 BattleScript_TerrainPreventsEnd2[]; extern const u8 BattleScript_MistyTerrainPrevents[]; extern const u8 BattleScript_ElectricTerrainPrevents[]; -extern const u8 BattleScript_DarkTypePreventsPrankster[]; +extern const u8 BattleScript_DoesntAffectTargetAtkString[]; extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; extern const u8 BattleScript_GulpMissileFormChange[]; diff --git a/include/config/battle.h b/include/config/battle.h index d09698c634..3cfd319304 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -131,7 +131,8 @@ #define B_SKIP_RECHARGE GEN_LATEST // In Gen1, recharging moves such as Hyper Beam skip the recharge if the target gets KO'd #define B_ENCORE_TARGET GEN_LATEST // In Gen5+, encored moves are allowed to choose a target #define B_TIME_OF_DAY_HEALING_MOVES GEN_LATEST // In Gen2, Morning Sun, Moonlight, and Synthesis heal twice as much HP based off the time of day. Also changes how much they heal. Evening affects Moonlight. - // If OW_TIMES_OF_DAY is set to Gen 3, then Morning Sun is boosted during the day. + // If OW_TIMES_OF_DAY is set to Gen 3, then Morning Sun is boosted during the day. +#define B_DREAM_EATER_LIQUID_OOZE GEN_LATEST // In Gen5+, Dream Eater is affected by Liquid Ooze. // Ability settings #define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger. diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 53c9843d5b..2ddb75adf6 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -9,7 +9,7 @@ enum __attribute__((packed)) BattleMoveEffects EFFECT_ABSORB, EFFECT_EXPLOSION, EFFECT_MISTY_EXPLOSION, // Same as EFFECT_EXPLOSION but it's boosted on Misty Terrain - EFFECT_DREAM_EATER, + EFFECT_DREAM_EATER, // Same as EFFECT_ABSORB but it can only be used on sleeping targets EFFECT_MIRROR_MOVE, EFFECT_ATTACK_UP, EFFECT_DEFENSE_UP, diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index df7b5e6232..3343a449e7 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -41,7 +41,6 @@ enum StringID STRINGID_PKMNMADESLEEP, STRINGID_PKMNALREADYASLEEP, STRINGID_PKMNALREADYASLEEP2, - STRINGID_PKMNWASNTAFFECTED, STRINGID_PKMNWASPOISONED, STRINGID_PKMNPOISONEDBY, STRINGID_PKMNHURTBYPOISON, diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 6892f70ee2..e51d57915c 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -28,6 +28,7 @@ enum GenConfigTag GEN_STEAL_WILD_ITEMS, GEN_SNOW_WARNING, GEN_ALLY_SWITCH_FAIL_CHANCE, + GEN_DREAM_EATER_LIQUID_OOZE, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index 9c24608e63..53991bab1f 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -31,6 +31,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_STEAL_WILD_ITEMS] = B_STEAL_WILD_ITEMS, [GEN_SNOW_WARNING] = B_SNOW_WARNING, [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, + [GEN_DREAM_EATER_LIQUID_OOZE] = B_DREAM_EATER_LIQUID_OOZE, }; #if TESTING diff --git a/include/test/battle.h b/include/test/battle.h index 2ec2b1da0a..b95038b09e 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -434,7 +434,7 @@ * Spaces in pattern match newlines (\n, \l, and \p) in the message. * Often used to check that a battler took its turn but it failed, e.g.: * MESSAGE("Wobbuffet used Dream Eater!"); - * MESSAGE("The opposing Wobbuffet wasn't affected!"); + * MESSAGE("It doesn't affect the opposing Wobbuffet…"); * * STATUS_ICON(battler, status1 | none: | sleep: | poison: | burn: | freeze: | paralysis:, badPoison:) * Causes the test to fail if the battler's status is not changed to the diff --git a/src/battle_message.c b/src/battle_message.c index d49b96b8be..132cfa66f0 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -200,7 +200,6 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNMADESLEEP] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} made {B_EFF_NAME_WITH_PREFIX2} sleep!"), //not in gen 5+, ability popup [STRINGID_PKMNALREADYASLEEP] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} is already asleep!"), [STRINGID_PKMNALREADYASLEEP2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is already asleep!"), - [STRINGID_PKMNWASNTAFFECTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} wasn't affected!"), //not in gen 5+, ability popup [STRINGID_PKMNWASPOISONED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} was poisoned!"), [STRINGID_PKMNPOISONEDBY] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} was poisoned by {B_SCR_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), //not in gen 5+, ability popup [STRINGID_PKMNHURTBYPOISON] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} was hurt by its poisoning!"), diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 109f044f2c..8bd6d3ab6a 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6066,6 +6066,7 @@ static void Cmd_moveend(void) switch (moveEffect) { case EFFECT_ABSORB: + case EFFECT_DREAM_EATER: if (!(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK) && gBattleStruct->moveDamage[gBattlerTarget] > 0 && IsBattlerAlive(gBattlerAttacker)) @@ -6075,18 +6076,19 @@ static void Cmd_moveend(void) gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE; effect = TRUE; - if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIQUID_OOZE) + if ((moveEffect == EFFECT_DREAM_EATER && GetGenConfig(GEN_DREAM_EATER_LIQUID_OOZE) < GEN_5) + || GetBattlerAbility(gBattlerTarget) != ABILITY_LIQUID_OOZE) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB; + BattleScriptCall(BattleScript_EffectAbsorb); + } + else { gBattleStruct->moveDamage[gBattlerAttacker] *= -1; gHitMarker |= HITMARKER_PASSIVE_DAMAGE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB_OOZE; BattleScriptCall(BattleScript_EffectAbsorbLiquidOoze); } - else - { - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB; - BattleScriptCall(BattleScript_EffectAbsorb); - } } break; case EFFECT_FINAL_GAMBIT: diff --git a/src/battle_util.c b/src/battle_util.c index 97753232c6..13f830d953 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1194,7 +1194,7 @@ void PrepareStringBattle(enum StringID stringId, u32 battler) SET_STATCHANGER(STAT_SPEED, 1, FALSE); } - if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED)) + if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNUNAFFECTED)) TryInitializeTrainerSlideEnemyMonUnaffected(gBattlerTarget); BtlController_EmitPrintString(battler, B_COMM_TO_CONTROLLER, stringId); @@ -3046,7 +3046,7 @@ bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 a if (option == RUN_SCRIPT && !IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) CancelMultiTurnMoves(battlerAtk, SKY_DROP_ATTACKCANCELLER_CHECK); // Don't cancel moves that can hit two targets bc one target might not be protected - battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster; + battleScriptBlocksMove = BattleScript_DoesntAffectTargetAtkString; } // Check def partner ability diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index 1bd3cbbdf8..2c89702911 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -140,9 +140,9 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder" SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+)") { - KNOWN_FAILING; s16 damage; GIVEN { + WITH_CONFIG(GEN_DREAM_EATER_LIQUID_OOZE, GEN_5); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); @@ -167,6 +167,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP inst { s16 damage; GIVEN { + WITH_CONFIG(GEN_DREAM_EATER_LIQUID_OOZE, GEN_3); ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP); ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); diff --git a/test/battle/move_effect/dream_eater.c b/test/battle/move_effect/dream_eater.c index caa365a17a..baefd2e4ff 100644 --- a/test/battle/move_effect/dream_eater.c +++ b/test/battle/move_effect/dream_eater.c @@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Dream Eater fails on awake targets") TURN { MOVE(player, MOVE_DREAM_EATER); } } SCENE { MESSAGE("Wobbuffet used Dream Eater!"); - MESSAGE("The opposing Wobbuffet wasn't affected!"); + MESSAGE("It doesn't affect the opposing Wobbuffet…"); } } @@ -88,7 +88,7 @@ SINGLE_BATTLE_TEST("Dream Eater fails if the target is behind a Substitute (Gen TURN { MOVE(opponent, MOVE_DREAM_EATER); } } SCENE { MESSAGE("The opposing Wobbuffet used Dream Eater!"); - MESSAGE("Wobbuffet wasn't affected!"); + MESSAGE("It doesn't affect Wobbuffet…"); } } #else From 38cfc4bacf3eb4dabb22c3a3e8b81abbb27840d1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:26:41 +0200 Subject: [PATCH 203/283] Modify move prediction to work in doubles (#7087) --- include/battle.h | 8 +-- include/battle_ai_util.h | 2 +- include/config/ai.h | 4 +- src/battle_ai_main.c | 108 +++++++++++++--------------- src/battle_ai_switch_items.c | 34 ++++----- src/battle_ai_util.c | 20 +++--- test/battle/ai/ai_check_viability.c | 24 +++++++ 7 files changed, 107 insertions(+), 93 deletions(-) diff --git a/include/battle.h b/include/battle.h index 47739ca264..086eb68f51 100644 --- a/include/battle.h +++ b/include/battle.h @@ -329,12 +329,12 @@ struct AiLogicData u8 ejectButtonSwitch:1; // Tracks whether current switch out was from Eject Button u8 ejectPackSwitch:1; // Tracks whether current switch out was from Eject Pack u8 predictingSwitch:1; // Determines whether AI will use switch predictions this turn or not - u8 predictingMove:1; // Determines whether AI will use move predictions this turn or not u8 aiPredictionInProgress:1; // Tracks whether the AI is in the middle of running prediction calculations - u8 padding:2; - u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out u8 aiCalcInProgress:1; - u8 battlerDoingPrediction; // Stores which battler is currently running its prediction calcs + u8 predictingMove:1; // Determines whether AI will use move predictions this turn or not + u8 padding1:1; + u8 shouldSwitch:4; // Stores result of ShouldSwitch, which decides whether a mon should be switched out + u8 padding2:4; u16 predictedMove[MAX_BATTLERS_COUNT]; }; diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 448fbf71c5..118fbf5984 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -80,6 +80,7 @@ u32 AI_GetDamage(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcC bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); +bool32 CanAiPredictMove(void); bool32 IsAiBattlerAssumingStab(void); bool32 IsAiBattlerAssumingStatusMoves(void); bool32 ShouldRecordStatusMove(u32 move); @@ -297,7 +298,6 @@ bool32 IsBattlerPredictedToSwitch(u32 battler); u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); -u32 GetThinkingBattler(u32 battler); bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); // These are for the purpose of not doubling up on moves during double battles. diff --git a/include/config/ai.h b/include/config/ai.h index 8d015ce9e4..b6eb7bfe21 100644 --- a/include/config/ai.h +++ b/include/config/ai.h @@ -52,7 +52,7 @@ #define AI_GOOD_SCORE_THRESHOLD 100 // Move scores above this threshold are considered "good" when deciding switching // AI held item-based move scoring -#define LOW_ACCURACY_THRESHOLD 75 // Moves with accuracy equal OR below this value are considered low accuracy +#define LOW_ACCURACY_THRESHOLD 75 // Moves with accuracy equal OR below this value are considered low accuracy // AI move scoring #define STATUS_MOVE_FOCUS_PUNCH_CHANCE 50 // Chance the AI will use a status move if the player's best move is Focus Punch @@ -73,7 +73,7 @@ // AI Terastalization chances #define AI_CONSERVE_TERA_CHANCE_PER_MON 10 // Chance for AI with smart tera flag to decide not to tera before considering defensive benefit is this*(X-1), where X is the number of alive pokemon that could tera -#define AI_TERA_PREDICT_CHANCE 40 // Chance for AI with smart tera flag to tera in the situation where tera would save it from a KO, but could be punished by a KO from a different move. +#define AI_TERA_PREDICT_CHANCE 40 // Chance for AI with smart tera flag to tera in the situation where tera would save it from a KO, but could be punished by a KO from a different move. // AI_FLAG_PP_STALL_PREVENTION settings #define PP_STALL_DISREGARD_MOVE_PERCENTAGE 50 // Detection chance per roll diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 5e75f1dfb3..5460e31dee 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -33,6 +33,7 @@ #define AI_ACTION_WATCH (1 << 2) #define AI_ACTION_DO_NOT_ATTACK (1 << 3) +static u32 ChooseMoveOrAction(u32 battler); static u32 ChooseMoveOrAction_Singles(u32 battler); static u32 ChooseMoveOrAction_Doubles(u32 battler); static inline void BattleAI_DoAIProcessing(struct AiThinkingStruct *aiThink, u32 battlerAtk, u32 battlerDef); @@ -278,16 +279,17 @@ void BattleAI_SetupFlags(void) { gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT]; } - else + else // Assign ai flags for player for prediction { - gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = 0; // player + u64 aiFlags = GetAiFlags(TRAINER_BATTLE_PARAM.opponentA) | GetAiFlags(TRAINER_BATTLE_PARAM.opponentB); + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_RIGHT] = aiFlags; + gAiThinkingStruct->aiFlags[B_POSITION_PLAYER_LEFT] = aiFlags; } } void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) { - u32 moveLimitations, moveLimitationsTarget; - u32 defaultScoreMovesTarget = defaultScoreMoves; + u32 moveLimitations; u64 flags[MAX_BATTLERS_COUNT]; u32 moveIndex; @@ -313,25 +315,6 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) gBattlerTarget = SetRandomTarget(battler); gAiBattleData->chosenTarget[battler] = gBattlerTarget; - - // Initialize move prediction scores - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE) - { - u32 opposingBattler = GetOppositeBattler(battler); - moveLimitationsTarget = gAiLogicData->moveLimitations[opposingBattler]; - - for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) - { - if (moveLimitationsTarget & (1u << moveIndex)) - SET_SCORE(opposingBattler, moveIndex, 0); - if (defaultScoreMovesTarget & 1) - SET_SCORE(opposingBattler, moveIndex, AI_SCORE_DEFAULT); - else - SET_SCORE(opposingBattler, moveIndex, 0); - - defaultScoreMovesTarget >>= 1; - } - } } bool32 BattlerChoseNonMoveAction(void) @@ -355,7 +338,6 @@ void SetupAIPredictionData(u32 battler, enum SwitchType switchType) { s32 opposingBattler = GetOppositeBattler(battler); gAiLogicData->aiPredictionInProgress = TRUE; - gAiLogicData->battlerDoingPrediction = battler; // Switch prediction if ((gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH)) @@ -364,31 +346,21 @@ void SetupAIPredictionData(u32 battler, enum SwitchType switchType) if (ShouldSwitch(opposingBattler)) gAiLogicData->shouldSwitch |= (1u << opposingBattler); gBattleStruct->prevTurnSpecies[opposingBattler] = gBattleMons[opposingBattler].species; - - // Determine whether AI will use predictions this turn - gAiLogicData->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, PREDICT_SWITCH_CHANCE); } - // Move prediction - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE) - { - gAiLogicData->predictedMove[opposingBattler] = gBattleMons[opposingBattler].moves[BattleAI_ChooseMoveIndex(opposingBattler)]; - ModifySwitchAfterMoveScoring(opposingBattler); + // Determine whether AI will use predictions this turn + gAiLogicData->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, PREDICT_SWITCH_CHANCE); - // Determine whether AI will use predictions this turn - gAiLogicData->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE); - } gAiLogicData->aiPredictionInProgress = FALSE; } void ComputeBattlerDecisions(u32 battler) { - if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) - && (BattlerHasAi(battler) - && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) + bool32 isAiBattler = (gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) && (BattlerHasAi(battler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE)); + if (isAiBattler || CanAiPredictMove()) { // If ai is about to flee or chosen to watch player, no need to calc anything - if (BattlerChoseNonMoveAction()) + if (isAiBattler && BattlerChoseNonMoveAction()) return; // Risky AI switches aggressively even mid battle @@ -401,10 +373,13 @@ void ComputeBattlerDecisions(u32 battler) SetupAIPredictionData(battler, switchType); // AI's own switching data - gAiLogicData->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType); - if (ShouldSwitch(battler)) - gAiLogicData->shouldSwitch |= (1u << battler); - gBattleStruct->prevTurnSpecies[battler] = gBattleMons[battler].species; + if (isAiBattler) + { + gAiLogicData->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType); + if (ShouldSwitch(battler)) + gAiLogicData->shouldSwitch |= (1u << battler); + gBattleStruct->prevTurnSpecies[battler] = gBattleMons[battler].species; + } // AI's move scoring gAiBattleData->chosenMoveIndex[battler] = BattleAI_ChooseMoveIndex(battler); // Calculate score and chose move index @@ -425,6 +400,13 @@ void ReconsiderGimmick(u32 battlerAtk, u32 battlerDef, u16 move) SetAIUsingGimmick(battlerAtk, NO_GIMMICK); } +static u32 ChooseMoveOrAction(u32 battler) +{ + if (IsDoubleBattle()) + return ChooseMoveOrAction_Doubles(battler); + return ChooseMoveOrAction_Singles(battler); +} + u32 BattleAI_ChooseMoveIndex(u32 battler) { u32 chosenMoveIndex; @@ -434,16 +416,11 @@ u32 BattleAI_ChooseMoveIndex(u32 battler) if (gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_TERA && (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_TERA)) DecideTerastal(battler); - - if (!IsDoubleBattle()) - chosenMoveIndex = ChooseMoveOrAction_Singles(battler); - else - chosenMoveIndex = ChooseMoveOrAction_Doubles(battler); + chosenMoveIndex = ChooseMoveOrAction(battler); if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE) ReconsiderGimmick(battler, gBattlerTarget, gBattleMons[battler].moves[chosenMoveIndex]); - // Clear protect structures, some flags may be set during AI calcs // e.g. pranksterElevated from GetBattleMovePriority memset(&gProtectStructs, 0, MAX_BATTLERS_COUNT * sizeof(struct ProtectStruct)); @@ -573,7 +550,6 @@ void RecordStatusMoves(u32 battler) void SetBattlerAiData(u32 battler, struct AiLogicData *aiData) { u32 ability, holdEffect; - ability = aiData->abilities[battler] = AI_DecideKnownAbilityForTurn(battler); aiData->items[battler] = gBattleMons[battler].item; holdEffect = aiData->holdEffects[battler] = AI_DecideHoldEffectForTurn(battler); @@ -691,6 +667,20 @@ void SetAiLogicDataForTurn(struct AiLogicData *aiData) SetBattlerAiMovesData(aiData, battlerAtk, battlersCount, weather); } + + for (battlerAtk = 0; battlerAtk < battlersCount; battlerAtk++) + { + // Prediction limited to player side but can be expanded to read partners move in the future + if (!IsOnPlayerSide(battlerAtk) || !CanAiPredictMove()) + continue; + + // This can potentially be cleaned up more + BattleAI_SetupAIData(0xF, battlerAtk); + u32 chosenMoveIndex = ChooseMoveOrAction(battlerAtk); + gAiLogicData->predictedMove[battlerAtk] = gBattleMons[battlerAtk].moves[chosenMoveIndex]; + aiData->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE); + } + if (DEBUG_AI_DELAY_TIMER) // We add to existing to compound multiple calls gBattleStruct->aiDelayCycles += CycleCountEnd(); @@ -749,7 +739,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battler) u8 consideredMoveArray[MAX_MON_MOVES]; u32 numOfBestMoves; s32 i; - u64 flags = gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)]; + u64 flags = gAiThinkingStruct->aiFlags[battler]; u32 opposingBattler = GetOppositeBattler(battler); gAiLogicData->partnerMove = 0; // no ally @@ -831,7 +821,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battler) gAiLogicData->partnerMove = GetAllyChosenMove(battler); gAiThinkingStruct->aiLogicId = 0; gAiThinkingStruct->movesetIndex = 0; - flags = gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)]; + flags = gAiThinkingStruct->aiFlags[battler]; while (flags != 0) { @@ -1139,7 +1129,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) abilityDef = ABILITY_NONE; // If a pokemon can be guaranteed flinched, don't target the pokemon that can't be flinched. - if (hasTwoOpponents + if (hasTwoOpponents && !IsFlinchGuaranteed(battlerAtk, battlerDef, move) && IsFlinchGuaranteed(battlerAtk, BATTLE_PARTNER(battlerDef), move) && aiData->effectiveness[battlerAtk][BATTLE_PARTNER(battlerDef)][gAiThinkingStruct->movesetIndex] != UQ_4_12(0.0)) ADJUST_SCORE(-5); @@ -1975,7 +1965,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CHILLY_RECEPTION: if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); - else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) + else if (weather & (B_WEATHER_ICY_ANY | B_WEATHER_PRIMAL_ANY) || (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))) ADJUST_SCORE(-8); break; @@ -2254,12 +2244,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); decreased = TRUE; } + break; case PROTECT_WIDE_GUARD: if(!(GetBattlerMoveTargetType(battlerAtk, predictedMove) & (MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH))) { ADJUST_SCORE(-10); decreased = TRUE; } + break; case PROTECT_CRAFTY_SHIELD: if (!hasPartner) { @@ -3000,7 +2992,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - + bool32 hasPartner = HasPartner(battlerAtk); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING); @@ -3095,7 +3087,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. // This unsets Trick Room and resets it with a full timer. case EFFECT_TRICK_ROOM: - if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM) && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) @@ -5741,8 +5733,8 @@ static s32 AI_AttacksPartner(u32 battlerAtk, u32 battlerDef, u32 move, s32 score u32 hitsToKO = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, AI_ATTACKING); - if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 && - (GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) + if (GetMoveTarget(move) == MOVE_TARGET_FOES_AND_ALLY && hitsToKO > 0 && + (GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerAtk), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0 || GetNoOfHitsToKOBattler(battlerAtk, FOE(battlerDef), gAiThinkingStruct->movesetIndex, AI_ATTACKING) > 0)) ADJUST_SCORE(BEST_EFFECT); if (hitsToKO > 0) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 379ce723fd..6f470d3c84 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -111,11 +111,11 @@ u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario) static bool32 IsAceMon(u32 battler, u32 monPartyId) { - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_ACE_POKEMON + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && monPartyId == CalculateEnemyPartyCountInSide(battler)-1) return TRUE; - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_DOUBLE_ACE_POKEMON + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2)) return TRUE; @@ -215,7 +215,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) bool32 canBattlerWin1v1 = FALSE, isBattlerFirst, isBattlerFirstPriority; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic @@ -486,7 +486,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); s32 i, j; - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; if (GetMoveEffect(incomingMove) == EFFECT_HIDDEN_POWER && RandomPercentage(RNG_AI_SWITCH_ABSORBING_HIDDEN_POWER, SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE)) return FALSE; @@ -618,7 +618,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler) bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove); - if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; if (isOpposingBattlerChargingOrInvulnerable && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN))) @@ -637,7 +637,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) s32 opposingBattler = GetOppositeBattler(battler); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Check if current mon has an ability that traps opponent @@ -681,7 +681,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && RandomPercentage(RNG_AI_SWITCH_PERISH_SONG, GetSwitchChance(SHOULD_SWITCH_PERISH_SONG))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) { //Yawn if (gStatuses3[battler] & STATUS3_YAWN @@ -869,7 +869,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc u16 move; // Similar functionality handled more thoroughly by ShouldSwitchIfHasBadOdds - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) return FALSE; if (gLastLandedMoves[battler] == MOVE_NONE) @@ -1007,7 +1007,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) u32 opposingBattler = GetOppositeBattler(battler); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // If not Encore'd don't switch @@ -1057,7 +1057,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler) s8 spAttackingStage = gBattleMons[battler].statStages[STAT_SPATK]; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Physical attacker @@ -1117,7 +1117,7 @@ bool32 ShouldSwitch(u32 battler) return FALSE; // Sequence Switching AI never switches mid-battle - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) return FALSE; availableToSwitch = 0; @@ -1169,7 +1169,7 @@ bool32 ShouldSwitch(u32 battler) if (ShouldSwitchIfWonderGuard(battler)) return TRUE; - if ((gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) + if ((gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) return FALSE; if (ShouldSwitchIfTrapperInParty(battler)) return TRUE; @@ -1197,7 +1197,7 @@ bool32 ShouldSwitch(u32 battler) // Removing switch capabilites under specific conditions // These Functions prevent the "FindMonWithFlagsAndSuperEffective" from getting out of hand. // We don't use FindMonWithFlagsAndSuperEffective with AI_FLAG_SMART_SWITCHING, so we can bail early. - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) return FALSE; if (CanUseSuperEffectiveMoveAgainstOpponents(battler)) return FALSE; @@ -1216,7 +1216,7 @@ bool32 ShouldSwitch(u32 battler) bool32 ShouldSwitchIfAllScoresBad(u32 battler) { u32 i, score, opposingBattler = GetOppositeBattler(battler); - if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) + if (!(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) return FALSE; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1268,7 +1268,7 @@ void ModifySwitchAfterMoveScoring(u32 battler) return; // Sequence Switching AI never switches mid-battle - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) return; availableToSwitch = 0; @@ -2329,14 +2329,14 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) GetAIPartyIndexes(battler, &firstId, &lastId); party = GetBattlerParty(battler); - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) { bestMonId = GetNextMonInParty(party, firstId, lastId, battlerIn1, battlerIn2); return bestMonId; } // Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer. - if (gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic + if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic { bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchType); return bestMonId; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 624dd7cf5a..e044f7b3e9 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -173,11 +173,17 @@ bool32 IsAiBattlerPredictingAbility(u32 battlerId) return BattlerHasAi(battlerId); } +bool32 CanAiPredictMove(void) +{ + return gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_PREDICT_MOVE + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_PREDICT_MOVE; +} + bool32 IsBattlerPredictedToSwitch(u32 battler) { // Check for prediction flag on AI, whether they're using those predictions this turn, and whether the AI thinks the player should switch - if (gAiThinkingStruct->aiFlags[gAiLogicData->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH - || gAiThinkingStruct->aiFlags[gAiLogicData->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH) + if (gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_LEFT] & AI_FLAG_PREDICT_SWITCH + || gAiThinkingStruct->aiFlags[B_POSITION_OPPONENT_RIGHT] & AI_FLAG_PREDICT_SWITCH) { if (gAiLogicData->predictingSwitch && gAiLogicData->shouldSwitch & (1u << battler)) return TRUE; @@ -188,9 +194,8 @@ bool32 IsBattlerPredictedToSwitch(u32 battler) // Either a predicted move or the last used move from an opposing battler u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData) { - if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_PREDICT_MOVE && aiData->predictingMove) + if (aiData->predictingMove && CanAiPredictMove()) return aiData->predictedMove[opposingBattler]; - return aiData->lastUsedMove[opposingBattler]; } @@ -5702,13 +5707,6 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData return WEAK_EFFECT; } -u32 GetThinkingBattler(u32 battler) -{ - if (gAiLogicData->aiPredictionInProgress) - return gAiLogicData->battlerDoingPrediction; - return battler; -} - bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget) { if (B_WILD_NATURAL_ENEMIES != TRUE) diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index 1407023ece..f18f7aceb1 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -339,3 +339,27 @@ AI_SINGLE_BATTLE_TEST("AI uses Skill Swap against Poison Heal") TURN { NOT_EXPECT_MOVE(opponent, MOVE_SKILL_SWAP); } } } + +AI_SINGLE_BATTLE_TEST("AI uses Quick Guard against Quick Attack when opponent would take poison damage") +{ + PASSES_RANDOMLY(PREDICT_MOVE_CHANCE, 100, RNG_AI_PREDICT_MOVE); + GIVEN { + PLAYER(SPECIES_RATTATA) { Moves(MOVE_QUICK_ATTACK); Status1(STATUS1_TOXIC_POISON); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); + OPPONENT(SPECIES_RATTATA) { Moves(MOVE_QUICK_GUARD, MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_QUICK_ATTACK); EXPECT_MOVE(opponent, MOVE_QUICK_GUARD); } + } +} + +AI_SINGLE_BATTLE_TEST("AI uses Wide Guard against Earthquake when opponent would take poison damage") +{ + PASSES_RANDOMLY(PREDICT_MOVE_CHANCE, 100, RNG_AI_PREDICT_MOVE); + GIVEN { + PLAYER(SPECIES_RATTATA) { Moves(MOVE_EARTHQUAKE); Status1(STATUS1_TOXIC_POISON); } + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); + OPPONENT(SPECIES_RATTATA) { Moves(MOVE_WIDE_GUARD, MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_EARTHQUAKE); EXPECT_MOVE(opponent, MOVE_WIDE_GUARD); } + } +} From 2469627c61f7e939bd2aadc2af16c453172c1bb4 Mon Sep 17 00:00:00 2001 From: surskitty Date: Mon, 11 Aug 2025 13:35:10 -0400 Subject: [PATCH 204/283] AI uses Court Change. (#7525) --- src/battle_ai_main.c | 39 +++++++++++++++++++++++++- test/battle/move_effect/court_change.c | 32 +++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 5460e31dee..6d7f4ed09d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2320,6 +2320,23 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-9); break; + case EFFECT_COURT_CHANGE: + if (gSideStatuses[GetBattlerSide(FOE(battlerAtk))] & SIDE_STATUS_BAD_COURT) + ADJUST_SCORE(BAD_EFFECT); + if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_GOOD_COURT) + ADJUST_SCORE(BAD_EFFECT); + if (AreAnyHazardsOnSide(GetBattlerSide(FOE(battlerAtk))) && CountUsablePartyMons(battlerAtk) != 0) + ADJUST_SCORE(WORST_EFFECT); + if (hasPartner) + { + if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the Court Change + { + ADJUST_SCORE(-10); + break; // Don't use Defog if partner is going to set up hazards + } + } + break; case EFFECT_DEFOG: if (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST) || AreAnyHazardsOnSide(GetBattlerSide(battlerAtk))) @@ -2880,7 +2897,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); } break; - case EFFECT_COURT_CHANGE: case EFFECT_TEATIME: if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -4603,6 +4619,27 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //if (CountUsablePartyMons(battlerDef) != 0) //ADJUST_SCORE(8); break; + case EFFECT_COURT_CHANGE: + if (gSideStatuses[GetBattlerSide(FOE(battlerAtk))] & SIDE_STATUS_GOOD_COURT) + ADJUST_SCORE(WEAK_EFFECT); + if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_BAD_COURT) + ADJUST_SCORE(WEAK_EFFECT); + + if (AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) + { + ADJUST_SCORE(DECENT_EFFECT); + } + + if (hasPartner) + { + if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the Court Change + { + ADJUST_SCORE(-10); + break; + } + } + break; case EFFECT_DEFOG: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) || (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_GOOD_FOG)) diff --git a/test/battle/move_effect/court_change.c b/test/battle/move_effect/court_change.c index 56d38c165d..40a1fe4e86 100644 --- a/test/battle/move_effect/court_change.c +++ b/test/battle/move_effect/court_change.c @@ -217,3 +217,35 @@ DOUBLE_BATTLE_TEST("Court Change used by the player swaps G-Max Vine Lash, G-Max } } } + +AI_SINGLE_BATTLE_TEST("AI uses Court Change") +{ + u32 move; + + PARAMETRIZE { move = MOVE_HEADBUTT; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_SAFEGUARD; } + PARAMETRIZE { move = MOVE_SPIKES; } + PARAMETRIZE { move = MOVE_STEALTH_ROCK; } + PARAMETRIZE { move = MOVE_TOXIC_SPIKES; } + PARAMETRIZE { move = MOVE_TAILWIND; } + PARAMETRIZE { move = MOVE_STICKY_WEB; } + PARAMETRIZE { move = MOVE_MIST; } + PARAMETRIZE { move = MOVE_LUCKY_CHANT; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_ZIGZAGOON) { Moves(move, MOVE_CELEBRATE); } + PLAYER(SPECIES_ZIGZAGOON) { Moves(move, MOVE_CELEBRATE); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_COURT_CHANGE, MOVE_HEADBUTT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_COURT_CHANGE, MOVE_HEADBUTT); } + } WHEN { + TURN { MOVE(player, move); EXPECT_MOVE(opponent, MOVE_HEADBUTT); } + if (move == MOVE_HEADBUTT) + TURN { MOVE(player, MOVE_CELEBRATE); NOT_EXPECT_MOVE(opponent, MOVE_COURT_CHANGE); } + else + TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_COURT_CHANGE); } + } +} + From f4c91b5539be83cb7d658bc8d77f475368a2ddc2 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 11 Aug 2025 23:19:36 +0200 Subject: [PATCH 205/283] Convert statuses3 to volatiles (#7514) --- asm/macros/battle_script.inc | 24 ++--- data/battle_scripts_1.s | 33 +++--- include/battle.h | 1 - include/battle_util.h | 2 +- include/constants/battle.h | 116 ++++++++++----------- src/battle_ai_field_statuses.c | 25 +++-- src/battle_ai_main.c | 90 +++++++++-------- src/battle_ai_switch_items.c | 16 +-- src/battle_ai_util.c | 45 +++++---- src/battle_anim_effects_1.c | 1 - src/battle_debug.c | 81 ++++----------- src/battle_end_turn.c | 59 +++++------ src/battle_main.c | 26 ++--- src/battle_script_commands.c | 179 ++++++++++++++------------------- src/battle_tv.c | 2 +- src/battle_util.c | 82 +++++++-------- src/item_use.c | 4 +- 17 files changed, 350 insertions(+), 436 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9dd0479c92..2d70c5e722 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -187,12 +187,8 @@ .4byte \jumpInstr .endm - .macro jumpifstatus3condition battler:req, flags:req, jumpIfTrue:req, jumpInstr:req + .macro unused_0x21 .byte 0x21 - .byte \battler - .4byte \flags - .byte \jumpIfTrue - .4byte \jumpInstr .endm .macro jumpbasedontype battler:req, type:req, jumpIfType:req, jumpInstr:req @@ -738,9 +734,8 @@ .4byte \jumpInstr .endm - .macro setmiracleeye failInstr:req + .macro unused_0x83 .byte 0x83 - .4byte \failInstr .endm .macro jumpifuproarwakes jumpInstr:req @@ -1085,7 +1080,7 @@ tryfiretwoturnmovenowbyeffect \battler, FALSE, \jumpInstr .endm - .macro setminimize + .macro unused_0xC7 .byte 0xc7 .endm @@ -1191,9 +1186,10 @@ .4byte \failInstr .endm - .macro setuserstatus3 flags:req, failInstr:req + .macro trysetvolatile battler:req, _volatile:req, failInstr:req .byte 0xdd - .4byte \flags + .byte \battler + .byte \_volatile .4byte \failInstr .endm @@ -1884,14 +1880,6 @@ jumpifhalfword CMP_NOT_EQUAL, gChosenMove, \move, \jumpInstr .endm - .macro jumpifstatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, FALSE, \jumpInstr - .endm - - .macro jumpifnostatus3 battler:req, flags:req, jumpInstr:req - jumpifstatus3condition \battler, \flags, TRUE, \jumpInstr - .endm - .macro jumpifmovehadnoeffect jumpInstr:req jumpifmoveresultflags MOVE_RESULT_NO_EFFECT, \jumpInstr .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 248d79714d..b7b4ec99cd 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1182,7 +1182,7 @@ BattleScript_StrengthSapAnimation: @ Drain HP without lowering a stat BattleScript_StrengthSapHp: jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_StrengthSapManipulateDmg - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_MoveEnd + jumpifvolatile BS_ATTACKER, VOLATILE_HEAL_BLOCK, BattleScript_MoveEnd jumpiffullhp BS_ATTACKER, BattleScript_MoveEnd BattleScript_StrengthSapManipulateDmg: manipulatedamage DMG_BIG_ROOT @@ -1240,7 +1240,7 @@ BattleScript_EffectLaserFocus:: attackcanceler attackstring ppreduce - setuserstatus3 STATUS3_LASER_FOCUS, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_LASER_FOCUS, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_LASERFOCUS @@ -2189,8 +2189,8 @@ BattleScript_EffectHealPulse:: attackcanceler attackstring ppreduce - jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents @ stops pollen puff - jumpifstatus3 BS_TARGET, STATUS3_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents + jumpifvolatile BS_ATTACKER, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents @ stops pollen puff + jumpifvolatile BS_TARGET, VOLATILE_HEAL_BLOCK, BattleScript_MoveUsedHealBlockPrevents accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifsubstituteblocks BattleScript_ButItFailed tryhealpulse BattleScript_AlreadyAtFullHp @@ -2485,9 +2485,9 @@ BattleScript_EffectMagnetRise:: attackcanceler attackstring ppreduce - jumpifstatus3 BS_ATTACKER, STATUS3_ROOTED, BattleScript_ButItFailed - jumpifstatus3 BS_ATTACKER, STATUS3_SMACKED_DOWN, BattleScript_ButItFailed - setuserstatus3 STATUS3_MAGNET_RISE, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_SMACK_DOWN, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_MAGNET_RISE, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNLEVITATEDONELECTROMAGNETISM @@ -2535,7 +2535,7 @@ BattleScript_EffectAquaRing:: attackcanceler attackstring ppreduce - setuserstatus3 STATUS3_AQUA_RING, BattleScript_ButItFailed + setvolatile BS_ATTACKER, VOLATILE_AQUA_RING attackanimation waitanimation printstring STRINGID_PKMNSURROUNDEDWITHVEILOFWATER @@ -2596,7 +2596,7 @@ BattleScript_EffectMiracleEye:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - setmiracleeye BattleScript_ButItFailed + setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE goto BattleScript_IdentifiedFoe BattleScript_EffectGravity:: @@ -2614,7 +2614,8 @@ BattleScript_EffectGravitySuccess:: BattleScript_GravityLoop: movevaluescleanup jumpfifsemiinvulnerable BS_TARGET, STATE_ON_AIR, BattleScript_GravityLoopDrop - jumpifstatus3 BS_TARGET, STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop + jumpifvolatile BS_TARGET, VOLATILE_MAGNET_RISE, BattleScript_GravityLoopDrop + jumpifvolatile BS_TARGET, VOLATILE_TELEKINESIS, BattleScript_GravityLoopDrop goto BattleScript_GravityLoopEnd BattleScript_GravityLoopDrop: gravityonairbornemons @@ -2726,7 +2727,7 @@ BattleScript_EffectNaturalGift:: jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MAGIC_ROOM, BattleScript_ButItFailed jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailed - jumpifstatus3 BS_ATTACKER, STATUS3_EMBARGO, BattleScript_ButItFailed + jumpifvolatile BS_ATTACKER, VOLATILE_EMBARGO, BattleScript_ButItFailed accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE call BattleScript_HitFromCritCalc @@ -3063,7 +3064,7 @@ BattleScript_EffectRoar:: jumpifcommanderactive BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_ButItFailed jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut - jumpifstatus3 BS_TARGET, STATUS3_ROOTED, BattleScript_PrintMonIsRooted + jumpifvolatile BS_TARGET, VOLATILE_ROOT, BattleScript_PrintMonIsRooted jumpiftargetdynamaxed BattleScript_RoarBlockedByDynamax accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE @@ -3787,7 +3788,7 @@ BattleScript_NightmareWorked:: BattleScript_EffectMinimize:: attackcanceler - setminimize + setvolatile BS_ATTACKER, VOLATILE_MINIMIZE .if B_MINIMIZE_EVASION >= GEN_5 setstatchanger STAT_EVASION, 2, FALSE .else @@ -4697,7 +4698,7 @@ BattleScript_EffectIngrain:: attackcanceler attackstring ppreduce - setuserstatus3 STATUS3_ROOTED, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_ROOT, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNPLANTEDROOTS @@ -4846,7 +4847,7 @@ BattleScript_EffectGrudge:: attackcanceler attackstring ppreduce - setuserstatus3 STATUS3_GRUDGE, BattleScript_ButItFailed + trysetvolatile BS_ATTACKER, VOLATILE_GRUDGE, BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNWANTSGRUDGE @@ -9061,7 +9062,7 @@ BattleScript_RedCardActivates:: printstring STRINGID_REDCARDACTIVATE waitmessage B_WAIT_TIME_LONG swapattackerwithtarget - jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain + jumpifvolatile BS_EFFECT_BATTLER, VOLATILE_ROOT, BattleScript_RedCardIngrain jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups jumpiftargetdynamaxed BattleScript_RedCardDynamaxed removeitem BS_SCRIPTING diff --git a/include/battle.h b/include/battle.h index 086eb68f51..e1cc318b25 100644 --- a/include/battle.h +++ b/include/battle.h @@ -1074,7 +1074,6 @@ extern u32 gHitMarker; extern u8 gBideTarget[MAX_BATTLERS_COUNT]; extern u32 gSideStatuses[NUM_BATTLE_SIDES]; extern struct SideTimer gSideTimers[NUM_BATTLE_SIDES]; -extern u32 gStatuses3[MAX_BATTLERS_COUNT]; extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT]; extern u16 gPauseCounterBattle; extern u16 gPaydayMoney; diff --git a/include/battle_util.h b/include/battle_util.h index 8f38e0f572..0c486f4a3a 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -394,7 +394,7 @@ bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); void UpdateStallMons(void); bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId); bool32 TrySwitchInEjectPack(enum ItemCaseId caseID); -u32 GetMonVolatile(u32 battler, enum Volatile _volatile); +u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile); void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue); u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID); bool32 ItemHealMonVolatile(u32 battler, u16 itemId); diff --git a/include/constants/battle.h b/include/constants/battle.h index 148438237b..0f83eaecae 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -144,39 +144,59 @@ enum VolatileFlags /* Volatile status ailments * These are removed after exiting the battle or switching - * Enum, Type Type, max value, flags */ + * Enum, Type Type, max value, flags */ #define VOLATILE_DEFINITIONS(F) \ - F(VOLATILE_CONFUSION, confusionTurns, (u32, 6), V_BATON_PASSABLE) \ - F(VOLATILE_FLINCHED, flinched, (u32, 1)) \ - F(VOLATILE_UPROAR, uproarTurns, (u32, 5)) \ - F(VOLATILE_TORMENT, torment, (u32, 1)) \ - F(VOLATILE_BIDE, bideTurns, (u32, 3)) \ - F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 3)) \ - F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ - F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ - F(VOLATILE_POWDER, powder, (u32, 1)) \ - F(VOLATILE_UNUSED, padding, (u32, 1)) \ - F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ - F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ - F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ - F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ - F(VOLATILE_RAGE, rage, (u32, 1)) \ - F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \ - F(VOLATILE_ESCAPE_PREVENTION, escapePrevention, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_NIGHTMARE, nightmare, (u32, 1)) \ - F(VOLATILE_CURSED, cursed, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ - F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \ - F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ - F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \ - F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1)) \ - F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \ - F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \ - F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) + F(VOLATILE_CONFUSION, confusionTurns, (u32, 6), V_BATON_PASSABLE) \ + F(VOLATILE_FLINCHED, flinched, (u32, 1)) \ + F(VOLATILE_UPROAR, uproarTurns, (u32, 5)) \ + F(VOLATILE_TORMENT, torment, (u32, 1)) \ + F(VOLATILE_BIDE, bideTurns, (u32, 3)) \ + F(VOLATILE_LOCK_CONFUSE, lockConfusionTurns, (u32, 3)) \ + F(VOLATILE_MULTIPLETURNS, multipleTurns, (u32, 1)) \ + F(VOLATILE_WRAPPED, wrapped, (u32, 1)) \ + F(VOLATILE_POWDER, powder, (u32, 1)) \ + F(VOLATILE_UNUSED, padding, (u32, 1)) \ + F(VOLATILE_INFATUATION, infatuation, (enum BattlerId, MAX_BITS(4))) \ + F(VOLATILE_DEFENSE_CURL, defenseCurl, (u32, 1)) \ + F(VOLATILE_TRANSFORMED, transformed, (u32, 1)) \ + F(VOLATILE_RECHARGE, recharge, (u32, 1)) \ + F(VOLATILE_RAGE, rage, (u32, 1)) \ + F(VOLATILE_SUBSTITUTE, substitute, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_DESTINY_BOND, destinyBond, (u32, 1)) \ + F(VOLATILE_ESCAPE_PREVENTION, escapePrevention, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_NIGHTMARE, nightmare, (u32, 1)) \ + F(VOLATILE_CURSED, cursed, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \ + F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \ + F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \ + F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \ + F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \ + F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1)) \ + F(VOLATILE_LEECH_SEED, leechSeed, (enum BattlerId, MAX_BITS(4)), V_BATON_PASSABLE) \ + F(VOLATILE_LOCK_ON, lockOn, (u32, 2), V_BATON_PASSABLE) \ + F(VOLATILE_PERISH_SONG, perishSong, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_MINIMIZE, minimize, (u32, 1)) \ + F(VOLATILE_CHARGE, charge, (u32, 1)) \ + F(VOLATILE_ROOT, root, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_YAWN, yawn, (u32, 2)) \ + F(VOLATILE_IMPRISON, imprison, (u32, 1)) \ + F(VOLATILE_GRUDGE, grudge, (u32, 1)) \ + F(VOLATILE_GASTRO_ACID, gastroAcid, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_EMBARGO, embargo, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_SMACK_DOWN, smackDown, (u32, 1)) \ + F(VOLATILE_TELEKINESIS, telekinesis, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_MIRACLE_EYE, miracleEye, (u32, 1)) \ + F(VOLATILE_MAGNET_RISE, magnetRise, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_HEAL_BLOCK, healBlock, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_AQUA_RING, aquaRing, (u32, 1), V_BATON_PASSABLE) \ + F(VOLATILE_LASER_FOCUS, laserFocus, (u32, 1)) \ + F(VOLATILE_POWER_TRICK, powerTrick, (u32, 1), V_BATON_PASSABLE) + /* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ #define GET_VOLATILE_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeMaxValue) @@ -193,37 +213,7 @@ enum Volatile // Helper macros #define INFATUATED_WITH(battler) (battler + 1) - -#define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed -#define STATUS3_LEECHSEED (1 << 2) -#define STATUS3_ALWAYS_HITS (1 << 3 | 1 << 4) -#define STATUS3_ALWAYS_HITS_TURN(num) (((num) << 3) & STATUS3_ALWAYS_HITS) // "Always Hits" is set as a 2 turn timer, i.e. next turn is the last turn when it's active -#define STATUS3_PERISH_SONG (1 << 5) -#define STATUS3_UNUSED_6 (1 << 6) -#define STATUS3_UNUSED_7 (1 << 7) -#define STATUS3_MINIMIZED (1 << 8) -#define STATUS3_CHARGED_UP (1 << 9) -#define STATUS3_ROOTED (1 << 10) -#define STATUS3_YAWN (1 << 11 | 1 << 12) // Number of turns to sleep -#define STATUS3_YAWN_TURN(num) (((num) << 11) & STATUS3_YAWN) -#define STATUS3_IMPRISONED_OTHERS (1 << 13) -#define STATUS3_GRUDGE (1 << 14) -#define STATUS3_UNUSED_15 (1 << 15) -#define STATUS3_GASTRO_ACID (1 << 16) -#define STATUS3_EMBARGO (1 << 17) -#define STATUS3_UNUSED_18 (1 << 18) -#define STATUS3_UNUSED_19 (1 << 19) -#define STATUS3_UNUSED_20 (1 << 20) -#define STATUS3_SMACKED_DOWN (1 << 21) -#define STATUS3_UNUSED_22 (1 << 22) -#define STATUS3_TELEKINESIS (1 << 23) -#define STATUS3_UNUSED_24 (1 << 24) -#define STATUS3_MIRACLE_EYED (1 << 25) -#define STATUS3_MAGNET_RISE (1 << 26) -#define STATUS3_HEAL_BLOCK (1 << 27) -#define STATUS3_AQUA_RING (1 << 28) -#define STATUS3_LASER_FOCUS (1 << 29) -#define STATUS3_POWER_TRICK (1 << 30) +#define LEECHSEEDED_BY(battler) (battler + 1) enum SemiInvulnerableState { diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c index d85df3e74a..423910a0e5 100644 --- a/src/battle_ai_field_statuses.c +++ b/src/battle_ai_field_statuses.c @@ -227,9 +227,9 @@ static enum FieldEffectOutcome BenefitsFromSun(u32 battler) return FIELD_EFFECT_NEUTRAL; } - if (DoesAbilityBenefitFromWeather(ability, B_WEATHER_SUN) - || HasLightSensitiveMove(battler) - || HasDamagingMoveOfType(battler, TYPE_FIRE) + if (DoesAbilityBenefitFromWeather(ability, B_WEATHER_SUN) + || HasLightSensitiveMove(battler) + || HasDamagingMoveOfType(battler, TYPE_FIRE) || HasMoveWithEffect(battler, EFFECT_HYDRO_STEAM)) return FIELD_EFFECT_POSITIVE; @@ -248,8 +248,8 @@ static enum FieldEffectOutcome BenefitsFromSandstorm(u32 battler) if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) { - if (!(IS_BATTLER_ANY_TYPE(FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) - || gAiLogicData->holdEffects[FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES + if (!(IS_BATTLER_ANY_TYPE(FOE(battler), TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)) + || gAiLogicData->holdEffects[FOE(battler)] == HOLD_EFFECT_SAFETY_GOGGLES || DoesAbilityBenefitFromWeather(gAiLogicData->abilities[FOE(battler)], B_WEATHER_SANDSTORM)) return FIELD_EFFECT_POSITIVE; else @@ -285,7 +285,7 @@ static enum FieldEffectOutcome BenefitsFromRain(u32 battler) { if (gAiLogicData->holdEffects[battler] == HOLD_EFFECT_UTILITY_UMBRELLA) return FIELD_EFFECT_NEUTRAL; - + if (DoesAbilityBenefitFromWeather(gAiLogicData->abilities[battler], B_WEATHER_RAIN) || HasMoveWithFlag(battler, MoveAlwaysHitsInRain) || HasDamagingMoveOfType(battler, TYPE_WATER)) @@ -316,8 +316,8 @@ static enum FieldEffectOutcome BenefitsFromElectricTerrain(u32 battler) if (grounded && HasBattlerSideMoveWithAdditionalEffect(FOE(battler), MOVE_EFFECT_SLEEP)) return FIELD_EFFECT_POSITIVE; - if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) - || (gStatuses3[battler] & STATUS3_YAWN) + if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) + || gBattleMons[battler].volatiles.yawn || HasDamagingMoveOfType(battler, TYPE_ELECTRIC))) return FIELD_EFFECT_POSITIVE; @@ -382,8 +382,7 @@ static enum FieldEffectOutcome BenefitsFromMistyTerrain(u32 battler) && (HasNonVolatileMoveEffect(FOE(battler), MOVE_EFFECT_SLEEP) || HasNonVolatileMoveEffect(BATTLE_PARTNER(FOE(battler)), MOVE_EFFECT_SLEEP))) return FIELD_EFFECT_POSITIVE; - if (grounded && ((gBattleMons[battler].status1 & STATUS1_SLEEP) - || (gStatuses3[battler] & STATUS3_YAWN))) + if (grounded && (gBattleMons[battler].status1 & STATUS1_SLEEP || gBattleMons[battler].volatiles.yawn)) return FIELD_EFFECT_POSITIVE; return FIELD_EFFECT_NEUTRAL; @@ -407,7 +406,7 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) if (grounded || allyGrounded) { // harass priority - if (HasBattlerSideAbility(FOE(battler), ABILITY_GALE_WINGS, gAiLogicData) + if (HasBattlerSideAbility(FOE(battler), ABILITY_GALE_WINGS, gAiLogicData) || HasBattlerSideAbility(FOE(battler), ABILITY_TRIAGE, gAiLogicData) || HasBattlerSideAbility(FOE(battler), ABILITY_PRANKSTER, gAiLogicData)) return FIELD_EFFECT_POSITIVE; @@ -419,7 +418,7 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) if (HasBattlerSideMoveWithEffect(FOE(battler), EFFECT_EXPANDING_FORCE)) return FIELD_EFFECT_NEGATIVE; - if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) + if (HasBattlerSideAbility(battler, ABILITY_GALE_WINGS, gAiLogicData) || HasBattlerSideAbility(battler, ABILITY_TRIAGE, gAiLogicData) || HasBattlerSideAbility(battler, ABILITY_PRANKSTER, gAiLogicData)) return FIELD_EFFECT_NEGATIVE; @@ -436,7 +435,7 @@ static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) return FIELD_EFFECT_POSITIVE; // If we tie, we shouldn't change trick room state. else if (GetBattlerSideSpeedAverage(battler) == GetBattlerSideSpeedAverage(FOE(battler))) - return FIELD_EFFECT_NEUTRAL; + return FIELD_EFFECT_NEUTRAL; else return FIELD_EFFECT_NEGATIVE; } diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6d7f4ed09d..430412966b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1281,7 +1281,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gDisableStructs[battlerAtk].throatChopTimer > gBattleTurnCounter && IsSoundMove(move)) return 0; // Can't even select move at all // heal block check - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(battlerAtk, move)) + if (gBattleMons[battlerAtk].volatiles.healBlock && IsHealBlockPreventingMove(battlerAtk, move)) return 0; // Can't even select heal blocked move // primal weather check @@ -1432,7 +1432,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_CHARGE: - if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP) + if (gBattleMons[battlerAtk].volatiles.charge) ADJUST_SCORE(-20); else if (!HasMoveWithType(battlerAtk, TYPE_ELECTRIC)) ADJUST_SCORE(-10); @@ -1761,7 +1761,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); break; case EFFECT_LEECH_SEED: - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED + if (gBattleMons[battlerDef].volatiles.leechSeed || IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -1891,9 +1891,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); //Don't wipe your team if you're going to lose } else if ((!IsBattlerAlive(FOE(battlerAtk)) || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF - || gStatuses3[FOE(battlerAtk)] & STATUS3_PERISH_SONG) + || gBattleMons[FOE(battlerAtk)].volatiles.perishSong) && (!IsBattlerAlive(BATTLE_PARTNER(FOE(battlerAtk))) || aiData->abilities[BATTLE_PARTNER(FOE(battlerAtk))] == ABILITY_SOUNDPROOF - || gStatuses3[BATTLE_PARTNER(FOE(battlerAtk))] & STATUS3_PERISH_SONG)) + || gBattleMons[BATTLE_PARTNER(FOE(battlerAtk))].volatiles.perishSong)) { ADJUST_SCORE(-10); //Both enemies are perish songed } @@ -1908,7 +1908,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && CountUsablePartyMons(battlerDef) >= 1) ADJUST_SCORE(-10); - if (gStatuses3[FOE(battlerAtk)] & STATUS3_PERISH_SONG || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF) + if (gBattleMons[FOE(battlerAtk)].volatiles.perishSong || aiData->abilities[FOE(battlerAtk)] == ABILITY_SOUNDPROOF) ADJUST_SCORE(-10); } break; @@ -1954,8 +1954,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CountUsablePartyMons(battlerAtk) == 0) ADJUST_SCORE(-10); else if (gBattleMons[battlerAtk].volatiles.substitute - || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) - || AnyStatIsRaised(battlerAtk)) + || gBattleMons[battlerAtk].volatiles.powerTrick + || gBattleMons[battlerAtk].volatiles.magnetRise + || gBattleMons[battlerAtk].volatiles.aquaRing + || gBattleMons[battlerAtk].volatiles.root + || AnyStatIsRaised(battlerAtk)) break; else ADJUST_SCORE(-6); @@ -2044,11 +2047,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_INGRAIN: - if (gStatuses3[battlerAtk] & STATUS3_ROOTED) + if (gBattleMons[battlerAtk].volatiles.root) ADJUST_SCORE(-10); break; case EFFECT_AQUA_RING: - if (gStatuses3[battlerAtk] & STATUS3_AQUA_RING) + if (gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(-10); break; case EFFECT_RECYCLE: @@ -2056,7 +2059,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_IMPRISON: - if (gStatuses3[battlerAtk] & STATUS3_IMPRISONED_OTHERS) + if (gBattleMons[battlerAtk].volatiles.imprison) ADJUST_SCORE(-10); break; case EFFECT_REFRESH: @@ -2128,7 +2131,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // don't scare away pokemon twice else if (aiData->hpPercents[battlerDef] < 10 && GetBattlerSecondaryDamage(battlerDef)) ADJUST_SCORE(-10); // don't blow away mon that will faint soon - else if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) + else if (gBattleMons[battlerDef].volatiles.perishSong) ADJUST_SCORE(-10); break; case EFFECT_CONVERSION: @@ -2200,14 +2203,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) //TODO break; case EFFECT_LOCK_ON: - if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS + if (gBattleMons[battlerDef].volatiles.lockOn || aiData->abilities[battlerAtk] == ABILITY_NO_GUARD || aiData->abilities[battlerDef] == ABILITY_NO_GUARD || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_LASER_FOCUS: - if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS) + if (gBattleMons[battlerDef].volatiles.laserFocus) ADJUST_SCORE(-10); else if (aiData->abilities[battlerDef] == ABILITY_SHELL_ARMOR || aiData->abilities[battlerDef] == ABILITY_BATTLE_ARMOR) ADJUST_SCORE(-8); @@ -2312,7 +2315,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_MIRACLE_EYE: - if (gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) + if (gBattleMons[battlerDef].volatiles.miracleEye) ADJUST_SCORE(-10); if (gBattleMons[battlerDef].statStages[STAT_EVASION] <= 4 @@ -2431,7 +2434,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_YAWN: - if (gStatuses3[battlerDef] & STATUS3_YAWN) + if (gBattleMons[battlerDef].volatiles.yawn) ADJUST_SCORE(-10); else if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -2651,7 +2654,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_EMBARGO: if (!IsBattlerItemEnabled(battlerAtk) - || gStatuses3[battlerDef] & STATUS3_EMBARGO + || gBattleMons[battlerDef].volatiles.embargo || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; @@ -2661,15 +2664,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_TELEKINESIS: - if (gStatuses3[battlerDef] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) - || gFieldStatuses & STATUS_FIELD_GRAVITY - || aiData->holdEffects[battlerDef] == HOLD_EFFECT_IRON_BALL - || IsTelekinesisBannedSpecies(gBattleMons[battlerDef].species) - || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + if (gBattleMons[battlerDef].volatiles.telekinesis + || gBattleMons[battlerDef].volatiles.root + || gBattleMons[battlerDef].volatiles.smackDown + || gFieldStatuses & STATUS_FIELD_GRAVITY + || aiData->holdEffects[battlerDef] == HOLD_EFFECT_IRON_BALL + || IsTelekinesisBannedSpecies(gBattleMons[battlerDef].species) + || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_HEAL_BLOCK: - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK + if (gBattleMons[battlerDef].volatiles.healBlock || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; @@ -2698,7 +2703,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_HIT_ENEMY_HEAL_ALLY: // pollen puff if (IsTargetingPartner(battlerAtk, battlerDef)) { - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerDef].volatiles.healBlock) return 0; // cannot even select if (AI_BattlerAtMaxHp(battlerDef)) ADJUST_SCORE(-10); @@ -2806,9 +2811,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAGNET_RISE: if (gFieldStatuses & STATUS_FIELD_GRAVITY - || gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter + || gDisableStructs[battlerAtk].magnetRiseTimer > gBattleTurnCounter || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_IRON_BALL - || gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_MAGNET_RISE | STATUS3_SMACKED_DOWN) + || gBattleMons[battlerAtk].volatiles.smackDown + || gBattleMons[battlerAtk].volatiles.root + || gBattleMons[battlerAtk].volatiles.magnetRise || !IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(-10); break; @@ -4205,7 +4212,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_SHEER_COLD: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - else if (gStatuses3[battlerAtk] & STATUS3_ALWAYS_HITS) + else if (gBattleMons[battlerAtk].volatiles.lockOn) ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_MEAN_LOOK: @@ -4237,7 +4244,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_LEECH_SEED: if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) - || gStatuses3[battlerDef] & STATUS3_LEECHSEED + || gBattleMons[battlerDef].volatiles.leechSeed || HasMoveWithEffect(battlerDef, EFFECT_RAPID_SPIN) || aiData->abilities[battlerDef] == ABILITY_LIQUID_OOZE || aiData->abilities[battlerDef] == ABILITY_MAGIC_GUARD) @@ -4286,7 +4293,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_BATON_PASS: if ((gAiLogicData->shouldSwitch & (1u << battlerAtk)) && (gBattleMons[battlerAtk].volatiles.substitute - || (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK)) + || gBattleMons[battlerAtk].volatiles.powerTrick + || gBattleMons[battlerAtk].volatiles.magnetRise + || gBattleMons[battlerAtk].volatiles.aquaRing + || gBattleMons[battlerAtk].volatiles.root || AnyStatIsRaised(battlerAtk))) ADJUST_SCORE(BEST_EFFECT); break; @@ -4940,9 +4950,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_POWER_TRICK: - if (!(gStatuses3[battlerAtk] & STATUS3_POWER_TRICK) - && gBattleMons[battlerAtk].defense > gBattleMons[battlerAtk].attack - && HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) + if (!gBattleMons[battlerAtk].volatiles.powerTrick + && gBattleMons[battlerAtk].defense > gBattleMons[battlerAtk].attack + && HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_PHYSICAL)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEART_SWAP: @@ -5016,7 +5026,7 @@ case EFFECT_GUARD_SPLIT: if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) { ADJUST_SCORE(GOOD_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) + if (gBattleMons[battlerAtk].volatiles.yawn && IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(BEST_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) ADJUST_SCORE(WEAK_EFFECT); @@ -5026,7 +5036,7 @@ case EFFECT_GUARD_SPLIT: if (ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_MISTY_TERRAIN)) { ADJUST_SCORE(GOOD_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) + if (gBattleMons[battlerAtk].volatiles.yawn && IsBattlerGrounded(battlerAtk)) ADJUST_SCORE(BEST_EFFECT); if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_TERRAIN_EXTENDER || HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_TERRAIN_PULSE)) ADJUST_SCORE(WEAK_EFFECT); @@ -5266,7 +5276,7 @@ case EFFECT_GUARD_SPLIT: break; case EFFECT_RAPID_SPIN: if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0) - || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].volatiles.wrapped)) + || (gBattleMons[battlerAtk].volatiles.leechSeed || gBattleMons[battlerAtk].volatiles.wrapped)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SPECTRAL_THIEF: @@ -5806,11 +5816,11 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor switch (effect) { case EFFECT_INGRAIN: - if (!(gStatuses3[battlerAtk] & STATUS3_ROOTED)) + if (!gBattleMons[battlerAtk].volatiles.root) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_AQUA_RING: - if (!(gStatuses3[battlerAtk] & STATUS3_AQUA_RING)) + if (!gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_PROTECT: @@ -5820,9 +5830,9 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_BATON_PASS: - if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING)) + if (gBattleMons[battlerAtk].volatiles.root || gBattleMons[battlerAtk].volatiles.aquaRing) ADJUST_SCORE(DECENT_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) + if (gBattleMons[battlerAtk].volatiles.leechSeed) ADJUST_SCORE(-3); ADJUST_SCORE(CountPositiveStatStages(battlerAtk) - CountNegativeStatStages(battlerAtk)); break; @@ -5848,7 +5858,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || (moveType == TYPE_GROUND && gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_EARTH_EATER) || (moveType == TYPE_WATER && (gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_DRY_SKIN || gAiLogicData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_WATER_ABSORB))) { - if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerDef].volatiles.healBlock) return 0; if (CanTargetFaintAi(FOE(battlerAtk), BATTLE_PARTNER(battlerAtk)) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 6f470d3c84..c11f448645 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -675,7 +675,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) bool32 hasStatRaised = AnyStatIsRaised(battler); //Perish Song - if (gStatuses3[battler] & STATUS3_PERISH_SONG + if (gBattleMons[battler].volatiles.perishSong && gDisableStructs[battler].perishSongTimer == 0 && monAbility != ABILITY_SOUNDPROOF && RandomPercentage(RNG_AI_SWITCH_PERISH_SONG, GetSwitchChance(SHOULD_SWITCH_PERISH_SONG))) @@ -684,7 +684,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) { //Yawn - if (gStatuses3[battler] & STATUS3_YAWN + if (gBattleMons[battler].volatiles.yawn && CanBeSlept(battler, battler, monAbility, BLOCKED_BY_SLEEP_CLAUSE) // TODO: ask for help from pawwkie && gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3 && RandomPercentage(RNG_AI_SWITCH_YAWN, GetSwitchChance(SHOULD_SWITCH_YAWN))) @@ -719,7 +719,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && gAiLogicData->abilities[opposingBattler] != ABILITY_MINDS_EYE && (GetGenConfig(GEN_ILLUMINATE_EFFECT) >= GEN_9 && gAiLogicData->abilities[opposingBattler] != ABILITY_ILLUMINATE) && !gBattleMons[battler].volatiles.foresight - && !(gStatuses3[battler] & STATUS3_MIRACLE_EYED)) + && !gBattleMons[battler].volatiles.miracleEye) switchMon = FALSE; if (switchMon) @@ -749,7 +749,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) return SetSwitchinAndSwitch(battler, PARTY_SIZE); //Leech Seed - if (gStatuses3[battler] & STATUS3_LEECHSEED + if (gBattleMons[battler].volatiles.leechSeed && (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED)))) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } @@ -770,7 +770,7 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler) bool32 hasStatRaised = AnyStatIsRaised(battler); //Check if ability is blocked - if (gStatuses3[battler] & STATUS3_GASTRO_ACID + if (gBattleMons[battler].volatiles.gastroAcid || IsNeutralizingGasOnField()) return FALSE; @@ -1109,7 +1109,7 @@ bool32 ShouldSwitch(u32 battler) return FALSE; if (gBattleMons[battler].volatiles.escapePrevention) return FALSE; - if (gStatuses3[battler] & STATUS3_ROOTED) + if (gBattleMons[battler].volatiles.root) return FALSE; if (IsAbilityPreventingEscape(battler)) return FALSE; @@ -1260,7 +1260,7 @@ void ModifySwitchAfterMoveScoring(u32 battler) return; if (gBattleMons[battler].volatiles.escapePrevention) return; - if (gStatuses3[battler] & STATUS3_ROOTED) + if (gBattleMons[battler].volatiles.root) return; if (IsAbilityPreventingEscape(battler)) return; @@ -2425,7 +2425,7 @@ static bool32 ShouldUseItem(u32 battler) || gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP) return FALSE; - if (gStatuses3[battler] & STATUS3_EMBARGO) + if (gBattleMons[battler].volatiles.embargo) return FALSE; if (AiExpectsToFaintPlayer(battler)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index e044f7b3e9..8fe1067a19 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -467,7 +467,7 @@ bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef) return TRUE; if (gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_SKY_DROP) return TRUE; - if (gStatuses3[battlerDef] & STATUS3_ROOTED) + if (gBattleMons[battlerDef].volatiles.root) return TRUE; if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return TRUE; @@ -1632,11 +1632,11 @@ enum ItemHoldEffect AI_DecideHoldEffectForTurn(u32 battlerId) if (gAiThinkingStruct->aiFlags[battlerId] & AI_FLAG_NEGATE_UNAWARE) return holdEffect; - if (gStatuses3[battlerId] & STATUS3_EMBARGO) + if (gBattleMons[battlerId].volatiles.embargo) return HOLD_EFFECT_NONE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return HOLD_EFFECT_NONE; - if (gAiLogicData->abilities[battlerId] == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID)) + if (gAiLogicData->abilities[battlerId] == ABILITY_KLUTZ && !gBattleMons[battlerId].volatiles.gastroAcid) return HOLD_EFFECT_NONE; return holdEffect; @@ -1890,7 +1890,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, atkAbility, move) && defAbility == ABILITY_STURDY) return FALSE; - if ((((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS) + if (((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) || atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD) && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level) @@ -1935,7 +1935,8 @@ bool32 IsBattlerDamagedByStatus(u32 battler) || gBattleMons[battler].volatiles.nightmare || gBattleMons[battler].volatiles.cursed || gBattleMons[battler].volatiles.saltCure - || gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED) + || gBattleMons[battler].volatiles.leechSeed + || gBattleMons[battler].volatiles.perishSong || gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_DAMAGE_NON_TYPES); } @@ -2087,9 +2088,9 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) case STAT_ACC: if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) + if (gBattleMons[battlerDef].volatiles.leechSeed) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_ROOTED) + if (gBattleMons[battlerDef].volatiles.root) tempScore += WEAK_EFFECT; if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; @@ -2097,9 +2098,9 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) case STAT_EVASION: if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) + if (gBattleMons[battlerDef].volatiles.leechSeed) tempScore += WEAK_EFFECT; - if (gStatuses3[battlerDef] & STATUS3_ROOTED) + if (gBattleMons[battlerDef].volatiles.root) tempScore += WEAK_EFFECT; if (gBattleMons[battlerDef].volatiles.cursed) tempScore += WEAK_EFFECT; @@ -2864,13 +2865,13 @@ bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move) } } -static u32 GetLeechSeedDamage(u32 battlerId) +static u32 GetLeechSeedDamage(u32 battler) { u32 damage = 0; - if ((gStatuses3[battlerId] & STATUS3_LEECHSEED) - && gBattleMons[gStatuses3[battlerId] & STATUS3_LEECHSEED_BATTLER].hp != 0) + u32 leechSeeder = gBattleMons[battler].volatiles.leechSeed; + if (leechSeeder && gBattleMons[leechSeeder - 1].hp != 0) { - damage = GetNonDynamaxMaxHP(battlerId) / 8; + damage = GetNonDynamaxMaxHP(battler) / 8; if (damage == 0) damage = 1; } @@ -3714,7 +3715,7 @@ bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) // using item or user goes first s32 healDmg = (GetMoveAbsorbPercentage(move) * damage) / 100; - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerAtk].volatiles.healBlock) healDmg = 0; if (CanTargetFaintAi(battlerDef, battlerAtk) @@ -3739,7 +3740,7 @@ bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent) u32 healAmount = (healPercent * maxHP) / 100; if (healAmount > maxHP) healAmount = maxHP; - if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battlerAtk].volatiles.healBlock) healAmount = 0; if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) { @@ -3800,7 +3801,7 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects mo bool32 IsBattle1v1() { if (IsDoubleBattle() - && ((IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) + && ((IsBattlerAlive(B_POSITION_PLAYER_LEFT) && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) || (IsBattlerAlive(B_POSITION_OPPONENT_LEFT) && IsBattlerAlive(B_POSITION_OPPONENT_RIGHT)))) return FALSE; return TRUE; @@ -5154,9 +5155,9 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (gBattleMons[battlerDef].volatiles.substitute) ADJUST_SCORE_PTR(GOOD_EFFECT); - if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) + if (gBattleMons[battlerAtk].volatiles.leechSeed) ADJUST_SCORE_PTR(DECENT_EFFECT); - if (gStatuses3[battlerDef] & STATUS3_LEECHSEED) + if (gBattleMons[battlerDef].volatiles.leechSeed) ADJUST_SCORE_PTR(-2); } @@ -5209,7 +5210,7 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move) scoreIncrease += BEST_EFFECT; } - if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) + if (gBattleMons[battlerDef].volatiles.perishSong) scoreIncrease += GOOD_EFFECT; if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP) @@ -5250,9 +5251,9 @@ bool32 IsBattlerItemEnabled(u32 battler) return TRUE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return FALSE; - if (gStatuses3[battler] & STATUS3_EMBARGO) + if (gBattleMons[battler].volatiles.embargo) return FALSE; - if (gBattleMons[battler].ability == ABILITY_KLUTZ && !(gStatuses3[battler] & STATUS3_GASTRO_ACID)) + if (gBattleMons[battler].ability == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) return FALSE; return TRUE; } @@ -5393,7 +5394,7 @@ bool32 CanEffectChangeAbility(u32 battlerAtk, u32 battlerDef, u32 effect, struct } } - if (gStatuses3[battlerDef] & STATUS3_GASTRO_ACID) + if (gBattleMons[battlerDef].volatiles.gastroAcid) return FALSE; u32 atkAbility = aiData->abilities[battlerAtk]; diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 12bd7859b9..e49c9f2003 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6906,7 +6906,6 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp); SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); - SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); SwapBattlerMoveData(battlerAtk, battlerPartner); diff --git a/src/battle_debug.c b/src/battle_debug.c index a991ac341a..149cb4065c 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -105,7 +105,6 @@ enum LIST_ITEM_STAT_STAGES, LIST_ITEM_STATUS1, LIST_ITEM_VOLATILE, - LIST_ITEM_STATUS3, LIST_ITEM_HAZARDS, LIST_ITEM_SIDE_STATUS, LIST_ITEM_AI, @@ -140,30 +139,6 @@ enum LIST_STATUS1_FROSTBITE, }; -enum -{ - LIST_STATUS3_LEECH_SEED_HEALER, - LIST_STATUS3_LEECH_SEEDED, - LIST_STATUS3_ALWAYS_HITS, - LIST_STATUS3_PERISH_SONG, - LIST_STATUS3_MINIMIZED, - LIST_STATUS3_CHARGED_UP, - LIST_STATUS3_ROOTED, - LIST_STATUS3_YAWN, - LIST_STATUS3_IMPRISONED_OTHERS, - LIST_STATUS3_GRUDGE, - LIST_STATUS3_GASTRO_ACID, - LIST_STATUS3_EMBARGO, - LIST_STATUS3_SMACKED_DOWN, - LIST_STATUS3_TELEKINESIS, - LIST_STATUS3_MIRACLE_EYED, - LIST_STATUS3_MAGNET_RISE, - LIST_STATUS3_HEAL_BLOCK, - LIST_STATUS3_AQUA_RING, - LIST_STATUS3_LASER_FOCUS, - LIST_STATUS3_POWER_TRICK, -}; - enum { LIST_SIDE_STICKY_WEB, @@ -346,7 +321,6 @@ static const struct ListMenuItem sMainListItems[] = {COMPOUND_STRING("Stat Stages"), LIST_ITEM_STAT_STAGES}, {COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1}, {COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE}, - {COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3}, {COMPOUND_STRING("Hazards"), LIST_ITEM_HAZARDS}, {COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS}, {COMPOUND_STRING("AI"), LIST_ITEM_AI}, @@ -402,30 +376,25 @@ static const struct ListMenuItem sVolatileStatusListItems[] = {COMPOUND_STRING("Salt Cure"), VOLATILE_SALT_CURE}, {COMPOUND_STRING("Syrup Bomb"), VOLATILE_SYRUP_BOMB}, {COMPOUND_STRING("Glaive Rush"), VOLATILE_GLAIVE_RUSH}, -}; - -static const struct ListMenuItem sStatus3ListItems[] = -{ - {COMPOUND_STRING("Leech Seed Healer"), LIST_STATUS3_LEECH_SEED_HEALER}, - {COMPOUND_STRING("Leech Seeded"), LIST_STATUS3_LEECH_SEEDED}, - {COMPOUND_STRING("Always Hits"), LIST_STATUS3_ALWAYS_HITS}, - {COMPOUND_STRING("Perish Song"), LIST_STATUS3_PERISH_SONG}, - {COMPOUND_STRING("Minimized"), LIST_STATUS3_MINIMIZED}, - {COMPOUND_STRING("Charged Up"), LIST_STATUS3_CHARGED_UP}, - {COMPOUND_STRING("Rooted"), LIST_STATUS3_ROOTED}, - {COMPOUND_STRING("Yawn"), LIST_STATUS3_YAWN}, - {COMPOUND_STRING("Imprisoned Others"), LIST_STATUS3_IMPRISONED_OTHERS}, - {COMPOUND_STRING("Grudge"), LIST_STATUS3_GRUDGE}, - {COMPOUND_STRING("Gastro Acid"), LIST_STATUS3_GASTRO_ACID}, - {COMPOUND_STRING("Embargo"), LIST_STATUS3_EMBARGO}, - {COMPOUND_STRING("Smacked Down"), LIST_STATUS3_SMACKED_DOWN}, - {COMPOUND_STRING("Telekinesis"), LIST_STATUS3_TELEKINESIS}, - {COMPOUND_STRING("Miracle Eyed"), LIST_STATUS3_MIRACLE_EYED}, - {COMPOUND_STRING("Magnet Rise"), LIST_STATUS3_MAGNET_RISE}, - {COMPOUND_STRING("Heal Block"), LIST_STATUS3_HEAL_BLOCK}, - {COMPOUND_STRING("Aqua Ring"), LIST_STATUS3_AQUA_RING}, - {COMPOUND_STRING("Laser Focus"), LIST_STATUS3_LASER_FOCUS}, - {COMPOUND_STRING("Power Trick"), LIST_STATUS3_POWER_TRICK}, + {COMPOUND_STRING("Leech Seed"), VOLATILE_LEECH_SEED}, + {COMPOUND_STRING("Lock On"), VOLATILE_LOCK_ON}, + {COMPOUND_STRING("Perish Song"), VOLATILE_PERISH_SONG}, + {COMPOUND_STRING("Minimize"), VOLATILE_MINIMIZE}, + {COMPOUND_STRING("Charge"), VOLATILE_CHARGE}, + {COMPOUND_STRING("Root"), VOLATILE_ROOT}, + {COMPOUND_STRING("Yawn"), VOLATILE_YAWN}, + {COMPOUND_STRING("Imprison"), VOLATILE_IMPRISON}, + {COMPOUND_STRING("Grudge"), VOLATILE_GRUDGE}, + {COMPOUND_STRING("Gastro Acid"), VOLATILE_GASTRO_ACID}, + {COMPOUND_STRING("Embargo"), VOLATILE_EMBARGO}, + {COMPOUND_STRING("Smack Down"), VOLATILE_SMACK_DOWN}, + {COMPOUND_STRING("Telekinesis"), VOLATILE_TELEKINESIS}, + {COMPOUND_STRING("Miracle Eye"), VOLATILE_MIRACLE_EYE}, + {COMPOUND_STRING("Magnet Rise"), VOLATILE_MAGNET_RISE}, + {COMPOUND_STRING("Heal Block"), VOLATILE_HEAL_BLOCK}, + {COMPOUND_STRING("Aqua Ring"), VOLATILE_AQUA_RING}, + {COMPOUND_STRING("Laser Focus"), VOLATILE_LASER_FOCUS}, + {COMPOUND_STRING("Power Trick"), VOLATILE_POWER_TRICK}, }; static const struct ListMenuItem sHazardsListItems[] = @@ -1403,11 +1372,6 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) listTemplate.items = sVolatileStatusListItems; itemsCount = ARRAY_COUNT(sVolatileStatusListItems); break; - case LIST_ITEM_STATUS3: - listTemplate.items = sStatus3ListItems; - itemsCount = ARRAY_COUNT(sStatus3ListItems); - data->bitfield = sStatus3Bitfield; - break; case LIST_ITEM_AI: listTemplate.items = sAIListItems; itemsCount = ARRAY_COUNT(sAIListItems); @@ -2024,7 +1988,7 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.typeOfVal = VAL_BITFIELD_32; goto CASE_ITEM_STATUS; case LIST_ITEM_VOLATILE: - data->modifyArrows.currValue = GetMonVolatile(data->battlerId, data->currentSecondaryListItemId); + data->modifyArrows.currValue = GetBattlerVolatile(data->battlerId, data->currentSecondaryListItemId); data->modifyArrows.typeOfVal = VAL_VOLATILE; data->modifyArrows.minValue = 0; #define UNPACK_VOLATILE_MAX_SIZE(_enum, _fieldName, _typeMaxValue, ...) case _enum: data->modifyArrows.maxValue = min(MAX_u16, GET_VOLATILE_MAXIMUM(_typeMaxValue)); break; @@ -2045,11 +2009,6 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) } data->modifyArrows.maxDigits = MAX_DIGITS(data->modifyArrows.maxValue); break; - case LIST_ITEM_STATUS3: - data->modifyArrows.modifiedValPtr = &gStatuses3[data->battlerId]; - data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); - data->modifyArrows.typeOfVal = VAL_BITFIELD_32; - goto CASE_ITEM_STATUS; case LIST_ITEM_AI: data->modifyArrows.modifiedValPtr = &gAiThinkingStruct->aiFlags[data->battlerId]; data->modifyArrows.currValue = GetBitfieldValue(gAiThinkingStruct->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 87ed8542a7..c39e4e114a 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -163,14 +163,14 @@ static bool32 HandleEndTurnVarious(u32 battler) for (i = 0; i < gBattlersCount; i++) { - if (gStatuses3[i] & STATUS3_ALWAYS_HITS) - gStatuses3[i] -= STATUS3_ALWAYS_HITS_TURN(1); + if (gBattleMons[i].volatiles.lockOn > 0) + gBattleMons[i].volatiles.lockOn--; if (gDisableStructs[i].chargeTimer && --gDisableStructs[i].chargeTimer == 0) - gStatuses3[i] &= ~STATUS3_CHARGED_UP; + gBattleMons[i].volatiles.charge = FALSE; - if (gStatuses3[i] & STATUS3_LASER_FOCUS && gDisableStructs[i].laserFocusTimer == gBattleTurnCounter) - gStatuses3[i] &= ~STATUS3_LASER_FOCUS; + if (gBattleMons[i].volatiles.laserFocus && gDisableStructs[i].laserFocusTimer == gBattleTurnCounter) + gBattleMons[i].volatiles.laserFocus = FALSE; gBattleStruct->hpBefore[i] = gBattleMons[i].hp; } @@ -409,7 +409,7 @@ static bool32 HandleEndTurnWish(u32 battler) } gBattleStruct->moveDamage[battler] *= -1; - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.healBlock) BattleScriptExecute(BattleScript_WishButHealBlocked); else if (gBattleMons[battler].hp == gBattleMons[battler].maxHP) BattleScriptExecute(BattleScript_WishButFullHp); @@ -486,7 +486,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + && !gBattleMons[battler].volatiles.healBlock && !IsSemiInvulnerable(battler, CHECK_ALL) && IsBattlerGrounded(battler)) { @@ -542,8 +542,8 @@ static bool32 HandleEndTurnAquaRing(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_AQUA_RING - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.aquaRing + && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { @@ -561,8 +561,8 @@ static bool32 HandleEndTurnIngrain(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_ROOTED - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.root + && !gBattleMons[battler].volatiles.healBlock && !IsBattlerAtMaxHp(battler) && IsBattlerAlive(battler)) { @@ -580,12 +580,12 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_LEECHSEED - && IsBattlerAlive(gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER) + if (gBattleMons[battler].volatiles.leechSeed + && IsBattlerAlive(gBattleMons[battler].volatiles.leechSeed - 1) && IsBattlerAlive(battler) && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { - gBattlerTarget = gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER; // Notice gBattlerTarget is actually the HP receiver. + gBattlerTarget = gBattleMons[battler].volatiles.leechSeed - 1; // leech seed receiver gBattleScripting.animArg1 = gBattlerTarget; gBattleScripting.animArg2 = gBattlerAttacker; gBattleStruct->moveDamage[gBattlerAttacker] = max(1, GetNonDynamaxMaxHP(battler) / 8); @@ -597,7 +597,7 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_OOZE; BattleScriptExecute(BattleScript_LeechSeedTurnDrainLiquidOoze); } - else if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + else if (gBattleMons[gBattlerTarget].volatiles.healBlock) { BattleScriptExecute(BattleScript_LeechSeedTurnDrainHealBlock); } @@ -626,7 +626,7 @@ static bool32 HandleEndTurnPoison(u32 battler) { if (ability == ABILITY_POISON_HEAL) { - if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!IsBattlerAtMaxHp(battler) && !gBattleMons[battler].volatiles.healBlock) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) @@ -946,9 +946,9 @@ static bool32 HandleEndTurnMagnetRise(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_MAGNET_RISE && gDisableStructs[battler].magnetRiseTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.magnetRise && gDisableStructs[battler].magnetRiseTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_MAGNET_RISE; + gBattleMons[battler].volatiles.magnetRise = FALSE; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_STRING_BUFFER(gBattleTextBuff1, STRINGID_ELECTROMAGNETISM); effect = TRUE; @@ -963,9 +963,9 @@ static bool32 HandleEndTurnTelekinesis(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_TELEKINESIS && gDisableStructs[battler].telekinesisTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.telekinesis && gDisableStructs[battler].telekinesisTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_TELEKINESIS; + gBattleMons[battler].volatiles.telekinesis = FALSE; BattleScriptExecute(BattleScript_TelekinesisEndTurn); effect = TRUE; } @@ -979,9 +979,9 @@ static bool32 HandleEndTurnHealBlock(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK && gDisableStructs[battler].healBlockTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.healBlock && gDisableStructs[battler].healBlockTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; + gBattleMons[battler].volatiles.healBlock = FALSE; BattleScriptExecute(BattleScript_BufferEndTurn); PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_HEAL_BLOCK); effect = TRUE; @@ -996,9 +996,9 @@ static bool32 HandleEndTurnEmbargo(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_EMBARGO && gDisableStructs[battler].embargoTimer == gBattleTurnCounter) + if (gBattleMons[battler].volatiles.embargo && gDisableStructs[battler].embargoTimer == gBattleTurnCounter) { - gStatuses3[battler] &= ~STATUS3_EMBARGO; + gBattleMons[battler].volatiles.embargo = FALSE; BattleScriptExecute(BattleScript_EmbargoEndTurn); effect = TRUE; } @@ -1014,10 +1014,11 @@ static bool32 HandleEndTurnYawn(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (gStatuses3[battler] & STATUS3_YAWN) + if (gBattleMons[battler].volatiles.yawn > 0) { - gStatuses3[battler] -= STATUS3_YAWN_TURN(1); - if (!(gStatuses3[battler] & STATUS3_YAWN) && !(gBattleMons[battler].status1 & STATUS1_ANY) + gBattleMons[battler].volatiles.yawn--; + if (!gBattleMons[battler].volatiles.yawn + && !(gBattleMons[battler].status1 & STATUS1_ANY) && ability != ABILITY_VITAL_SPIRIT && ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(battler) @@ -1064,12 +1065,12 @@ static bool32 HandleEndTurnPerishSong(u32 battler) gBattleStruct->turnEffectsBattlerId++; - if (IsBattlerAlive(battler) && gStatuses3[battler] & STATUS3_PERISH_SONG) + if (IsBattlerAlive(battler) && gBattleMons[battler].volatiles.perishSong) { PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[battler].perishSongTimer); if (gDisableStructs[battler].perishSongTimer == 0) { - gStatuses3[battler] &= ~STATUS3_PERISH_SONG; + gBattleMons[battler].volatiles.perishSong = FALSE; gBattleStruct->moveDamage[battler] = gBattleMons[battler].hp; BattleScriptExecute(BattleScript_PerishSongTakesLife); } diff --git a/src/battle_main.c b/src/battle_main.c index ac60bab82a..b5bba9eebe 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -193,7 +193,6 @@ EWRAM_DATA u32 gHitMarker = 0; EWRAM_DATA u8 gBideTarget[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u32 gSideStatuses[NUM_BATTLE_SIDES] = {0}; EWRAM_DATA struct SideTimer gSideTimers[NUM_BATTLE_SIDES] = {0}; -EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u16 gPauseCounterBattle = 0; EWRAM_DATA u16 gPaydayMoney = 0; @@ -3025,7 +3024,6 @@ static void BattleStartClearSetData(void) for (i = 0; i < MAX_BATTLERS_COUNT; i++) { - gStatuses3[i] = 0; gDisableStructs[i].isFirstTurn = 2; gLastMoves[i] = MOVE_NONE; gLastLandedMoves[i] = MOVE_NONE; @@ -3148,9 +3146,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) { if (gBattleMons[i].volatiles.escapePrevention && gDisableStructs[i].battlerPreventingEscape == battler) gBattleMons[i].volatiles.escapePrevention = FALSE; - if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].battlerWithSureHit == battler) + if (gBattleMons[i].volatiles.lockOn && gDisableStructs[i].battlerWithSureHit == battler) { - gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; + gBattleMons[i].volatiles.lockOn = 0; gDisableStructs[i].battlerWithSureHit = 0; } } @@ -3168,26 +3166,19 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) * gBattleMons[battler].volatiles.escapePrevention = volatilesCopy->escapePrevention; * ...etc */ - gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED - | STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK - | STATUS3_AQUA_RING | STATUS3_POWER_TRICK); + for (i = 0; i < gBattlersCount; i++) { if (!IsBattlerAlly(battler, i) - && (gStatuses3[i] & STATUS3_ALWAYS_HITS) != 0 + && gBattleMons[i].volatiles.lockOn != 0 && (gDisableStructs[i].battlerWithSureHit == battler)) { - gStatuses3[i] &= ~STATUS3_ALWAYS_HITS; - gStatuses3[i] |= STATUS3_ALWAYS_HITS_TURN(2); + gBattleMons[i].volatiles.lockOn = 0; } } - if (gStatuses3[battler] & STATUS3_POWER_TRICK) + if (gBattleMons[battler].volatiles.powerTrick) SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, i); } - else - { - gStatuses3[battler] = 0; - } for (i = 0; i < gBattlersCount; i++) { @@ -3301,8 +3292,11 @@ const u8* FaintClearSetData(u32 battler) for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; + bool32 keepGastroAcid = FALSE; + if (gBattleMons[battler].volatiles.gastroAcid) + keepGastroAcid = TRUE; memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); - gStatuses3[battler] &= STATUS3_GASTRO_ACID; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. + gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. for (i = 0; i < gBattlersCount; i++) { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8bd6d3ab6a..86cb831bb0 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -369,7 +369,7 @@ static void Cmd_jumpifvolatile(void); static void Cmd_jumpifability(void); static void Cmd_jumpifsideaffecting(void); static void Cmd_jumpifstat(void); -static void Cmd_jumpifstatus3condition(void); +static void Cmd_unused_0x21(void); static void Cmd_jumpbasedontype(void); static void Cmd_getexp(void); static void Cmd_checkteamslost(void); @@ -467,7 +467,7 @@ static void Cmd_setseeded(void); static void Cmd_manipulatedamage(void); static void Cmd_trysetrest(void); static void Cmd_jumpifnotfirstturn(void); -static void Cmd_setmiracleeye(void); +static void Cmd_unused_0x83(void); static void Cmd_jumpifuproarwakes(void); static void Cmd_stockpile(void); static void Cmd_stockpiletobasedamage(void); @@ -535,7 +535,7 @@ static void Cmd_trysetfutureattack(void); static void Cmd_trydobeatup(void); static void Cmd_setsemiinvulnerablebit(void); static void Cmd_tryfiretwoturnmovenowbyeffect(void); -static void Cmd_setminimize(void); +static void Cmd_unused_0xC7(void); static void Cmd_unused_c8(void); static void Cmd_trymemento(void); static void Cmd_setforcedtarget(void); @@ -557,7 +557,7 @@ static void Cmd_setroom(void); static void Cmd_tryswapabilities(void); static void Cmd_tryimprison(void); static void Cmd_setstealthrock(void); -static void Cmd_setuserstatus3(void); +static void Cmd_trysetvolatile(void); static void Cmd_assistattackselect(void); static void Cmd_trysetmagiccoat(void); static void Cmd_trysetsnatch(void); @@ -628,7 +628,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_jumpifability, //0x1E Cmd_jumpifsideaffecting, //0x1F Cmd_jumpifstat, //0x20 - Cmd_jumpifstatus3condition, //0x21 + Cmd_unused_0x21, //0x21 Cmd_jumpbasedontype, //0x22 Cmd_getexp, //0x23 Cmd_checkteamslost, //0x24 @@ -726,7 +726,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_manipulatedamage, //0x80 Cmd_trysetrest, //0x81 Cmd_jumpifnotfirstturn, //0x82 - Cmd_setmiracleeye, //0x83 + Cmd_unused_0x83, //0x83 Cmd_jumpifuproarwakes, //0x84 Cmd_stockpile, //0x85 Cmd_stockpiletobasedamage, //0x86 @@ -794,7 +794,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_trydobeatup, //0xC4 Cmd_setsemiinvulnerablebit, //0xC5 Cmd_tryfiretwoturnmovenowbyeffect, //0xC6 - Cmd_setminimize, //0xC7 + Cmd_unused_0xC7, //0xC7 Cmd_unused_c8, //0xC8 Cmd_trymemento, //0xC9 Cmd_setforcedtarget, //0xCA @@ -816,7 +816,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_tryswapabilities, //0xDA Cmd_tryimprison, //0xDB Cmd_setstealthrock, //0xDC - Cmd_setuserstatus3, //0xDD + Cmd_trysetvolatile, //0xDD Cmd_assistattackselect, //0xDE Cmd_trysetmagiccoat, //0xDF Cmd_trysetsnatch, //0xE0 @@ -1364,7 +1364,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u if (move == NO_ACC_CALC_CHECK_LOCK_ON) { - if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) + if (gBattleMons[gBattlerTarget].volatiles.lockOn && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) gBattlescriptCurrInstr = nextInstr; else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)) gBattlescriptCurrInstr = failInstr; @@ -1621,7 +1621,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA { critChance = CRITICAL_HIT_BLOCKED; } - else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS + else if (gBattleMons[battlerAtk].volatiles.laserFocus || MoveAlwaysCrits(move) || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)) { @@ -1704,7 +1704,7 @@ s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec } // Guaranteed crits - else if (gStatuses3[battlerAtk] & STATUS3_LASER_FOCUS + else if (gBattleMons[battlerAtk].volatiles.laserFocus || MoveAlwaysCrits(move) || (abilityAtk == ABILITY_MERCILESS && gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)) { @@ -3565,9 +3565,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_AromaVeilProtectsRet; } - else if (!(gStatuses3[gEffectBattler] & STATUS3_HEAL_BLOCK)) + else if (!gBattleMons[gEffectBattler].volatiles.healBlock) { - gStatuses3[gEffectBattler] |= STATUS3_HEAL_BLOCK; + gBattleMons[gEffectBattler].volatiles.healBlock = TRUE; gDisableStructs[gEffectBattler].healBlockTimer = gBattleTurnCounter + 2; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_EffectPsychicNoise; @@ -3637,10 +3637,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattlescriptCurrInstr = BattleScript_MoveEffectHaze; break; case MOVE_EFFECT_LEECH_SEED: - if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !(gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED)) + if (!IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) && !gBattleMons[gBattlerTarget].volatiles.leechSeed) { - gStatuses3[gBattlerTarget] |= gBattlerAttacker; - gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + gBattleMons[gBattlerTarget].volatiles.leechSeed = LEECHSEEDED_BY(gBattlerAttacker); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectLeechSeed; } @@ -3944,11 +3943,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai } case MOVE_EFFECT_YAWN_FOE: { - if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN) + if (gBattleMons[gBattlerTarget].volatiles.yawn == 0 && CanBeSlept(gBattlerTarget, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE) && RandomPercentage(RNG_G_MAX_SNOOZE, 50)) { - gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); + gBattleMons[gBattlerTarget].volatiles.yawn = 2; BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_EffectYawnSuccess; } @@ -4248,7 +4247,7 @@ static void Cmd_tryfaintmon(void) gBattleStruct->moveDamage[destinyBondBattler] = gBattleMons[destinyBondBattler].hp; gBattlescriptCurrInstr = BattleScript_DestinyBondTakesLife; } - if ((gStatuses3[gBattlerTarget] & STATUS3_GRUDGE) + if (gBattleMons[gBattlerTarget].volatiles.grudge && !(gHitMarker & HITMARKER_GRUDGE) && !IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) @@ -4340,7 +4339,7 @@ static void Cmd_jumpifvolatile(void) u8 battler = GetBattlerForBattleScript(cmd->battler); const u8 *jumpInstr = cmd->jumpInstr; - if (GetMonVolatile(battler, cmd->_volatile) && IsBattlerAlive(battler)) + if (GetBattlerVolatile(battler, cmd->_volatile) != 0 && IsBattlerAlive(battler)) gBattlescriptCurrInstr = jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -4422,25 +4421,8 @@ static void Cmd_jumpifstat(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifstatus3condition(void) +static void Cmd_unused_0x21(void) { - CMD_ARGS(u8 battler, u32 flags, bool8 jumpIfTrue, const u8 *jumpInstr); - - u32 battler = GetBattlerForBattleScript(cmd->battler); - if (cmd->jumpIfTrue) - { - if ((gStatuses3[battler] & cmd->flags) != 0) - gBattlescriptCurrInstr = cmd->nextInstr; - else - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - if ((gStatuses3[battler] & cmd->flags) != 0) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; - } } static void Cmd_jumpbasedontype(void) @@ -4772,7 +4754,7 @@ static void Cmd_getexp(void) if (battler != 0xFF) { CopyMonLevelAndBaseStatsToBattleMon(battler, &gPlayerParty[*expMonId]); - if (gStatuses3[battler] & STATUS3_POWER_TRICK) + if (gBattleMons[battler].volatiles.powerTrick) SWAP(gBattleMons[battler].attack, gBattleMons[battler].defense, temp); } @@ -5786,7 +5768,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) { BattleScriptCall(BattleScript_AbilityPreventsPhasingOutRet); } - else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED) + else if (gBattleMons[gBattlerTarget].volatiles.root) { BattleScriptCall(BattleScript_PrintMonIsRootedRet); } @@ -5808,9 +5790,10 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) && IsBattlerAlive(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { + gBattleMons[gBattlerTarget].volatiles.smackDown = TRUE; + gBattleMons[gBattlerTarget].volatiles.telekinesis = FALSE; + gBattleMons[gBattlerTarget].volatiles.magnetRise = FALSE; gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; - gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS); BattleScriptCall(BattleScript_MoveEffectSmackDown); effect = TRUE; } @@ -6067,7 +6050,7 @@ static void Cmd_moveend(void) { case EFFECT_ABSORB: case EFFECT_DREAM_EATER: - if (!(gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK) + if (!gBattleMons[gBattlerAttacker].volatiles.healBlock && gBattleStruct->moveDamage[gBattlerTarget] > 0 && IsBattlerAlive(gBattlerAttacker)) { @@ -6927,7 +6910,7 @@ static void Cmd_moveend(void) if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP); + gBattleMons[gBattlerAttacker].volatiles.charge = FALSE; // check if Stellar type boost should be used up if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA && GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR @@ -7040,13 +7023,13 @@ static void Cmd_sethealblock(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + if (gBattleMons[gBattlerTarget].volatiles.healBlock) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_HEAL_BLOCK; + gBattleMons[gBattlerTarget].volatiles.healBlock = TRUE; gDisableStructs[gBattlerTarget].healBlockTimer = gBattleTurnCounter + 5; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -8583,7 +8566,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) { if (GetItemPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) + && !gBattleMons[battler].volatiles.healBlock && GetBattlerPartyState(battler)->ateBerry && !IsBattlerAtMaxHp(battler)) { @@ -9769,7 +9752,7 @@ static void Cmd_setseeded(void) { CMD_ARGS(); - if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gStatuses3[gBattlerTarget] & STATUS3_LEECHSEED) + if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT || gBattleMons[gBattlerTarget].volatiles.leechSeed) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_MISS; @@ -9781,8 +9764,7 @@ static void Cmd_setseeded(void) } else { - gStatuses3[gBattlerTarget] |= gBattlerAttacker; - gStatuses3[gBattlerTarget] |= STATUS3_LEECHSEED; + gBattleMons[gBattlerTarget].volatiles.leechSeed = LEECHSEEDED_BY(gBattlerAttacker); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LEECH_SEED_SET; } @@ -9864,19 +9846,8 @@ static void Cmd_jumpifnotfirstturn(void) gBattlescriptCurrInstr = jumpInstr; } -static void Cmd_setmiracleeye(void) +static void Cmd_unused_0x83(void) { - CMD_ARGS(const u8 *failInstr); - - if (!(gStatuses3[gBattlerTarget] & STATUS3_MIRACLE_EYED)) - { - gStatuses3[gBattlerTarget] |= STATUS3_MIRACLE_EYED; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } } bool8 UproarWakeUpCheck(u8 battler) @@ -10953,7 +10924,7 @@ static void Cmd_tryKO(void) else { if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level - && ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS + && ((gBattleMons[gBattlerTarget].volatiles.lockOn && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))) @@ -11625,9 +11596,7 @@ static void Cmd_settypetorandomresistance(void) static void Cmd_setalwayshitflag(void) { CMD_ARGS(); - - gStatuses3[gBattlerTarget] &= ~STATUS3_ALWAYS_HITS; - gStatuses3[gBattlerTarget] |= STATUS3_ALWAYS_HITS_TURN(2); + gBattleMons[gBattlerTarget].volatiles.lockOn = 2; gDisableStructs[gBattlerTarget].battlerWithSureHit = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12021,7 +11990,7 @@ static void Cmd_trysetperishsong(void) for (i = 0; i < gBattlersCount; i++) { - if (gStatuses3[i] & STATUS3_PERISH_SONG + if (gBattleMons[i].volatiles.perishSong || GetBattlerAbility(i) == ABILITY_SOUNDPROOF || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE) || gBattleMons[i].volatiles.semiInvulnerable == STATE_COMMANDER) @@ -12030,7 +11999,7 @@ static void Cmd_trysetperishsong(void) } else { - gStatuses3[i] |= STATUS3_PERISH_SONG; + gBattleMons[i].volatiles.perishSong = TRUE; gDisableStructs[i].perishSongTimer = 3; } } @@ -12111,13 +12080,13 @@ static void Cmd_setembargo(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_EMBARGO) + if (gBattleMons[gBattlerTarget].volatiles.embargo) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerTarget] |= STATUS3_EMBARGO; + gBattleMons[gBattlerTarget].volatiles.embargo = TRUE; gDisableStructs[gBattlerTarget].embargoTimer = gBattleTurnCounter + 5; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12355,10 +12324,9 @@ static void Cmd_rapidspinfree(void) PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gBattlerAttacker]); BattleScriptCall(BattleScript_WrapFree); } - else if (gStatuses3[gBattlerAttacker] & STATUS3_LEECHSEED) + else if (gBattleMons[gBattlerAttacker].volatiles.leechSeed) { - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED; - gStatuses3[gBattlerAttacker] &= ~STATUS3_LEECHSEED_BATTLER; + gBattleMons[gBattlerAttacker].volatiles.leechSeed = 0; BattleScriptCall(BattleScript_LeechSeedFree); } else if (AreAnyHazardsOnSide(atkSide)) @@ -12617,14 +12585,8 @@ static void Cmd_tryfiretwoturnmovenowbyeffect(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_setminimize(void) +static void Cmd_unused_0xC7(void) { - CMD_ARGS(); - - if (gHitMarker & HITMARKER_OBEYS) - gStatuses3[gBattlerAttacker] |= STATUS3_MINIMIZED; - - gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_unused_c8(void) @@ -12678,7 +12640,7 @@ static void Cmd_setcharge(void) CMD_ARGS(u8 battler); u8 battler = GetBattlerForBattleScript(cmd->battler); - gStatuses3[battler] |= STATUS3_CHARGED_UP; + gBattleMons[battler].volatiles.charge = TRUE; if (B_CHARGE < GEN_9) gDisableStructs[battler].chargeTimer = 2; else @@ -12968,7 +12930,7 @@ static void Cmd_trywish(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + if (gBattleMons[gBattlerTarget].volatiles.healBlock) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -13002,6 +12964,7 @@ static void Cmd_settoxicspikes(void) } } +// TODO: possible failing bug for when gastro acid is already active static void Cmd_setgastroacid(void) { CMD_ARGS(const u8 *failInstr); @@ -13015,7 +12978,7 @@ static void Cmd_setgastroacid(void) if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; - gStatuses3[gBattlerTarget] |= STATUS3_GASTRO_ACID; + gBattleMons[gBattlerTarget].volatiles.gastroAcid = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -13024,7 +12987,7 @@ static void Cmd_setyawn(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & STATUS3_YAWN + if (gBattleMons[gBattlerTarget].volatiles.yawn || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) { gBattlescriptCurrInstr = cmd->failInstr; @@ -13043,7 +13006,7 @@ static void Cmd_setyawn(void) } else { - gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2); + gBattleMons[gBattlerTarget].volatiles.yawn = 2; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -13139,13 +13102,13 @@ static void Cmd_tryimprison(void) { CMD_ARGS(const u8 *failInstr); - if ((gStatuses3[gBattlerAttacker] & STATUS3_IMPRISONED_OTHERS)) + if (gBattleMons[gBattlerAttacker].volatiles.imprison) { gBattlescriptCurrInstr = cmd->failInstr; } else if (B_IMPRISON >= GEN_5) { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattleMons[gBattlerAttacker].volatiles.imprison = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13171,7 +13134,7 @@ static void Cmd_tryimprison(void) } if (attackerMoveId != MAX_MON_MOVES) { - gStatuses3[gBattlerAttacker] |= STATUS3_IMPRISONED_OTHERS; + gBattleMons[gBattlerAttacker].volatiles.imprison = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; break; } @@ -13198,23 +13161,30 @@ static void Cmd_setstealthrock(void) } } -static void Cmd_setuserstatus3(void) +static void Cmd_trysetvolatile(void) { - CMD_ARGS(u32 flags, const u8 *failInstr); + CMD_ARGS(u8 battler, u8 _volatile, const u8 *failInstr); - u32 flags = cmd->flags; + u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gStatuses3[gBattlerAttacker] & flags) + if (GetBattlerVolatile(battler, cmd->_volatile) != 0) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gStatuses3[gBattlerAttacker] |= flags; - if (flags & STATUS3_MAGNET_RISE) - gDisableStructs[gBattlerAttacker].magnetRiseTimer = gBattleTurnCounter + 5; - if (flags & STATUS3_LASER_FOCUS) - gDisableStructs[gBattlerAttacker].laserFocusTimer = gBattleTurnCounter + 2; + SetMonVolatile(battler, cmd->_volatile, TRUE); + switch (cmd->_volatile) + { + case VOLATILE_MAGNET_RISE: + gDisableStructs[battler].magnetRiseTimer = gBattleTurnCounter + 5; + break; + case VOLATILE_LASER_FOCUS: + gDisableStructs[battler].laserFocusTimer = gBattleTurnCounter + 2; + break; + default: + break; + } gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -14459,7 +14429,9 @@ static void Cmd_settelekinesis(void) { CMD_ARGS(const u8 *failInstr); - if (gStatuses3[gBattlerTarget] & (STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN) + if (gBattleMons[gBattlerTarget].volatiles.telekinesis + || gBattleMons[gBattlerTarget].volatiles.root + || gBattleMons[gBattlerTarget].volatiles.smackDown || gFieldStatuses & STATUS_FIELD_GRAVITY || IsTelekinesisBannedSpecies(gBattleMons[gBattlerTarget].species)) { @@ -14467,7 +14439,7 @@ static void Cmd_settelekinesis(void) } else { - gStatuses3[gBattlerTarget] |= STATUS3_TELEKINESIS; + gBattleMons[gBattlerTarget].volatiles.telekinesis = TRUE; gDisableStructs[gBattlerTarget].telekinesisTimer = gBattleTurnCounter + 3; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16901,7 +16873,8 @@ void BS_GravityOnAirborneMons(void) CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_GRAVITY_ON_AIRBORNE); gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE; - gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS); + gBattleMons[gBattlerTarget].volatiles.magnetRise = FALSE; + gBattleMons[gBattlerTarget].volatiles.telekinesis = FALSE; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -17674,7 +17647,7 @@ void BS_PowerTrick(void) { NATIVE_ARGS(); u32 temp; - gStatuses3[gBattlerAttacker] ^= STATUS3_POWER_TRICK; + gBattleMons[gBattlerAttacker].volatiles.powerTrick = !gBattleMons[gBattlerAttacker].volatiles.powerTrick; SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerAttacker].defense, temp); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -18297,9 +18270,9 @@ void BS_CureCertainStatuses(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; } // Check heal block - if (gStatuses3[gBattlerTarget] & STATUS3_HEAL_BLOCK) + if (gBattleMons[gBattlerTarget].volatiles.healBlock) { - gStatuses3[gBattlerTarget] &= ~(STATUS3_HEAL_BLOCK); + gBattleMons[gBattlerTarget].volatiles.healBlock = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; } // Check disable diff --git a/src/battle_tv.c b/src/battle_tv.c index e23712beab..6504a3cc43 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -591,7 +591,7 @@ void BattleTv_SetDataBasedOnMove(u16 move, u16 weatherFlags, struct DisableStruc tvPtr->side[atkSide].usedMoveSlot = moveSlot; AddMovePoints(PTS_MOVE_EFFECT, moveSlot, move, 0); AddPointsBasedOnWeather(weatherFlags, move, moveSlot); - if (gStatuses3[gBattlerAttacker] & STATUS3_CHARGED_UP) + if (gBattleMons[gBattlerAttacker].volatiles.charge) AddMovePoints(PTS_ELECTRIC, move, moveSlot, 0); if (move == MOVE_WISH) diff --git a/src/battle_util.c b/src/battle_util.c index 13f830d953..8eb6a89bc1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1281,7 +1281,7 @@ static bool32 IsGravityPreventingMove(u32 move) bool32 IsHealBlockPreventingMove(u32 battler, u32 move) { - if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!gBattleMons[battler].volatiles.healBlock) return FALSE; return IsHealingMove(move); @@ -1656,7 +1656,7 @@ u8 GetImprisonedMovesCount(u32 battler, u16 move) for (i = 0; i < gBattlersCount; i++) { - if (battlerSide != GetBattlerSide(i) && gStatuses3[i] & STATUS3_IMPRISONED_OTHERS) + if (battlerSide != GetBattlerSide(i) && gBattleMons[i].volatiles.imprison) { s32 j; for (j = 0; j < MAX_MON_MOVES; j++) @@ -1892,7 +1892,7 @@ void SetAtkCancellerForCalledMove(void) static enum MoveCanceller CancellerFlags(void) { gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE; - gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE; + gBattleMons[gBattlerAttacker].volatiles.grudge = FALSE; gBattleMons[gBattlerAttacker].volatiles.glaiveRush = FALSE; return MOVE_STEP_SUCCESS; } @@ -2095,7 +2095,7 @@ static enum MoveCanceller CancellerDisabled(void) static enum MoveCanceller CancellerVolatileBlocked(void) { - if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) + if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gBattleMons[gBattlerAttacker].volatiles.healBlock && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove)) { gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE; gBattleScripting.battler = gBattlerAttacker; @@ -3173,7 +3173,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 return FALSE; case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY: gBattleStruct->pledgeMove = FALSE; - if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK)) + if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gBattleMons[battlerDef].volatiles.healBlock)) { if ((gProtectStructs[battlerAtk].notFirstStrike)) battleScript = BattleScript_MonMadeMoveUseless; @@ -4096,7 +4096,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() - && !(gStatuses3[partner] & STATUS3_HEAL_BLOCK) + && !gBattleMons[partner].volatiles.healBlock && gBattleMons[partner].hp < gBattleMons[partner].maxHP && IsBattlerAlive(partner)) { @@ -4213,7 +4213,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IsBattlerAtMaxHp(battler) && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND && gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && !gBattleMons[battler].volatiles.healBlock) { BattleScriptPushCursorAndCallback(BattleScript_IceBodyHeal); gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; @@ -4230,7 +4230,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_RAIN_DISH: if (IsBattlerWeatherAffected(battler, B_WEATHER_RAIN) && !IsBattlerAtMaxHp(battler) - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && !gBattleMons[battler].volatiles.healBlock) { BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates); gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (gLastUsedAbility == ABILITY_RAIN_DISH ? 16 : 8); @@ -4832,14 +4832,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) - && !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG)) + && !gBattleMons[gBattlerAttacker].volatiles.perishSong) { - if (!(gStatuses3[battler] & STATUS3_PERISH_SONG)) + if (!gBattleMons[battler].volatiles.perishSong) { - gStatuses3[battler] |= STATUS3_PERISH_SONG; + gBattleMons[battler].volatiles.perishSong = TRUE; gDisableStructs[battler].perishSongTimer = 3; } - gStatuses3[gBattlerAttacker] |= STATUS3_PERISH_SONG; + gBattleMons[gBattlerAttacker].volatiles.perishSong = TRUE; gDisableStructs[gBattlerAttacker].perishSongTimer = 3; BattleScriptCall(BattleScript_PerishBodyActivates); effect++; @@ -5339,7 +5339,7 @@ bool32 IsNeutralizingGasOnField(void) for (i = 0; i < gBattlersCount; i++) { - if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gStatuses3[i] & STATUS3_GASTRO_ACID)) + if (IsBattlerAlive(i) && gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gBattleMons[i].volatiles.gastroAcid) return TRUE; } @@ -5348,7 +5348,7 @@ bool32 IsNeutralizingGasOnField(void) bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) { - if (gStatuses3[battler] & STATUS3_GASTRO_ACID) + if (gBattleMons[battler].volatiles.gastroAcid) return FALSE; if (ability == ABILITY_MOLD_BREAKER @@ -5400,7 +5400,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS { // Edge case: pokemon under the effect of gastro acid transforms into a pokemon with Comatose (Todo: verify how other unsuppressable abilities behave) if (gBattleMons[battler].volatiles.transformed - && gStatuses3[battler] & STATUS3_GASTRO_ACID + && gBattleMons[battler].volatiles.gastroAcid && gBattleMons[battler].ability == ABILITY_COMATOSE) return ABILITY_NONE; @@ -5410,7 +5410,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS return gBattleMons[battler].ability; } - if (gStatuses3[battler] & STATUS3_GASTRO_ACID) + if (gBattleMons[battler].volatiles.gastroAcid) return ABILITY_NONE; if (!hasAbilityShield @@ -5502,7 +5502,7 @@ bool32 CanBattlerEscape(u32 battler) // no ability check return FALSE; else if (gBattleMons[battler].volatiles.wrapped) return FALSE; - else if (gStatuses3[battler] & STATUS3_ROOTED) + else if (gBattleMons[battler].volatiles.root) return FALSE; else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK) return FALSE; @@ -5875,7 +5875,7 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, enum ItemCaseId caseID) { if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId); @@ -6003,7 +6003,7 @@ static enum ItemEffect TrySetEnigmaBerry(u32 battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && ((IsBattlerTurnDamaged(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { gBattleScripting.battler = battler; gBattleStruct->moveDamage[battler] = (gBattleMons[battler].maxHP * 25 / 100) * -1; @@ -6125,7 +6125,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, enum ItemCaseId caseID) static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 percentHeal) { if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock) && HasEnoughHpToEatBerry(battler, 2, itemId)) { if (percentHeal) @@ -6196,9 +6196,9 @@ static bool32 GetMentalHerbEffect(u32 battler) ret = TRUE; } // Check heal block - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + if (gBattleMons[battler].volatiles.healBlock) { - gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; + gBattleMons[battler].volatiles.healBlock = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; ret = TRUE; } @@ -6789,7 +6789,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) case HOLD_EFFECT_LEFTOVERS: LEFTOVERS: if (gBattleMons[battler].hp < gBattleMons[battler].maxHP - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) @@ -7025,7 +7025,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler) && IsBattlerAlive(gBattlerAttacker) && GetMoveEffect(gCurrentMove) != EFFECT_FUTURE_SIGHT && GetMoveEffect(gCurrentMove) != EFFECT_PAIN_SPLIT - && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) + && (B_HEAL_BLOCKING < GEN_5 || !gBattleMons[battler].volatiles.healBlock)) { gLastUsedItem = atkItem; gPotentialItemEffectBattler = gBattlerAttacker; @@ -7299,7 +7299,7 @@ void ClearVariousBattlerFlags(u32 battler) gDisableStructs[battler].furyCutterCounter = 0; gBattleMons[battler].volatiles.destinyBond = FALSE; gBattleMons[battler].volatiles.glaiveRush = FALSE; - gStatuses3[battler] &= ~STATUS3_GRUDGE; + gBattleMons[battler].volatiles.grudge = FALSE; } void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands @@ -7539,11 +7539,11 @@ enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegati { if (checkNegating) { - if (gStatuses3[battler] & STATUS3_EMBARGO) + if (gBattleMons[battler].volatiles.embargo) return HOLD_EFFECT_NONE; if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM) return HOLD_EFFECT_NONE; - if (checkAbility && GetBattlerAbility(battler) == ABILITY_KLUTZ && !(gStatuses3[battler] & STATUS3_GASTRO_ACID)) + if (checkAbility && GetBattlerAbility(battler) == ABILITY_KLUTZ && !gBattleMons[battler].volatiles.gastroAcid) return HOLD_EFFECT_NONE; } @@ -7708,13 +7708,13 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY) return TRUE; - if (B_ROOTED_GROUNDING >= GEN_4 && gStatuses3[battler] & STATUS3_ROOTED) + if (B_ROOTED_GROUNDING >= GEN_4 && gBattleMons[battler].volatiles.root) return TRUE; - if (gStatuses3[battler] & STATUS3_SMACKED_DOWN) + if (gBattleMons[battler].volatiles.smackDown) return TRUE; - if (gStatuses3[battler] & STATUS3_TELEKINESIS) + if (gBattleMons[battler].volatiles.telekinesis) return FALSE; - if (gStatuses3[battler] & STATUS3_MAGNET_RISE) + if (gBattleMons[battler].volatiles.magnetRise) return FALSE; if (holdEffect == HOLD_EFFECT_AIR_BALLOON) return FALSE; @@ -8300,7 +8300,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (gSpecialStatuses[battlerAtk].gemBoost) modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam))); - if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) + if (gBattleMons[battlerAtk].volatiles.charge && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); if (GetMoveEffect(gChosenMove) == EFFECT_ME_FIRST) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); @@ -9091,7 +9091,7 @@ static inline uq4_12_t GetZMaxMoveAgainstProtectionModifier(struct DamageContext static inline uq4_12_t GetMinimizeModifier(u32 move, u32 battlerDef) { - if (MoveIncreasesPowerToMinimizedTargets(move) && gStatuses3[battlerDef] & STATUS3_MINIMIZED) + if (MoveIncreasesPowerToMinimizedTargets(move) && gBattleMons[battlerDef].volatiles.minimize) return UQ_4_12(2.0); return UQ_4_12(1.0); } @@ -9569,7 +9569,7 @@ static inline void MulByTypeEffectiveness(struct DamageContext *ctx, uq4_12_t *m RecordAbilityBattle(ctx->battlerAtk, ctx->abilityAtk); } - if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gStatuses3[ctx->battlerDef] & STATUS3_MIRACLE_EYED && mod == UQ_4_12(0.0)) + if (ctx->moveType == TYPE_PSYCHIC && defType == TYPE_DARK && gBattleMons[ctx->battlerDef].volatiles.miracleEye && mod == UQ_4_12(0.0)) mod = UQ_4_12(1.0); if (GetMoveEffect(ctx->move) == EFFECT_SUPER_EFFECTIVE_ON_ARG && defType == GetMoveArgType(ctx->move)) mod = UQ_4_12(2.0); @@ -10524,7 +10524,7 @@ bool32 CanFling(u32 battler) if (item == ITEM_NONE || (B_KLUTZ_FLING_INTERACTION >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ) || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM - || gStatuses3[battler] & STATUS3_EMBARGO + || gBattleMons[battler].volatiles.embargo || GetFlingPowerFromItemId(item) == 0 || !CanBattlerGetOrLoseItem(battler, item)) return FALSE; @@ -10843,7 +10843,7 @@ bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move) { if (GetMoveEffect(move) == EFFECT_HIT_ENEMY_HEAL_ALLY && IsBattlerAlly(battlerAtk, battlerDef) - && gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK) + && gBattleMons[battlerAtk].volatiles.healBlock) return FALSE; // Pokémon affected by Heal Block cannot target allies with Pollen Puff if (IsBattlerAlly(battlerAtk, battlerDef) && (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX || IsGimmickSelected(battlerAtk, GIMMICK_DYNAMAX))) @@ -11468,7 +11468,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) // Gets the value of a volatile status flag for a certain battler // Primarily used for the debug menu and scripts. Outside of it explicit references are preferred -u32 GetMonVolatile(u32 battler, enum Volatile _volatile) +u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile) { switch (_volatile) { @@ -11608,7 +11608,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u enum BattleMoveEffects moveEffect = GetMoveEffect(move); u32 nonVolatileStatus = GetMoveNonVolatileStatus(move); - if ((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) + if ((gBattleMons[battlerDef].volatiles.lockOn && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk) || (B_TOXIC_NEVER_MISS >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) || gBattleMons[battlerDef].volatiles.glaiveRush) { @@ -11630,7 +11630,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u ability = ABILITY_NO_GUARD; } // If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits. - else if (gStatuses3[battlerDef] & STATUS3_TELEKINESIS + else if (gBattleMons[battlerDef].volatiles.telekinesis && !IsSemiInvulnerable(battlerDef, CHECK_ALL) && moveEffect != EFFECT_OHKO && moveEffect != EFFECT_SHEER_COLD) @@ -11658,7 +11658,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u } } else if (B_MINIMIZE_DMG_ACC >= GEN_6 - && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) + && gBattleMons[battlerDef].volatiles.minimize && MoveIncreasesPowerToMinimizedTargets(move)) { effect = TRUE; @@ -11703,7 +11703,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (defAbility == ABILITY_UNAWARE) accStage = DEFAULT_STAT_STAGE; - if (gBattleMons[battlerDef].volatiles.foresight || gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) + if (gBattleMons[battlerDef].volatiles.foresight || gBattleMons[battlerDef].volatiles.miracleEye) buff = accStage; else buff = accStage + DEFAULT_STAT_STAGE - evasionStage; diff --git a/src/item_use.c b/src/item_use.c index 5895016399..a086737bd9 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1244,8 +1244,8 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon) u16 hp = GetMonData(mon, MON_DATA_HP); // Embargo Check - if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO) - || (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO)) + if ((gPartyMenu.slotId == 0 && gBattleMons[B_POSITION_PLAYER_LEFT].volatiles.embargo) + || (gPartyMenu.slotId == 1 && gBattleMons[B_POSITION_PLAYER_RIGHT].volatiles.embargo)) { return TRUE; } From eab10dc2f0a2a19f53dafbcf394dcf4b3935e28d Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 12 Aug 2025 04:30:14 -0400 Subject: [PATCH 206/283] Fix AI's KO evaluation getting messed up by priority (#7533) --- include/battle_ai_util.h | 1 + src/battle_ai_main.c | 92 +++++++++++++++------------ src/battle_ai_util.c | 48 +++++++++----- test/battle/ai/ai.c | 29 +++++---- test/battle/ai/ai_flag_predict_move.c | 15 +++++ test/battle/ai/ai_switching.c | 15 +++++ 6 files changed, 130 insertions(+), 70 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 118fbf5984..5759427f4b 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -296,6 +296,7 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsBattlerItemEnabled(u32 battler); bool32 IsBattlerPredictedToSwitch(u32 battler); u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); +u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicData *aiData); bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); bool32 IsNaturalEnemy(u32 speciesAttacker, u32 speciesTarget); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 430412966b..78f1b72b28 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -742,7 +742,10 @@ static u32 ChooseMoveOrAction_Singles(u32 battler) u64 flags = gAiThinkingStruct->aiFlags[battler]; u32 opposingBattler = GetOppositeBattler(battler); + gAiThinkingStruct->aiLogicId = 0; + gAiThinkingStruct->movesetIndex = 0; gAiLogicData->partnerMove = 0; // no ally + while (flags != 0) { if (flags & 1) @@ -1078,6 +1081,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 i; u32 weather; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); u32 abilityAtk = aiData->abilities[battlerAtk]; u32 abilityDef = aiData->abilities[battlerDef]; s32 atkPriority = GetBattleMovePriority(battlerAtk, abilityAtk, move); @@ -1088,7 +1092,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); - if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) RETURN_SCORE_MINUS(10); if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk)) @@ -1320,7 +1324,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (moveEffect) { case EFFECT_HIT: // only applies to Vital Throw - if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && aiData->hpPercents[battlerAtk] < 40) + if (GetBattleMovePriority(battlerAtk, aiData->abilities[battlerAtk], move) < 0 && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && aiData->hpPercents[battlerAtk] < 40) ADJUST_SCORE(-2); // don't want to move last break; default: @@ -1775,7 +1779,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to disable @@ -1797,7 +1801,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) ADJUST_SCORE(-10); // no anticipated move to encore @@ -2184,7 +2188,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SPITE: case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker should go first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker should go first { if (gLastMoves[battlerDef] == MOVE_NONE || gLastMoves[battlerDef] == 0xFFFF) @@ -2360,7 +2364,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // partner is going to set up hazards - && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // partner is going to set up before the potential Defog + && AI_IsFaster(BATTLE_PARTNER(battlerAtk), battlerAtk, aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // partner is going to set up before the potential Defog { ADJUST_SCORE(-10); break; // Don't use Defog if partner is going to set up hazards @@ -2388,7 +2392,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_SEMI_INVULNERABLE: if (predictedMove != MOVE_NONE - && AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && GetMoveEffect(predictedMove) == EFFECT_SEMI_INVULNERABLE) ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you @@ -2536,7 +2540,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_ME_FIRST: if (predictedMove != MOVE_NONE) { - if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail else if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); @@ -2712,7 +2716,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_ELECTRIFY: - if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) //|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); @@ -2744,7 +2748,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INSTRUCT: { u32 instructedMove; - if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = predictedMove; else instructedMove = gLastMoves[battlerDef]; @@ -2781,21 +2785,21 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_QUASH: if (!hasPartner - || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_AFTER_YOU: if (!IsTargetingPartner(battlerAtk, battlerDef) || !hasPartner - || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; case EFFECT_SUCKER_PUNCH: if ((HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_STATUS) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_CHANCE)) // Player has a status move || (IsBattleMoveStatus(predictedMove) && RandomPercentage(RNG_AI_SUCKER_PUNCH, SUCKER_PUNCH_PREDICTION_CHANCE) && (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_PREDICT_MOVE)) // AI actively predicting incoming status move - || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Opponent going first + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent going first ADJUST_SCORE(-10); break; case EFFECT_TAILWIND: @@ -2832,7 +2836,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_FLAIL: - if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) // Opponent should go first + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent should go first || aiData->hpPercents[battlerAtk] > 50) ADJUST_SCORE(-4); break; @@ -2867,7 +2871,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) else if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) ADJUST_SCORE(-10); else if (CanTargetFaintAi(battlerDef, battlerAtk) - && AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(-10); break; case EFFECT_JUNGLE_HEALING: @@ -2898,7 +2902,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 defPrio = GetBattleMovePriority(battlerDef, aiData->abilities[battlerDef], predictedMove); if (predictedMove == MOVE_NONE || IsBattleMoveStatus(predictedMove) - || AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) || defPrio < 1 || defPrio > 3) // Opponent going first or not using priority move ADJUST_SCORE(-10); @@ -2967,6 +2971,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u32 movesetIndex = gAiThinkingStruct->movesetIndex; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (IsTargetingPartner(battlerAtk, battlerDef)) return score; @@ -2978,7 +2983,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (CanIndexMoveFaintTarget(battlerAtk, battlerDef, movesetIndex, AI_ATTACKING) && effect != EFFECT_EXPLOSION && effect != EFFECT_MISTY_EXPLOSION) { - if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(FAST_KILL); else ADJUST_SCORE(SLOW_KILL); @@ -3012,6 +3017,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) bool32 partnerProtecting = IsAllyProtectingFromMove(battlerAtk, move, aiData->partnerMove) && !MoveIgnoresProtect(move); bool32 partnerHasBadAbility = (gAbilitiesInfo[atkPartnerAbility].aiRating < 0); u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); @@ -3059,7 +3065,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Adjust for always crit moves if (MoveAlwaysCrits(aiData->partnerMove) && aiData->abilities[battlerAtk] == ABILITY_ANGER_POINT) { - if (AI_IsSlower(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY)) // Partner moving first + if (AI_IsSlower(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Partner moving first { // discourage raising our attack since it's about to be maxed out if (IsAttackBoostMoveEffect(effect)) @@ -3232,7 +3238,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_ANGER_POINT: if (MoveAlwaysCrits(move) && BattlerStatCanRise(battlerAtkPartner, atkPartnerAbility, STAT_ATK) - && AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && isFriendlyFireOK) { if (MoveAlwaysCrits(move)) @@ -3551,7 +3557,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_INSTRUCT: { u16 instructedMove; - if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMove, CONSIDER_PRIORITY)) + if (AI_IsFaster(battlerAtk, battlerAtkPartner, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) instructedMove = aiData->partnerMove; else instructedMove = gLastMoves[battlerAtkPartner]; @@ -3568,8 +3574,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)) ADJUST_SCORE(DECENT_EFFECT); - if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove, predictedMove, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner - && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner + if (AI_IsSlower(battlerAtkPartner, FOE(battlerAtkPartner), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Opponent mon 1 goes before partner + && AI_IsSlower(battlerAtkPartner, BATTLE_PARTNER(FOE(battlerAtkPartner)), aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Opponent mon 2 goes before partner { if (partnerEffect == EFFECT_COUNTER || partnerEffect == EFFECT_MIRROR_COAT) break; // These moves need to go last @@ -3578,8 +3584,8 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_HEAL_PULSE: case EFFECT_HIT_ENEMY_HEAL_ALLY: - if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move, predictedMove, CONSIDER_PRIORITY) - && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move, predictedMove, CONSIDER_PRIORITY) + if (AI_IsFaster(battlerAtk, FOE(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, BATTLE_PARTNER(FOE(battlerAtk)), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && gBattleMons[battlerAtkPartner].hp < gBattleMons[battlerAtkPartner].maxHP / 2) RETURN_SCORE_PLUS(WEAK_EFFECT); break; @@ -3699,9 +3705,9 @@ static enum MoveComparisonResult CompareMoveAccuracies(u32 battlerAtk, u32 battl static enum MoveComparisonResult CompareMoveSpeeds(u32 battlerAtk, u32 battlerDef, u16 move1, u16 move2) { - u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); - u32 speed1 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move1, predictedMove, CONSIDER_PRIORITY); - u32 speed2 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move2, predictedMove, CONSIDER_PRIORITY); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + u32 speed1 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move1, predictedMoveSpeedCheck, CONSIDER_PRIORITY); + u32 speed2 = AI_WhoStrikesFirst(battlerAtk, battlerDef, move2, predictedMoveSpeedCheck, CONSIDER_PRIORITY); if (speed1 == AI_IS_FASTER && speed2 == AI_IS_SLOWER) return MOVE_WON_COMPARISON; @@ -3937,6 +3943,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) s32 score = 0; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); u32 predictedType = GetMoveType(predictedMove); u32 predictedMoveSlot = GetMoveSlot(GetMovesArray(battlerDef), predictedMove); bool32 isBattle1v1 = IsBattle1v1(); @@ -4235,7 +4242,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseSubstituteMoveScore(battlerAtk, battlerDef, move)); break; case EFFECT_MIMIC: - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) @@ -4307,7 +4314,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) && (gLastMoves[battlerDef] != MOVE_NONE) && (gLastMoves[battlerDef] != 0xFFFF) && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) - && (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY))) + && (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))) { if (CanTargetMoveFaintAi(gLastMoves[battlerDef], battlerDef, battlerAtk, 1)) ADJUST_SCORE(GOOD_EFFECT); // Disable move that can kill attacker @@ -4347,7 +4354,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_DESTINY_BOND: if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) break; - else if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk)) + else if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(GOOD_EFFECT); break; case EFFECT_SPITE: @@ -4564,7 +4571,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (predictedMove != MOVE_NONE && isBattle1v1) { enum BattleMoveEffects predictedEffect = GetMoveEffect(predictedMove); - if ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && (predictedEffect == EFFECT_EXPLOSION || predictedEffect == EFFECT_MISTY_EXPLOSION || predictedEffect == EFFECT_PROTECT)) @@ -4613,7 +4620,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_ATTRACT: if (isBattle1v1 - && (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + && (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && BattlerWillFaintFromSecondaryDamage(battlerDef, aiData->abilities[battlerDef])) break; // Don't use if the attract won't have a change to activate if (gBattleMons[battlerDef].status1 & STATUS1_ANY @@ -4661,7 +4668,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (hasPartner) { if (IsHazardMove(aiData->partnerMove) // Partner is going to set up hazards - && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move, predictedMove, CONSIDER_PRIORITY)) // Partner going first + && AI_IsSlower(battlerAtk, BATTLE_PARTNER(battlerAtk), move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Partner going first break; // Don't use Defog if partner is going to set up hazards } ADJUST_SCORE(IncreaseStatDownScore(battlerAtk, battlerDef, STAT_EVASION)); @@ -5155,7 +5162,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_HEAL_BLOCK: - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && predictedMove != MOVE_NONE && IsHealingMove(predictedMove)) ADJUST_SCORE(DECENT_EFFECT); // Try to cancel healing move else if (HasHealingEffect(battlerDef) || aiData->holdEffects[battlerDef] == HOLD_EFFECT_LEFTOVERS || (aiData->holdEffects[battlerDef] == HOLD_EFFECT_BLACK_SLUDGE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_POISON))) @@ -5189,7 +5196,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(BEST_EFFECT); break; case EFFECT_QUASH: - if (hasPartner && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMove, CONSIDER_PRIORITY)) + if (hasPartner && AI_IsSlower(BATTLE_PARTNER(battlerAtk), battlerDef, aiData->partnerMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target break; case EFFECT_TAILWIND: @@ -5204,7 +5211,7 @@ case EFFECT_GUARD_SPLIT: if (IsBattlerGrounded(battlerAtk) && HasDamagingMoveOfType(battlerDef, TYPE_ELECTRIC) && !(effectiveness == UQ_4_12(0.0))) // Doesn't resist ground move { - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first { if (predictedType == TYPE_GROUND) ADJUST_SCORE(GOOD_EFFECT); // Cause the enemy's move to fail @@ -5219,7 +5226,7 @@ case EFFECT_GUARD_SPLIT: } break; case EFFECT_CAMOUFLAGE: - if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) // Attacker goes first + if (predictedMove != MOVE_NONE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) // Attacker goes first && !IsBattleMoveStatus(move) && effectiveness != UQ_4_12(0.0)) ADJUST_SCORE(DECENT_EFFECT); break; @@ -5246,7 +5253,7 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_ENDEAVOR: - if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) && !CanTargetFaintAi(battlerDef, battlerAtk)) + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && !CanTargetFaintAi(battlerDef, battlerAtk)) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_REVIVAL_BLESSING: @@ -5516,7 +5523,7 @@ case EFFECT_GUARD_SPLIT: case MOVE_EFFECT_THROAT_CHOP: if (IsSoundMove(GetBestDmgMoveFromBattler(battlerDef, battlerAtk, AI_DEFENDING))) { - if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); else ADJUST_SCORE(DECENT_EFFECT); @@ -5571,8 +5578,10 @@ static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 || gBattleResults.battleTurnCounter != 0) return score; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (gAiThinkingStruct->aiFlags[battlerAtk] & AI_FLAG_SMART_SWITCHING - && AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && CanTargetFaintAi(battlerDef, battlerAtk) && GetBattleMovePriority(battlerAtk, gAiLogicData->abilities[battlerAtk], move) == 0) { @@ -6162,6 +6171,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) struct AiLogicData *aiData = gAiLogicData; uq4_12_t effectiveness = aiData->effectiveness[battlerAtk][battlerDef][gAiThinkingStruct->movesetIndex]; u32 predictedMove = GetIncomingMove(battlerAtk, battlerDef, gAiLogicData); + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); // Switch benefit switch (moveEffect) @@ -6173,7 +6183,7 @@ static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(GOOD_EFFECT); else if (hitsToKO == 1) ADJUST_SCORE(BEST_EFFECT); - else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY) == AI_IS_SLOWER) // Pursuit against fast U-Turn + else if (IsSwitchOutEffect(GetMoveEffect(predictedMove)) && AI_WhoStrikesFirst(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY) == AI_IS_SLOWER) // Pursuit against fast U-Turn ADJUST_SCORE(DECENT_EFFECT); break; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 8fe1067a19..e6dec3e58d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -199,6 +199,14 @@ u32 GetIncomingMove(u32 battler, u32 opposingBattler, struct AiLogicData *aiData return aiData->lastUsedMove[opposingBattler]; } +// When not predicting, don't want to reference player's previous move; leads to weird behaviour for cases like Fake Out or Protect, especially in doubles +u32 GetIncomingMoveSpeedCheck(u32 battler, u32 opposingBattler, struct AiLogicData *aiData) +{ + if (aiData->predictingMove && CanAiPredictMove()) + return aiData->predictedMove[opposingBattler]; + return MOVE_NONE; +} + void ClearBattlerMoveHistory(u32 battlerId) { memset(gBattleHistory->usedMoves[battlerId], 0, sizeof(gBattleHistory->usedMoves[battlerId])); @@ -497,6 +505,7 @@ u32 GetTotalBaseStat(u32 species) bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) { int i; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAI, opposingBattler, gAiLogicData); for (i = 0; i < MAX_MON_MOVES; i++) { @@ -504,7 +513,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) enum BattleMoveEffects effect = GetMoveEffect(move); if (effect == EFFECT_PROTECT && move != MOVE_ENDURE) return TRUE; - if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI), GetIncomingMove(battlerAI, opposingBattler, gAiLogicData), CONSIDER_PRIORITY)) + if (effect == EFFECT_SEMI_INVULNERABLE && AI_IsSlower(battlerAI, opposingBattler, GetAIChosenMove(battlerAI), predictedMoveSpeedCheck, CONSIDER_PRIORITY)) return TRUE; } return FALSE; @@ -2031,8 +2040,9 @@ bool32 CanLowerStat(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData, if (stat == STAT_SPEED) { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); // If AI is faster and doesn't have any mons left, lowering speed doesn't give any - return !(AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY) + return !(AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY) && CountUsablePartyMons(battlerAtk) == 0 && !HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)); } @@ -2074,7 +2084,8 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_SPEED: - if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) tempScore += DECENT_EFFECT; break; case STAT_SPATK: @@ -3112,6 +3123,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov { bool32 hasStatBoost = AnyUsefulStatIsRaised(battlerAtk) || gBattleMons[battlerDef].statStages[STAT_EVASION] >= 9; //Significant boost in evasion for any class u32 battlerToSwitch; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); battlerToSwitch = gBattleStruct->AI_monToSwitchIntoId[battlerAtk]; @@ -3132,7 +3144,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (IsBattlerPredictedToSwitch(battlerDef)) return SHOULD_PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent - if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) // Attacker goes first + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) // Attacker goes first { if (!CanAIFaintTarget(battlerAtk, battlerDef, 0)) // Can't KO foe otherwise { @@ -3514,10 +3526,11 @@ bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility) u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move) { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (((!IsMoldBreakerTypeAbility(battlerAtk, gAiLogicData->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS)) || gAiLogicData->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) - || AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY))) // Opponent goes first + || AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY))) // Opponent goes first { return 0; } @@ -3525,7 +3538,7 @@ u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbi || gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS || gBattleMons[battlerDef].volatiles.infatuation || gBattleMons[battlerDef].volatiles.confusionTurns > 0) - || ((AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) && CanTargetFaintAi(battlerDef, battlerAtk))) + || ((AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) && CanTargetFaintAi(battlerDef, battlerAtk))) { return 2; // good idea to flinch } @@ -3558,7 +3571,8 @@ bool32 IsFlinchGuaranteed(u32 battlerAtk, u32 battlerDef, u32 move) if (!MoveHasAdditionalEffect(move, MOVE_EFFECT_FLINCH)) return FALSE; - if (AI_IsSlower(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (AI_IsSlower(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) return FALSE; u32 i; @@ -3710,7 +3724,8 @@ bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 mo bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage) { - if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (move == 0xFFFF || AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { // using item or user goes first s32 healDmg = (GetMoveAbsorbPercentage(move) * damage) / 100; @@ -3738,11 +3753,12 @@ bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent) { u32 maxHP = gBattleMons[battlerAtk].maxHP; u32 healAmount = (healPercent * maxHP) / 100; + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (healAmount > maxHP) healAmount = maxHP; if (gBattleMons[battlerAtk].volatiles.healBlock) healAmount = 0; - if (AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), CONSIDER_PRIORITY)) + if (AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) { if (CanTargetFaintAi(battlerDef, battlerAtk) && !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healAmount, 0)) @@ -4479,7 +4495,8 @@ static enum AIScore IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, { enum AIScore tempScore = NO_INCREASE; u32 noOfHitsToFaint = NoOfHitsForTargetToFaintBattler(battlerDef, battlerAtk); - u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + u32 aiIsFaster = AI_IsFaster(battlerAtk, battlerDef, MOVE_NONE, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY); // Don't care about the priority of our setup move, care about outspeeding otherwise u32 shouldSetUp = ((noOfHitsToFaint >= 2 && aiIsFaster) || (noOfHitsToFaint >= 3 && !aiIsFaster) || noOfHitsToFaint == UNKNOWN_NO_OF_HITS); u32 i; u32 statId = GetStatBeingChanged(statChange); @@ -5025,8 +5042,9 @@ enum AIConsiderGimmick ShouldTeraFromCalcs(u32 battler, u32 opposingBattler, str } else { + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battler, opposingBattler, gAiLogicData); // will we go first? - if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove, GetIncomingMove(battler, opposingBattler, gAiLogicData), CONSIDER_PRIORITY) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) + if (AI_WhoStrikesFirst(battler, opposingBattler, killingMove, predictedMoveSpeedCheck, CONSIDER_PRIORITY) == AI_IS_FASTER && GetBattleMovePriority(battler, gAiLogicData->abilities[battler], killingMove) >= GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], hardPunishingMove)) return USE_GIMMICK; } } @@ -5149,8 +5167,8 @@ void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) ADJUST_SCORE_PTR(GOOD_EFFECT); if (AreAnyHazardsOnSide(GetBattlerSide(battlerDef)) && CountUsablePartyMons(battlerDef) != 0) ADJUST_SCORE_PTR(-2); - - if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move, GetIncomingMove(battlerAtk, battlerDef, gAiLogicData), DONT_CONSIDER_PRIORITY)) + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); + if (gBattleMons[battlerAtk].volatiles.substitute && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE_PTR(-10); if (gBattleMons[battlerDef].volatiles.substitute) ADJUST_SCORE_PTR(GOOD_EFFECT); @@ -5188,9 +5206,9 @@ bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, st default: break; } - + u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, opposingBattler, gAiLogicData); return (preventsStatLoss - && AI_IsFaster(battlerAtk, battlerAtkPartner, MOVE_NONE, GetIncomingMove(battlerAtk, opposingBattler, gAiLogicData), CONSIDER_PRIORITY) + && AI_IsFaster(battlerAtk, battlerAtkPartner, MOVE_NONE, predictedMoveSpeedCheck, CONSIDER_PRIORITY) && HasMoveWithCategory(battlerAtkPartner, DAMAGE_CATEGORY_PHYSICAL)); } diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 4c65a23489..4c86673473 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -661,20 +661,6 @@ AI_SINGLE_BATTLE_TEST("AI stays choice locked into moves in spite of the player' } } -AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a move of the same priority bracket and the opponent is faster") -{ - GIVEN { - ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) == 1); - ASSUME(GetMovePriority(MOVE_SUCKER_PUNCH) == 1); - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); - PLAYER(SPECIES_WOBBUFFET) { Speed(300); Moves(MOVE_QUICK_ATTACK); } - OPPONENT(SPECIES_WOBBUFFET) { Speed(100); Moves(MOVE_SUCKER_PUNCH, MOVE_SCRATCH); } - } WHEN { - TURN { MOVE(player, MOVE_QUICK_ATTACK); EXPECT_MOVE(opponent, MOVE_SUCKER_PUNCH); } - TURN { MOVE(player, MOVE_QUICK_ATTACK); EXPECT_MOVE(opponent, MOVE_SCRATCH); } - } -} - AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a status move a percentage of the time") { PASSES_RANDOMLY(SUCKER_PUNCH_CHANCE, 100, RNG_AI_SUCKER_PUNCH); @@ -1022,3 +1008,18 @@ AI_SINGLE_BATTLE_TEST("AI has a chance to prioritize last chance priority damage TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_AQUA_JET); } } } + +AI_DOUBLE_BATTLE_TEST("AI won't be confused by player's previous priority moves when evaluating KOs") +{ + PASSES_RANDOMLY(100, 100); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_BEAUTIFLY) { Speed(1); Moves(MOVE_DETECT, MOVE_SCRATCH); } + PLAYER(SPECIES_MASQUERAIN) { Speed(10); Moves(MOVE_DETECT, MOVE_SCRATCH); } + OPPONENT(SPECIES_CRADILY) { Speed(5); Moves(MOVE_POWER_GEM); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(4); Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_DETECT); MOVE(playerRight, MOVE_DETECT); EXPECT_MOVE(opponentLeft, MOVE_POWER_GEM, target:playerLeft); EXPECT_MOVE(opponentRight, MOVE_CELEBRATE); } + TURN { MOVE(playerLeft, MOVE_DETECT); MOVE(playerRight, MOVE_DETECT); EXPECT_MOVE(opponentLeft, MOVE_POWER_GEM, target:playerLeft); EXPECT_MOVE(opponentRight, MOVE_CELEBRATE); } + } +} diff --git a/test/battle/ai/ai_flag_predict_move.c b/test/battle/ai/ai_flag_predict_move.c index 97a7c12afa..6a8554b734 100644 --- a/test/battle/ai/ai_flag_predict_move.c +++ b/test/battle/ai/ai_flag_predict_move.c @@ -27,3 +27,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_MOVE: AI will still attack you when it sh TURN { MOVE(player, MOVE_SURF); EXPECT_MOVE(opponent, MOVE_LEAF_BLADE); } } } + +AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a move of the same priority bracket and the opponent is faster") +{ + PASSES_RANDOMLY(PREDICT_MOVE_CHANCE, 100, RNG_AI_PREDICT_MOVE); + GIVEN { + ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) == 1); + ASSUME(GetMovePriority(MOVE_SUCKER_PUNCH) == 1); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE); + PLAYER(SPECIES_WOBBUFFET) { Speed(300); Moves(MOVE_QUICK_ATTACK); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); Moves(MOVE_SUCKER_PUNCH, MOVE_SCRATCH); } + } WHEN { + TURN { MOVE(player, MOVE_QUICK_ATTACK); EXPECT_MOVE(opponent, MOVE_SCRATCH); } + TURN { MOVE(player, MOVE_QUICK_ATTACK); EXPECT_MOVE(opponent, MOVE_SCRATCH); } + } +} diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 79ffccc618..0a41343427 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1385,3 +1385,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will consider Hidden Power wh TURN { MOVE(player, MOVE_HIDDEN_POWER); EXPECT_SWITCH(opponent, 1); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: Fake Out style moves won't confuse choiced AI into thinking it does no damage") +{ + + GIVEN { + ASSUME(gItemsInfo[ITEM_CHOICE_SCARF].holdEffect == HOLD_EFFECT_CHOICE_SCARF); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_FAKE_OUT, MOVE_SCRATCH); } + OPPONENT(SPECIES_INFERNAPE) { Item(ITEM_CHOICE_SCARF); Moves(MOVE_CLOSE_COMBAT); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } + } WHEN { + TURN { MOVE(player, MOVE_FAKE_OUT); EXPECT_MOVE(opponent, MOVE_CLOSE_COMBAT); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CLOSE_COMBAT); } + } +} From 18363207d91a62e8b3fa13477fcfe06f201c0adc Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:40:10 -0400 Subject: [PATCH 207/283] Fix Mimicry Only Activating Once per Turn (#7537) Co-authored-by: ghoulslash --- asm/macros/battle_script.inc | 4 ++++ data/battle_scripts_1.s | 1 + src/battle_script_commands.c | 10 ++++++++++ test/battle/ability/mimicry.c | 25 +++++++++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 02546d2f8a..721c844554 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1737,6 +1737,10 @@ callnative BS_ActivateTerrainChangeAbilities .byte \battler .endm + + .macro resetterrainabilityflags + callnative BS_ResetTerrainAbilityFlags + .endm @ Stores Healing Wish effect. .macro storehealingwish battler:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 23c1e10aa9..8688b2e97e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7889,6 +7889,7 @@ BattleScript_SnowWarningActivatesSnow:: BattleScript_ActivateTerrainEffects: saveattacker savetarget + resetterrainabilityflags setbyte gBattlerAttacker, 0 BattleScript_ActivateTerrainSeed: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 870f21d7a8..e74bb4c60a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -18175,6 +18175,16 @@ void BS_ActivateTerrainChangeAbilities(void) AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); } +void BS_ResetTerrainAbilityFlags(void) +{ + NATIVE_ARGS(); + // reset terrain ability checks + for (u32 i = 0; i < gBattlersCount; i++) + gDisableStructs[i].terrainAbilityDone = 0; + + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_StoreHealingWish(void) { NATIVE_ARGS(u8 battler); diff --git a/test/battle/ability/mimicry.c b/test/battle/ability/mimicry.c index fbdb5cf98a..b9c3bb5fc3 100644 --- a/test/battle/ability/mimicry.c +++ b/test/battle/ability/mimicry.c @@ -70,3 +70,28 @@ SINGLE_BATTLE_TEST("Mimicry restores the battler's types when terrain is removed EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].types[1], TYPE_STEEL); } } + +DOUBLE_BATTLE_TEST("Mimicry can trigger multiple times in a turn") +{ + GIVEN { + PLAYER(SPECIES_STUNFISK_GALAR) { Speed(50); Ability(ABILITY_MIMICRY); } + PLAYER(SPECIES_MORELULL) { Speed(40); } + OPPONENT(SPECIES_IGGLYBUFF) { Speed(60); } + OPPONENT(SPECIES_BAGON) { Speed(70); } + } WHEN { + TURN { MOVE(opponentRight, MOVE_ELECTRIC_TERRAIN); MOVE(opponentLeft, MOVE_MISTY_TERRAIN); } + } SCENE { + MESSAGE("The opposing Bagon used Electric Terrain!"); + ABILITY_POPUP(playerLeft, ABILITY_MIMICRY); + MESSAGE("Stunfisk's type changed to Electric!"); + // igglybuff + MESSAGE("The opposing Igglybuff used Misty Terrain!"); + ABILITY_POPUP(playerLeft, ABILITY_MIMICRY); + MESSAGE("Stunfisk's type changed to Fairy!"); + } THEN { + EXPECT_EQ(gBattleMons[0].types[0], TYPE_FAIRY); + EXPECT_EQ(gBattleMons[0].types[1], TYPE_FAIRY); + EXPECT_EQ(gBattleMons[0].types[2], TYPE_MYSTERY); + } +} + From c6ee7feaa3cfe0d926f713fd95b3f24102e7779d Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:45:02 +0100 Subject: [PATCH 208/283] Fixes some Ability Shield interactions (#7532) --- data/battle_scripts_1.s | 1 + src/battle_script_commands.c | 58 +++++++++++++----- src/battle_util.c | 11 +++- test/battle/hold_effect/ability_shield.c | 77 ++++++++++++++++++++++-- 4 files changed, 125 insertions(+), 22 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b7b4ec99cd..8318d7d214 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2459,6 +2459,7 @@ BattleScript_EffectGastroAcid:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce + jumpifvolatile BS_TARGET, VOLATILE_GASTRO_ACID, BattleScript_ButItFailed setgastroacid BattleScript_ButItFailed attackanimation waitanimation diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 86cb831bb0..c58b85d187 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -335,6 +335,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u static void ResetValuesForCalledMove(void); static void TryRestoreDamageAfterCheekPouch(u32 battler); static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd); +static bool32 CanAbilityShieldActivateForBattler(u32 battler); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -12901,22 +12902,40 @@ static void Cmd_tryswapitems(void) } } +static bool32 CanAbilityShieldActivateForBattler(u32 battler) +{ + if (GetBattlerHoldEffectIgnoreAbility(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD) + return FALSE; + + RecordItemEffectBattle(battler, HOLD_EFFECT_ABILITY_SHIELD); + gBattlerAbility = battler; + gLastUsedItem = gBattleMons[battler].item; + return TRUE; +} + // Role Play, Doodle static void Cmd_trycopyability(void) { CMD_ARGS(u8 battler, const u8 *failInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 partner = BATTLE_PARTNER(battler); u16 defAbility = gBattleMons[gBattlerTarget].ability; + bool32 shouldConsiderPartner = IsBattlerAlive(partner) && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE; if (gBattleMons[battler].ability == defAbility || defAbility == ABILITY_NONE || gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed - || (IsBattlerAlive(BATTLE_PARTNER(battler)) && gAbilitiesInfo[gBattleMons[BATTLE_PARTNER(battler)].ability].cantBeSuppressed && GetMoveEffect(gCurrentMove) == EFFECT_DOODLE) + || (shouldConsiderPartner && gAbilitiesInfo[gBattleMons[partner].ability].cantBeSuppressed) || gAbilitiesInfo[defAbility].cantBeCopied) { gBattlescriptCurrInstr = cmd->failInstr; } + else if (CanAbilityShieldActivateForBattler(battler) || (shouldConsiderPartner && CanAbilityShieldActivateForBattler(partner))) + { + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); + } else { gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; @@ -12964,7 +12983,6 @@ static void Cmd_settoxicspikes(void) } } -// TODO: possible failing bug for when gastro acid is already active static void Cmd_setgastroacid(void) { CMD_ARGS(const u8 *failInstr); @@ -12973,6 +12991,11 @@ static void Cmd_setgastroacid(void) { gBattlescriptCurrInstr = cmd->failInstr; } + else if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + gBattlescriptCurrInstr = cmd->failInstr; + } else { if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) @@ -13074,10 +13097,10 @@ static void Cmd_tryswapabilities(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerAttacker) || CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { @@ -14535,10 +14558,10 @@ static void Cmd_tryworryseed(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { @@ -16645,10 +16668,15 @@ void BS_TryActivateAbilityShield(void) { NATIVE_ARGS(u8 battler); u32 battler = GetBattlerForBattleScript(cmd->battler); + u32 ability = GetBattlerAbility(battler); gBattlescriptCurrInstr = cmd->nextInstr; - if (GetBattlerAbilityNoAbilityShield(battler) != GetBattlerAbility(battler)) + if (ability != ABILITY_NONE // if ability would be negated by breaking effects Ability Shield doesn't print message + && ability == GetBattlerAbilityInternal(battler, TRUE, TRUE)) + return; + + if (GetBattlerAbilityNoAbilityShield(battler) != ability) { gLastUsedItem = gBattleMons[battler].item; RecordItemEffectBattle(battler, GetItemHoldEffect(gLastUsedItem)); @@ -17344,10 +17372,10 @@ void BS_SetSimpleBeam(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { @@ -17369,10 +17397,10 @@ void BS_TryEntrainment(void) RecordAbilityBattle(gBattlerTarget, gBattleMons[gBattlerTarget].ability); gBattlescriptCurrInstr = cmd->failInstr; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + else if (CanAbilityShieldActivateForBattler(gBattlerTarget)) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); - gBattlescriptCurrInstr = cmd->failInstr; + gBattlescriptCurrInstr = BattleScript_MoveEnd; + BattleScriptCall(BattleScript_AbilityShieldProtects); } else { diff --git a/src/battle_util.c b/src/battle_util.c index 8eb6a89bc1..ed00fb4d45 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3533,6 +3533,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gSpecialStatuses[battler].switchInAbilityDone) break; + if (GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + break; side = (BATTLE_OPPOSITE(GetBattlerPosition(battler))) & BIT_SIDE; target1 = GetBattlerAtPosition(side); @@ -4529,7 +4531,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSuppressed) { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; @@ -4549,11 +4551,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped) { - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + if (GetBattlerHoldEffectIgnoreAbility(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) { RecordItemEffectBattle(gBattlerAttacker, HOLD_EFFECT_ABILITY_SHIELD); break; } + if (GetBattlerHoldEffectIgnoreAbility(gBattlerTarget, TRUE) == HOLD_EFFECT_ABILITY_SHIELD) + { + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_ABILITY_SHIELD); + break; + } gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; diff --git a/test/battle/hold_effect/ability_shield.c b/test/battle/hold_effect/ability_shield.c index ded39ff05b..9f98ea98ef 100644 --- a/test/battle/hold_effect/ability_shield.c +++ b/test/battle/hold_effect/ability_shield.c @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Neutralizing Gas") } } -SINGLE_BATTLE_TEST("Ability Shield protects against Mold Breaker") +SINGLE_BATTLE_TEST("Ability Shield protects against Mold Breaker (no message)") { u32 item; @@ -50,16 +50,20 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mold Breaker") TURN { MOVE(opponent, MOVE_EARTHQUAKE); } } SCENE { if (item == ITEM_ABILITY_SHIELD) { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Flygon's Ability is protected by the effects of its Ability Shield!"); + HP_BAR(player); + } ABILITY_POPUP(player, ABILITY_LEVITATE); - NOT HP_BAR(player); } else { - NOT ABILITY_POPUP(player, ABILITY_LEVITATE); HP_BAR(player); + NOT ABILITY_POPUP(player, ABILITY_LEVITATE); } } } -SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might") +SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might (no message)") { u32 item; @@ -79,7 +83,10 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might") NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); STATUS_ICON(player, sleep: TRUE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Vigoroth's Ability is protected by the effects of its Ability Shield!"); } + ABILITY_POPUP(player, ABILITY_VITAL_SPIRIT); } else { ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, opponent); STATUS_ICON(player, sleep: TRUE); @@ -87,7 +94,7 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might") } } -SINGLE_BATTLE_TEST("Ability Shield protects against Sunsteel Strike") +SINGLE_BATTLE_TEST("Ability Shield protects against Sunsteel Strike (no message)") { u32 item; @@ -103,10 +110,38 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Sunsteel Strike") } SCENE { if (item == ITEM_ABILITY_SHIELD) { NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Shedinja's Ability is protected by the effects of its Ability Shield!"); MESSAGE("Shedinja fainted!"); } + ABILITY_POPUP(player, ABILITY_WONDER_GUARD); } else { MESSAGE("Shedinja fainted!"); + NOT ABILITY_POPUP(player, ABILITY_WONDER_GUARD); + } + } +} + +SINGLE_BATTLE_TEST("Ability Shield protects the user's ability from being suppressed by Gastro Acid") +{ + u32 item; + + PARAMETRIZE { item = ITEM_ABILITY_SHIELD; } + PARAMETRIZE { item = ITEM_NONE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_GASTRO_ACID) == EFFECT_GASTRO_ACID); + PLAYER(SPECIES_BLAZIKEN) { Ability(ABILITY_SPEED_BOOST); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GASTRO_ACID); } + } SCENE { + if (item == ITEM_ABILITY_SHIELD) { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_GASTRO_ACID, opponent); + ABILITY_POPUP(player, ABILITY_SPEED_BOOST); + } else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GASTRO_ACID, opponent); + NOT ABILITY_POPUP(player, ABILITY_SPEED_BOOST); } } } @@ -130,9 +165,41 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Skill Swap") ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Gyarados's Ability is protected by the effects of its Ability Shield!"); } else { ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); } } } + +SINGLE_BATTLE_TEST("Ability Shield protects against Skill Swap even if user has Klutz") +{ + u32 item; + + PARAMETRIZE { item = ITEM_ABILITY_SHIELD; } + PARAMETRIZE { item = ITEM_NONE; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP); + PLAYER(SPECIES_LOPUNNY) { Ability(ABILITY_KLUTZ); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + if (item == ITEM_ABILITY_SHIELD) { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Lopunny's Ability is protected by the effects of its Ability Shield!"); + } else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + } + } +} + +// These currently do not activate, but probably should do held item animation + message +TO_DO_BATTLE_TEST("Ability Shield prevents the user's Trace from changing its ability"); +TO_DO_BATTLE_TEST("Ability Shield prevents the user's Receiver from changing its ability"); +TO_DO_BATTLE_TEST("Ability Shield protects against Wandering Spirit"); +TO_DO_BATTLE_TEST("Ability Shield protects against Mummy/Lingering Aroma"); From 7fb5d98bf6d9a5f41eb416ebb2573f0191c9f24c Mon Sep 17 00:00:00 2001 From: surskitty Date: Tue, 12 Aug 2025 17:12:45 -0400 Subject: [PATCH 209/283] AI uses Tailwind. (#7515) --- include/battle_ai_util.h | 1 - src/battle_ai_field_statuses.c | 8 +++--- src/battle_ai_main.c | 42 +++++++++++++++++++++++++++-- src/battle_ai_util.c | 21 --------------- test/battle/ai/ai_check_viability.c | 18 +++++++++++++ test/battle/ai/ai_doubles.c | 28 +++++++++++++++++++ 6 files changed, 90 insertions(+), 28 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 5759427f4b..2e62a1340b 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -125,7 +125,6 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability); bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability); bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move); bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex); -u32 GetBattlerSideSpeedAverage(u32 battler); bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage); bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent); bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect); diff --git a/src/battle_ai_field_statuses.c b/src/battle_ai_field_statuses.c index 423910a0e5..bd7bdd8e17 100644 --- a/src/battle_ai_field_statuses.c +++ b/src/battle_ai_field_statuses.c @@ -429,13 +429,13 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler) static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler) { // If we're in singles, we literally only care about speed. - if (!IsDoubleBattle()) + if (IsBattle1v1()) { - if (GetBattlerSideSpeedAverage(battler) < GetBattlerSideSpeedAverage(FOE(battler))) + if (gAiLogicData->speedStats[battler] < gAiLogicData->speedStats[FOE(battler)]) return FIELD_EFFECT_POSITIVE; // If we tie, we shouldn't change trick room state. - else if (GetBattlerSideSpeedAverage(battler) == GetBattlerSideSpeedAverage(FOE(battler))) - return FIELD_EFFECT_NEUTRAL; + else if (gAiLogicData->speedStats[battler] == gAiLogicData->speedStats[FOE(battler)]) + return FIELD_EFFECT_NEUTRAL; else return FIELD_EFFECT_NEGATIVE; } diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 78f1b72b28..30093aafd4 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5092,6 +5092,9 @@ case EFFECT_GUARD_SPLIT: { if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); + // Set it for next pokemon in singles. + else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0)) + ADJUST_SCORE(DECENT_EFFECT); // Don't unset it on last turn. else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); @@ -5200,9 +5203,44 @@ case EFFECT_GUARD_SPLIT: ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target break; case EFFECT_TAILWIND: - if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef)) - ADJUST_SCORE(GOOD_EFFECT); + { + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter) + break; + + if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)) + ADJUST_SCORE(WEAK_EFFECT); + + if (isBattle1v1) + { + IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED); + + if (CountUsablePartyMons(battlerAtk) != 0) + ADJUST_SCORE(WEAK_EFFECT); + } + else + { + u32 tailwindScore = 0; + u32 speed = aiData->speedStats[battlerAtk]; + u32 partnerSpeed = aiData->speedStats[BATTLE_PARTNER(battlerAtk)]; + u32 foe1Speed = aiData->speedStats[FOE(battlerAtk)]; + u32 foe2Speed = aiData->speedStats[BATTLE_PARTNER(FOE(battlerAtk))]; + + if (speed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + if (speed <= foe2Speed && (speed * 2) > foe2Speed) + tailwindScore += 1; + if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed) + tailwindScore += 1; + + if (tailwindScore > 0) + tailwindScore += 1; + + ADJUST_SCORE(tailwindScore); + } break; + } case EFFECT_LUCKY_CHANT: if (isBattle1v1 && CountUsablePartyMons(battlerDef) > 0) ADJUST_SCORE(GOOD_EFFECT); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index e6dec3e58d..a0e5e7716b 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3687,27 +3687,6 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof) return FALSE; } -u32 GetBattlerSideSpeedAverage(u32 battler) -{ - u32 speed1 = 0; - u32 speed2 = 0; - u32 numBattlersAlive = 0; - - if (IsBattlerAlive(battler)) - { - speed1 = gAiLogicData->speedStats[battler]; - numBattlersAlive++; - } - - if (HasPartner(battler)) - { - speed2 = gAiLogicData->speedStats[BATTLE_PARTNER(battler)]; - numBattlersAlive++; - } - - return (speed1 + speed2) / numBattlersAlive; -} - bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex) { if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index f18f7aceb1..c586b6fc81 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -340,6 +340,24 @@ AI_SINGLE_BATTLE_TEST("AI uses Skill Swap against Poison Heal") } } +AI_SINGLE_BATTLE_TEST("AI uses Trick Room (singles)") +{ + u32 speed; + PARAMETRIZE { speed = 10; } + PARAMETRIZE { speed = 20; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Speed(11); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(speed); Moves(MOVE_TACKLE, MOVE_TRICK_ROOM); } + } WHEN { + if (speed == 10) + TURN { EXPECT_MOVE(opponent, MOVE_TRICK_ROOM); } + else + TURN { NOT_EXPECT_MOVE(opponent, MOVE_TRICK_ROOM); } + } +} + AI_SINGLE_BATTLE_TEST("AI uses Quick Guard against Quick Attack when opponent would take poison damage") { PASSES_RANDOMLY(PREDICT_MOVE_CHANCE, 100, RNG_AI_PREDICT_MOVE); diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index ab6b4a4425..9e6edc4c56 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -594,6 +594,34 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently") TURN { NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } } } + +AI_DOUBLE_BATTLE_TEST("AI uses Tailwind") +{ + u32 speed1, speed2, speed3, speed4; + + PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 20; speed4 = 20; } + PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 5; speed4 = 5; } + PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 15; speed4 = 15; } + PARAMETRIZE { speed1 = 1; speed2 = 1; speed3 = 5; speed4 = 5; } + PARAMETRIZE { speed1 = 1; speed2 = 20; speed3 = 15; speed4 = 15; } + PARAMETRIZE { speed1 = 1; speed2 = 20; speed3 = 20; speed4 = 15; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU); + ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(SPECIES_WOBBUFFET) { Speed(speed1); } + PLAYER(SPECIES_WOBBUFFET) { Speed(speed2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(speed3); Moves(MOVE_TAILWIND, MOVE_HEADBUTT); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(speed4); Moves(MOVE_TAILWIND, MOVE_HEADBUTT); } + } WHEN { + if (speed3 > 10) + TURN { EXPECT_MOVE(opponentLeft, MOVE_TAILWIND); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TAILWIND); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats") { From 69cbd866aa82a40d1cd201db4f1b6f8ec4fa4b2b Mon Sep 17 00:00:00 2001 From: surskitty Date: Tue, 12 Aug 2025 17:16:43 -0400 Subject: [PATCH 210/283] Fixing Refresh AI scoring (#7539) --- src/battle_ai_main.c | 4 ++-- test/battle/ai/ai_check_viability.c | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 30093aafd4..2d9e37d688 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2067,7 +2067,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerDef].status1 & STATUS1_CAN_MOVE)) + if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)) ADJUST_SCORE(-10); break; case EFFECT_PSYCHO_SHIFT: @@ -4861,7 +4861,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); break; case EFFECT_REFRESH: - if (gBattleMons[battlerAtk].status1 & STATUS1_ANY) + if (gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_TAKE_HEART: diff --git a/test/battle/ai/ai_check_viability.c b/test/battle/ai/ai_check_viability.c index c586b6fc81..4dff0e08ca 100644 --- a/test/battle/ai/ai_check_viability.c +++ b/test/battle/ai/ai_check_viability.c @@ -197,12 +197,22 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% c AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner") { - u32 status1_0, status1_1, partnerAbility; + u32 status1_0, status1_1, partnerAbility, move; + + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; + move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } + PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; + move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; + move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SCRAPPY; } + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; + move = MOVE_HEAL_BELL; partnerAbility = ABILITY_SOUNDPROOF; } + + PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; + move = MOVE_REFRESH; partnerAbility = ABILITY_SCRAPPY; } + PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; + move = MOVE_REFRESH; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_NONE; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_TOXIC_POISON; status1_1 = STATUS1_NONE; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; partnerAbility = ABILITY_SCRAPPY; } - PARAMETRIZE { status1_0 = STATUS1_NONE; status1_1 = STATUS1_PARALYSIS; partnerAbility = ABILITY_SOUNDPROOF; } GIVEN { ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL); @@ -210,11 +220,11 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner") AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_ROCK_SLIDE, MOVE_HEAL_BELL, MOVE_ACID); Status1(status1_0); } + OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_ROCK_SLIDE, move, MOVE_ACID); Status1(status1_0); } OPPONENT(SPECIES_EXPLOUD) { Status1(status1_1); Ability(partnerAbility); } } WHEN { if (status1_0 != STATUS1_NONE || (status1_1 != STATUS1_NONE && partnerAbility != ABILITY_SOUNDPROOF)) - TURN { EXPECT_MOVE(opponentLeft, MOVE_HEAL_BELL); } + TURN { EXPECT_MOVE(opponentLeft, move); } else TURN { EXPECT_MOVE(opponentLeft, MOVE_ROCK_SLIDE); } } From 9e49f55aaa4b5624d97dc6f073756fbfd07f227d Mon Sep 17 00:00:00 2001 From: surskitty Date: Tue, 12 Aug 2025 17:17:08 -0400 Subject: [PATCH 211/283] Uncommenting out No Retreat, Clangorous Soul, and Extreme Evoboost from CheckBadMove (#7541) --- src/battle_ai_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2d9e37d688..6eeabc1823 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2853,18 +2853,18 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || GetBattlerWeight(battlerDef) >= 2000) //200.0 kg ADJUST_SCORE(-10); break; - /*case EFFECT_NO_RETREAT: - if (TrappedByNoRetreat(battlerAtk)) + case EFFECT_NO_RETREAT: + if (gDisableStructs[battlerAtk].noRetreat) ADJUST_SCORE(-10); break; case EFFECT_EXTREME_EVOBOOST: - if (MainStatsMaxed(battlerAtk)) + if (AreBattlersStatsMaxed(battlerAtk)) ADJUST_SCORE(-10); break; case EFFECT_CLANGOROUS_SOUL: if (gBattleMons[battlerAtk].hp <= gBattleMons[battlerAtk].maxHP / 3) ADJUST_SCORE(-10); - break;*/ + break; case EFFECT_REVIVAL_BLESSING: if (GetFirstFaintedPartyIndex(battlerAtk) == PARTY_SIZE) ADJUST_SCORE(-10); From 608c123c395a380e979df5cc3a843742c6599e73 Mon Sep 17 00:00:00 2001 From: surskitty Date: Tue, 12 Aug 2025 17:18:18 -0400 Subject: [PATCH 212/283] AI should not use Dark Void or Hyperspace Fury while wrong species (#7540) --- src/battle_ai_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6eeabc1823..65e61e2ff5 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2912,6 +2912,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) ADJUST_SCORE(-10); break; + case EFFECT_DARK_VOID: + if (B_DARK_VOID_FAIL >= GEN_7 && gBattleMons[battlerAtk].species != SPECIES_DARKRAI) + ADJUST_SCORE(-10); + break; + case EFFECT_HYPERSPACE_FURY: + if (gBattleMons[battlerAtk].species != SPECIES_HOOPA_UNBOUND) + ADJUST_SCORE(-10); + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks From 98a51bc97afe13a7b2bc0a00e3b9a87c2be63043 Mon Sep 17 00:00:00 2001 From: surskitty Date: Tue, 12 Aug 2025 18:05:15 -0400 Subject: [PATCH 213/283] AI Tailwind singles fix correction. (#7543) --- src/battle_ai_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 65e61e2ff5..fe3ff13ee2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5220,7 +5220,8 @@ case EFFECT_GUARD_SPLIT: if (isBattle1v1) { - IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED); + if (aiData->speedStats[battlerAtk] * 2 > aiData->speedStats[battlerDef]) + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); if (CountUsablePartyMons(battlerAtk) != 0) ADJUST_SCORE(WEAK_EFFECT); From 7b5844762dda10f163d7fd9b1fb5bee265a334c9 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 13 Aug 2025 09:39:55 +0100 Subject: [PATCH 214/283] make check TESTS="..." support for filenames and infix matches (#7536) --- Makefile | 2 +- include/test/battle.h | 7 ++++++- include/test/test.h | 8 ++++++++ test/test_runner.c | 45 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 759512ea63..8e5259ad1e 100644 --- a/Makefile +++ b/Makefile @@ -300,7 +300,7 @@ $(TESTELF): $(OBJ_DIR)/ld_script_test.ld $(OBJS) $(TEST_OBJS) libagbsyscall tool @echo "cd $(OBJ_DIR) && $(LD) -T ld_script_test.ld -o ../../$@ " @cd $(OBJ_DIR) && $(LD) $(TESTLDFLAGS) -T ld_script_test.ld -o ../../$@ $(OBJS_REL) $(TEST_OBJS_REL) $(LIB) $(FIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) -d0 --silent - $(PATCHELF) $(TESTELF) gTestRunnerArgv "$(TESTS)\0" + $(PATCHELF) $(TESTELF) gTestRunnerArgv "$(TESTS:%*=%)\0" ifeq ($(GITHUB_REPOSITORY_OWNER),rh-hideout) TEST_SKIP_IS_FAIL := \x01 diff --git a/include/test/battle.h b/include/test/battle.h index b95038b09e..d909aa0332 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -2,8 +2,13 @@ * * To run all the tests use: * make check -j - * To run specific tests, e.g. Spikes ones, use: + * To run specific tests, e.g. Spikes ones, use either: * make check TESTS="Spikes" + * make check TESTS="*Spikes*" + * The first runs tests with names that start with Spikes, whereas the + * second runs tests with names that include Spikes anywhere in them. + * To run tests from a specific file, e.g. 'test/battle/move_effect/spikes.c', use: + * make check TESTS="test/battle/move_effect/spikes.c" * To build a ROM (pokemerald-test.elf) that can be opened in mgba to * view specific tests, e.g. Spikes ones, use: * make pokeemerald-test.elf TESTS="Spikes" diff --git a/include/test/test.h b/include/test/test.h index 835634df7b..48a6e84aa2 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -37,10 +37,18 @@ struct Test u16 sourceLine; }; +enum TestFilterMode +{ + TEST_FILTER_MODE_TEST_NAME_PREFIX, + TEST_FILTER_MODE_TEST_NAME_INFIX, + TEST_FILTER_MODE_FILENAME_EXACT, +}; + struct TestRunnerState { u8 state; u8 exitCode; + enum TestFilterMode filterMode:8; const char *skipFilename; u32 failedAssumptionsBlockLine; const struct Test *test; diff --git a/test/test_runner.c b/test/test_runner.c index 99ba3f42ab..fe9a5eccb6 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -34,6 +34,25 @@ static void Intr_Timer2(void); extern const struct Test __start_tests[]; extern const struct Test __stop_tests[]; +static enum TestFilterMode DetectFilterMode(const char *pattern) +{ + size_t n = strlen(pattern); + if (n > 2 && pattern[n-2] == '.' && pattern[n-1] == 'c') + return TEST_FILTER_MODE_FILENAME_EXACT; + else if (pattern[0] == '*') // TODO: Support '*pattern*'. + return TEST_FILTER_MODE_TEST_NAME_INFIX; + else + return TEST_FILTER_MODE_TEST_NAME_PREFIX; +} + +static bool32 ExactMatch(const char *pattern, const char *string) +{ + if (string == NULL) + return TRUE; + + return strcmp(pattern, string) == 0; +} + static bool32 PrefixMatch(const char *pattern, const char *string) { if (string == NULL) @@ -50,6 +69,14 @@ static bool32 PrefixMatch(const char *pattern, const char *string) } } +static bool32 InfixMatch(const char *pattern, const char *string) +{ + if (string == NULL) + return TRUE; + + return strstr(string, &pattern[1]) != NULL; +} + enum { STATE_INIT, @@ -171,6 +198,8 @@ void CB2_TestRunner(void) return; } + gTestRunnerState.filterMode = DetectFilterMode(gTestRunnerArgv); + MoveSaveBlocks_ResetHeap(); ClearSav1(); ClearSav2(); @@ -231,11 +260,17 @@ void CB2_TestRunner(void) gTestRunnerState.state = STATE_EXIT; return; } - if (gTestRunnerState.test->runner != &gAssumptionsRunner - && !PrefixMatch(gTestRunnerArgv, gTestRunnerState.test->name)) - ++gTestRunnerState.test; - else - break; + if (gTestRunnerState.test->runner != &gAssumptionsRunner) + { + if ((gTestRunnerState.filterMode == TEST_FILTER_MODE_TEST_NAME_PREFIX && !PrefixMatch(gTestRunnerArgv, gTestRunnerState.test->name)) + || (gTestRunnerState.filterMode == TEST_FILTER_MODE_TEST_NAME_INFIX && !InfixMatch(gTestRunnerArgv, gTestRunnerState.test->name)) + || (gTestRunnerState.filterMode == TEST_FILTER_MODE_FILENAME_EXACT && !ExactMatch(gTestRunnerArgv, gTestRunnerState.test->filename))) + { + ++gTestRunnerState.test; + continue; + } + } + break; } Test_MgbaPrintf(":N%s", gTestRunnerState.test->name); From 916f083852a7dd83e3152bdac3bb579570961e3e Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:02:41 +0100 Subject: [PATCH 215/283] Added trainerBackPic to Trainer struct to de-couple trainer pic and trainer back pic defines (#7425) --- include/data.h | 12 +++++++++- src/battle_controller_player_partner.c | 6 ++--- src/battle_transition.c | 2 +- src/data/battle_partners.party | 2 ++ src/data/pokemon/trainer_class_lookups.h | 12 ---------- tools/trainerproc/main.c | 30 ++++++++++++++++++++---- 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/include/data.h b/include/data.h index 4663bae33c..2128685e19 100644 --- a/include/data.h +++ b/include/data.h @@ -106,6 +106,7 @@ struct Trainer /*0x23*/ u8 poolPickIndex; /*0x24*/ u8 poolPruneIndex; /*0x25*/ u16 overrideTrainer; + /*0x26*/ u8 trainerBackPic; }; struct TrainerClass @@ -178,7 +179,6 @@ extern const union AnimCmd *const gAnims_MonPic[]; extern const union AnimCmd *const gAnims_Trainer[]; extern const struct TrainerSprite gTrainerSprites[]; extern const struct TrainerBacksprite gTrainerBacksprites[]; -extern const u16 gTrainerPicToTrainerBackPic[]; extern const struct Trainer gTrainers[DIFFICULTY_COUNT][TRAINERS_COUNT]; extern const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT]; @@ -261,6 +261,16 @@ static inline const u8 GetTrainerPicFromId(u16 trainerId) return GetTrainerStructFromId(trainerId)->trainerPic; } +static inline const u8 GetTrainerBackPicFromId(u16 trainerId) +{ + enum DifficultyLevel partnerDifficulty = GetBattlePartnerDifficultyLevel(trainerId); + + if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) + return gBattlePartners[partnerDifficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerBackPic; + + return GetTrainerStructFromId(trainerId)->trainerBackPic; +} + static inline const u8 GetTrainerStartingStatusFromId(u16 trainerId) { return GetTrainerStructFromId(trainerId)->startingStatus; diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 513e286d12..5426f0239f 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -206,7 +206,7 @@ static void PlayerPartnerHandleDrawTrainerPic(u32 battler) if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { - trainerPicId = gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic; + trainerPicId = gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerBackPic; xPos = 90; yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; } @@ -320,9 +320,9 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(u32 battler) enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(gPartnerTrainerId); if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) - trainerPal = gTrainerBacksprites[gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic].palette.data; + trainerPal = gTrainerBacksprites[gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerBackPic].palette.data; else if (IsAiVsAiBattle()) - trainerPal = gTrainerSprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; + trainerPal = gTrainerSprites[GetTrainerBackPicFromId(gPartnerTrainerId)].palette.data; else trainerPal = gTrainerSprites[GetFrontierTrainerFrontSpriteId(gPartnerTrainerId)].palette.data; // 2 vs 2 multi battle in Battle Frontier, load front sprite and pal. diff --git a/src/battle_transition.c b/src/battle_transition.c index 4b350dd706..114248b93d 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2587,7 +2587,7 @@ static void Mugshots_CreateTrainerPics(struct Task *task) u8 trainerAPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.opponentA); u8 trainerBPicId = GetTrainerPicFromId(TRAINER_BATTLE_PARAM.opponentB); - u8 partnerPicId = gTrainerPicToTrainerBackPic[GetTrainerPicFromId(gPartnerTrainerId)]; + u8 partnerPicId = GetTrainerPicFromId(gPartnerTrainerId); s16 opponentARotationScales = 0; s16 opponentBRotationScales = 0; diff --git a/src/data/battle_partners.party b/src/data/battle_partners.party index e1ecfe35fa..4b93292c6a 100644 --- a/src/data/battle_partners.party +++ b/src/data/battle_partners.party @@ -4,6 +4,7 @@ Class: Pkmn Trainer 1 Pic: Brendan Gender: Male Music: Male +Back Pic: Brendan === PARTNER_STEVEN === Name: STEVEN @@ -11,6 +12,7 @@ Class: Rival Pic: Steven Gender: Male Music: Male +Back Pic: Steven Metang Brave Nature diff --git a/src/data/pokemon/trainer_class_lookups.h b/src/data/pokemon/trainer_class_lookups.h index b3f9282a43..9ce0b629e3 100644 --- a/src/data/pokemon/trainer_class_lookups.h +++ b/src/data/pokemon/trainer_class_lookups.h @@ -84,18 +84,6 @@ const u16 gFacilityClassToPicIndex[] = [FACILITY_CLASS_RS_MAY] = TRAINER_PIC_RS_MAY, }; -const u16 gTrainerPicToTrainerBackPic[] = -{ - [TRAINER_BACK_PIC_BRENDAN] = TRAINER_PIC_BRENDAN, - [TRAINER_BACK_PIC_MAY] = TRAINER_PIC_MAY, - [TRAINER_BACK_PIC_RED] = TRAINER_PIC_RED, - [TRAINER_BACK_PIC_LEAF] = TRAINER_PIC_LEAF, - [TRAINER_BACK_PIC_RUBY_SAPPHIRE_BRENDAN] = TRAINER_PIC_RS_BRENDAN, - [TRAINER_BACK_PIC_RUBY_SAPPHIRE_MAY] = TRAINER_PIC_RS_MAY, - [TRAINER_BACK_PIC_WALLY] = TRAINER_PIC_WALLY, - [TRAINER_BACK_PIC_STEVEN] = TRAINER_PIC_STEVEN, -}; - const enum TrainerClassID gFacilityClassToTrainerClass[] = { [FACILITY_CLASS_HIKER] = TRAINER_CLASS_HIKER, diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 5330c9fe3d..8547735789 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -155,6 +155,9 @@ struct Trainer struct String macro; int macro_line; + + struct String back_pic; + int back_pic_line; }; static bool is_empty_string(struct String s) @@ -1300,6 +1303,13 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct trainer->macro_line = value.location.line; trainer->macro = token_string(&value); } + else if (is_literal_token(&key, "Back Pic")) + { + if (trainer->back_pic_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Back Pic'"); + trainer->back_pic_line = value.location.line; + trainer->back_pic = token_string(&value); + } else { any_error = !set_show_parse_error(p, key.location, "expected one of 'Name', 'Class', 'Pic', 'Gender', 'Music', 'Items', 'Battle Type', 'Difficulty', 'Party Size', 'Pool Rules', 'Pool Pick Functions', 'Pool Prune' or 'AI'"); @@ -1776,10 +1786,7 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par { fprintf(f, "#line %d\n", trainer->pic_line); fprintf(f, " .trainerPic = "); - if (starts_with(trainer->id, "PARTNER_")) - fprint_constant(f, "TRAINER_BACK_PIC", trainer->pic); - else - fprint_constant(f, "TRAINER_PIC", trainer->pic); + fprint_constant(f, "TRAINER_PIC", trainer->pic); fprintf(f, ",\n"); } @@ -1884,6 +1891,21 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par fprint_string(f, trainer->copy_pool); fprintf(f, ",\n"); } + if (!is_empty_string(trainer->back_pic)) + { + fprintf(f, "#line %d\n", trainer->back_pic_line); + fprintf(f, " .trainerBackPic = "); + fprint_constant(f, "TRAINER_BACK_PIC", trainer->back_pic); + fprintf(f, ",\n"); + } + else // defaults to front pic in absence of defined back pic + { + fprintf(f, "#line %d\n", trainer->back_pic_line); + fprintf(f, " .trainerBackPic = "); + fprint_constant(f, "TRAINER_PIC", trainer->pic); + fprintf(f, ",\n"); + } + if (trainer->macro_line) { fprintf(f, "#line %d\n", trainer->macro_line); From 5794b26a31462225b83141e0b231d80d55f76d17 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 13 Aug 2025 05:41:14 -0400 Subject: [PATCH 216/283] Remove funcResult from AiThinkingStruct (#7545) --- include/battle.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/battle.h b/include/battle.h index e1cc318b25..5d37d8f500 100644 --- a/include/battle.h +++ b/include/battle.h @@ -344,7 +344,6 @@ struct AiThinkingStruct u8 movesetIndex; u16 moveConsidered; s32 score[MAX_MON_MOVES]; - u32 funcResult; u64 aiFlags[MAX_BATTLERS_COUNT]; u8 aiAction; u8 aiLogicId; From b4826b446ca2e983eace0fa4251cfd70480f7c7c Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 05:41:26 -0400 Subject: [PATCH 217/283] AI uses Rototiller. (#7542) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_main.c | 26 ++++++++++++++++++++++++++ test/battle/move_effect/rototiller.c | 16 ++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index fe3ff13ee2..9789aa8339 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4134,6 +4134,32 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); break; + case EFFECT_ROTOTILLER: + if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && IsBattlerGrounded(battlerAtk)) + { + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPATK)); + } + if (hasPartner && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS) && IsBattlerGrounded(BATTLE_PARTNER(battlerAtk))) + { + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_SPATK)); + } + if (IS_BATTLER_OF_TYPE(FOE(battlerAtk), TYPE_GRASS) && IsBattlerGrounded(FOE(battlerAtk))) + { + if (aiData->abilities[FOE(battlerAtk)] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + if (IS_BATTLER_OF_TYPE(BATTLE_PARTNER(FOE(battlerAtk)), TYPE_GRASS) && IsBattlerGrounded(BATTLE_PARTNER(FOE(battlerAtk)))) + { + if (aiData->abilities[BATTLE_PARTNER(FOE(battlerAtk))] == ABILITY_CONTRARY) + ADJUST_SCORE(WEAK_EFFECT); + else + ADJUST_SCORE(AWFUL_EFFECT); + } + break; case EFFECT_HAZE: if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk)) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) diff --git a/test/battle/move_effect/rototiller.c b/test/battle/move_effect/rototiller.c index 73ad6c9c85..7214133110 100644 --- a/test/battle/move_effect/rototiller.c +++ b/test/battle/move_effect/rototiller.c @@ -96,3 +96,19 @@ SINGLE_BATTLE_TEST("Rototiller fails if the only valid target is semi-invulnerab EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE); } } + +AI_DOUBLE_BATTLE_TEST("AI uses Rototiller") +{ + GIVEN { + ASSUME(GetSpeciesType(SPECIES_TANGELA, 0) == TYPE_GRASS); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 0) != TYPE_GRASS); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 1) != TYPE_GRASS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(SPECIES_TANGELA) { Moves(MOVE_ROTOTILLER, MOVE_POUND); } + OPPONENT(SPECIES_TANGELA); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_ROTOTILLER); } + } +} From 65b316625f843ef752cbe1279d02fbf0f9e6858b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:00:04 +0200 Subject: [PATCH 218/283] Fixes Knock Off still activating when there is no Item (#7496) --- src/battle_script_commands.c | 8 +++++--- test/battle/hold_effect/eject_pack.c | 2 +- test/battle/hold_effect/red_card.c | 2 +- test/battle/move_effect/future_sight.c | 2 +- test/battle/move_effect/knock_off.c | 16 ++++++++++++++++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e74bb4c60a..d9900c26a1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2756,7 +2756,7 @@ static void Cmd_datahpupdate(void) if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF && IsBattlerTurnDamaged(gBattlerTarget) - && gBattleMons[gBattlerTarget].item != 0 + && gBattleMons[gBattlerTarget].item != ITEM_NONE && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) && !NoAliveMonsForEitherParty()) @@ -6260,7 +6260,9 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) switch (moveEffect) { case EFFECT_KNOCK_OFF: - if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff && IsBattlerAlive(gBattlerAttacker)) + if (gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff + && gBattleMons[gBattlerTarget].item != ITEM_NONE + && IsBattlerAlive(gBattlerAttacker)) { u32 side = GetBattlerSide(gBattlerTarget); gLastUsedItem = gBattleMons[gBattlerTarget].item; @@ -6280,11 +6282,11 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect) gWishFutureKnock.knockedOffMons[side] |= 1u << gBattlerPartyIndexes[gBattlerTarget]; } - gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_KnockedOff; effect = TRUE; } + gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = FALSE; break; case EFFECT_STEAL_ITEM: if (!CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index f33a59de21..208d656362 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Eject Pack does not cause the new Pokémon to lose HP due to ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); MESSAGE("Wobbuffet is switched out with the Eject Pack!"); SEND_IN_MESSAGE("Wynaut"); - NOT MESSAGE("Wynaut was hurt by its Life Orb!"); + NOT HP_BAR(player); ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); } } diff --git a/test/battle/hold_effect/red_card.c b/test/battle/hold_effect/red_card.c index a21318d246..6b5e08c450 100644 --- a/test/battle/hold_effect/red_card.c +++ b/test/battle/hold_effect/red_card.c @@ -455,7 +455,7 @@ SINGLE_BATTLE_TEST("Red Card does not cause the dragged out mon to lose hp due t ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); MESSAGE("The opposing Wobbuffet held up its Red Card against Wobbuffet!"); MESSAGE("Wynaut was dragged out!"); - NOT MESSAGE("Wynaut was hurt by its Life Orb!"); + NOT HP_BAR(player); } } diff --git a/test/battle/move_effect/future_sight.c b/test/battle/move_effect/future_sight.c index 3995e8479f..71e3aa7378 100644 --- a/test/battle/move_effect/future_sight.c +++ b/test/battle/move_effect/future_sight.c @@ -60,7 +60,7 @@ SINGLE_BATTLE_TEST("Future Sight is not boosted by Life Orb is original user if ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); MESSAGE("The opposing Regice took the Future Sight attack!"); HP_BAR(opponent, captureDamage: &futureSightDmg); - NOT MESSAGE("Raichu was hurt by its Life Orb!"); + NOT HP_BAR(player); } THEN { EXPECT_EQ(seedFlareDmg, futureSightDmg); } diff --git a/test/battle/move_effect/knock_off.c b/test/battle/move_effect/knock_off.c index 60be862c4c..eca09a33a6 100644 --- a/test/battle/move_effect/knock_off.c +++ b/test/battle/move_effect/knock_off.c @@ -394,3 +394,19 @@ SINGLE_BATTLE_TEST("Knock Off doesn't remove item if it's prevented by Sticky Ho ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); } } + +SINGLE_BATTLE_TEST("Knock Off does not activate if the item was previously consumed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); } + } WHEN { + TURN { MOVE(player, MOVE_KNOCK_OFF); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_KNOCK_OFF, player); + MESSAGE("The opposing Wobbuffet's Air Balloon popped!"); + NOT MESSAGE("Wobbuffet knocked off the opposing Wobbuffet's Air Balloon!"); + } THEN { + EXPECT(opponent->item == ITEM_NONE); + } +} From 260b12337e8ef6c3d380f40ada2e8d3d10791b0d Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 10:21:13 -0400 Subject: [PATCH 219/283] Helping Hand logic (#7504) --- include/battle_ai_util.h | 1 + src/battle_ai_main.c | 55 ++++++++++++++++++++++++++++++++++--- src/battle_ai_util.c | 23 ++++++++++++++++ test/battle/ai/ai_doubles.c | 37 +++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 2e62a1340b..1b23dd7e1a 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -160,6 +160,7 @@ bool32 AI_IsDamagedByRecoil(u32 battler); u32 GetNoOfHitsToKO(u32 dmg, s32 hp); u32 GetNoOfHitsToKOBattlerDmg(u32 dmg, u32 battlerDef); u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum DamageCalcContext calcContext); +u32 GetBestNoOfHitsToKO(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext); uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef); u16 *GetMovesArray(u32 battler); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 9789aa8339..1bd9b0fb8d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -211,7 +211,7 @@ static u64 GetAiFlags(u16 trainerId) flags = GetTrainerAIFlagsFromId(trainerId); } - if (IsDoubleBattle()) + if (IsDoubleBattle() && flags != 0) { flags |= AI_FLAG_DOUBLE_BATTLE; } @@ -2042,7 +2042,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove)) || gBattleStruct->monToSwitchIntoId[BATTLE_PARTNER(battlerAtk)] != PARTY_SIZE) //Partner is switching out. - ADJUST_SCORE(-10); + ADJUST_SCORE(-20); break; case EFFECT_TRICK: case EFFECT_KNOCK_OFF: @@ -3030,6 +3030,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); + bool32 hasTwoOpponents = HasTwoOpponents(battlerAtk); bool32 hasPartner = HasPartner(battlerAtk); u32 friendlyFireThreshold = GetFriendlyFireKOThreshold(battlerAtk); u32 noOfHitsToKOPartner = GetNoOfHitsToKOBattler(battlerAtk, battlerAtkPartner, gAiThinkingStruct->movesetIndex, AI_ATTACKING); @@ -3088,8 +3089,54 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) switch (effect) { case EFFECT_HELPING_HAND: - if (!hasPartner || !HasDamagingMove(battlerAtkPartner)) - ADJUST_SCORE(-20); + if (!hasPartner + || !HasDamagingMove(battlerAtkPartner) + || (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove))) + { + ADJUST_SCORE(WORST_EFFECT); + } + else + { + u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, FOE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, FOE(battlerAtk), AI_ATTACKING); + u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, FOE(battlerAtkPartner), AI_ATTACKING); + u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, FOE(battlerAtkPartner), AI_ATTACKING); + + if (hasTwoOpponents) + { + // Might be about to die + if (CanTargetFaintAi(FOE(battlerAtk), battlerAtk) && CanTargetFaintAi(FOE(battlerAtkPartner), battlerAtk) + && AI_IsSlower(battlerAtk, FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, FOE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1 + && ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) + ADJUST_SCORE(GOOD_EFFECT); + } + else if (IsBattlerAlive(FOE(battlerAtk))) + { + // Might be about to die + if (CanTargetFaintAi(FOE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1) + ADJUST_SCORE(GOOD_EFFECT); + } + else if (IsBattlerAlive(FOE(battlerAtkPartner))) + { + // Might be about to die + if (CanTargetFaintAi(FOE(battlerAtkPartner), battlerAtk) + && AI_IsSlower(battlerAtk, FOE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + ADJUST_SCORE(GOOD_EFFECT); + + if (ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) + ADJUST_SCORE(GOOD_EFFECT); + + } + + } break; case EFFECT_PERISH_SONG: if (aiData->partnerMove != 0 && HasTrappingMoveEffect(battlerAtkPartner)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a0e5e7716b..2b31bdf98d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1252,6 +1252,29 @@ u32 GetNoOfHitsToKOBattler(u32 battlerAtk, u32 battlerDef, u32 moveIndex, enum D return GetNoOfHitsToKOBattlerDmg(AI_GetDamage(battlerAtk, battlerDef, moveIndex, calcContext, gAiLogicData), battlerDef); } +u32 GetBestNoOfHitsToKO(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) +{ + u32 result = 100; + u32 tempResult = 0; + + struct AiLogicData *aiData = gAiLogicData; + s32 moveIndex; + u16 *moves = GetMovesArray(battlerAtk); + u32 moveLimitations = aiData->moveLimitations[battlerAtk]; + + for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) + { + if (IsMoveUnusable(moveIndex, moves[moveIndex], moveLimitations)) + continue; + + tempResult = GetNoOfHitsToKOBattler(battlerAtk, battlerDef, moveIndex, calcContext); + if (tempResult != 0 && tempResult < result) + result = tempResult; + } + + return result; +} + u32 GetCurrDamageHpPercent(u32 battlerAtk, u32 battlerDef, enum DamageCalcContext calcContext) { int bestDmg = AI_GetDamage(battlerAtk, battlerDef, gAiThinkingStruct->movesetIndex, calcContext, gAiLogicData); diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index 9e6edc4c56..ff880fb2e2 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -595,6 +595,43 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently") } } +AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if it's about to die") +{ + u32 hp; + + PARAMETRIZE { hp = 1; } + PARAMETRIZE { hp = 500; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_HELPING_HAND) == EFFECT_HELPING_HAND); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { HP(hp); Moves(MOVE_HELPING_HAND, MOVE_MUDDY_WATER); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_MUDDY_WATER); } + } WHEN { + if (hp == 1) + TURN { EXPECT_MOVE(opponentLeft, MOVE_HELPING_HAND); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_HELPING_HAND); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if the ally does notably more damage") +{ + + GIVEN { + ASSUME(GetMoveEffect(MOVE_HELPING_HAND) == EFFECT_HELPING_HAND); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CELEBRATE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HELPING_HAND, MOVE_MUD_SLAP); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_MUDDY_WATER); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_HELPING_HAND); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses Tailwind") { u32 speed1, speed2, speed3, speed4; From 296707434200a2e9272a3cd7751f2725c3124bc6 Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 12:06:16 -0400 Subject: [PATCH 220/283] AI handling for Autotomize. (#7550) --- src/battle_ai_main.c | 1 + src/battle_ai_util.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 1bd9b0fb8d..34f0cb2d2f 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4112,6 +4112,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_SPEED_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED)); break; + case EFFECT_AUTOTOMIZE: case EFFECT_SPEED_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED_2)); break; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2b31bdf98d..02915816e0 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2641,6 +2641,7 @@ bool32 IsStatRaisingEffect(enum BattleMoveEffects effect) case EFFECT_DEFENSE_UP: case EFFECT_DEFENSE_UP_2: case EFFECT_DEFENSE_UP_3: + case EFFECT_AUTOTOMIZE: case EFFECT_SPEED_UP: case EFFECT_SPEED_UP_2: case EFFECT_SPECIAL_ATTACK_UP: From a5f569d4ee52065e086b5848a763aab315f370a6 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Wed, 13 Aug 2025 21:27:59 +0200 Subject: [PATCH 221/283] Fix Shell Side Arm in battle test WITH_RNG (#7548) --- test/test_runner_battle.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index c009219e26..a116dd0b52 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -444,7 +444,7 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) if (sum == 0) Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":LRandomWeightedArray called with zero sum"); - if (gCurrentTurnActionNumber < gBattlersCount) + if (gCurrentTurnActionNumber < gBattlersCount || tag == RNG_SHELL_SIDE_ARM) { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; @@ -2216,6 +2216,17 @@ void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx) DATA.battleRecordTurns[DATA.turns][battlerId].secondaryEffect = 1 + ctx.secondaryEffect; if (ctx.explicitRNG) DATA.battleRecordTurns[DATA.turns][battlerId].rng = ctx.rng; + + u32 shellSideArmCount = 0; + for (u32 i = 0; i < STATE->battlersCount; i++) + { + if (DATA.battleRecordTurns[DATA.turns][i].rng.tag == RNG_SHELL_SIDE_ARM) + { + shellSideArmCount++; + if (shellSideArmCount > 1) + Test_ExitWithResult(TEST_RESULT_ERROR, SourceLine(0), ":L Tried to use fixed RNG for multiple Shell Side Arm moves in the same turn"); + } + } if (!(DATA.actionBattlers & (1 << battlerId))) { From 0ab811a239ccf29da3095b7f1499d23c3fa8bda9 Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 15:29:23 -0400 Subject: [PATCH 222/283] AI uses Stuff Cheeks; treating it simply as a def +2 move for now. (#7554) --- src/battle_ai_main.c | 1 + test/battle/move_effect/stuff_cheeks.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 34f0cb2d2f..81fd9716df 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4106,6 +4106,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_DEFENSE_UP_3: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF)); break; + case EFFECT_STUFF_CHEEKS: case EFFECT_DEFENSE_UP_2: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_DEF_2)); break; diff --git a/test/battle/move_effect/stuff_cheeks.c b/test/battle/move_effect/stuff_cheeks.c index 9e6a34c306..b8dda1d8b6 100644 --- a/test/battle/move_effect/stuff_cheeks.c +++ b/test/battle/move_effect/stuff_cheeks.c @@ -103,3 +103,16 @@ SINGLE_BATTLE_TEST("Stuff Cheeks fails if the user's berry is removed before the MESSAGE("But it failed!"); } } + +AI_SINGLE_BATTLE_TEST("AI uses Stuff Cheeks") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_STUFF_CHEEKS) == EFFECT_STUFF_CHEEKS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_HEADBUTT); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE, MOVE_HEADBUTT); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); Moves(MOVE_HEADBUTT, MOVE_STUFF_CHEEKS); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_STUFF_CHEEKS); } + } +} From 45a7c136560cb06fe52c04955974455f22743870 Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 15:30:03 -0400 Subject: [PATCH 223/283] Slight Purify adjustment for targeting ally; test that AI can use Purify. (#7553) --- src/battle_ai_main.c | 4 +++- test/battle/move_effect/purify.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 81fd9716df..2971e68bdb 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3562,7 +3562,9 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_PURIFY: if (gBattleMons[battlerAtkPartner].status1 & STATUS1_ANY) { - RETURN_SCORE_PLUS(WEAK_EFFECT); + if (gBattleMons[battlerAtkPartner].status1 & STATUS1_CAN_MOVE) + RETURN_SCORE_PLUS(WEAK_EFFECT); + RETURN_SCORE_PLUS(GOOD_EFFECT); } break; case EFFECT_SWAGGER: diff --git a/test/battle/move_effect/purify.c b/test/battle/move_effect/purify.c index 134c96119f..26cc661054 100644 --- a/test/battle/move_effect/purify.c +++ b/test/battle/move_effect/purify.c @@ -2,3 +2,25 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Purify (Move Effect) test titles") + +AI_DOUBLE_BATTLE_TEST("AI uses Purify") +{ + u32 status1; + + PARAMETRIZE { status1 = STATUS1_NONE; } + PARAMETRIZE { status1 = STATUS1_FREEZE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HEADBUTT, MOVE_PURIFY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(status1); Moves(MOVE_HEADBUTT); } + } WHEN { + if (status1 == STATUS1_NONE) + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_PURIFY); } + else + TURN { EXPECT_MOVE(opponentLeft, MOVE_PURIFY, target: opponentRight); } + } +} + From 0a8c8ad338bab93bb2211964a8bb968b18487f2d Mon Sep 17 00:00:00 2001 From: surskitty Date: Wed, 13 Aug 2025 15:31:05 -0400 Subject: [PATCH 224/283] AI handling for Howl. (#7549) --- src/battle_ai_main.c | 3 ++- src/battle_ai_util.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2971e68bdb..ddd0bf131b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4097,8 +4097,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckViability(battlerAtk, battlerDef, predictedMove, score); break; - case EFFECT_ATTACK_UP: case EFFECT_ATTACK_UP_USER_ALLY: + ADJUST_SCORE(IncreaseStatUpScore(BATTLE_PARTNER(battlerAtk), battlerDef, STAT_CHANGE_ATK)); + case EFFECT_ATTACK_UP: ADJUST_SCORE(IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_ATK)); break; case EFFECT_ATTACK_UP_2: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 02915816e0..2712c4499f 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2636,6 +2636,7 @@ bool32 IsStatRaisingEffect(enum BattleMoveEffects effect) { switch (effect) { + case EFFECT_ATTACK_UP_USER_ALLY: case EFFECT_ATTACK_UP: case EFFECT_ATTACK_UP_2: case EFFECT_DEFENSE_UP: From 4986e06caeb278ea750da32ad0322b852cde9f4b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 15 Aug 2025 03:03:21 -0400 Subject: [PATCH 225/283] Fixed `B_PSYWAVE_DMG` (#7557) --- include/config/battle.h | 2 +- src/battle_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index f4a14f4df4..57fc4cdf44 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -28,7 +28,7 @@ #define B_BURN_DAMAGE GEN_LATEST // In Gen7+, burn damage is 1/16th of max HP instead of 1/8th. Also applies to Frostbite. #define B_BURN_FACADE_DMG GEN_LATEST // In Gen6+, burn's effect of lowering the Attack stat no longer applies to Facade. #define B_BINDING_DAMAGE GEN_LATEST // In Gen6+, binding damage is 1/8 of max HP instead of 1/16. (With Binding Band, 1/6 and 1/8 respectively.) -#define B_PSYWAVE_DMG GEN_LATEST // Psywave's damage formula. See Cmd_psywavedamageeffect. +#define B_PSYWAVE_DMG GEN_LATEST // Psywave's damage formula. See DoFixedDamageMoveCalc for details. #define B_PAYBACK_SWITCH_BOOST GEN_LATEST // In Gen5+, if the opponent switches out, Payback's damage will no longer be doubled. #define B_HIDDEN_POWER_DMG GEN_LATEST // In Gen6+, Hidden Power's base power was set to always be 60. Before, it was determined by the mon's IVs. #define B_ROUGH_SKIN_DMG GEN_LATEST // In Gen4+, Rough Skin contact damage is 1/8th of max HP instead of 1/16th. This will also affect Iron Barbs. diff --git a/src/battle_util.c b/src/battle_util.c index f8fb5faa86..e27347b4bd 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9493,7 +9493,7 @@ static inline s32 DoFixedDamageMoveCalc(struct DamageCalculationData *damageCalc dmg = gBattleMons[damageCalcData->battlerAtk].level; break; case EFFECT_PSYWAVE: - randDamage = B_PSYWAVE_DMG >= GEN_6 ? (Random() % 101) : ((Random() % 11) * 10); + randDamage = B_PSYWAVE_DMG >= GEN_5 ? (Random() % 101) : ((Random() % 11) * 10); dmg = gBattleMons[damageCalcData->battlerAtk].level * (randDamage + 50) / 100; break; case EFFECT_FIXED_DAMAGE_ARG: From 905bda386fea36cfe0c612e70f3aac6ead7782ff Mon Sep 17 00:00:00 2001 From: surskitty Date: Fri, 15 Aug 2025 03:03:33 -0400 Subject: [PATCH 226/283] Test that AI uses Dragon Cheer. (#7552) --- test/battle/move_effect/dragon_cheer.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/battle/move_effect/dragon_cheer.c b/test/battle/move_effect/dragon_cheer.c index c6dfa3c4dd..a7fff9e7d5 100644 --- a/test/battle/move_effect/dragon_cheer.c +++ b/test/battle/move_effect/dragon_cheer.c @@ -103,3 +103,29 @@ DOUBLE_BATTLE_TEST("Dragon Cheer fails if critical hit stage was already increas } TO_DO_BATTLE_TEST("Baton Pass passes Dragon Cheer's effect"); + +AI_DOUBLE_BATTLE_TEST("AI uses Dragon Cheer") +{ + u32 species; + PARAMETRIZE { species = SPECIES_DRATINI; } + PARAMETRIZE { species = SPECIES_WOBBUFFET; } + + GIVEN { + ASSUME(GetSpeciesType(SPECIES_DRATINI, 0) == TYPE_DRAGON); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 0) != TYPE_DRAGON); + ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 1) != TYPE_DRAGON); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, MOVE_CELEBRATE); } + OPPONENT(species) { Moves(MOVE_DRAGON_CHEER, MOVE_POUND); } + OPPONENT(species) { Moves(MOVE_DRAGON_CHEER, MOVE_POUND); } + } WHEN { + if (species == SPECIES_DRATINI) + TURN { EXPECT_MOVE(opponentLeft, MOVE_DRAGON_CHEER); } + else + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_DRAGON_CHEER); } + } +} + + + From d5ada824550577da30edddaf46b3f132f71d6baf Mon Sep 17 00:00:00 2001 From: Ruby Date: Sat, 16 Aug 2025 01:33:39 +0800 Subject: [PATCH 227/283] Moved summary screen nature colors to summary_screen.h (#7560) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/config/general.h | 1 - include/config/summary_screen.h | 1 + src/pokemon_summary_screen.c | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config/general.h b/include/config/general.h index 1bb70ce00d..97838504ee 100644 --- a/include/config/general.h +++ b/include/config/general.h @@ -68,7 +68,6 @@ // General settings #define EXPANSION_INTRO TRUE // If TRUE, a custom RHH intro will play after the vanilla copyright screen. -#define SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. #define HQ_RANDOM TRUE // If TRUE, replaces the default RNG with an implementation of SFC32 RNG. May break code that relies on RNG. #define COMPETITIVE_PARTY_SYNTAX TRUE // If TRUE, parties are defined in "competitive syntax". #define AUTO_SCROLL_TEXT FALSE // If TRUE, text will automatically scroll to the next line after NUM_FRAMES_AUTO_SCROLL_DELAY. Players can still press A_BUTTON or B_BUTTON to scroll on their own. diff --git a/include/config/summary_screen.h b/include/config/summary_screen.h index 9407d93c7e..4b5f434cb3 100644 --- a/include/config/summary_screen.h +++ b/include/config/summary_screen.h @@ -3,6 +3,7 @@ // Settings #define P_SUMMARY_SCREEN_MOVE_RELEARNER TRUE // If TRUE, shows an option for Pokémon to relearn moves on the summary screen moves page. +#define P_SUMMARY_SCREEN_NATURE_COLORS TRUE // If TRUE, nature-based stat boosts and reductions will be red and blue in the summary screen. #define P_SUMMARY_MOVE_RELEARNER_FULL_PP TRUE // If TRUE, the move relearner in the summary screen restores relearned moves' PP to full. #define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page. #define P_SUMMARY_SCREEN_IV_EV_INFO FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page. diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index d4ea8e5d4e..ca2bf37490 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -3765,7 +3765,7 @@ static void BufferStat(u8 *dst, u8 statIndex, u32 stat, u32 strId, u32 n) static const u8 sTextNatureNeutral[] = _("{COLOR}{01}"); u8 *txtPtr; - if (statIndex == 0 || !SUMMARY_SCREEN_NATURE_COLORS || gNaturesInfo[sMonSummaryScreen->summary.mintNature].statUp == gNaturesInfo[sMonSummaryScreen->summary.mintNature].statDown) + if (statIndex == 0 || !P_SUMMARY_SCREEN_NATURE_COLORS || gNaturesInfo[sMonSummaryScreen->summary.mintNature].statUp == gNaturesInfo[sMonSummaryScreen->summary.mintNature].statDown) txtPtr = StringCopy(dst, sTextNatureNeutral); else if (statIndex == gNaturesInfo[sMonSummaryScreen->summary.mintNature].statUp) txtPtr = StringCopy(dst, sTextNatureUp); From 3a4dbec0216a2dacbd2012a7f48142f81ef71ab4 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 15 Aug 2025 19:34:54 +0200 Subject: [PATCH 228/283] Re-order moves in fling test (#7559) Co-authored-by: Hedara --- test/battle/move_effect/fling.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/battle/move_effect/fling.c b/test/battle/move_effect/fling.c index b98020474b..87074430d2 100644 --- a/test/battle/move_effect/fling.c +++ b/test/battle/move_effect/fling.c @@ -446,12 +446,12 @@ SINGLE_BATTLE_TEST("Fling deals damage based on items fling power") PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_VENUSAURITE); } OPPONENT(SPECIES_REGIROCK); } WHEN { - TURN { MOVE(player, MOVE_CRUNCH); } TURN { MOVE(player, MOVE_FLING); } + TURN { MOVE(player, MOVE_CRUNCH); } } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_CRUNCH, player); - HP_BAR(opponent, captureDamage: &damage[0]); ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CRUNCH, player); HP_BAR(opponent, captureDamage: &damage[1]); } THEN { EXPECT_EQ(damage[0], damage[1]); From f998ec8ea8637c803bd8fe91c2cd26e7e934b67f Mon Sep 17 00:00:00 2001 From: surskitty Date: Sun, 17 Aug 2025 03:14:18 -0400 Subject: [PATCH 229/283] Incorrect call in Rest (#7569) --- src/battle_ai_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 5c0c0b0590..95ac1e43b3 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4114,8 +4114,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) { if (aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_SLP || aiData->holdEffects[battlerAtk] == HOLD_EFFECT_CURE_STATUS - || HasMoveWithEffect(EFFECT_SLEEP_TALK, battlerAtk) - || HasMoveWithEffect(EFFECT_SNORE, battlerAtk) + || HasMoveWithEffect(battlerAtk, EFFECT_SLEEP_TALK) + || HasMoveWithEffect(battlerAtk, EFFECT_SNORE) || aiData->abilities[battlerAtk] == ABILITY_SHED_SKIN || aiData->abilities[battlerAtk] == ABILITY_EARLY_BIRD || (AI_GetWeather() & B_WEATHER_RAIN && gWishFutureKnock.weatherDuration != 1 && aiData->abilities[battlerAtk] == ABILITY_HYDRATION && aiData->holdEffects[battlerAtk] != HOLD_EFFECT_UTILITY_UMBRELLA)) From 60f5f3302d591971245b0e6e5025b8e124f2307c Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 17 Aug 2025 21:49:53 +0200 Subject: [PATCH 230/283] Fix tossing a stack of berries hiding following berries (#7571) Co-authored-by: Hedara --- src/item.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/item.c b/src/item.c index 6802b2272c..162798acde 100644 --- a/src/item.c +++ b/src/item.c @@ -32,6 +32,7 @@ static bool32 CheckPyramidBagHasItem(u16 itemId, u16 count); static bool32 CheckPyramidBagHasSpace(u16 itemId, u16 count); static const u8 *GetItemPluralName(u16); static bool32 DoesItemHavePluralName(u16); +static void NONNULL BagPocket_CompactItems(struct BagPocket *pocket); EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; @@ -391,6 +392,9 @@ static bool32 NONNULL BagPocket_RemoveItem(struct BagPocket *pocket, u16 itemId, } } + if (totalQuantity == count) + BagPocket_CompactItems(pocket); + Free(tempPocketSlotQuantities); return totalQuantity >= count; } From 7b8edfa631e026d9e97300f9ea8336e3bcbd518e Mon Sep 17 00:00:00 2001 From: Ruby Date: Mon, 18 Aug 2025 03:50:23 +0800 Subject: [PATCH 231/283] Added comment in event.inc for simple menus in dynmultichoice (#7568) --- asm/macros/event.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 1cf9c7fca7..891c93e6d5 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1875,6 +1875,7 @@ @ Displays a multichoice box from which the user can choose a selection, and blocks script execution until a selection is made. @ Lists of options are provided in argv. @ If ignoreBPress is set to a non-zero value, then the user will not be allowed to back out of the multichoice with the B button. + @ For a simple menu supply DYN_MULTICHOICE_CB_NONE in callbacks. .macro dynmultichoice left:req, top:req, ignoreBPress:req, maxBeforeScroll:req, initialSelected:req, callbacks:req argv:vararg _dynmultichoice \left, \top, \ignoreBPress, \maxBeforeScroll, FALSE, \initialSelected, \callbacks, \argv .endm From 7d459fd6dccd76d11d47e9f3150e5e7fc0fd6492 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 18 Aug 2025 13:44:43 -0400 Subject: [PATCH 232/283] Fixed Transistor damage calculation test failing when `GEN_LATEST` is less than `GEN_9` (#7577) --- include/constants/generational_changes.h | 1 + include/generational_changes.h | 1 + src/battle_util.c | 2 +- test/battle/ai/check_bad_move.c | 1 + test/battle/damage_formula.c | 29 +++++++++++++++++------- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index e51d57915c..83c9caa203 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -29,6 +29,7 @@ enum GenConfigTag GEN_SNOW_WARNING, GEN_ALLY_SWITCH_FAIL_CHANCE, GEN_DREAM_EATER_LIQUID_OOZE, + GEN_CONFIG_TRANSISTOR_BOOST, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index 53991bab1f..a6f3a56ef7 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -32,6 +32,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_SNOW_WARNING] = B_SNOW_WARNING, [GEN_ALLY_SWITCH_FAIL_CHANCE] = B_ALLY_SWITCH_FAIL_CHANCE, [GEN_DREAM_EATER_LIQUID_OOZE] = B_DREAM_EATER_LIQUID_OOZE, + [GEN_CONFIG_TRANSISTOR_BOOST] = B_TRANSISTOR_BOOST, }; #if TESTING diff --git a/src/battle_util.c b/src/battle_util.c index ed00fb4d45..7729b0f67a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8706,7 +8706,7 @@ static inline u32 CalcAttackStat(struct DamageContext *ctx) case ABILITY_TRANSISTOR: if (moveType == TYPE_ELECTRIC) { - if (B_TRANSISTOR_BOOST >= GEN_9) + if (GetGenConfig(GEN_CONFIG_TRANSISTOR_BOOST) >= GEN_9) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); else modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); diff --git a/test/battle/ai/check_bad_move.c b/test/battle/ai/check_bad_move.c index 79b960ec60..776dcd7de2 100644 --- a/test/battle/ai/check_bad_move.c +++ b/test/battle/ai/check_bad_move.c @@ -15,6 +15,7 @@ AI_SINGLE_BATTLE_TEST("AI will not try to lower opposing stats if target is prot PARAMETRIZE { ability = ABILITY_CLEAR_BODY; species = SPECIES_BELDUM; move = MOVE_NOBLE_ROAR; } GIVEN { + WITH_CONFIG(GEN_ILLUMINATE_EFFECT, GEN_9); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_OMNISCIENT); PLAYER(species) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, move); } diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c index 0679725510..f41f6a2145 100644 --- a/test/battle/damage_formula.c +++ b/test/battle/damage_formula.c @@ -231,23 +231,36 @@ SINGLE_BATTLE_TEST("Gem boosted Damage calculation") #define NUM_DAMAGE_SPREADS (DMG_ROLL_PERCENT_HI - DMG_ROLL_PERCENT_LO) + 1 -static const s16 sThunderShockTransistorSpread[] = { 54, 55, 56, 57, 57, 58, 59, 60, 60, 60, 61, 62, 63, 63, 64, 65 }; +static const s16 sThunderShockTransistorSpreadGen9[] = { 54, 55, 56, 57, 57, 58, 59, 60, 60, 60, 61, 62, 63, 63, 64, 65 }; +static const s16 sThunderShockTransistorSpreadGen8[] = { 63, 64, 65, 66, 66, 67, 68, 69, 69, 70, 71, 72, 72, 73, 74, 75 }; static const s16 sThunderShockRegularSpread[] = { 42, 42, 43, 43, 44, 45, 45, 45, 46, 46, 47, 48, 48, 48, 49, 50 }; -static const s16 sWildChargeTransistorSpread[] = { 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145 }; +static const s16 sWildChargeTransistorSpreadGen9[] = { 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145 }; +static const s16 sWildChargeTransistorSpreadGen8[] = { 141, 143, 145, 147, 148, 150, 151, 153, 155, 156, 158, 160, 162, 163, 165, 167 }; static const s16 sWildChargeRegularSpread[] = { 94, 96, 96, 98, 99, 100, 101, 102, 103, 105, 105, 107, 108, 109, 110, 111 }; DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage) { s16 expectedDamageTransistorSpec = 0, expectedDamageRegularPhys = 0, expectedDamageRegularSpec = 0, expectedDamageTransistorPhys = 0; s16 damagePlayerLeft, damagePlayerRight, damageOpponentLeft, damageOpponentRight; + u32 gen = 0; for (u32 spread = 0; spread < 16; ++spread) { - PARAMETRIZE { expectedDamageTransistorSpec = sThunderShockTransistorSpread[spread], + PARAMETRIZE { gen = GEN_9, + expectedDamageTransistorSpec = sThunderShockTransistorSpreadGen9[spread], + expectedDamageRegularSpec = sThunderShockRegularSpread[spread]; + expectedDamageTransistorPhys = sWildChargeTransistorSpreadGen9[spread], + expectedDamageRegularPhys = sWildChargeRegularSpread[spread]; + } + } + for (u32 spread = 0; spread < 16; ++spread) { + PARAMETRIZE { gen = GEN_8, + expectedDamageTransistorSpec = sThunderShockTransistorSpreadGen8[spread], expectedDamageRegularSpec = sThunderShockRegularSpread[spread], - expectedDamageTransistorPhys = sWildChargeTransistorSpread[spread], + expectedDamageTransistorPhys = sWildChargeTransistorSpreadGen8[spread], expectedDamageRegularPhys = sWildChargeRegularSpread[spread]; } } GIVEN { + WITH_CONFIG(GEN_CONFIG_TRANSISTOR_BOOST, gen); ASSUME(GetMoveType(MOVE_WILD_CHARGE) == TYPE_ELECTRIC); ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC); ASSUME(GetMoveCategory(MOVE_WILD_CHARGE) == DAMAGE_CATEGORY_PHYSICAL); @@ -260,10 +273,10 @@ DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage) OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); } } WHEN { TURN { - MOVE(playerLeft, MOVE_THUNDER_SHOCK, target: opponentLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); - MOVE(playerRight, MOVE_THUNDER_SHOCK, target: opponentRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); - MOVE(opponentLeft, MOVE_WILD_CHARGE, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); - MOVE(opponentRight, MOVE_WILD_CHARGE, target: playerRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); + MOVE(playerLeft, MOVE_THUNDER_SHOCK, target: opponentLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - (i % 16))); + MOVE(playerRight, MOVE_THUNDER_SHOCK, target: opponentRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - (i % 16))); + MOVE(opponentLeft, MOVE_WILD_CHARGE, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - (i % 16))); + MOVE(opponentRight, MOVE_WILD_CHARGE, target: playerRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - (i % 16))); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerLeft); From 5c70eeb7ed57816cbc0acb09da3a77126ffe316a Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 18 Aug 2025 13:45:18 -0400 Subject: [PATCH 233/283] Fix switch AI not seeing its own move PP (#7578) --- src/battle_ai_switch_items.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index c11f448645..a52541c8c8 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -230,7 +230,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { damageTaken = AI_GetDamage(opposingBattler, battler, i, AI_DEFENDING, gAiLogicData); if (damageTaken > maxDamageTaken && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) @@ -254,7 +254,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) { aiMove = gBattleMons[battler].moves[i]; aiMoveEffect = GetMoveEffect(aiMove); - if (aiMove != MOVE_NONE) + if (aiMove != MOVE_NONE && gBattleMons[battler].pp[i] > 0) { u32 nonVolatileStatus = GetMoveNonVolatileStatus(aiMove); // Check if mon has an "important" status move @@ -1972,7 +1972,7 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move @@ -1997,7 +1997,8 @@ static s32 GetMaxPriorityDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposi for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = SMART_SWITCHING_OMNISCIENT ? gBattleMons[opposingBattler].moves[i] : playerMoves[i]; - if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 && playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH) + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 + && playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && GetMoveEffect(playerMove) != EFFECT_FOCUS_PUNCH && gBattleMons[opposingBattler].pp[i] > 0) { damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, AI_DEFENDING); if (playerMove == gBattleStruct->choicedMove[opposingBattler]) // If player is choiced, only care about the choice locked move @@ -2135,6 +2136,10 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, // Check through current mon's moves for (j = 0; j < MAX_MON_MOVES; j++) { + // Check that move has PP remaining before running calcs + if (gAiLogicData->switchinCandidate.battleMon.pp[j] < 1) + continue; + aiMove = gAiLogicData->switchinCandidate.battleMon.moves[j]; damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon, AI_ATTACKING); hitsToKOPlayer = GetNoOfHitsToKOBattlerDmg(damageDealt, opposingBattler); From e60b9e979f78b846da9603034345ddeac64ccce1 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 18 Aug 2025 13:45:41 -0400 Subject: [PATCH 234/283] Fix wrong battler argument in `GetBattleMovePriority` call (#7576) --- src/battle_ai_switch_items.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index a52541c8c8..1bc3ae31f0 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -238,7 +238,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) maxDamageTaken = damageTaken; bestPlayerMove = playerMove; } - if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[battler], playerMove) > 0 && damageTaken > maxDamageTakenPriority && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) + if (GetBattleMovePriority(opposingBattler, gAiLogicData->abilities[opposingBattler], playerMove) > 0 && damageTaken > maxDamageTakenPriority && !AI_DoesChoiceEffectBlockMove(opposingBattler, playerMove)) { maxDamageTakenPriority = damageTaken; bestPlayerPriorityMove = playerMove; From 1a39ebd7da57f33316b38115027d2ead0f9de3d2 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 18 Aug 2025 19:51:19 +0200 Subject: [PATCH 235/283] Changed default print level for DebugPrintf for mGBA to MGBA_LOG_WARN (#7567) Co-authored-by: Hedara --- include/gba/isagbprint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gba/isagbprint.h b/include/gba/isagbprint.h index d362b5cb38..c94df4fe1d 100644 --- a/include/gba/isagbprint.h +++ b/include/gba/isagbprint.h @@ -30,7 +30,7 @@ void AGBPrintInit(void); #if (LOG_HANDLER == LOG_HANDLER_MGBA_PRINT) -#define DebugPrintf(pBuf, ...) MgbaPrintf(MGBA_LOG_INFO, pBuf, ## __VA_ARGS__) +#define DebugPrintf(pBuf, ...) MgbaPrintf(MGBA_LOG_WARN, pBuf, ## __VA_ARGS__) #define DebugAssert(pFile, nLine, pExpression, nStopProgram) MgbaAssert(pFile, nLine, pExpression, nStopProgram) #define DebugPrintfLevel(level, pBuf, ...) MgbaPrintf(level, pBuf, ## __VA_ARGS__) From e974adcbeb8ff217a019d7c93949b26f46a3efc1 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 18 Aug 2025 13:54:28 -0400 Subject: [PATCH 236/283] Wrote some tests (#7563) --- test/battle/hold_effect/safety_goggles.c | 30 +++++++- test/battle/move_effect/belly_drum.c | 91 +++++++++++++++++++++++- test/battle/move_effect/bolt_beak.c | 50 ++++++++++++- 3 files changed, 165 insertions(+), 6 deletions(-) diff --git a/test/battle/hold_effect/safety_goggles.c b/test/battle/hold_effect/safety_goggles.c index e2d329bcf6..346e41fbfe 100644 --- a/test/battle/hold_effect/safety_goggles.c +++ b/test/battle/hold_effect/safety_goggles.c @@ -44,4 +44,32 @@ SINGLE_BATTLE_TEST("Safety Goggles blocks damage from Sandstorm") } } -TO_DO_BATTLE_TEST("Safety Goggles blocks Effect Spore's effect"); +SINGLE_BATTLE_TEST("Safety Goggles blocks Effect Spore's effect") +{ + PASSES_RANDOMLY(100, 100, RNG_EFFECT_SPORE); + GIVEN { + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SAFETY_GOGGLES); } + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, player); + MESSAGE("Wobbuffet was poisoned by the opposing Breloom's Effect Spore!"); + STATUS_ICON(player, poison: TRUE); + + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, player); + MESSAGE("The opposing Breloom's Effect Spore paralyzed Wobbuffet, so it may be unable to move!"); + STATUS_ICON(player, paralysis: TRUE); + + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + } + } +} diff --git a/test/battle/move_effect/belly_drum.c b/test/battle/move_effect/belly_drum.c index 1580487cca..20024f5b91 100644 --- a/test/battle/move_effect/belly_drum.c +++ b/test/battle/move_effect/belly_drum.c @@ -130,6 +130,91 @@ SINGLE_BATTLE_TEST("Belly Drum minimizes the user's Attack stat with Contrary", } } -TO_DO_BATTLE_TEST("Belly Drum maximizes the user's Attack stat, even when below 0"); -TO_DO_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary"); -TO_DO_BATTLE_TEST("Belly Drum deducts HP if the user has contrary and is at -6"); +SINGLE_BATTLE_TEST("Belly Drum maximizes the user's Attack stat, even when below 0", s16 damage) +{ + bool32 raiseAttack; + PARAMETRIZE { raiseAttack = FALSE; } + PARAMETRIZE { raiseAttack = TRUE; } + GIVEN { + ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (raiseAttack) TURN { MOVE(opponent, MOVE_GROWL); MOVE(player, MOVE_BELLY_DRUM); } + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + if (raiseAttack) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet cut its own HP and maximized its Attack!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } THEN { + if (raiseAttack) EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 6); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(4), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(GetMoveEffect(MOVE_CHARM) == EFFECT_ATTACK_DOWN_2); + PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CHARM); } + TURN { MOVE(opponent, MOVE_CHARM); } + TURN { MOVE(opponent, MOVE_CHARM); } + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack sharply rose!"); + + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } + } +} + +SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack harshly fell!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack harshly fell!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Serperior's Attack harshly fell!"); + + NOT MESSAGE("But it failed!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + HP_BAR(player, hp: maxHP / 2); + MESSAGE("Wobbuffet cut its own HP and maximized its Attack!"); + } +} diff --git a/test/battle/move_effect/bolt_beak.c b/test/battle/move_effect/bolt_beak.c index fdd95da700..f7c11858da 100644 --- a/test/battle/move_effect/bolt_beak.c +++ b/test/battle/move_effect/bolt_beak.c @@ -1,5 +1,51 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Bolt Beak's base power is doubled if it attacks before the target"); -TO_DO_BATTLE_TEST("Bolt Beak's base power is doubled the target switches out"); +SINGLE_BATTLE_TEST("Bolt Beak's base power is doubled if it attacks before the target", s16 damage) +{ + u32 speed; + PARAMETRIZE { speed = 1; } + PARAMETRIZE { speed = 3; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_BOLT_BEAK) == EFFECT_BOLT_BEAK); + PLAYER(SPECIES_DRACOZOLT) { Speed(speed); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(player, MOVE_BOLT_BEAK); } + } SCENE { + if (speed == 1) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_BOLT_BEAK, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + if (speed == 3) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Bolt Beak's base power is doubled the target switches out", s16 damage) +{ + bool32 switchOut; + PARAMETRIZE { switchOut = FALSE; } + PARAMETRIZE { switchOut = TRUE; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_BOLT_BEAK) == EFFECT_BOLT_BEAK); + PLAYER(SPECIES_DRACOZOLT) { Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { + MOVE(player, MOVE_BOLT_BEAK); + if (switchOut) + SWITCH(opponent, 1); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BOLT_BEAK, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} From 6c261fe41667363ad477ad7b09419906c18a143d Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 18 Aug 2025 15:09:09 -0400 Subject: [PATCH 237/283] Fixed compile issue in gcc 11 (#7579) --- src/battle_ai_util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2712c4499f..84d247a617 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2107,10 +2107,12 @@ u32 IncreaseStatDownScore(u32 battlerAtk, u32 battlerDef, u32 stat) tempScore += DECENT_EFFECT; break; case STAT_SPEED: + { u32 predictedMoveSpeedCheck = GetIncomingMoveSpeedCheck(battlerAtk, battlerDef, gAiLogicData); if (AI_IsSlower(battlerAtk, battlerDef, gAiThinkingStruct->moveConsidered, predictedMoveSpeedCheck, DONT_CONSIDER_PRIORITY)) tempScore += DECENT_EFFECT; break; + } case STAT_SPATK: if (HasMoveWithCategory(battlerDef, DAMAGE_CATEGORY_SPECIAL)) tempScore += DECENT_EFFECT; @@ -3632,7 +3634,7 @@ bool32 HasChoiceEffect(u32 battler) if (ability == ABILITY_KLUTZ) return FALSE; - + enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battler]; switch (holdEffect) { @@ -3881,7 +3883,7 @@ bool32 AreMovesEquivalent(u32 battlerAtk, u32 battlerAtkPartner, u32 move, u32 p return FALSE; u32 battlerDef = gBattleStruct->moveTarget[battlerAtk]; - + // We don't care the effect is basically the same; we would use this move anyway. if (GetBestDmgMoveFromBattler(battlerAtk, battlerDef, AI_ATTACKING) == move) return FALSE; From 82bf955e3519268631bc674fa578f1ae5457bdb4 Mon Sep 17 00:00:00 2001 From: khbsd Date: Tue, 19 Aug 2025 06:54:43 +0000 Subject: [PATCH 238/283] fix: remove unused wild_encounters.json.txt jinja file (#7581) --- src/data/wild_encounters.json.txt | 103 ------------------------------ 1 file changed, 103 deletions(-) delete mode 100755 src/data/wild_encounters.json.txt diff --git a/src/data/wild_encounters.json.txt b/src/data/wild_encounters.json.txt deleted file mode 100755 index 8ae70efc6e..0000000000 --- a/src/data/wild_encounters.json.txt +++ /dev/null @@ -1,103 +0,0 @@ -{{ doNotModifyHeader }} - -## for wild_encounter_group in wild_encounter_groups -{% if wild_encounter_group.for_maps %} -## for wild_encounter_field in wild_encounter_group.fields -{% if not existsIn(wild_encounter_field, "groups") %} -## for encounter_rate in wild_encounter_field.encounter_rates -{% if loop.index == 0 %} -#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_SLOT_{{ loop.index }} {{ encounter_rate }} {% else %}#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_SLOT_{{ loop.index }} ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_SLOT_{{ subtract(loop.index, 1) }} + {{ encounter_rate }}{% endif %} {{ setVarInt(wild_encounter_field.type, loop.index) }} -## endfor -#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_TOTAL (ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_SLOT_{{ getVar(wild_encounter_field.type) }}) -{% else %} -## for field_subgroup_key, field_subgroup_subarray in wild_encounter_field.groups -## for field_subgroup_index in field_subgroup_subarray -{% if loop.index == 0 %} -#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_{{ upper(field_subgroup_key) }}_SLOT_{{ field_subgroup_index }} {{ at(wild_encounter_field.encounter_rates, field_subgroup_index) }} {% else %}#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_{{ upper(field_subgroup_key) }}_SLOT_{{ field_subgroup_index }} ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_{{ upper(field_subgroup_key) }}_SLOT_{{ getVar("previous_slot") }} + {{ at(wild_encounter_field.encounter_rates, field_subgroup_index) }}{% endif %}{{ setVarInt(concat(wild_encounter_field.type, field_subgroup_key), field_subgroup_index) }}{{ setVarInt("previous_slot", field_subgroup_index) }} -## endfor -#define ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_{{ upper(field_subgroup_key) }}_TOTAL (ENCOUNTER_CHANCE_{{ upper(wild_encounter_field.type) }}_{{ upper(field_subgroup_key) }}_SLOT_{{ getVar(concat(wild_encounter_field.type, field_subgroup_key)) }}) -## endfor -{% endif %} -## endfor -{% endif %} - - - -## for encounter in wild_encounter_group.encounters -{% if existsIn(encounter, "land_mons") %} -const struct WildPokemon {{ encounter.base_label }}_LandMons[] = -{ -## for wild_mon in encounter.land_mons.mons - { {{ wild_mon.min_level }}, {{ wild_mon.max_level }}, {{ wild_mon.species }} }, -## endfor -}; - -const struct WildPokemonInfo {{ encounter.base_label }}_LandMonsInfo = { {{encounter.land_mons.encounter_rate}}, {{ encounter.base_label }}_LandMons }; -{% endif %} -{% if existsIn(encounter, "water_mons") %} -const struct WildPokemon {{ encounter.base_label }}_WaterMons[] = -{ -## for wild_mon in encounter.water_mons.mons - { {{ wild_mon.min_level }}, {{ wild_mon.max_level }}, {{ wild_mon.species }} }, -## endfor -}; - -const struct WildPokemonInfo {{ encounter.base_label }}_WaterMonsInfo = { {{encounter.water_mons.encounter_rate}}, {{ encounter.base_label }}_WaterMons }; -{% endif %} -{% if existsIn(encounter, "rock_smash_mons") %} -const struct WildPokemon {{ encounter.base_label }}_RockSmashMons[] = -{ -## for wild_mon in encounter.rock_smash_mons.mons - { {{ wild_mon.min_level }}, {{ wild_mon.max_level }}, {{ wild_mon.species }} }, -## endfor -}; - -const struct WildPokemonInfo {{ encounter.base_label }}_RockSmashMonsInfo = { {{encounter.rock_smash_mons.encounter_rate}}, {{ encounter.base_label }}_RockSmashMons }; -{% endif %} -{% if existsIn(encounter, "fishing_mons") %} -const struct WildPokemon {{ encounter.base_label }}_FishingMons[] = -{ -## for wild_mon in encounter.fishing_mons.mons - { {{ wild_mon.min_level }}, {{ wild_mon.max_level }}, {{ wild_mon.species }} }, -## endfor -}; - -const struct WildPokemonInfo {{ encounter.base_label }}_FishingMonsInfo = { {{encounter.fishing_mons.encounter_rate}}, {{ encounter.base_label }}_FishingMons }; -{% endif %} - -{% if existsIn(encounter, "hidden_mons") %} -const struct WildPokemon {{ encounter.base_label }}_HiddenMons[] = -{ -## for wild_mon in encounter.hidden_mons.mons - { {{ wild_mon.min_level }}, {{ wild_mon.max_level }}, {{ wild_mon.species }} }, -## endfor -}; - -const struct WildPokemonInfo {{ encounter.base_label }}_HiddenMonsInfo = { {{encounter.hidden_mons.encounter_rate}}, {{ encounter.base_label }}_HiddenMons }; -{% endif %} - -## endfor -const struct WildPokemonHeader {{ wild_encounter_group.label }}[] = -{ -## for encounter in wild_encounter_group.encounters - { - .mapGroup = {% if wild_encounter_group.for_maps %}MAP_GROUP({{ encounter.map }}){% else %}0{% endif %}, - .mapNum = {% if wild_encounter_group.for_maps %}MAP_NUM({{ encounter.map }}){% else %}{{ loop.index1 }}{% endif %}, - .landMonsInfo = {% if existsIn(encounter, "land_mons") %}&{{ encounter.base_label }}_LandMonsInfo{% else %}NULL{% endif %}, - .waterMonsInfo = {% if existsIn(encounter, "water_mons") %}&{{ encounter.base_label }}_WaterMonsInfo{% else %}NULL{% endif %}, - .rockSmashMonsInfo = {% if existsIn(encounter, "rock_smash_mons") %}&{{ encounter.base_label }}_RockSmashMonsInfo{% else %}NULL{% endif %}, - .fishingMonsInfo = {% if existsIn(encounter, "fishing_mons") %}&{{ encounter.base_label }}_FishingMonsInfo{% else %}NULL{% endif %}, - .hiddenMonsInfo = {% if existsIn(encounter, "hidden_mons") %}&{{ encounter.base_label }}_HiddenMonsInfo{% else %}NULL{% endif %}, - }, -## endfor - { - .mapGroup = MAP_GROUP(MAP_UNDEFINED), - .mapNum = MAP_NUM(MAP_UNDEFINED), - .landMonsInfo = NULL, - .waterMonsInfo = NULL, - .rockSmashMonsInfo = NULL, - .fishingMonsInfo = NULL, - .hiddenMonsInfo = NULL, - }, -}; -## endfor From 554c9099839920006d274819453400dc2075ccc1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 19 Aug 2025 08:56:21 +0200 Subject: [PATCH 239/283] Fixes Counter / Mirror Coat / Metal Burst damage assignment (#7538) --- src/battle_script_commands.c | 9 ++- test/battle/move_effect/counter.c | 113 +++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d9900c26a1..80a5ad664e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -13451,13 +13451,12 @@ static void Cmd_counterdamagecalculator(void) && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; - if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 2; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13478,13 +13477,13 @@ static void Cmd_mirrorcoatdamagecalculator(void) && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 2; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -16732,26 +16731,26 @@ void BS_CalcMetalBurstDmg(void) && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].physicalBattlerId)) && gBattleMons[gProtectStructs[gBattlerAttacker].physicalBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100; gBattlescriptCurrInstr = cmd->nextInstr; } else if (gProtectStructs[gBattlerAttacker].specialDmg && sideAttacker != (sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId)) && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp) { - gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget, gCurrentMove)) gBattlerTarget = gSideTimers[sideTarget].followmeTarget; else gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId; + gBattleStruct->moveDamage[gBattlerTarget] = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100; gBattlescriptCurrInstr = cmd->nextInstr; } else diff --git a/test/battle/move_effect/counter.c b/test/battle/move_effect/counter.c index d45e75b478..ece0ea9a9f 100644 --- a/test/battle/move_effect/counter.c +++ b/test/battle/move_effect/counter.c @@ -1,6 +1,12 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_COUNTER) == EFFECT_COUNTER); + ASSUME(GetMoveCategory(MOVE_POUND) == DAMAGE_CATEGORY_PHYSICAL); +} + SINGLE_BATTLE_TEST("Counter is not affected by Protect effects") { u32 move; @@ -38,9 +44,110 @@ SINGLE_BATTLE_TEST("Counter is not affected by Protect effects") } } -TO_DO_BATTLE_TEST("Counter will do twice as much damage received from the opponent"); -TO_DO_BATTLE_TEST("Counter cannot affect ally Pokémon"); -TO_DO_BATTLE_TEST("Counter hits the last opponent that hit the user"); //Doubles +SINGLE_BATTLE_TEST("Counter will do twice as much damage received from the opponent") +{ + s16 normalDmg; + s16 counterDmg; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_POUND); MOVE(player, MOVE_COUNTER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent); + HP_BAR(player, captureDamage: &normalDmg); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, player); + HP_BAR(opponent, captureDamage: &counterDmg); + } THEN { + EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), counterDmg); + } +} + +DOUBLE_BATTLE_TEST("Counter cannot affect ally Pokémon") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(playerLeft, MOVE_POUND, target: playerRight); + MOVE(playerRight, MOVE_COUNTER, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Counter hits the last opponent that hit the user") +{ + s16 normalDmg; + s16 counterDmg; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_POUND, target: playerLeft); + MOVE(opponentRight, MOVE_SLAM, target: playerLeft); + MOVE(playerLeft, MOVE_COUNTER); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SLAM, opponentRight); + HP_BAR(playerLeft, captureDamage: &normalDmg); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, playerLeft); + HP_BAR(opponentRight, captureDamage: &counterDmg); + } THEN { + EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), counterDmg); + } +} + +DOUBLE_BATTLE_TEST("Counter respects Follow me") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentRight, MOVE_FOLLOW_ME); + MOVE(opponentLeft, MOVE_POUND, target: playerLeft); + MOVE(playerLeft, MOVE_COUNTER, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FOLLOW_ME, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, playerLeft); + HP_BAR(opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Counter fails if mon that damaged counter user is no longer on the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); }; + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_POUND, target: playerLeft); + MOVE(playerRight, MOVE_POUND, target: opponentLeft); + MOVE(playerLeft, MOVE_COUNTER, target: opponentLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_COUNTER, playerLeft); + } +} // Gen 1 TO_DO_BATTLE_TEST("Counter can only counter Normal and Fighting-type moves (Gen 1)"); From cc705a580de21ec61e3e42e4fff4a42a36f2a187 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Tue, 19 Aug 2025 02:57:35 -0400 Subject: [PATCH 240/283] Fix Form Change Item Task Data and Clean Up Field Use Funcs (#7535) --- src/item_use.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/item_use.c b/src/item_use.c index 0a8a5be06e..ca7bb494f3 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1402,41 +1402,35 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) void ItemUseOutOfBattle_FormChange(u8 taskId) { gItemUseCB = ItemUseCB_FormChange; - gTasks[taskId].data[0] = FALSE; SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8 taskId) { gItemUseCB = ItemUseCB_FormChange_ConsumedOnUse; - gTasks[taskId].data[0] = TRUE; SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_RotomCatalog(u8 taskId) { gItemUseCB = ItemUseCB_RotomCatalog; - gTasks[taskId].data[0] = TRUE; SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_ZygardeCube(u8 taskId) { gItemUseCB = ItemUseCB_ZygardeCube; - gTasks[taskId].data[0] = TRUE; SetUpItemUseCallback(taskId); } void ItemUseOutOfBattle_Fusion(u8 taskId) { gItemUseCB = ItemUseCB_Fusion; - gTasks[taskId].data[0] = FALSE; SetUpItemUseCallback(taskId); } void Task_UseHoneyOnField(u8 taskId) { - //ResetInitialPlayerAvatarState(); StartSweetScentFieldEffect(); DestroyTask(taskId); } @@ -1447,7 +1441,6 @@ static void ItemUseOnFieldCB_Honey(u8 taskId) RemoveBagItem(gSpecialVar_ItemId, 1); CopyItemName(gSpecialVar_ItemId, gStringVar2); StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); - gTasks[taskId].data[0] = 0; DisplayItemMessageOnField(taskId, gStringVar4, Task_UseHoneyOnField); } @@ -1532,7 +1525,7 @@ static void Task_DisplayPokeFluteMessage(u8 taskId) { if (WaitFanfare(FALSE)) { - if (gTasks[taskId].data[3] == 0) + if (!gTasks[taskId].tUsingRegisteredKeyItem) DisplayItemMessage(taskId, FONT_NORMAL, sText_PokeFluteAwakenedMon, CloseItemMessage); else DisplayItemMessageOnField(taskId, sText_PokeFluteAwakenedMon, Task_CloseCantUseKeyItemMessage); @@ -1558,14 +1551,14 @@ void ItemUseOutOfBattle_PokeFlute(u8 taskId) if (wokeSomeoneUp) { - if (gTasks[taskId].data[3] == 0) + if (!gTasks[taskId].tUsingRegisteredKeyItem) DisplayItemMessage(taskId, FONT_NORMAL, sText_PlayedPokeFlute, Task_PlayPokeFlute); else DisplayItemMessageOnField(taskId, sText_PlayedPokeFlute, Task_PlayPokeFlute); } else { - if (gTasks[taskId].data[3] == 0) + if (!gTasks[taskId].tUsingRegisteredKeyItem) DisplayItemMessage(taskId, FONT_NORMAL, sText_PlayedPokeFluteCatchy, CloseItemMessage); else DisplayItemMessageOnField(taskId, sText_PlayedPokeFluteCatchy, Task_CloseCantUseKeyItemMessage); From 96653e704e465307580fa2302a828a53d1e800e6 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 19 Aug 2025 08:39:20 -0400 Subject: [PATCH 241/283] Fixed Teleport's description not being updated based on `B_TELEPORT_BEHAVIOR` (#7580) --- src/data/moves_info.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 00da8aa15f..248e69ccca 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -2668,10 +2668,10 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = [MOVE_TELEPORT] = { .name = COMPOUND_STRING("Teleport"), - #if B_TELEPORT_BEHAVIOUR >= GEN_8 + #if B_TELEPORT_BEHAVIOR >= GEN_8 .description = COMPOUND_STRING( "Switches the user out last.\n" - "Flees when used by wild {PKMN}.") + "Flees when used by wild {PKMN}."), #else .description = COMPOUND_STRING( "A psychic move for fleeing\n" From 888783aaa5d90135da38f10beac6a001d879e8a6 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Wed, 20 Aug 2025 15:22:19 +0100 Subject: [PATCH 242/283] Restore AI: Basic Trainer to PARTNER_STEVEN (#7586) --- src/battle_tower.c | 1 + src/data/battle_partners.party | 1 + 2 files changed, 2 insertions(+) diff --git a/src/battle_tower.c b/src/battle_tower.c index 6eeac96d4a..2d0cbbe11e 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -25,6 +25,7 @@ #include "battle_factory.h" #include "constants/abilities.h" #include "constants/apprentice.h" +#include "constants/battle_ai.h" #include "constants/battle_dome.h" #include "constants/battle_frontier.h" #include "constants/battle_frontier_mons.h" diff --git a/src/data/battle_partners.party b/src/data/battle_partners.party index 4b93292c6a..8de1dc0f2b 100644 --- a/src/data/battle_partners.party +++ b/src/data/battle_partners.party @@ -13,6 +13,7 @@ Pic: Steven Gender: Male Music: Male Back Pic: Steven +AI: Basic Trainer Metang Brave Nature From 553e5bd09c88f780d6fb93d1271f045b85d6ca6b Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:26:48 +0100 Subject: [PATCH 243/283] Fixes refusing to replace a move on evolution causing a softlock (#7585) --- src/evolution_scene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evolution_scene.c b/src/evolution_scene.c index 1f9d2af8fa..fb3e79a655 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -986,7 +986,7 @@ static void Task_EvolutionScene(u8 taskId) if (var == MAX_MON_MOVES) { // Didn't select move slot - gTasks[taskId].tLearnMoveNoState = (P_ASK_MOVE_CONFIRMATION) ? MVSTATE_ASK_CANCEL : MVSTATE_CANCEL; + gTasks[taskId].tLearnMoveState = (P_ASK_MOVE_CONFIRMATION) ? MVSTATE_ASK_CANCEL : MVSTATE_CANCEL; } else { @@ -1370,7 +1370,7 @@ static void Task_TradeEvolutionScene(u8 taskId) if (var == MAX_MON_MOVES) { // Didn't select move slot - gTasks[taskId].tLearnMoveNoState = (P_ASK_MOVE_CONFIRMATION) ? T_MVSTATE_ASK_CANCEL : T_MVSTATE_CANCEL; + gTasks[taskId].tLearnMoveState = (P_ASK_MOVE_CONFIRMATION) ? T_MVSTATE_ASK_CANCEL : T_MVSTATE_CANCEL; } else { From 2d9dc28b7a2a5c500f33b796a0d592c49cc3a5b9 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Thu, 21 Aug 2025 06:44:15 -0400 Subject: [PATCH 244/283] Fix in-game partner battles always causing a whiteout (#7587) --- data/battle_scripts_1.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8688b2e97e..2b086fd1d6 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5389,13 +5389,13 @@ BattleScript_PayDayMoneyAndPickUpItems:: end2 BattleScript_LocalBattleLost:: - jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut jumpifbattletype BATTLE_TYPE_DOME, BattleScript_CheckDomeDrew jumpifbattletype BATTLE_TYPE_FRONTIER, BattleScript_LocalBattleLostPrintTrainersWinText jumpifbattletype BATTLE_TYPE_TRAINER_HILL, BattleScript_LocalBattleLostPrintTrainersWinText jumpifbattletype BATTLE_TYPE_EREADER_TRAINER, BattleScript_LocalBattleLostEnd jumpifhalfword CMP_EQUAL, gTrainerBattleParameter + 2, TRAINER_SECRET_BASE, BattleScript_LocalBattleLostEnd jumpifnowhiteout BattleScript_LocalBattleLostEnd_ + jumpifbattletype BATTLE_TYPE_INGAME_PARTNER, BattleScript_LocalBattleLostPrintWhiteOut BattleScript_LocalBattleLostPrintWhiteOut:: getmoneyreward .if B_WHITEOUT_MONEY >= GEN_4 From 8e5855108882d861deb638619fc2bb0f80b104f7 Mon Sep 17 00:00:00 2001 From: surskitty Date: Thu, 21 Aug 2025 08:41:43 -0400 Subject: [PATCH 245/283] Tests to see that the AI uses moves. (#7555) --- test/battle/ai/can_use_all_moves.c | 702 +++++++++++++++++++++++++++++ 1 file changed, 702 insertions(+) create mode 100644 test/battle/ai/can_use_all_moves.c diff --git a/test/battle/ai/can_use_all_moves.c b/test/battle/ai/can_use_all_moves.c new file mode 100644 index 0000000000..3bf33a98c1 --- /dev/null +++ b/test/battle/ai/can_use_all_moves.c @@ -0,0 +1,702 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +// All tests here compare the move to Splash, a move that does nothing and scores 90: the same as Thundershock on a ground type. +// The switch case for effects skips moves that have been human reviewed in three categories: something is wrong in some way; the move is equivalent to Splash for a good reason but a test is not known to exist; a test is known to exist. +// Jump to "TODO: AI HANDLING" and "TODO: AI TESTS" +// In many cases, AI handling exists but is likely insufficient in some way. + +AI_DOUBLE_BATTLE_TEST("AI uses Final Gambit") +{ + KNOWN_FAILING; + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_FINAL_GAMBIT); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_FINAL_GAMBIT); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Guillotine") +{ + KNOWN_FAILING; + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_GUILLOTINE); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_GUILLOTINE); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI uses Sheer Cold") +{ + KNOWN_FAILING; + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_SHEER_COLD); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_SHEER_COLD); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 1-100") +{ + u32 moveStart = 0; + u32 moveCap = 100; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_OHKO: // Guillotine is crashing the test entirely. + case EFFECT_MIST: + case EFFECT_TELEPORT: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_MIMIC: + case EFFECT_DISABLE: + + // tests exist elsewhere + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 101-200") +{ + u32 moveStart = 100; + u32 moveCap = 200; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: + case EFFECT_BIDE: + case EFFECT_NIGHTMARE: + case EFFECT_SNORE: + case EFFECT_SKETCH: + case EFFECT_BELLY_DRUM: + case EFFECT_DESTINY_BOND: + case EFFECT_MIRROR_MOVE: + case EFFECT_REST: + case EFFECT_SUBSTITUTE: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_MIMIC: + case EFFECT_SOFTBOILED: + case EFFECT_DREAM_EATER: + case EFFECT_CONVERSION: + case EFFECT_PERISH_SONG: + case EFFECT_FOCUS_ENERGY: + case EFFECT_SPITE: + + // tests exist elsewhere + case EFFECT_HAZE: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 201-300") +{ + u32 moveStart = 200; + u32 moveCap = 300; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_SLEEP_TALK: // logic exists but does not account for Rest correctly + case EFFECT_SAFEGUARD: // logic exists but does not account for Rest correctly + case EFFECT_FOLLOW_ME: + case EFFECT_SNATCH: + case EFFECT_GRUDGE: + case EFFECT_CAMOUFLAGE: + case EFFECT_IMPRISON: + case EFFECT_INGRAIN: + case EFFECT_MAGIC_COAT: + case EFFECT_MUD_SPORT: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_SOFTBOILED: + case EFFECT_ENDURE: + case EFFECT_BATON_PASS: + case EFFECT_ENCORE: + case EFFECT_MORNING_SUN: + case EFFECT_MOONLIGHT: + case EFFECT_SYNTHESIS: + case EFFECT_SPIT_UP: + case EFFECT_SWALLOW: + case EFFECT_WISH: + case EFFECT_RECYCLE: + + // tests exist elsewhere + case EFFECT_HEAL_BELL: + case EFFECT_SUNNY_DAY: + case EFFECT_RAIN_DANCE: + case EFFECT_HAIL: + case EFFECT_ROLE_PLAY: + case EFFECT_REFRESH: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_SANDSTORM: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400") +{ + u32 moveStart = 300; + u32 moveCap = 400; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_SHEER_COLD: // Guillotine is crashing the test entirely. + case EFFECT_WATER_SPORT: + case EFFECT_LUCKY_CHANT: + case EFFECT_ME_FIRST: + case EFFECT_PSYCHO_SHIFT: + case EFFECT_COPYCAT: + case EFFECT_LAST_RESORT: + case EFFECT_AQUA_RING: + case EFFECT_GRAVITY: + case EFFECT_HEALING_WISH: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_ROOST: + case EFFECT_GUARD_SWAP: + case EFFECT_POWER_SWAP: + case EFFECT_HEART_SWAP: + case EFFECT_TAILWIND: + case EFFECT_POWER_TRICK: + case EFFECT_MAGNET_RISE: + + // tests exist elsewhere + case EFFECT_HEAL_BELL: + case EFFECT_ATTACK_UP_USER_ALLY: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500") +{ + u32 moveStart = 400; + u32 moveCap = 500; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_HEALING_WISH: + case EFFECT_WONDER_ROOM: + case EFFECT_FOLLOW_ME: + case EFFECT_MAGIC_ROOM: + case EFFECT_AFTER_YOU: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_CAPTIVATE: + + // tests exist elsewhere + case EFFECT_TRICK_ROOM: + case EFFECT_GUARD_SPLIT: + case EFFECT_POWER_SPLIT: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 501-600") +{ + u32 moveStart = 515; + u32 moveCap = 600; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + case EFFECT_FINAL_GAMBIT: + //TODO: AI HANDLING + case EFFECT_ALLY_SWITCH: + case EFFECT_QUASH: + case EFFECT_REFLECT_TYPE: + case EFFECT_SKY_DROP: + case EFFECT_MAT_BLOCK: + case EFFECT_ION_DELUGE: + case EFFECT_AROMATIC_MIST: + case EFFECT_POWDER: + case EFFECT_FLOWER_SHIELD: + case EFFECT_ELECTRIFY: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_HEAL_PULSE: + case EFFECT_BELCH: + case EFFECT_TOPSY_TURVY: + case EFFECT_FAIRY_LOCK: + + // tests exist elsewhere + case EFFECT_ROTOTILLER: + case EFFECT_GRASSY_TERRAIN: + case EFFECT_MISTY_TERRAIN: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700") +{ + u32 moveStart = 600; + u32 moveCap = 700; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_MAGNETIC_FLUX: + case EFFECT_GEAR_UP: + case EFFECT_FAIL_IF_NOT_ARG_TYPE: + case EFFECT_STUFF_CHEEKS: + case EFFECT_NO_RETREAT: + case EFFECT_TEATIME: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_SHORE_UP: + case EFFECT_HEAL_PULSE: + case EFFECT_LASER_FOCUS: + case EFFECT_PURIFY: + case EFFECT_INSTRUCT: + case EFFECT_SOAK: + + // tests exist elsewhere + case EFFECT_ELECTRIC_TERRAIN: + case EFFECT_PSYCHIC_TERRAIN: + case EFFECT_AURORA_VEIL: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 701-800") +{ + u32 moveStart = 700; + u32 moveCap = 800; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_CLANGOROUS_SOUL: + case EFFECT_LIFE_DEW: + case EFFECT_POLTERGEIST: + case EFFECT_COACHING: + case EFFECT_REVIVAL_BLESSING: + case EFFECT_FILLET_AWAY: + + //TODO: AI TESTS + case EFFECT_RESTORE_HP: + case EFFECT_STEEL_ROLLER: + case EFFECT_JUNGLE_HEALING: + case EFFECT_POWER_TRICK: + case EFFECT_TAKE_HEART: + + // tests exist elsewhere + case EFFECT_COURT_CHANGE: + case EFFECT_DOODLE: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} + +AI_DOUBLE_BATTLE_TEST("AI can use all moves, 801-900") +{ + u32 moveStart = 800; + u32 moveCap = 900; + + if (moveCap > MOVES_COUNT) + moveCap = MOVES_COUNT - 1; + + s32 j; + u32 move = MOVE_NONE; + + enum BattleMoveEffects effect; + + for (j = moveStart + 1; j <= moveCap; j++) + { + effect = GetMoveEffect(j); + + // Stat raising effects are not meant to be used when you have only Splash. + if (IsStatRaisingEffect(effect)) + continue; + + switch (effect) + { + //TODO: AI HANDLING + case EFFECT_SHED_TAIL: + case EFFECT_FAIL_IF_NOT_ARG_TYPE: + + //TODO: AI TESTS + case EFFECT_CHILLY_RECEPTION: + case EFFECT_TIDY_UP: + + // tests exist elsewhere + case EFFECT_SNOWSCAPE: + case EFFECT_DRAGON_CHEER: + + // Skipped on purpose. + case EFFECT_PROTECT: + case EFFECT_NON_VOLATILE_STATUS: + case EFFECT_DO_NOTHING: + case EFFECT_HOLD_HANDS: + case EFFECT_CELEBRATE: + case EFFECT_HAPPY_HOUR: + break; + default: + PARAMETRIZE { move = j; } + } + } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, move); Status1(STATUS1_BURN); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_POUND, move); Item(ITEM_STARF_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); } + } +} From 208f97e1e3c40766611865d475a6d2ec755af975 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:43:19 +0200 Subject: [PATCH 246/283] Rename passive damage hitmarker (#2174) --- data/battle_scripts_1.s | 26 +++++++++++++------------- include/constants/battle.h | 2 +- src/battle_main.c | 4 ++-- src/battle_script_commands.c | 8 ++++---- src/battle_util.c | 4 ++-- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 00a40fbbb0..49ffeffb42 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3208,7 +3208,7 @@ BattleScript_DamagingWeatherLoop:: jumpifword CMP_EQUAL, gBattleMoveDamage, 0, BattleScript_DamagingWeatherLoopIncrement printfromtable gSandStormHailDmgStringIds waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE + orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_GRUDGE effectivenesssound hitanimation BS_ATTACKER healthbarupdate BS_ATTACKER @@ -3220,7 +3220,7 @@ BattleScript_DamagingWeatherLoopIncrement:: addbyte gBattleCommunication, 1 jumpifbytenotequal gBattleCommunication, gBattlersCount, BattleScript_DamagingWeatherLoop BattleScript_DamagingWeatherContinuesEnd:: - bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE | HITMARKER_GRUDGE + bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_GRUDGE end2 BattleScript_SandStormHailEnds:: @@ -3264,7 +3264,7 @@ BattleScript_SafeguardEnds:: BattleScript_LeechSeedTurnDrain:: playanimation BS_ATTACKER, B_ANIM_LEECH_SEED_DRAIN, sB_ANIM_ARG1 - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER copyword gBattleMoveDamage, gHpDealt @@ -3275,7 +3275,7 @@ BattleScript_LeechSeedTurnDrain:: BattleScript_LeechSeedTurnPrintLiquidOoze:: setbyte cMULTISTRING_CHOOSER, B_MSG_LEECH_SEED_OOZE BattleScript_LeechSeedTurnPrintAndUpdateHp:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET printfromtable gLeechSeedStringIds @@ -3379,14 +3379,14 @@ BattleScript_EncoredNoMore:: BattleScript_DestinyBondTakesLife:: printstring STRINGID_PKMNTOOKFOE waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER return BattleScript_SpikesOnAttacker:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER call BattleScript_PrintHurtBySpikes @@ -3401,7 +3401,7 @@ BattleScript_SpikesOnAttackerFainted:: goto BattleScript_HandleFaintedMon BattleScript_SpikesOnTarget:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_TARGET datahpupdate BS_TARGET call BattleScript_PrintHurtBySpikes @@ -3416,7 +3416,7 @@ BattleScript_SpikesOnTargetFainted:: goto BattleScript_HandleFaintedMon BattleScript_SpikesOnFaintedBattler:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_FAINTED datahpupdate BS_FAINTED call BattleScript_PrintHurtBySpikes @@ -3438,7 +3438,7 @@ BattleScript_PrintHurtBySpikes:: BattleScript_PerishSongTakesLife:: printstring STRINGID_PKMNPERISHCOUNTFELL waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER @@ -3739,7 +3739,7 @@ BattleScript_PoisonTurnDmg:: BattleScript_DoStatusTurnDmg:: statusanimation BS_ATTACKER BattleScript_DoTurnDmg:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER tryfaintmon BS_ATTACKER @@ -3806,7 +3806,7 @@ BattleScript_DoSelfConfusionDmg:: effectivenesssound hitanimation BS_ATTACKER waitstate - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER resultmessage @@ -3939,7 +3939,7 @@ BattleScript_MoveEffectRecoil:: jumpifmove MOVE_STRUGGLE, BattleScript_DoRecoil jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd BattleScript_DoRecoil:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_PKMNHITWITHRECOIL @@ -4182,7 +4182,7 @@ BattleScript_ColorChangeActivates:: return BattleScript_RoughSkinActivates:: - orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER printstring STRINGID_PKMNHURTSWITH diff --git a/include/constants/battle.h b/include/constants/battle.h index 0bc9cc658e..f6b4836ba2 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -194,7 +194,7 @@ enum BattlerId #define HITMARKER_IGNORE_UNDERGROUND (1 << 17) #define HITMARKER_IGNORE_UNDERWATER (1 << 18) #define HITMARKER_UNABLE_TO_USE_MOVE (1 << 19) -#define HITMARKER_PASSIVE_DAMAGE (1 << 20) +#define HITMARKER_PASSIVE_HP_UPDATE (1 << 20) #define HITMARKER_DISOBEDIENT_MOVE (1 << 21) #define HITMARKER_PLAYER_FAINTED (1 << 22) #define HITMARKER_ALLOW_NO_PP (1 << 23) diff --git a/src/battle_main.c b/src/battle_main.c index 6aa9fc1902..d6cbad4727 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3975,7 +3975,7 @@ void BattleTurnPassed(void) gHitMarker &= ~HITMARKER_NO_ATTACKSTRING; gHitMarker &= ~HITMARKER_UNABLE_TO_USE_MOVE; gHitMarker &= ~HITMARKER_PLAYER_FAINTED; - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleScripting.animTurn = 0; gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; @@ -4944,7 +4944,7 @@ static void RunTurnActionsFunctions(void) if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished { - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F]; } else diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b8b17a8123..429551e889 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1929,13 +1929,13 @@ static void Cmd_datahpupdate(void) } // Record damage for Shell Bell - if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + if (gSpecialStatuses[gActiveBattler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) gSpecialStatuses[gActiveBattler].shellBellDmg = gHpDealt; // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are // used in combination as general damage trackers for other purposes. specialDmg is additionally used // to help determine if a fire move should defrost the target. - if (IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE) && gCurrentMove != MOVE_PAIN_SPLIT) + if (IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE) && gCurrentMove != MOVE_PAIN_SPLIT) { // Record physical damage/attacker for Counter gProtectStructs[gActiveBattler].physicalDmg = gHpDealt; @@ -1951,7 +1951,7 @@ static void Cmd_datahpupdate(void) gSpecialStatuses[gActiveBattler].physicalBattlerId = gBattlerTarget; } } - else if (!IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + else if (!IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_PASSIVE_HP_UPDATE)) { // Record special damage/attacker for Mirror Coat gProtectStructs[gActiveBattler].specialDmg = gHpDealt; @@ -1968,7 +1968,7 @@ static void Cmd_datahpupdate(void) } } } - gHitMarker &= ~HITMARKER_PASSIVE_DAMAGE; + gHitMarker &= ~HITMARKER_PASSIVE_HP_UPDATE; // Send updated HP BtlController_EmitSetMonData(B_COMM_TO_CONTROLLER, REQUEST_HP_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].hp), &gBattleMons[gActiveBattler].hp); diff --git a/src/battle_util.c b/src/battle_util.c index 7a9786b67f..ffe5f38743 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -650,7 +650,7 @@ void HandleAction_NothingIsFainted(void) gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_IGNORE_ON_AIR - | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_PASSIVE_DAMAGE + | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT | HITMARKER_CHARGING | HITMARKER_NEVER_SET); } @@ -663,7 +663,7 @@ void HandleAction_ActionFinished(void) SpecialStatusesClear(); gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_IGNORE_ON_AIR - | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_PASSIVE_DAMAGE + | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_PASSIVE_HP_UPDATE | HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT | HITMARKER_CHARGING | HITMARKER_NEVER_SET); From 95eb3ba1a7e36166e507a67ab2cdde3df3c59f70 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Thu, 21 Aug 2025 14:43:41 +0200 Subject: [PATCH 247/283] Fix B_ANIMATE_MON_AFTER_KO with a new counter (#7531) Co-authored-by: Hedara Co-authored-by: Martin Griffin --- data/battle_scripts_1.s | 6 ++++++ include/battle.h | 2 +- src/battle_controllers.c | 2 ++ src/battle_script_commands.c | 2 +- src/pokemon_animation.c | 5 +++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2b086fd1d6..6d20887fb4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5232,6 +5232,7 @@ BattleScript_FaintAttacker:: dofaintanimation BS_ATTACKER printstring STRINGID_ATTACKERFAINTED cleareffectsonfaint BS_ATTACKER + waitanimation tryactivatesoulheart tryactivatereceiver BS_ATTACKER trytrainerslidefirstdownmsg BS_ATTACKER @@ -5246,6 +5247,7 @@ BattleScript_FaintTarget:: dofaintanimation BS_TARGET printstring STRINGID_TARGETFAINTED cleareffectsonfaint BS_TARGET + waitanimation tryactivatesoulheart tryactivatereceiver BS_TARGET trytrainerslidefirstdownmsg BS_TARGET @@ -8980,6 +8982,7 @@ BattleScript_ArenaDoJudgment:: waitcry BS_ATTACKER dofaintanimation BS_OPPONENT1 cleareffectsonfaint BS_OPPONENT1 + waitanimation arenaopponentmonlost end2 @@ -8994,6 +8997,7 @@ BattleScript_ArenaJudgmentPlayerLoses: waitcry BS_ATTACKER dofaintanimation BS_PLAYER1 cleareffectsonfaint BS_PLAYER1 + waitanimation arenaplayermonlost end2 @@ -9008,10 +9012,12 @@ BattleScript_ArenaJudgmentDraw: waitcry BS_ATTACKER dofaintanimation BS_PLAYER1 cleareffectsonfaint BS_PLAYER1 + waitanimation playfaintcry BS_OPPONENT1 waitcry BS_ATTACKER dofaintanimation BS_OPPONENT1 cleareffectsonfaint BS_OPPONENT1 + waitanimation arenabothmonlost end2 diff --git a/include/battle.h b/include/battle.h index cd3126ba6b..23002e91c5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -687,7 +687,7 @@ struct BattleStruct u8 startingStatusDone:1; u8 terrainDone:1; u8 overworldWeatherDone:1; - u8 unused:3; + u8 battlerKOAnimsRunning:3; u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. u8 friskedAbility:1; // If identifies two mons, show the ability pop-up only once. u8 fickleBeamBoosted:1; diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 9bee760800..885b2a922a 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -3122,6 +3122,8 @@ static void LaunchKOAnimation(u32 battlerId, u16 animId, bool32 isFront) u32 species = GetBattlerVisualSpecies(battlerId); u32 spriteId = gBattlerSpriteIds[battlerId]; + gBattleStruct->battlerKOAnimsRunning++; + if (isFront) { LaunchAnimationTaskForFrontSprite(&gSprites[spriteId], animId); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 80a5ad664e..b1cab2f717 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2558,7 +2558,7 @@ static void Cmd_waitanimation(void) { CMD_ARGS(); - if (gBattleControllerExecFlags == 0) + if (gBattleControllerExecFlags == 0 && gBattleStruct->battlerKOAnimsRunning == 0) gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/pokemon_animation.c b/src/pokemon_animation.c index 41bc400105..7f28bff4ce 100644 --- a/src/pokemon_animation.c +++ b/src/pokemon_animation.c @@ -523,6 +523,11 @@ static void Task_HandleMonAnimation(u8 taskId) sprite->data[2] = gTasks[taskId].tSpeciesId; sprite->data[1] = 0; + // Task_HandleMonAnimation handles more than just KO animations, + // but if the counter is non-zero then only KO animations are running. + // This assumption is not checked. + if (gBattleStruct->battlerKOAnimsRunning > 0) + gBattleStruct->battlerKOAnimsRunning--; DestroyTask(taskId); } } From c0231c9bb10f604e6f48a17d356c5365a27ce797 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 21 Aug 2025 15:46:31 +0200 Subject: [PATCH 248/283] Fixes Rage Fist counter increment (#7582) Co-authored-by: Bassoonian --- src/battle_script_commands.c | 5 ++++- test/battle/move_effect/rage_fist.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b1cab2f717..ba64832ed6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2635,6 +2635,7 @@ static void Cmd_healthbarupdate(void) static void Cmd_datahpupdate(void) { CMD_ARGS(u8 battler); + bool32 isPassiveDamageOrHealing = gHitMarker & HITMARKER_PASSIVE_DAMAGE; if (gBattleControllerExecFlags) return; @@ -2750,11 +2751,13 @@ static void Cmd_datahpupdate(void) } if (gBattlerAttacker != gBattlerTarget + && !isPassiveDamageOrHealing && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS && IsBattlerTurnDamaged(gBattlerTarget)) gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF + && !isPassiveDamageOrHealing && IsBattlerTurnDamaged(gBattlerTarget) && gBattleMons[gBattlerTarget].item != ITEM_NONE && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) @@ -6630,7 +6633,7 @@ static void Cmd_moveend(void) { gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100)); gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE; + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_DAMAGE; effect = TRUE; if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIQUID_OOZE) { diff --git a/test/battle/move_effect/rage_fist.c b/test/battle/move_effect/rage_fist.c index e803a05a9d..ba8fcecc06 100644 --- a/test/battle/move_effect/rage_fist.c +++ b/test/battle/move_effect/rage_fist.c @@ -342,3 +342,28 @@ SINGLE_BATTLE_TEST("Rage Fist doesn't get increased power if Substitute is hit") EXPECT_EQ(timesGotHit[0], timesGotHit[1]); } } + +SINGLE_BATTLE_TEST("Rage Fist - X") +{ + s16 timesGotHit[2]; + + GIVEN { + ASSUME(GetMoveEffect(MOVE_GIGA_DRAIN) == EFFECT_ABSORB); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_RAGE_FIST); MOVE(opponent, MOVE_GIGA_DRAIN); } + TURN { MOVE(player, MOVE_RAGE_FIST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGE_FIST, player); + HP_BAR(opponent, captureDamage: ×GotHit[0]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_GIGA_DRAIN, opponent); + HP_BAR(player); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGE_FIST, player); + HP_BAR(opponent, captureDamage: ×GotHit[1]); + } THEN { + EXPECT_MUL_EQ(timesGotHit[0], Q_4_12(2.0), timesGotHit[1]); + } +} From 504d3bc31ff6e397f8c4289c3ea75bea9d757fb4 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 21 Aug 2025 16:49:13 +0200 Subject: [PATCH 249/283] Fixes moveend_absorb hitmarker (#7591) --- src/battle_script_commands.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index acd04e23da..bc97a288d8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2635,7 +2635,7 @@ static void Cmd_healthbarupdate(void) static void Cmd_datahpupdate(void) { CMD_ARGS(u8 battler); - bool32 isPassiveDamageOrHealing = gHitMarker & HITMARKER_PASSIVE_DAMAGE; + bool32 isPassiveHpUpdate = gHitMarker & HITMARKER_PASSIVE_HP_UPDATE; if (gBattleControllerExecFlags) return; @@ -2751,13 +2751,13 @@ static void Cmd_datahpupdate(void) } if (gBattlerAttacker != gBattlerTarget - && !isPassiveDamageOrHealing + && !isPassiveHpUpdate && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS && IsBattlerTurnDamaged(gBattlerTarget)) gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; if (GetMoveEffect(gCurrentMove) == EFFECT_KNOCK_OFF - && !isPassiveDamageOrHealing + && !isPassiveHpUpdate && IsBattlerTurnDamaged(gBattlerTarget) && gBattleMons[gBattlerTarget].item != ITEM_NONE && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) @@ -6633,12 +6633,11 @@ static void Cmd_moveend(void) { gBattleStruct->moveDamage[gBattlerAttacker] = max(1, (gBattleStruct->moveDamage[gBattlerTarget] * GetMoveAbsorbPercentage(gCurrentMove) / 100)); gBattleStruct->moveDamage[gBattlerAttacker] = GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->moveDamage[gBattlerAttacker]); - gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_DAMAGE; + gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE | HITMARKER_PASSIVE_HP_UPDATE; effect = TRUE; if (GetBattlerAbility(gBattlerTarget) == ABILITY_LIQUID_OOZE) { gBattleStruct->moveDamage[gBattlerAttacker] *= -1; - gHitMarker |= HITMARKER_PASSIVE_HP_UPDATE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ABSORB_OOZE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_EffectAbsorbLiquidOoze; From c80a41b730bf98f9c59d291f90189d601742ce79 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 21 Aug 2025 17:31:59 +0200 Subject: [PATCH 250/283] Suppress trainerproc compile warning for unused func (#7592) --- tools/trainerproc/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 8547735789..c3a39dc5a1 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -178,7 +178,7 @@ static bool is_literal_string(struct String s1, const char *s2) } } -static bool starts_with(struct String s, const char *prefix) +static bool __attribute__((unused)) starts_with(struct String s, const char *prefix) { int n = strlen(prefix); return strncmp((const char *)s.string, prefix, n) == 0; From 1e6bb4f47cdf5ae978e17d1297f889d44f1d5502 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Fri, 22 Aug 2025 20:23:18 +0200 Subject: [PATCH 251/283] Fix overlap between spin evolution and script evolution (#7593) --- asm/macros/event.inc | 2 +- include/constants/pokemon.h | 1 + src/pokemon.c | 49 ++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 3bc6516097..da6d64edd4 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2175,7 +2175,7 @@ setvar VAR_0x8000, \evoMethod setvar VAR_0x8001, \canStopEvo setvar VAR_0x8002, \tryMultiple - special TrySpecialOverworldEvo + special TrySpecialScriptEvolution .endm .macro ai_vs_ai_battle trainer1:req, trainer2:req diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index af01007cd2..20cff8a30f 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -322,6 +322,7 @@ enum EvolutionMode { EVO_MODE_ITEM_CHECK, // If an Everstone is being held, still want to show that the stone *could* be used on that Pokémon to evolve EVO_MODE_BATTLE_SPECIAL, EVO_MODE_OVERWORLD_SPECIAL, + EVO_MODE_SCRIPT_TRIGGER, EVO_MODE_BATTLE_ONLY, // This mode is only used in battles to support Tandemaus' unique requirement }; diff --git a/src/pokemon.c b/src/pokemon.c index 62abadca7c..b76683254e 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4896,7 +4896,6 @@ u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 switch (evolutions[i].method) { - case EVO_SCRIPT_TRIGGER: case EVO_SPIN: if (gSpecialVar_0x8000 == evolutions[i].param) conditionsMet = TRUE; @@ -4914,6 +4913,23 @@ u32 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 } } break; + case EVO_MODE_SCRIPT_TRIGGER: + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) + { + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) + continue; + if (evolutions[i].method != EVO_SCRIPT_TRIGGER) + continue; + if (DoesMonMeetAdditionalConditions(mon, evolutions[i].params, NULL, PARTY_SIZE, canStopEvo, evoState)) + { + // All checks passed, so stop checking the rest of the evolutions. + // This is different from vanilla where the loop continues. + // If you have overlapping evolutions, put the ones you want to happen first on top of the list. + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; } // Pikachu, Meowth, Eevee and Duraludon cannot evolve if they have the @@ -6760,6 +6776,37 @@ void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv) } // Attempts to perform non-level/item related overworld evolutions; called by tryspecialevo command. +void TryScriptEvolution(void) +{ + u8 i; + bool32 canStopEvo = gSpecialVar_0x8001; + u16 tryMultiple = gSpecialVar_0x8002; + + for (i = 0; i < PARTY_SIZE; i++) + { + u32 targetSpecies = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_SCRIPT_TRIGGER, 0, NULL, &canStopEvo, CHECK_EVO); + + if (targetSpecies != SPECIES_NONE && !(sTriedEvolving & (1u << i))) + { + GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_SCRIPT_TRIGGER, 0, NULL, &canStopEvo, DO_EVO); + sTriedEvolving |= 1u << i; + if(gMain.callback2 == TryScriptEvolution) // This fixes small graphics glitches. + EvolutionScene(&gPlayerParty[i], targetSpecies, canStopEvo, i); + else + BeginEvolutionScene(&gPlayerParty[i], targetSpecies, canStopEvo, i); + + if (tryMultiple) + gCB2_AfterEvolution = TryScriptEvolution; + else + gCB2_AfterEvolution = CB2_ReturnToField; + return; + } + } + + sTriedEvolving = 0; + SetMainCallback2(CB2_ReturnToField); +} + void TrySpecialOverworldEvo(void) { u8 i; From f00955013753189511b88188712f8ec9846a9fcf Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 22 Aug 2025 14:24:26 -0400 Subject: [PATCH 252/283] Added Ability TODO tests - Volume C (#7562) --- test/battle/ability/bad_dreams.c | 2 + test/battle/ability/cheek_pouch.c | 9 + test/battle/ability/comatose.c | 11 +- test/battle/ability/competitive.c | 333 +++++++++++++++++- test/battle/ability/contrary.c | 2 + test/battle/ability/corrosion.c | 7 + test/battle/ability/costar.c | 2 + test/battle/ability/cud_chew.c | 2 + test/battle/ability/cursed_body.c | 8 + test/battle/ability/cute_charm.c | 6 +- test/battle/ability/defiant.c | 4 +- test/battle/ability/flower_veil.c | 2 + test/battle/ability/insomnia.c | 2 +- test/battle/ability/moxie.c | 18 +- test/battle/gimmick/dynamax.c | 3 + test/battle/gimmick/zmove.c | 4 + test/battle/hold_effect/cure_status.c | 3 +- test/battle/move_effect/beat_up.c | 1 + .../move_effect/double_power_on_arg_status.c | 2 + test/battle/move_effect/mist.c | 2 + test/battle/move_effect/nightmare.c | 2 + test/battle/move_effect/purify.c | 2 + test/battle/move_effect/strength_sap.c | 2 + .../move_effect_secondary/remove_status.c | 2 + 24 files changed, 413 insertions(+), 18 deletions(-) diff --git a/test/battle/ability/bad_dreams.c b/test/battle/ability/bad_dreams.c index 41cedf8e3e..9882ce19ba 100644 --- a/test/battle/ability/bad_dreams.c +++ b/test/battle/ability/bad_dreams.c @@ -35,6 +35,8 @@ 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") + DOUBLE_BATTLE_TEST("Bad Dreams does not activate if only the partner Pokemon is sleeping") { GIVEN { diff --git a/test/battle/ability/cheek_pouch.c b/test/battle/ability/cheek_pouch.c index 3c932c4aa1..ffd1c8416e 100644 --- a/test/battle/ability/cheek_pouch.c +++ b/test/battle/ability/cheek_pouch.c @@ -1,6 +1,15 @@ #include "global.h" #include "test/battle.h" +TO_DO_BATTLE_TEST("Cheek Pouch restores 33% max HP") +TO_DO_BATTLE_TEST("Cheek Pouch restores HP after the berry's effect") +TO_DO_BATTLE_TEST("Cheek Pouch activates via Bug Bite/Pluck if it would trigger an effect") +TO_DO_BATTLE_TEST("Cheek Pouch activates when receiving from Fling if it would trigger an effect") +TO_DO_BATTLE_TEST("Cheek Pouch doesn't activate when using Natural Gift") +TO_DO_BATTLE_TEST("Cheek Pouch doesn't activate when using Fling") +TO_DO_BATTLE_TEST("Cheek Pouch doesn't activate when using a berry from the bag") +TO_DO_BATTLE_TEST("Cheek Pouch doesn't activate under Heal Block's effect") + SINGLE_BATTLE_TEST("Cheek Pouch activation doesn't mutate damage when restoring HP mid battle") { s16 damage; diff --git a/test/battle/ability/comatose.c b/test/battle/ability/comatose.c index d714ee5e3d..c049d5624d 100644 --- a/test/battle/ability/comatose.c +++ b/test/battle/ability/comatose.c @@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Comatose prevents status-inducing moves") } } -SINGLE_BATTLE_TEST("Comatose may be suppressed if pokemon transformed into a pokemon with Comatose ability and was under the effects of Gastro Acid") +SINGLE_BATTLE_TEST("Comatose may be suppressed if Pokémon transformed into a Pokémon with Comatose ability and was under the effects of Gastro Acid") { u32 move; @@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Comatose may be suppressed if pokemon transformed into a pok } } -SINGLE_BATTLE_TEST("Comatose pokemon doesn't get poisoned by Toxic Spikes on switch-in") +SINGLE_BATTLE_TEST("Comatose Pokémon doesn't get poisoned by Toxic Spikes on switch-in") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -72,7 +72,7 @@ SINGLE_BATTLE_TEST("Comatose pokemon doesn't get poisoned by Toxic Spikes on swi } } -SINGLE_BATTLE_TEST("Comatose pokemon don't get poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker") +SINGLE_BATTLE_TEST("Comatose Pokémon don't get poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -87,3 +87,8 @@ SINGLE_BATTLE_TEST("Comatose pokemon don't get poisoned by Toxic Spikes on switc NOT HP_BAR(player); } } + +TO_DO_BATTLE_TEST("Comatose makes Rest fail") +TO_DO_BATTLE_TEST("Comatose isn't affected by Mold Breaker, Turboblaze or Teravolt") +TO_DO_BATTLE_TEST("Comatose isn't affected by Poison Touch + Sunsteel Strike") +TO_DO_BATTLE_TEST("Comatose boosts Dream Ball's multiplier") diff --git a/test/battle/ability/competitive.c b/test/battle/ability/competitive.c index cc3e582eab..a4dd6db625 100644 --- a/test/battle/ability/competitive.c +++ b/test/battle/ability/competitive.c @@ -1,4 +1,335 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Competitive (Ability) test titles") +DOUBLE_BATTLE_TEST("Competitive sharply raises player's Sp. Atk after Intimidate") +{ + u32 abilityLeft, abilityRight; + + PARAMETRIZE { abilityLeft = ABILITY_FRIEND_GUARD; abilityRight = ABILITY_FRIEND_GUARD; } + PARAMETRIZE { abilityLeft = ABILITY_FRIEND_GUARD; abilityRight = ABILITY_COMPETITIVE; } + PARAMETRIZE { abilityLeft = ABILITY_COMPETITIVE; abilityRight = ABILITY_FRIEND_GUARD; } + PARAMETRIZE { abilityLeft = ABILITY_COMPETITIVE; abilityRight = ABILITY_COMPETITIVE; } + + GIVEN { + PLAYER(SPECIES_IGGLYBUFF) { Ability(abilityLeft); } + PLAYER(SPECIES_JIGGLYPUFF) { Ability(abilityRight); } + OPPONENT(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SCRATCH, target:opponentLeft); MOVE(playerRight, MOVE_SCRATCH, target:opponentRight); } + } SCENE { + //1st mon Intimidate + ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("The opposing Gyarados's Intimidate cuts Igglybuff's Attack!"); + if (abilityLeft == ABILITY_COMPETITIVE) { + ABILITY_POPUP(playerLeft, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("The opposing Gyarados's Intimidate cuts Jigglypuff's Attack!"); + if (abilityRight == ABILITY_COMPETITIVE) { + ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Jigglypuff's Sp. Atk sharply rose!"); + } + + //2nd mon Intimidate + ABILITY_POPUP(opponentRight, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("The opposing Arbok's Intimidate cuts Igglybuff's Attack!"); + if (abilityLeft == ABILITY_COMPETITIVE) { + ABILITY_POPUP(playerLeft, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("The opposing Arbok's Intimidate cuts Jigglypuff's Attack!"); + if (abilityRight == ABILITY_COMPETITIVE) { + ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Jigglypuff's Sp. Atk sharply rose!"); + } + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + (abilityLeft == ABILITY_COMPETITIVE ? 4 : 0)); + EXPECT_EQ(playerRight->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + (abilityRight == ABILITY_COMPETITIVE ? 4 : 0)); + } +} + +// Same as above, but for opponent. +DOUBLE_BATTLE_TEST("Competitive sharply raises opponent's Sp. Atk after Intimidate") +{ + u32 abilityLeft, abilityRight; + + PARAMETRIZE { abilityLeft = ABILITY_FRIEND_GUARD; abilityRight = ABILITY_FRIEND_GUARD; } + PARAMETRIZE { abilityLeft = ABILITY_FRIEND_GUARD; abilityRight = ABILITY_COMPETITIVE; } + PARAMETRIZE { abilityLeft = ABILITY_COMPETITIVE; abilityRight = ABILITY_FRIEND_GUARD; } + PARAMETRIZE { abilityLeft = ABILITY_COMPETITIVE; abilityRight = ABILITY_COMPETITIVE; } + + GIVEN { + OPPONENT(SPECIES_IGGLYBUFF) { Ability(abilityLeft); } + OPPONENT(SPECIES_JIGGLYPUFF) { Ability(abilityRight); } + PLAYER(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); } + PLAYER(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SCRATCH, target:playerLeft); MOVE(opponentRight, MOVE_SCRATCH, target:playerRight); } + } SCENE { + //1st mon Intimidate + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Gyarados's Intimidate cuts the opposing Igglybuff's Attack!"); + if (abilityLeft == ABILITY_COMPETITIVE) { + ABILITY_POPUP(opponentLeft, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Igglybuff's Sp. Atk sharply rose!"); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Gyarados's Intimidate cuts the opposing Jigglypuff's Attack!"); + if (abilityRight == ABILITY_COMPETITIVE) { + ABILITY_POPUP(opponentRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Jigglypuff's Sp. Atk sharply rose!"); + } + + //2nd mon Intimidate + ABILITY_POPUP(playerRight, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Arbok's Intimidate cuts the opposing Igglybuff's Attack!"); + if (abilityLeft == ABILITY_COMPETITIVE) { + ABILITY_POPUP(opponentLeft, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Igglybuff's Sp. Atk sharply rose!"); + } + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Arbok's Intimidate cuts the opposing Jigglypuff's Attack!"); + if (abilityRight == ABILITY_COMPETITIVE) { + ABILITY_POPUP(opponentRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Jigglypuff's Sp. Atk sharply rose!"); + } + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + (abilityLeft == ABILITY_COMPETITIVE ? 4 : 0)); + EXPECT_EQ(opponentRight->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + (abilityRight == ABILITY_COMPETITIVE ? 4 : 0)); + } +} + +SINGLE_BATTLE_TEST("Competitive activates after Sticky Web lowers Speed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STICKY_WEB); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponent); + // Switch-in - Sticky Web activates + SEND_IN_MESSAGE("Igglybuff"); + MESSAGE("Igglybuff was caught in a sticky web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Speed fell!"); + // Competitive activates + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } +} + +SINGLE_BATTLE_TEST("Competitive doesn't activate after Sticky Web lowers Speed if Court Changed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STICKY_WEB); MOVE(opponent, MOVE_COURT_CHANGE); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COURT_CHANGE, opponent); + // Switch-in - Sticky Web activates + SEND_IN_MESSAGE("Igglybuff"); + MESSAGE("Igglybuff was caught in a sticky web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Speed fell!"); + // Competitive doesn't activate + NONE_OF { + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } + } +} + +SINGLE_BATTLE_TEST("Competitive correctly activates after Sticky Web lowers Speed if Court Changed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STICKY_WEB); MOVE(opponent, MOVE_COURT_CHANGE); } + TURN { SWITCH(player, 1); } + TURN { MOVE(opponent, MOVE_GROWL);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COURT_CHANGE, opponent); + // Switch-in - Sticky Web activates + SEND_IN_MESSAGE("Igglybuff"); + MESSAGE("Igglybuff was caught in a sticky web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Speed fell!"); + // Competitive doesn't activate + NONE_OF { + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } + // Competitive triggers correctly after Sticky Web + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Attack fell!"); + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } +} + +DOUBLE_BATTLE_TEST("Competitive is activated by Cotton Down for non-ally pokemon") +{ + GIVEN { + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_ELDEGOSS) { Ability(ABILITY_COTTON_DOWN); } + OPPONENT(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SCRATCH, target: opponentLeft); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_COTTON_DOWN); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Igglybuff's Speed fell!"); + ABILITY_POPUP(playerLeft, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Igglybuff's Speed fell!"); + ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Igglybuff's Speed fell!"); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(playerRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(opponentRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(playerRight->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + } +} + +SINGLE_BATTLE_TEST("Competitive activates before White Herb") +{ + u32 move; + + PARAMETRIZE { move = MOVE_LEER; } + PARAMETRIZE { move = MOVE_CONFIDE; } + + GIVEN { + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); Item(ITEM_WHITE_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + + if (move == MOVE_LEER) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Igglybuff returned its stats to normal using its White Herb!"); + } else { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Igglybuff returned its stats to normal using its White Herb!"); + } + } + } THEN { + if (move == MOVE_LEER) { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + } else { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + } + } +} + +SINGLE_BATTLE_TEST("Competitive activates for each stat that is lowered") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_TICKLE) == EFFECT_TICKLE); + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TICKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TICKLE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + + MESSAGE("Igglybuff's Attack fell!"); + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + + MESSAGE("Igglybuff's Defense fell!"); + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 4); + } +} + +SINGLE_BATTLE_TEST("Competitive doesn't activate if the pokemon lowers it's own stats") +{ + u32 move; + + PARAMETRIZE { move = MOVE_SUPERPOWER; } + PARAMETRIZE { move = MOVE_CLOSE_COMBAT; } + PARAMETRIZE { move = MOVE_MAKE_IT_RAIN; } + PARAMETRIZE { move = MOVE_SPIN_OUT; } + + GIVEN { + ASSUME(MoveHasAdditionalEffectSelf(MOVE_SUPERPOWER, MOVE_EFFECT_ATK_DEF_DOWN)); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_CLOSE_COMBAT, MOVE_EFFECT_DEF_SPDEF_DOWN)); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_SP_ATK_MINUS_1)); + ASSUME(MoveHasAdditionalEffectSelf(MOVE_SPIN_OUT, MOVE_EFFECT_SPD_MINUS_2)); + PLAYER(SPECIES_IGGLYBUFF) { Ability(ABILITY_COMPETITIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + + NONE_OF { + ABILITY_POPUP(player, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Igglybuff's Sp. Atk sharply rose!"); + } + } THEN { + if (move == MOVE_SUPERPOWER) + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + else + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + } +} diff --git a/test/battle/ability/contrary.c b/test/battle/ability/contrary.c index e174427406..e11635ec67 100644 --- a/test/battle/ability/contrary.c +++ b/test/battle/ability/contrary.c @@ -241,3 +241,5 @@ SINGLE_BATTLE_TEST("Sticky Web raises Speed by 1 for Contrary mon on switch-in") MESSAGE("The opposing Snivy's Speed rose!"); } } + +TO_DO_BATTLE_TEST("Contrary does not invert stat changes that have been Baton-passed") diff --git a/test/battle/ability/corrosion.c b/test/battle/ability/corrosion.c index 1e589967db..ca6b602002 100644 --- a/test/battle/ability/corrosion.c +++ b/test/battle/ability/corrosion.c @@ -238,3 +238,10 @@ SINGLE_BATTLE_TEST("Corrosion's effect is lost if the move used by the Pokémon } } } + +TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Baneful Bunker") +TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Psycho Shift while poisoned") +TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Toxic Orb") +TO_DO_BATTLE_TEST("Corrosion can poison Poison/Steel types if the Pokémon uses Fling while holding a Poison Barb") +TO_DO_BATTLE_TEST("Dynamax: Corrosion can poison Poison/Steel types if the Pokémon uses G-Max Malodor") +TO_DO_BATTLE_TEST("Corrosion does not affect Poison Spikes") diff --git a/test/battle/ability/costar.c b/test/battle/ability/costar.c index 7107b00d61..3d041a8d53 100644 --- a/test/battle/ability/costar.c +++ b/test/battle/ability/costar.c @@ -28,3 +28,5 @@ DOUBLE_BATTLE_TEST("Costar copies an ally's stat stages upon entering battle") // Copy from Ruin ability tests TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player"); TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent"); + +TO_DO_BATTLE_TEST("Costar can copy an ally's critical hit ratio"); diff --git a/test/battle/ability/cud_chew.c b/test/battle/ability/cud_chew.c index 486e2e9dac..41d05c94d7 100644 --- a/test/battle/ability/cud_chew.c +++ b/test/battle/ability/cud_chew.c @@ -47,3 +47,5 @@ SINGLE_BATTLE_TEST("Cud Chew will activate Oran Berry effect again on the next t EXPECT_EQ(opponent->hp, 40); } } + +TO_DO_BATTLE_TEST("Cud Chew will activate Lum Berry effect again on the next turn") diff --git a/test/battle/ability/cursed_body.c b/test/battle/ability/cursed_body.c index 26d97a9f11..25dbdc4b5b 100644 --- a/test/battle/ability/cursed_body.c +++ b/test/battle/ability/cursed_body.c @@ -15,3 +15,11 @@ SINGLE_BATTLE_TEST("Cursed Body triggers 30% of the time") MESSAGE("Wobbuffet's Aqua Jet was disabled by the opposing Frillish's Cursed Body!"); } } + +TO_DO_BATTLE_TEST("Cursed Body cannot disable Struggle") +TO_DO_BATTLE_TEST("Cursed Body can trigger if the attacker is behind a Substitute") +TO_DO_BATTLE_TEST("Cursed Body cannot trigger if the target is behind a Substitute") +TO_DO_BATTLE_TEST("Cursed Body does not stop a multistrike move mid-execution") +TO_DO_BATTLE_TEST("Cursed Body disables the move that called another move instead of the called move") +TO_DO_BATTLE_TEST("Cursed Body disables damaging Z-Moves, but not the base move") // Rotom Powers can restore Z-Moves +TO_DO_BATTLE_TEST("Cursed Body disables the base move of a status Z-Move") diff --git a/test/battle/ability/cute_charm.c b/test/battle/ability/cute_charm.c index 0bba66b8ac..0813296a2e 100644 --- a/test/battle/ability/cute_charm.c +++ b/test/battle/ability/cute_charm.c @@ -46,7 +46,11 @@ SINGLE_BATTLE_TEST("Cute Charm cannot infatuate same gender") } } -SINGLE_BATTLE_TEST("Cute Charm triggers 30% of the time") +TO_DO_BATTLE_TEST("Cute Charm cannot infatuate if either Pokémon are Gender-unknown") + +TO_DO_BATTLE_TEST("Cute Charm triggers 1/3 of the time (Gen 3)") + +SINGLE_BATTLE_TEST("Cute Charm triggers 30% of the time (Gen 4+)") { PASSES_RANDOMLY(3, 10, RNG_CUTE_CHARM); GIVEN { diff --git a/test/battle/ability/defiant.c b/test/battle/ability/defiant.c index 5ec4ebb093..c19c4286ea 100644 --- a/test/battle/ability/defiant.c +++ b/test/battle/ability/defiant.c @@ -51,7 +51,7 @@ DOUBLE_BATTLE_TEST("Defiant sharply raises player's Attack after Intimidate") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); MESSAGE("Primeape's Attack sharply rose!"); } - } FINALLY { + } THEN { // -2 from Intimidates and +4 from Defiants gets +2 total EXPECT_EQ(playerLeft->statStages[STAT_ATK], (abilityLeft == ABILITY_DEFIANT) ? DEFAULT_STAT_STAGE + 2 : DEFAULT_STAT_STAGE - 2); EXPECT_EQ(playerRight->statStages[STAT_ATK], (abilityRight == ABILITY_DEFIANT) ? DEFAULT_STAT_STAGE + 2 : DEFAULT_STAT_STAGE - 2); @@ -109,7 +109,7 @@ DOUBLE_BATTLE_TEST("Defiant sharply raises opponent's Attack after Intimidate") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); MESSAGE("The opposing Primeape's Attack sharply rose!"); } - } FINALLY { + } THEN { // -2 from Intimidates and +4 from Defiants gets +2 total EXPECT_EQ(opponentLeft->statStages[STAT_ATK], (abilityLeft == ABILITY_DEFIANT) ? DEFAULT_STAT_STAGE + 2 : DEFAULT_STAT_STAGE - 2); EXPECT_EQ(opponentRight->statStages[STAT_ATK], (abilityRight == ABILITY_DEFIANT) ? DEFAULT_STAT_STAGE + 2 : DEFAULT_STAT_STAGE - 2); diff --git a/test/battle/ability/flower_veil.c b/test/battle/ability/flower_veil.c index 2b36d08d60..cb72cd33ae 100644 --- a/test/battle/ability/flower_veil.c +++ b/test/battle/ability/flower_veil.c @@ -62,3 +62,5 @@ DOUBLE_BATTLE_TEST("Flower Veil prevents Toxic bad poison on partner - left targ MESSAGE("The opposing Chikorita surrounded itself with a veil of petals!"); } } + +TO_DO_BATTLE_TEST("Flower Veil's stat reduction protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist. diff --git a/test/battle/ability/insomnia.c b/test/battle/ability/insomnia.c index 61bb1931fa..c95b294907 100644 --- a/test/battle/ability/insomnia.c +++ b/test/battle/ability/insomnia.c @@ -40,7 +40,7 @@ SINGLE_BATTLE_TEST("Insomnia prevents yawn") } } -SINGLE_BATTLE_TEST("Insomnia prevents rest") +SINGLE_BATTLE_TEST("Insomnia prevents Rest") { GIVEN { ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); diff --git a/test/battle/ability/moxie.c b/test/battle/ability/moxie.c index a39fb91df8..1dda9f7926 100644 --- a/test/battle/ability/moxie.c +++ b/test/battle/ability/moxie.c @@ -4,8 +4,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after directly causing a Pokemon to faint") { u32 species = 0, ability = 0, abilityPopUp = 0; - PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } - PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); @@ -37,8 +37,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after direct DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger if Pokemon faint to indirect damage or damage from other Pokemon") { u32 species = 0, ability = 0, abilityPopUp = 0; - PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } - PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { PLAYER(species) { Ability(ability); } @@ -74,8 +74,8 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger if Pokemon faint to in SINGLE_BATTLE_TEST("Moxie/Chilling Neigh does not trigger when already at maximum Attack stage") { u32 species = 0, ability = 0, abilityPopUp = 0; - PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } - PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { ASSUME(GetMoveEffect(MOVE_BELLY_DRUM) == EFFECT_BELLY_DRUM); @@ -112,9 +112,9 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not increase damage done by the sa { s16 damage[2]; u32 species = 0, ability = 0, abilityPopUp = 0; - PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } - PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } - PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_SALAMENCE; ability = ABILITY_MOXIE; abilityPopUp = ABILITY_MOXIE; } + PARAMETRIZE { species = SPECIES_GLASTRIER; ability = ABILITY_CHILLING_NEIGH; abilityPopUp = ABILITY_CHILLING_NEIGH; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; abilityPopUp = ABILITY_CHILLING_NEIGH; } GIVEN { ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY); diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index a929c82068..b8b0290adf 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -1660,3 +1660,6 @@ SINGLE_BATTLE_TEST("Dynamax: Destiny Bond fails if a dynamaxed battler is presen MESSAGE("The move was blocked by the power of Dynamax!"); } } + +TO_DO_BATTLE_TEST("Dynamax: Contrary inverts stat-lowering Max Moves, without showing a message") +TO_DO_BATTLE_TEST("Dynamax: Contrary inverts stat-increasing Max Moves, without showing a message") diff --git a/test/battle/gimmick/zmove.c b/test/battle/gimmick/zmove.c index 058d59c620..14457fa0b7 100644 --- a/test/battle/gimmick/zmove.c +++ b/test/battle/gimmick/zmove.c @@ -679,3 +679,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z-Revelation Dance always transforms into Breakneck ANIMATION(ANIM_TYPE_MOVE, MOVE_BREAKNECK_BLITZ, player); } } + +TO_DO_BATTLE_TEST("(Z-MOVE) Stat changes from status Z-Moves are not inverted by Contrary") +TO_DO_BATTLE_TEST("(Z-MOVE) Stat changes from Extreme Evoboost are inverted by Contrary") +TO_DO_BATTLE_TEST("(Z-MOVE) Stat changes from Clangorous Soulblaze are inverted by Contrary") diff --git a/test/battle/hold_effect/cure_status.c b/test/battle/hold_effect/cure_status.c index 133eeafb41..f2bf4333d4 100644 --- a/test/battle/hold_effect/cure_status.c +++ b/test/battle/hold_effect/cure_status.c @@ -116,6 +116,8 @@ SINGLE_BATTLE_TEST("Chesto and Lum Berries cure sleep") } } +TO_DO_BATTLE_TEST("Chesto and Lum Berries don't trigger if the holder has Comatose") + SINGLE_BATTLE_TEST("Cheri and Lum Berries cure paralysis") { u16 item; @@ -289,6 +291,5 @@ DOUBLE_BATTLE_TEST("Lum Berry correctly cures all battlers if multiple fainted t EXPECT_EQ(playerLeft->status1, STATUS1_NONE); EXPECT_EQ(playerRight->status1, STATUS1_NONE); EXPECT_EQ(opponentLeft->status1, STATUS1_NONE); - } } diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c index 5e11360531..dd0d19925f 100644 --- a/test/battle/move_effect/beat_up.c +++ b/test/battle/move_effect/beat_up.c @@ -3,6 +3,7 @@ // General TO_DO_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party"); +TO_DO_BATTLE_TEST("Beat Up doesn't consider Comatose as a status") TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit"); // B_BEAT_UP Gen2-4 diff --git a/test/battle/move_effect/double_power_on_arg_status.c b/test/battle/move_effect/double_power_on_arg_status.c index d733d04c4f..14bfdb57af 100644 --- a/test/battle/move_effect/double_power_on_arg_status.c +++ b/test/battle/move_effect/double_power_on_arg_status.c @@ -29,6 +29,8 @@ SINGLE_BATTLE_TEST("Hex deals double damage to foes with a status", s16 damage) } } +TO_DO_BATTLE_TEST("Hex deals double damage to Pokémon with Comatose") + SINGLE_BATTLE_TEST("Venoshock's power doubles if the target is poisoned/badly poisoned", s16 damage) { u32 status1; diff --git a/test/battle/move_effect/mist.c b/test/battle/move_effect/mist.c index 332d82a6f9..dedf84cebc 100644 --- a/test/battle/move_effect/mist.c +++ b/test/battle/move_effect/mist.c @@ -2,3 +2,5 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Mist (Move Effect) test titles") + +TO_DO_BATTLE_TEST("Mist's protection considers Contrary") // Eg. If a move would reduce stats due to Contrary, it will be protected by Mist. diff --git a/test/battle/move_effect/nightmare.c b/test/battle/move_effect/nightmare.c index c243664f2d..4cf051ba7d 100644 --- a/test/battle/move_effect/nightmare.c +++ b/test/battle/move_effect/nightmare.c @@ -2,3 +2,5 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Nightmare (Move Effect) test titles") + +TO_DO_BATTLE_TEST("Nightmare affects Pokémon with Comatose") diff --git a/test/battle/move_effect/purify.c b/test/battle/move_effect/purify.c index 134c96119f..d18cab76dd 100644 --- a/test/battle/move_effect/purify.c +++ b/test/battle/move_effect/purify.c @@ -2,3 +2,5 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Purify (Move Effect) test titles") + +TO_DO_BATTLE_TEST("Purify doesn't heal HP if the target has Comatose") diff --git a/test/battle/move_effect/strength_sap.c b/test/battle/move_effect/strength_sap.c index c38048ba8f..675d5090ee 100644 --- a/test/battle/move_effect/strength_sap.c +++ b/test/battle/move_effect/strength_sap.c @@ -141,6 +141,8 @@ SINGLE_BATTLE_TEST("Strength Sap fails if target is at -6 Atk") } } +TO_DO_BATTLE_TEST("Strength Sap doesn't fail if target has Contrary and is at +6 Atk, restoring HP based on +5 Atk") + SINGLE_BATTLE_TEST("Strength Sap restores more HP if Big Root is held", s16 hp) { u32 item; diff --git a/test/battle/move_effect_secondary/remove_status.c b/test/battle/move_effect_secondary/remove_status.c index 0ff3d0f78c..0a07ef6368 100644 --- a/test/battle/move_effect_secondary/remove_status.c +++ b/test/battle/move_effect_secondary/remove_status.c @@ -113,6 +113,8 @@ SINGLE_BATTLE_TEST("Wake-Up Slap gets increased power against sleeping targets") } } +TO_DO_BATTLE_TEST("Wake-Up Slap gets increased power against Pokémon with Comatose") + DOUBLE_BATTLE_TEST("Sparkling Aria cures burns from all Pokemon on the field and behind substitutes") { GIVEN { From 8febd246045cbab3a7855cefef991f2651d950b8 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 23 Aug 2025 16:25:19 -0400 Subject: [PATCH 253/283] Added missing Move Effect TODO tests - Volume F (#7605) --- test/battle/ability/bad_dreams.c | 2 +- test/battle/ability/battle_bond.c | 2 +- test/battle/ability/defiant.c | 4 ++-- test/battle/ability/desolate_land.c | 2 +- test/battle/ability/frisk.c | 2 +- test/battle/ability/immunity.c | 2 +- test/battle/ability/mirror_armor.c | 2 +- test/battle/ability/opportunist.c | 2 +- test/battle/ability/primordial_sea.c | 4 ++-- test/battle/ability/purifying_salt.c | 2 +- test/battle/ability/volt_absorb.c | 2 +- test/battle/ai/ai_switching.c | 4 ++-- test/battle/gimmick/dynamax.c | 2 +- test/battle/gimmick/terastal.c | 11 ++++----- test/battle/hold_effect/cure_status.c | 2 +- test/battle/move.c | 2 +- test/battle/move_effect/after_you.c | 2 +- test/battle/move_effect/ally_switch.c | 2 +- test/battle/move_effect/beak_blast.c | 2 +- test/battle/move_effect/facade.c | 4 +++- .../battle/move_effect/fail_if_not_arg_type.c | 23 ++++++++++++++++++- test/battle/move_effect/fairy_lock.c | 7 +++++- test/battle/move_effect/false_swipe.c | 4 +++- test/battle/move_effect/fell_stinger.c | 2 +- test/battle/move_effect/fillet_away.c | 2 ++ test/battle/move_effect/final_gambit.c | 14 ++++++++++- test/battle/move_effect/first_turn_only.c | 6 ++++- test/battle/move_effect/fixed_damage_arg.c | 4 +++- test/battle/move_effect/flail.c | 19 ++++++++++++++- test/battle/move_effect/flatter.c | 7 +++++- test/battle/move_effect/fling.c | 13 +++++++---- test/battle/move_effect/flower_shield.c | 4 +++- test/battle/move_effect/focus_energy.c | 5 +++- test/battle/move_effect/focus_punch.c | 12 ++++++++++ test/battle/move_effect/follow_me.c | 13 +++++++++++ test/battle/move_effect/foresight.c | 12 +++++++++- test/battle/move_effect/foul_play.c | 6 ++++- test/battle/move_effect/frustration.c | 4 +++- test/battle/move_effect/fury_cutter.c | 6 ++++- test/battle/move_effect/fusion_combo.c | 4 +++- test/battle/move_effect/future_sight.c | 9 ++++++-- test/battle/move_effect/grassy_terrain.c | 2 +- test/battle/move_effect/haze.c | 3 +++ test/battle/move_effect/healing_wish.c | 2 +- test/battle/move_effect/hit_escape.c | 2 +- test/battle/move_effect/protect.c | 8 +++---- test/battle/move_effect/quash.c | 2 +- test/battle/move_effect/return.c | 4 +++- test/battle/move_effect/rototiller.c | 2 +- test/battle/move_effect/round.c | 2 +- test/battle/move_effect/shed_tail.c | 2 +- test/battle/move_effect/stealth_rock.c | 4 ++-- test/battle/move_effect/swagger.c | 8 ++++++- test/battle/move_effect/teleport.c | 6 ++--- test/battle/move_effect/uproar.c | 2 +- test/battle/move_effect_secondary/bug_bite.c | 2 +- test/battle/move_effect_secondary/dire_claw.c | 2 +- .../battle/move_effect_secondary/tri_attack.c | 4 ++-- test/battle/spread_moves.c | 2 +- test/battle/status1/frostbite.c | 2 +- 60 files changed, 218 insertions(+), 76 deletions(-) diff --git a/test/battle/ability/bad_dreams.c b/test/battle/ability/bad_dreams.c index 9882ce19ba..491d5a91a2 100644 --- a/test/battle/ability/bad_dreams.c +++ b/test/battle/ability/bad_dreams.c @@ -59,7 +59,7 @@ DOUBLE_BATTLE_TEST("Bad Dreams does not activate if only the partner Pokemon is } } -DOUBLE_BATTLE_TEST("Bad Dreams activates for both sleeping pokemon on the player side") +DOUBLE_BATTLE_TEST("Bad Dreams activates for both sleeping Pokémon on the player side") { GIVEN { PLAYER(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} diff --git a/test/battle/ability/battle_bond.c b/test/battle/ability/battle_bond.c index 401df267b6..d268536964 100644 --- a/test/battle/ability/battle_bond.c +++ b/test/battle/ability/battle_bond.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(!IsBattleMoveStatus(MOVE_WATER_GUN)); } -// Battle Bond transforms the pokemon when fainting any battler(opposing or partner), unless it's the last pokemon and the battle ends. +// Battle Bond transforms the Pokémon when fainting any battler(opposing or partner), unless it's the last Pokémon and the battle ends. SINGLE_BATTLE_TEST("Battle Bond transforms player's Greninja - Singles") { u32 monsCountPlayer, monsCountOpponent; diff --git a/test/battle/ability/defiant.c b/test/battle/ability/defiant.c index c19c4286ea..1bb97aa59e 100644 --- a/test/battle/ability/defiant.c +++ b/test/battle/ability/defiant.c @@ -199,7 +199,7 @@ SINGLE_BATTLE_TEST("Defiant correctly activates after Sticky Web lowers Speed if } } -DOUBLE_BATTLE_TEST("Defiant is activated by Cotton Down for non-ally pokemon") +DOUBLE_BATTLE_TEST("Defiant is activated by Cotton Down for non-ally Pokémon") { GIVEN { PLAYER(SPECIES_MANKEY) { Ability(ABILITY_DEFIANT); } @@ -301,7 +301,7 @@ SINGLE_BATTLE_TEST("Defiant activates for each stat that is lowered") } } -SINGLE_BATTLE_TEST("Defiant doesn't activate if the pokemon lowers it's own stats") +SINGLE_BATTLE_TEST("Defiant doesn't activate if the Pokémon lowers it's own stats") { u32 move; diff --git a/test/battle/ability/desolate_land.c b/test/battle/ability/desolate_land.c index e058b7b514..0b99040189 100644 --- a/test/battle/ability/desolate_land.c +++ b/test/battle/ability/desolate_land.c @@ -53,7 +53,7 @@ DOUBLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves and prints th } } -SINGLE_BATTLE_TEST("Desolate Land does not block a move if pokemon is asleep and uses a Water-type move") // Sleep/confusion/paralysis all happen before the check for primal weather +SINGLE_BATTLE_TEST("Desolate Land does not block a move if Pokémon is asleep and uses a Water-type move") // Sleep/confusion/paralysis all happen before the check for primal weather { GIVEN { PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB);} diff --git a/test/battle/ability/frisk.c b/test/battle/ability/frisk.c index e6d7f275fb..e20d2f5205 100644 --- a/test/battle/ability/frisk.c +++ b/test/battle/ability/frisk.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -DOUBLE_BATTLE_TEST("Frisk does not trigger when pokemon hold no items") +DOUBLE_BATTLE_TEST("Frisk does not trigger when Pokémon hold no items") { GIVEN { PLAYER(SPECIES_FURRET) { Ability(ABILITY_FRISK); }; diff --git a/test/battle/ability/immunity.c b/test/battle/ability/immunity.c index 81fbe1b8c1..88ff45d2a4 100644 --- a/test/battle/ability/immunity.c +++ b/test/battle/ability/immunity.c @@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Immunity prevents Toxic Spikes poison") } } -SINGLE_BATTLE_TEST("Immunity doesn't prevent pokemon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker, but it cures it immediately") +SINGLE_BATTLE_TEST("Immunity doesn't prevent Pokémon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker, but it cures it immediately") { GIVEN { ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET); diff --git a/test/battle/ability/mirror_armor.c b/test/battle/ability/mirror_armor.c index 66d7ad5284..7d027398f3 100644 --- a/test/battle/ability/mirror_armor.c +++ b/test/battle/ability/mirror_armor.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking pokemon") +SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking Pokémon") { u16 move, statId; diff --git a/test/battle/ability/opportunist.c b/test/battle/ability/opportunist.c index d48b7c1eeb..7c0bce4771 100644 --- a/test/battle/ability/opportunist.c +++ b/test/battle/ability/opportunist.c @@ -212,7 +212,7 @@ DOUBLE_BATTLE_TEST("Opportunist copies the stat increase of each opposing mon") } -DOUBLE_BATTLE_TEST("Opportunist copies the stat of each pokemon that were raised at the same time") +DOUBLE_BATTLE_TEST("Opportunist copies the stat of each Pokémon that were raised at the same time") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/ability/primordial_sea.c b/test/battle/ability/primordial_sea.c index e895d8ba48..39d350d3a0 100644 --- a/test/battle/ability/primordial_sea.c +++ b/test/battle/ability/primordial_sea.c @@ -52,7 +52,7 @@ DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints th } } -SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather +SINGLE_BATTLE_TEST("Primordial Sea does not block a move if Pokémon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather { GIVEN { PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} @@ -63,4 +63,4 @@ SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep an NOT MESSAGE("The Fire-type attack fizzled out in the heavy rain!"); MESSAGE("The opposing Wobbuffet is fast asleep."); } -} \ No newline at end of file +} diff --git a/test/battle/ability/purifying_salt.c b/test/battle/ability/purifying_salt.c index 49060e6596..23f097e8aa 100644 --- a/test/battle/ability/purifying_salt.c +++ b/test/battle/ability/purifying_salt.c @@ -105,7 +105,7 @@ SINGLE_BATTLE_TEST("Purifying Salt user can't be poisoned by Toxic Spikes") } } -SINGLE_BATTLE_TEST("Purifying Salt doesn't prevent pokemon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker") +SINGLE_BATTLE_TEST("Purifying Salt doesn't prevent Pokémon from being poisoned by Toxic Spikes on switch-in if forced in by phazing with Mold Breaker") { GIVEN { ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET); diff --git a/test/battle/ability/volt_absorb.c b/test/battle/ability/volt_absorb.c index 5d88cb95e4..becc76fd13 100644 --- a/test/battle/ability/volt_absorb.c +++ b/test/battle/ability/volt_absorb.c @@ -61,7 +61,7 @@ SINGLE_BATTLE_TEST("Volt Absorb is only triggered once on multi strike moves") } } -DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from damaging other pokemon") // Fixed issue #1961 +DOUBLE_BATTLE_TEST("Volt Absorb does not stop Electric Typed Explosion from damaging other Pokémon") // Fixed issue #1961 { s16 damage1, damage2; GIVEN { diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 75ff02cb88..712076fc70 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -40,7 +40,7 @@ AI_SINGLE_BATTLE_TEST("AI switches if Perish Song is about to kill") } } -AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spots in a double battle (all bad moves)") +AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same Pokémon for 2 spots in a double battle (all bad moves)") { u32 flags; @@ -98,7 +98,7 @@ AI_SINGLE_BATTLE_TEST("When AI switches out due to having no move that affects t } } -AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spots in a double battle (Wonder Guard)") +AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same Pokémon for 2 spots in a double battle (Wonder Guard)") { PASSES_RANDOMLY(SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE, 100, RNG_AI_SWITCH_WONDER_GUARD); GIVEN { diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index b8b0290adf..0e9118252e 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -601,7 +601,7 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon cannot use Max Guard while holdin // Almost anything that calculates damage based on HP has been changed to non-Dynamax HP. // This includes Leftovers, Life Orb, Heal Pulse, Rocky Helmet, Sandstorm, etc. etc. -// There are some redundant cases (i.e Substitute) that can never be used by a Dynamaxed pokemon. +// There are some redundant cases (i.e Substitute) that can never be used by a Dynamaxed Pokémon. // Anything that is conditional based off max HP still uses gBattleMons[battler].maxHP. // Below are some tests, but very far from all encompassing: diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index 7ce10a5942..66a34def92 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -755,7 +755,7 @@ SINGLE_BATTLE_TEST("(TERA) Terapagos retains its base defensive profile when Ter } } -SINGLE_BATTLE_TEST("(TERA) Illusion breaks if the pokemon Terastallizes when illusioned as a mon that changes forms by Terastallizing") +SINGLE_BATTLE_TEST("(TERA) Illusion breaks if the Pokémon Terastallizes when illusioned as a mon that changes forms by Terastallizing") { u32 species; PARAMETRIZE { species = SPECIES_TERAPAGOS; } @@ -791,19 +791,16 @@ SINGLE_BATTLE_TEST("(TERA) Illusion doesn't break upon Terastallizing when illus } } -/* -// This test freezes the emulator -SINGLE_BATTLE_TEST("(TERA) Transformed pokemon can't Terastalize") +SINGLE_BATTLE_TEST("(TERA) Transformed Pokémon can't Terastalize") { GIVEN { - PLAYER(SPECIES_DITTO); - OPPONENT(SPECIES_TERAPAGOS) { Moves(MOVE_CELEBRATE); } + PLAYER(SPECIES_DITTO) { Moves(MOVE_TRANSFORM, MOVE_CELEBRATE); } + OPPONENT(SPECIES_TERAPAGOS) { Moves(MOVE_TRANSFORM, MOVE_CELEBRATE); } } WHEN { TURN { MOVE(player, MOVE_TRANSFORM); } TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_TERA); } } } -*/ SINGLE_BATTLE_TEST("(TERA) Pokemon with Tera forms change upon Terastallizing") { diff --git a/test/battle/hold_effect/cure_status.c b/test/battle/hold_effect/cure_status.c index f2bf4333d4..0fa0f7ba07 100644 --- a/test/battle/hold_effect/cure_status.c +++ b/test/battle/hold_effect/cure_status.c @@ -160,7 +160,7 @@ SINGLE_BATTLE_TEST("Perism and Lum Berries cure confusion") } } -SINGLE_BATTLE_TEST("Berry hold effect cures status if a pokemon enters a battle") +SINGLE_BATTLE_TEST("Berry hold effect cures status if a Pokémon enters a battle") { u16 status; u16 item; diff --git a/test/battle/move.c b/test/battle/move.c index 541dc3812c..c2d2b6645f 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -226,7 +226,7 @@ DOUBLE_BATTLE_TEST("Moves do not fail if an alive partner is the target") } } -DOUBLE_BATTLE_TEST("Moves fail if they target into a pokemon that was fainted by the previous move") +DOUBLE_BATTLE_TEST("Moves fail if they target into a Pokémon that was fainted by the previous move") { GIVEN { ASSUME(GetMoveTarget(MOVE_HYPER_VOICE) == MOVE_TARGET_BOTH); diff --git a/test/battle/move_effect/after_you.c b/test/battle/move_effect/after_you.c index 42eb0f3ff9..222b94c7b6 100644 --- a/test/battle/move_effect/after_you.c +++ b/test/battle/move_effect/after_you.c @@ -52,7 +52,7 @@ DOUBLE_BATTLE_TEST("After You does nothing if the target has already moved") } } -DOUBLE_BATTLE_TEST("After You calculates correct turn order if only one pokemon is left on the opposing side") +DOUBLE_BATTLE_TEST("After You calculates correct turn order if only one Pokémon is left on the opposing side") { GIVEN { PLAYER(SPECIES_GRENINJA) { Speed(120); } diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index 59844879d4..b808183fbd 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -90,7 +90,7 @@ DOUBLE_BATTLE_TEST("Ally Switch does not redirect the target of Snipe Shot") } } -DOUBLE_BATTLE_TEST("Ally Switch does not redirect moves done by pokemon with Stalwart and Propeller Tail") +DOUBLE_BATTLE_TEST("Ally Switch does not redirect moves done by Pokémon with Stalwart and Propeller Tail") { u16 ability; PARAMETRIZE { ability = ABILITY_STALWART; } diff --git a/test/battle/move_effect/beak_blast.c b/test/battle/move_effect/beak_blast.c index 75796de13a..8c28e7f8ea 100644 --- a/test/battle/move_effect/beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -33,7 +33,7 @@ DOUBLE_BATTLE_TEST("Beak Blast's charging message is shown before other moves ar } } -DOUBLE_BATTLE_TEST("Beak Blast burns all who make contact with the pokemon") +DOUBLE_BATTLE_TEST("Beak Blast burns all who make contact with the Pokémon") { GIVEN { ASSUME(GetMovePriority(MOVE_BEAK_BLAST) < 0); diff --git a/test/battle/move_effect/facade.c b/test/battle/move_effect/facade.c index cc1e21e34f..2ed337cd1c 100644 --- a/test/battle/move_effect/facade.c +++ b/test/battle/move_effect/facade.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Facade (Move Effect) test titles") +TO_DO_BATTLE_TEST("Facade doubles in power when the user is Paralyzed and Poisoned") +TO_DO_BATTLE_TEST("Facade does not ignore burn's attack-halving effect, cancelling out its power (Gen3-5)") +TO_DO_BATTLE_TEST("Facade ignores burn's attack-halving effect, making it double in power (Gen3-5)") diff --git a/test/battle/move_effect/fail_if_not_arg_type.c b/test/battle/move_effect/fail_if_not_arg_type.c index 368c3410c0..e1693f029c 100644 --- a/test/battle/move_effect/fail_if_not_arg_type.c +++ b/test/battle/move_effect/fail_if_not_arg_type.c @@ -32,12 +32,33 @@ SINGLE_BATTLE_TEST("Burn Up fails if the user isn't a Fire-type") } WHEN { TURN { MOVE(player, MOVE_BURN_UP); } } SCENE { - NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } MESSAGE("Wobbuffet used Burn Up!"); + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } + MESSAGE("But it failed!"); + } +} + +TO_DO_BATTLE_TEST("Burn Up doesn't thaw the user if it fails due to the user not being Fire-type") + +SINGLE_BATTLE_TEST("Burn Up fails if the user has Protean/Libero and is not a Fire-type") +{ + KNOWN_FAILING; + GIVEN { + WITH_CONFIG(GEN_PROTEAN_LIBERO, GEN_6); + PLAYER(SPECIES_REGIROCK); + OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_PROTEAN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_BURN_UP); } + } SCENE { + MESSAGE("The opposing Kecleon used Burn Up!"); + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } MESSAGE("But it failed!"); } } +TO_DO_BATTLE_TEST("(TERA) Burn Up user does not lose their Fire type if they've Terastallized into Fire type") + SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type if enemy faints") { GIVEN { diff --git a/test/battle/move_effect/fairy_lock.c b/test/battle/move_effect/fairy_lock.c index a42aa6aa48..e2a941d7e7 100644 --- a/test/battle/move_effect/fairy_lock.c +++ b/test/battle/move_effect/fairy_lock.c @@ -1,4 +1,9 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fairy Lock (Move Effect) test titles") +TO_DO_BATTLE_TEST("Fairy Lock prevents all Pokémon from switching out on their next turn") +TO_DO_BATTLE_TEST("Fairy Lock does not prevent switch out via Dragon Tail") +TO_DO_BATTLE_TEST("Fairy Lock does not prevent switch out via Whirlwind") +TO_DO_BATTLE_TEST("Fairy Lock does not prevent switch out via Eject Button") +TO_DO_BATTLE_TEST("Fairy Lock does not prevent switch out via Red Card") +TO_DO_BATTLE_TEST("Fairy Lock prevents a Pokémon from switching out on the following turn after replacing a fainted mon") diff --git a/test/battle/move_effect/false_swipe.c b/test/battle/move_effect/false_swipe.c index da2cbf6a21..3e84404067 100644 --- a/test/battle/move_effect/false_swipe.c +++ b/test/battle/move_effect/false_swipe.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write False Swipe (Move Effect) test titles") +TO_DO_BATTLE_TEST("False Swipe always leaves the target with at least 1 HP") +TO_DO_BATTLE_TEST("False Swipe still hits the target if it has 1 HP") // Test with Rocky Helmet or something +TO_DO_BATTLE_TEST("False Swipe does not reduce its damage when hitting a substitute") diff --git a/test/battle/move_effect/fell_stinger.c b/test/battle/move_effect/fell_stinger.c index 994cba3457..a5112fe897 100644 --- a/test/battle/move_effect/fell_stinger.c +++ b/test/battle/move_effect/fell_stinger.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Fell Stinger raises user's Attack by 3 stages if it faints target") +SINGLE_BATTLE_TEST("Fell Stinger raises user's Attack by 2 stages (Gen6) or 3 stages (Gen7+) if it faints target") { u32 config; diff --git a/test/battle/move_effect/fillet_away.c b/test/battle/move_effect/fillet_away.c index f9b679bfe5..70f180a700 100644 --- a/test/battle/move_effect/fillet_away.c +++ b/test/battle/move_effect/fillet_away.c @@ -72,3 +72,5 @@ SINGLE_BATTLE_TEST("Fillet Away's HP cost doesn't trigger effects that trigger o NOT MESSAGE("Wobbuffet's Air Balloon popped!"); } } + +TO_DO_BATTLE_TEST("Fillet Away fails if the user's Attack, Sp. Atk and Speed are all maxed out") diff --git a/test/battle/move_effect/final_gambit.c b/test/battle/move_effect/final_gambit.c index be815abf5a..3ab65375c5 100644 --- a/test/battle/move_effect/final_gambit.c +++ b/test/battle/move_effect/final_gambit.c @@ -1,4 +1,16 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Final Gambit (Move Effect) test titles") +TO_DO_BATTLE_TEST("Final Gambit faints the user, and the target receives damage equal to the user's HP") // User should faint before the target +TO_DO_BATTLE_TEST("Final Gambit doesn't faint the user if it misses") +TO_DO_BATTLE_TEST("Final Gambit doesn't faint the user if the target is immune") +TO_DO_BATTLE_TEST("Final Gambit doesn't faint the user if the target is protected") +TO_DO_BATTLE_TEST("Final Gambit doesn't trigger the user's Focus Band") +TO_DO_BATTLE_TEST("Final Gambit doesn't trigger the user's Focus Sash") +TO_DO_BATTLE_TEST("Final Gambit doesn't trigger the user's Sturdy") +TO_DO_BATTLE_TEST("Final Gambit triggers the target's Focus Band") +TO_DO_BATTLE_TEST("Final Gambit triggers the target's Focus Sash") +TO_DO_BATTLE_TEST("Final Gambit triggers the target's Sturdy") +TO_DO_BATTLE_TEST("Final Gambit triggers the target's Endure") +TO_DO_BATTLE_TEST("Final Gambit fails in Max Raids") +TO_DO_BATTLE_TEST("Final Gambit fails in Tera Raids") diff --git a/test/battle/move_effect/first_turn_only.c b/test/battle/move_effect/first_turn_only.c index b26245a3d9..045a84f899 100644 --- a/test/battle/move_effect/first_turn_only.c +++ b/test/battle/move_effect/first_turn_only.c @@ -1,4 +1,8 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fake Out/First Impression (Move Effect) test titles") +TO_DO_BATTLE_TEST("Fake Out can only be used on the user's first turn") +TO_DO_BATTLE_TEST("Fake Out fails if it's called via Instruct") + +TO_DO_BATTLE_TEST("First Impression can only be used on the user's first turn") +TO_DO_BATTLE_TEST("First Impression fails if it's called via Instruct") diff --git a/test/battle/move_effect/fixed_damage_arg.c b/test/battle/move_effect/fixed_damage_arg.c index 8cb2987072..e20498d3fd 100644 --- a/test/battle/move_effect/fixed_damage_arg.c +++ b/test/battle/move_effect/fixed_damage_arg.c @@ -27,7 +27,9 @@ SINGLE_BATTLE_TEST("Sonic Boom deals fixed damage", s16 damage) } } -SINGLE_BATTLE_TEST("Sonic Boom doesn't affect ghost types") +TO_DO_BATTLE_TEST("Sonic Boom affects ghost types (Gen1)") + +SINGLE_BATTLE_TEST("Sonic Boom doesn't affect ghost types (Gen2+)") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/flail.c b/test/battle/move_effect/flail.c index af5544d9b4..e1ba1a2e5e 100644 --- a/test/battle/move_effect/flail.c +++ b/test/battle/move_effect/flail.c @@ -1,4 +1,21 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Flail (Move Effect) test titles") +TO_DO_BATTLE_TEST("Flail has 20 power when HP is greater or equal than 68.8% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 20 power when HP is greater or equal than 67.2% (Gen4+)") +TO_DO_BATTLE_TEST("Flail has 40 power when HP is greater or equal than 35.4% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 40 power when HP is greater or equal than 34.4% (Gen4+)") +TO_DO_BATTLE_TEST("Flail has 80 power when HP is greater or equal than 20.8% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 80 power when HP is greater or equal than 20.3% (Gen4+)") +TO_DO_BATTLE_TEST("Flail has 100 power when HP is greater or equal than 10.4% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 100 power when HP is greater or equal than 9.4% (Gen4+)") +TO_DO_BATTLE_TEST("Flail has 150 power when HP is greater or equal than 4.2% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 150 power when HP is greater or equal than 3.1% (Gen4+)") +TO_DO_BATTLE_TEST("Flail has 200 power when HP is less than 4.2% (Gen2-3)") +TO_DO_BATTLE_TEST("Flail has 200 power when HP is less than 3.1% (Gen4+)") + +TO_DO_BATTLE_TEST("Flail cannot get a Critical Hit (Gen2)") +TO_DO_BATTLE_TEST("Flail can get a Critical Hit (Gen3+)") + +TO_DO_BATTLE_TEST("Flail's damage doesn't vary by a random factor (Gen2)") +TO_DO_BATTLE_TEST("Flail's damage varies by a random factor (Gen3+)") diff --git a/test/battle/move_effect/flatter.c b/test/battle/move_effect/flatter.c index 7effb09329..d9d05a98f2 100644 --- a/test/battle/move_effect/flatter.c +++ b/test/battle/move_effect/flatter.c @@ -1,4 +1,9 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Flatter (Move Effect) test titles") +TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk and confuses them") +TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even if they're already confused") +TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even when protected by Safeguard") +TO_DO_BATTLE_TEST("Flatter raises the target's Sp. Atk even when protected Own Tempo") +TO_DO_BATTLE_TEST("Flatter confuses the target even when they have their Sp. Atk maxed") +TO_DO_BATTLE_TEST("Flatter confuses the target even when at -6 Sp. Atk and has Contrary") diff --git a/test/battle/move_effect/fling.c b/test/battle/move_effect/fling.c index 87074430d2..5435fbcafe 100644 --- a/test/battle/move_effect/fling.c +++ b/test/battle/move_effect/fling.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING); } -SINGLE_BATTLE_TEST("Fling fails if pokemon holds no item") +SINGLE_BATTLE_TEST("Fling fails if Pokémon holds no item") { u16 item; @@ -29,7 +29,7 @@ SINGLE_BATTLE_TEST("Fling fails if pokemon holds no item") } } -SINGLE_BATTLE_TEST("Fling fails if pokemon is under the effects of Embargo or Magic Room") +SINGLE_BATTLE_TEST("Fling fails if Pokémon is under the effects of Embargo or Magic Room") { u16 move; @@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Fling fails if pokemon is under the effects of Embargo or Ma } } -SINGLE_BATTLE_TEST("Fling fails for pokemon with Klutz ability") +SINGLE_BATTLE_TEST("Fling fails for Pokémon with Klutz ability") { u16 ability; @@ -80,6 +80,9 @@ SINGLE_BATTLE_TEST("Fling fails for pokemon with Klutz ability") } } +TO_DO_BATTLE_TEST("Fling fails if the item changes the Pokémon's form") +TO_DO_BATTLE_TEST("Fling works if the item changes a Pokémon's form but not the one holding it") //Eg. non-matching Mega Stones + SINGLE_BATTLE_TEST("Fling's thrown item can be regained with Recycle") { GIVEN { @@ -150,7 +153,7 @@ SINGLE_BATTLE_TEST("Fling - Item is lost when target protects itself") } } -SINGLE_BATTLE_TEST("Fling doesn't consume the item if pokemon is asleep/frozen/paralyzed") +SINGLE_BATTLE_TEST("Fling doesn't consume the item if Pokémon is asleep/frozen/paralyzed") { u32 status; u16 item; @@ -457,3 +460,5 @@ SINGLE_BATTLE_TEST("Fling deals damage based on items fling power") EXPECT_EQ(damage[0], damage[1]); } } + +TO_DO_BATTLE_TEST("Fling deals damage based on a TM's move power") diff --git a/test/battle/move_effect/flower_shield.c b/test/battle/move_effect/flower_shield.c index 784cce99f2..634f0917de 100644 --- a/test/battle/move_effect/flower_shield.c +++ b/test/battle/move_effect/flower_shield.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_FLOWER_SHIELD) == EFFECT_FLOWER_SHIELD); } -DOUBLE_BATTLE_TEST("Flower Shield raises the defense of all grass type pokemon") +DOUBLE_BATTLE_TEST("Flower Shield raises the defense of all Grass-type Pokémon") { GIVEN { ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); @@ -35,3 +35,5 @@ DOUBLE_BATTLE_TEST("Flower Shield raises the defense of all grass type pokemon") MESSAGE("The opposing Sunflora's Defense rose!"); } } + +TO_DO_BATTLE_TEST("Flower Shield fails if there's no Grass-type Pokémon on the field") diff --git a/test/battle/move_effect/focus_energy.c b/test/battle/move_effect/focus_energy.c index 8ecb3ccb47..f42de5dd76 100644 --- a/test/battle/move_effect/focus_energy.c +++ b/test/battle/move_effect/focus_energy.c @@ -12,7 +12,7 @@ SINGLE_BATTLE_TEST("Focus Energy increases the user's critical hit ratio by 1 st u32 genConfig = 0, chance = 0; for (u32 j = GEN_1; j <= GEN_9; j++) { PARAMETRIZE { genConfig = j; useFocusEnergy = FALSE; chance = j >= GEN_7 ? 24 : 16; } // ~4.16%/6.25% with Wobbuffet's base speed - PARAMETRIZE { genConfig = j; useFocusEnergy = TRUE; + PARAMETRIZE { genConfig = j; useFocusEnergy = TRUE; if (j >= GEN_6) chance = 2; // 50% / 25% else if (j >= GEN_3) @@ -39,3 +39,6 @@ SINGLE_BATTLE_TEST("Focus Energy increases the user's critical hit ratio by 1 st MESSAGE("A critical hit!"); } } + +TO_DO_BATTLE_TEST("Focus Energy fails if critical hit stage was already increased by Dragon Cheer") +TO_DO_BATTLE_TEST("Baton Pass passes Focus Energy's effect"); diff --git a/test/battle/move_effect/focus_punch.c b/test/battle/move_effect/focus_punch.c index 7696831dab..e186c094a8 100644 --- a/test/battle/move_effect/focus_punch.c +++ b/test/battle/move_effect/focus_punch.c @@ -75,6 +75,18 @@ DOUBLE_BATTLE_TEST("Focus Punch activation is based on Speed") } } +TO_DO_BATTLE_TEST("Focus Punch activates when the user's Substitute is hit"); +TO_DO_BATTLE_TEST("Focus Punch activates when the user is hit by a status move"); +TO_DO_BATTLE_TEST("Focus Punch uses PP when losing focus (Gen 3-4)"); +TO_DO_BATTLE_TEST("Focus Punch doesn't use PP when losing focus (Gen 5+)"); +TO_DO_BATTLE_TEST("Focus Punch losing focus is considered as the last move used (Gen 3-4)"); //Eg. Encore +TO_DO_BATTLE_TEST("Focus Punch losing focus is not considered as the last move used (Gen 5+)"); //Eg. Encore +TO_DO_BATTLE_TEST("Focus Punch's initial message is not considered as using the move for Zoom Lens"); +TO_DO_BATTLE_TEST("Focus Punch's initial message is not shown if the user selected a different move and was Encored into using Focus Punch"); +TO_DO_BATTLE_TEST("Focus Punch will use the selected move's priority when being Encored into Focus Punch"); +TO_DO_BATTLE_TEST("Focus Punch will lose focus if damaged when used by selecting a different move and being Encored (Gen 3-4)"); +TO_DO_BATTLE_TEST("Focus Punch will NOT lose focus if damaged when used by selecting a different move and being Encored (Gen 5+)"); + AI_SINGLE_BATTLE_TEST("AI won't use Focus Punch if it predicts a damaging move") { GIVEN { diff --git a/test/battle/move_effect/follow_me.c b/test/battle/move_effect/follow_me.c index 89591b8c6e..1acf193864 100644 --- a/test/battle/move_effect/follow_me.c +++ b/test/battle/move_effect/follow_me.c @@ -34,6 +34,19 @@ DOUBLE_BATTLE_TEST("Follow Me redirects single target moves used by opponents to } } +TO_DO_BATTLE_TEST("Follow Me doesn't redirect opponent moves that can't affect opponents") //Eg. Helping Hand +TO_DO_BATTLE_TEST("Follow Me no longer redirects if the center of attention faints mid-turn") +TO_DO_BATTLE_TEST("Follow Me can only redirect charging moves on the turn that they would hit") +TO_DO_BATTLE_TEST("Follow Me can only redirect Future Sight/Doom Desire on the turn they were selected (Gen3-5)") +TO_DO_BATTLE_TEST("Follow Me does not redirect Future Sight/Doom Desire (Gen 6+)") +TO_DO_BATTLE_TEST("Follow Me draws Electric/Water moves even if there's a Pokémon with Lightning Rod/Storm Drain") +TO_DO_BATTLE_TEST("Follow Me prioritizes the first Pokémon that used it") // There can be 2 centers of attention. If the first is gone, the 2nd is used +//TO_DO_BATTLE_TEST("Triples: Follow Me can only draw non-adjacent moves if they use a long-range move") +TO_DO_BATTLE_TEST("Follow Me can be used in Single Battles (Gen3-SwSh)") +TO_DO_BATTLE_TEST("Follow Me fails in Single Battles (BDSP+)") +TO_DO_BATTLE_TEST("Follow Me cannot redirect Sky Drop") +TO_DO_BATTLE_TEST("Follow Me does not draw attack when the user is being Sky-Dropped") + DOUBLE_BATTLE_TEST("Spotlight redirects single target moves used by the opposing side to Spotlight's target") { struct BattlePokemon *moveTarget = NULL; diff --git a/test/battle/move_effect/foresight.c b/test/battle/move_effect/foresight.c index 082e2d6fa4..59209030d0 100644 --- a/test/battle/move_effect/foresight.c +++ b/test/battle/move_effect/foresight.c @@ -1,4 +1,14 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Foresight (Move Effect) test titles") +TO_DO_BATTLE_TEST("Foresight removes Ghost's type immunity to Normal and Fighting types") +TO_DO_BATTLE_TEST("Foresight causes accuracy/evasion stat changes only between the user/target when the user's accuracy stage is less than the target's evasion stage (Gen 2)") +TO_DO_BATTLE_TEST("Foresight causes all moves against the target to ignore evasion stat changes (Gen 3)") +TO_DO_BATTLE_TEST("Foresight causes all moves against the target to ignore only positive evasion stat changes (Gen 4+)") // Eg. Doesn't ignore Sweet Scent +TO_DO_BATTLE_TEST("Foresight doesn't cause moves used against the target to always hit (Gen 2-3)") +TO_DO_BATTLE_TEST("Foresight causes moves used against the target to always hit (Gen 4+)") +TO_DO_BATTLE_TEST("Foresight does not make moves hit semi-invulnerable targets") +TO_DO_BATTLE_TEST("Foresight fails if the target is already under its effect (Gen 2 and Gen5+)") +TO_DO_BATTLE_TEST("Foresight doesn't fail if the target is already under its effect (Gen 3-4)") +TO_DO_BATTLE_TEST("Baton Pass passes Foresight's effect (Gen 2)"); +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Foresight's effect (Gen 3+)"); diff --git a/test/battle/move_effect/foul_play.c b/test/battle/move_effect/foul_play.c index 7df04201ef..58af6bc4f0 100644 --- a/test/battle/move_effect/foul_play.c +++ b/test/battle/move_effect/foul_play.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_FOUL_PLAY) == EFFECT_FOUL_PLAY); } -SINGLE_BATTLE_TEST("Foul Play uses physical attack stat of target", s16 damage) +SINGLE_BATTLE_TEST("Foul Play uses the target's Attack stat and stat stages of target", s16 damage) { u32 move; @@ -27,3 +27,7 @@ SINGLE_BATTLE_TEST("Foul Play uses physical attack stat of target", s16 damage) EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); } } + +TO_DO_BATTLE_TEST("Foul Play uses the user's attack modifiers - Held Item") +TO_DO_BATTLE_TEST("Foul Play uses the user's attack modifiers - Ability") +TO_DO_BATTLE_TEST("Foul Play uses the user's attack modifiers - Burn") diff --git a/test/battle/move_effect/frustration.c b/test/battle/move_effect/frustration.c index eb994c5076..bc9682a954 100644 --- a/test/battle/move_effect/frustration.c +++ b/test/battle/move_effect/frustration.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Frustration (Move Effect) test titles") +TO_DO_BATTLE_TEST("Frustration's power increases the lower friendship of the user is") +TO_DO_BATTLE_TEST("Frustration does 0 damage at max Friendship (Gen2)") +TO_DO_BATTLE_TEST("Frustration does 1 damage at max Friendship (Gen3+)") diff --git a/test/battle/move_effect/fury_cutter.c b/test/battle/move_effect/fury_cutter.c index 10d9d8a64e..74362c6316 100644 --- a/test/battle/move_effect/fury_cutter.c +++ b/test/battle/move_effect/fury_cutter.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_FURY_CUTTER) == EFFECT_FURY_CUTTER); } -SINGLE_BATTLE_TEST("Fury Cutter power doubles with each use, up to 160 power") +SINGLE_BATTLE_TEST("Fury Cutter's power doubles with each use, up to 160 power") { s16 damage[6]; int turn; @@ -37,6 +37,10 @@ SINGLE_BATTLE_TEST("Fury Cutter power doubles with each use, up to 160 power") } } +TO_DO_BATTLE_TEST("Fury Cutter's power is reset if the user misses") +TO_DO_BATTLE_TEST("Fury Cutter's power is reset if the user is switched out") +TO_DO_BATTLE_TEST("Fury Cutter's power is reset if the trainer uses an item") + SINGLE_BATTLE_TEST("Fury Cutter counter is the same for both hits of Parental Bond") { s16 damage[4]; diff --git a/test/battle/move_effect/fusion_combo.c b/test/battle/move_effect/fusion_combo.c index 7561536b11..30c4508a00 100644 --- a/test/battle/move_effect/fusion_combo.c +++ b/test/battle/move_effect/fusion_combo.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Fusion Flare/Bolt (Move Effect) test titles") +TO_DO_BATTLE_TEST("Fusion Flare and Fusion Bolt double in power if the other move was immediately used in the same turn") +TO_DO_BATTLE_TEST("Fusion Flare and Fusion Bolt do not double in power if there was a move used in-between the two of them") +TO_DO_BATTLE_TEST("Fusion Flare and Fusion Bolt double in power if used by the same Pokémon in the same turn") // Use Instruct to replicate this diff --git a/test/battle/move_effect/future_sight.c b/test/battle/move_effect/future_sight.c index 71e3aa7378..246c384a07 100644 --- a/test/battle/move_effect/future_sight.c +++ b/test/battle/move_effect/future_sight.c @@ -66,7 +66,8 @@ SINGLE_BATTLE_TEST("Future Sight is not boosted by Life Orb is original user if } } -SINGLE_BATTLE_TEST("Future Sight receives STAB from party mon") +TO_DO_BATTLE_TEST("Future Sight does not receive STAB from party mon (Gen 2-4)") +SINGLE_BATTLE_TEST("Future Sight receives STAB from party mon (Gen 5+)") { s16 seedFlareDmg; s16 futureSightDmg; @@ -91,7 +92,8 @@ SINGLE_BATTLE_TEST("Future Sight receives STAB from party mon") } } -SINGLE_BATTLE_TEST("Future Sight is affected by type effectiveness") +TO_DO_BATTLE_TEST("Future Sight is not affected by type effectiveness (Gen 2-4)") +SINGLE_BATTLE_TEST("Future Sight is affected by type effectiveness (Gen 5+)") { GIVEN { PLAYER(SPECIES_PIKACHU); @@ -113,6 +115,9 @@ SINGLE_BATTLE_TEST("Future Sight is affected by type effectiveness") } } +TO_DO_BATTLE_TEST("Future Sight ignores Wonder Guard (Gen 2-4)") +TO_DO_BATTLE_TEST("Future Sight doesn't ignore Wonder Guard (Gen 5+)") + SINGLE_BATTLE_TEST("Future Sight will miss timing if target faints before it is about to get hit") { GIVEN { diff --git a/test/battle/move_effect/grassy_terrain.c b/test/battle/move_effect/grassy_terrain.c index 8b1895928b..2b5e166bfd 100644 --- a/test/battle/move_effect/grassy_terrain.c +++ b/test/battle/move_effect/grassy_terrain.c @@ -81,7 +81,7 @@ SINGLE_BATTLE_TEST("Grassy Terrain lasts for 5 turns") } } -SINGLE_BATTLE_TEST("Grassy Terrain heals the pokemon on the field for the duration of the terrain, including last turn") +SINGLE_BATTLE_TEST("Grassy Terrain heals the Pokémon on the field for the duration of the terrain, including last turn") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/haze.c b/test/battle/move_effect/haze.c index 81a30d5796..3f530834fe 100644 --- a/test/battle/move_effect/haze.c +++ b/test/battle/move_effect/haze.c @@ -30,3 +30,6 @@ SINGLE_BATTLE_TEST("Haze resets stat changes", s16 damage) EXPECT_EQ(results[0].damage, results[1].damage); } } + +TO_DO_BATTLE_TEST("Haze resets Focus Energy (Gen 1 and 4)") +TO_DO_BATTLE_TEST("Haze doesn't reset Focus Energy (Gen 2-3 and 5+)") diff --git a/test/battle/move_effect/healing_wish.c b/test/battle/move_effect/healing_wish.c index a29b04367c..f303456a38 100644 --- a/test/battle/move_effect/healing_wish.c +++ b/test/battle/move_effect/healing_wish.c @@ -49,7 +49,7 @@ DOUBLE_BATTLE_TEST("Lunar Dance causes the user to faint and fully heals the rep } } -SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched pokemon can be healed") +SINGLE_BATTLE_TEST("Healing Wish effect activates only if the switched Pokémon can be healed") { GIVEN { ASSUME(B_HEALING_WISH_SWITCH >= GEN_8); diff --git a/test/battle/move_effect/hit_escape.c b/test/battle/move_effect/hit_escape.c index a268f991b4..0ced64d7e5 100644 --- a/test/battle/move_effect/hit_escape.c +++ b/test/battle/move_effect/hit_escape.c @@ -159,7 +159,7 @@ SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon } } -SINGLE_BATTLE_TEST("Hit Escape: Electric Seed boost is received by the right pokemon after U-turn and Intimidate") +SINGLE_BATTLE_TEST("Hit Escape: Electric Seed boost is received by the right Pokémon after U-turn and Intimidate") { GIVEN { PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }; diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 6dddfae4e7..b1bebf9123 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -162,7 +162,7 @@ SINGLE_BATTLE_TEST("Protect: Spiky Shield does 1/8 dmg of max hp of attackers ma } } -SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making contact") +SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons Pokémon for moves making contact") { u16 usedMove = MOVE_NONE; @@ -194,7 +194,7 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making con } } -SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are already statused") +SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison Pokémon if they are already statused") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -215,7 +215,7 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are alr } } -SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making contact") +SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns Pokémon for moves making contact") { u16 usedMove = MOVE_NONE; @@ -247,7 +247,7 @@ SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making cont } } -SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn pokemon if they are already statused") +SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn Pokémon if they are already statused") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/quash.c b/test/battle/move_effect/quash.c index 1d2f89230c..0869b45aeb 100644 --- a/test/battle/move_effect/quash.c +++ b/test/battle/move_effect/quash.c @@ -44,7 +44,7 @@ DOUBLE_BATTLE_TEST("Quash is not affected by dynamic speed") } } -DOUBLE_BATTLE_TEST("Quash calculates correct turn order if only one pokemon is left on the opposing side") +DOUBLE_BATTLE_TEST("Quash calculates correct turn order if only one Pokémon is left on the opposing side") { GIVEN { PLAYER(SPECIES_GRENINJA) { Speed(120); } diff --git a/test/battle/move_effect/return.c b/test/battle/move_effect/return.c index 50945ca556..2a2614200d 100644 --- a/test/battle/move_effect/return.c +++ b/test/battle/move_effect/return.c @@ -1,4 +1,6 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Return (Move Effect) test titles") +TO_DO_BATTLE_TEST("Return's power increases the higher friendship of the user is") +TO_DO_BATTLE_TEST("Return does 0 damage at min Friendship (Gen2)") +TO_DO_BATTLE_TEST("Return does 1 damage at min Friendship (Gen3+)") diff --git a/test/battle/move_effect/rototiller.c b/test/battle/move_effect/rototiller.c index 34b62a2666..669d971269 100644 --- a/test/battle/move_effect/rototiller.c +++ b/test/battle/move_effect/rototiller.c @@ -51,7 +51,7 @@ SINGLE_BATTLE_TEST("Rototiller fails if there are no valid targets") } } -SINGLE_BATTLE_TEST("Rototiller doesn't affect pokemon that are semi-invulnerable") +SINGLE_BATTLE_TEST("Rototiller doesn't affect Pokémon that are semi-invulnerable") { GIVEN { ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); diff --git a/test/battle/move_effect/round.c b/test/battle/move_effect/round.c index 0bac324b0f..985822d46d 100644 --- a/test/battle/move_effect/round.c +++ b/test/battle/move_effect/round.c @@ -94,7 +94,7 @@ DOUBLE_BATTLE_TEST("Round still preserves the turn order outside of the other Ro } } -DOUBLE_BATTLE_TEST("Round causes opposing pokemon to use Round immediately") +DOUBLE_BATTLE_TEST("Round causes opposing Pokémon to use Round immediately") { GIVEN { ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL); diff --git a/test/battle/move_effect/shed_tail.c b/test/battle/move_effect/shed_tail.c index 4ce05c3f8c..68a6f62630 100644 --- a/test/battle/move_effect/shed_tail.c +++ b/test/battle/move_effect/shed_tail.c @@ -57,7 +57,7 @@ SINGLE_BATTLE_TEST("Shed Tail's HP cost can trigger a berry before the user swit } } -SINGLE_BATTLE_TEST("Shed Tail fails if there are no usable pokemon left") +SINGLE_BATTLE_TEST("Shed Tail fails if there are no usable Pokémon left") { GIVEN { PLAYER(SPECIES_WOBBUFFET) diff --git a/test/battle/move_effect/stealth_rock.c b/test/battle/move_effect/stealth_rock.c index ccd0ea496b..1ea6bea23b 100644 --- a/test/battle/move_effect/stealth_rock.c +++ b/test/battle/move_effect/stealth_rock.c @@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Stealth Rock damage on switch in based on typing") } } -SINGLE_BATTLE_TEST("Stealth Rock damages the correct pokemon when Eject Button is triggered") +SINGLE_BATTLE_TEST("Stealth Rock damages the correct Pokémon when Eject Button is triggered") { GIVEN { PLAYER(SPECIES_METAPOD) { Item(ITEM_EJECT_BUTTON); } @@ -53,7 +53,7 @@ SINGLE_BATTLE_TEST("Stealth Rock damages the correct pokemon when Eject Button i } } -DOUBLE_BATTLE_TEST("Stealth Rock damages the correct pokemon when Eject Button is triggered in double battle") +DOUBLE_BATTLE_TEST("Stealth Rock damages the correct Pokémon when Eject Button is triggered in double battle") { GIVEN { PLAYER(SPECIES_METAPOD) { Item(ITEM_EJECT_BUTTON); } diff --git a/test/battle/move_effect/swagger.c b/test/battle/move_effect/swagger.c index 5845d4292f..3217e48903 100644 --- a/test/battle/move_effect/swagger.c +++ b/test/battle/move_effect/swagger.c @@ -1,4 +1,10 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Swagger (Move Effect) test titles") +TO_DO_BATTLE_TEST("Swagger raises the target's Attack and confuses them") +TO_DO_BATTLE_TEST("Swagger raises the target's Attack even if they're already confused") +TO_DO_BATTLE_TEST("Swagger raises the target's Attack even when protected by Safeguard") +TO_DO_BATTLE_TEST("Swagger raises the target's Attack even when protected Own Tempo") +TO_DO_BATTLE_TEST("Swagger doesn't confuse the target when they have their Attack maxed (Gen2)") +TO_DO_BATTLE_TEST("Swagger confuses the target even when they have their Attack maxed (Gen3+)") +TO_DO_BATTLE_TEST("Swagger confuses the target even when at -6 Attack and has Contrary") diff --git a/test/battle/move_effect/teleport.c b/test/battle/move_effect/teleport.c index f77dffc658..76fb499722 100644 --- a/test/battle/move_effect/teleport.c +++ b/test/battle/move_effect/teleport.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_TELEPORT) == EFFECT_TELEPORT); } -SINGLE_BATTLE_TEST("Teleport fails when there is no pokemon to switch in") +SINGLE_BATTLE_TEST("Teleport fails when there is no Pokémon to switch in") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Teleport fails when there is no pokemon to switch in") } } -SINGLE_BATTLE_TEST("Teleport fails when there no alive pokemon left") +SINGLE_BATTLE_TEST("Teleport fails when there no alive Pokémon left") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Teleport fails when there no alive pokemon left") } } -SINGLE_BATTLE_TEST("Teleport forces the pokemon to switch out") +SINGLE_BATTLE_TEST("Teleport forces the Pokémon to switch out") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/uproar.c b/test/battle/move_effect/uproar.c index cbe17ce066..23bcdce458 100644 --- a/test/battle/move_effect/uproar.c +++ b/test/battle/move_effect/uproar.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_UPROAR) == EFFECT_UPROAR); } -DOUBLE_BATTLE_TEST("Uproar status causes sleeping pokemon to wake up during an attack") +DOUBLE_BATTLE_TEST("Uproar status causes sleeping Pokémon to wake up during an attack") { PASSES_RANDOMLY(1, 2, RNG_RANDOM_TARGET); // test fails if we target soundproof mon GIVEN { diff --git a/test/battle/move_effect_secondary/bug_bite.c b/test/battle/move_effect_secondary/bug_bite.c index 70e0966caa..e6df81dc70 100644 --- a/test/battle/move_effect_secondary/bug_bite.c +++ b/test/battle/move_effect_secondary/bug_bite.c @@ -36,7 +36,7 @@ SINGLE_BATTLE_TEST("Bug Bite eats the target's berry and immediately gains its e PLAYER(SPECIES_WOBBUFFET) { HP(399); MaxHP(400); Status1(status1); Moves(MOVE_SLEEP_TALK, MOVE_BUG_BITE); } OPPONENT(SPECIES_WOBBUFFET) { Item(item); } } WHEN { - // Chesto Berry can only be applied if the pokemon is asleep and uses Sleep Talk. + // Chesto Berry can only be applied if the Pokémon is asleep and uses Sleep Talk. if (item == ITEM_CHESTO_BERRY) { TURN { MOVE(player, MOVE_SLEEP_TALK); } } else { diff --git a/test/battle/move_effect_secondary/dire_claw.c b/test/battle/move_effect_secondary/dire_claw.c index 35c6e73d94..ad9ffcc4e2 100644 --- a/test/battle/move_effect_secondary/dire_claw.c +++ b/test/battle/move_effect_secondary/dire_claw.c @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe } } -SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep pokemon with abilities preventing respective statuses") +SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep Pokémon with abilities preventing respective statuses") { u8 statusAnim; u16 species, ability; diff --git a/test/battle/move_effect_secondary/tri_attack.c b/test/battle/move_effect_secondary/tri_attack.c index e84573dcdf..ab33561cf0 100644 --- a/test/battle/move_effect_secondary/tri_attack.c +++ b/test/battle/move_effect_secondary/tri_attack.c @@ -74,9 +74,9 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ } #if B_USE_FROSTBITE == TRUE -SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/frostbite pokemon with abilities preventing respective statuses") +SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/frostbite Pokémon with abilities preventing respective statuses") #else -SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilities preventing respective statuses") +SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze Pokémon with abilities preventing respective statuses") #endif { u8 statusAnim; diff --git a/test/battle/spread_moves.c b/test/battle/spread_moves.c index a37fb847db..9ea104597a 100644 --- a/test/battle/spread_moves.c +++ b/test/battle/spread_moves.c @@ -83,7 +83,7 @@ DOUBLE_BATTLE_TEST("Spread Moves: A spread move attack will activate both resist } } -DOUBLE_BATTLE_TEST("Spread Moves: If a spread move attack will activate a resist berries on one pokemon, only the damage for that mon will be reduced") +DOUBLE_BATTLE_TEST("Spread Moves: If a spread move attack will activate a resist berries on one Pokémon, only the damage for that mon will be reduced") { s16 opponentLeftDmg[2]; s16 opponentRightDmg[2]; diff --git a/test/battle/status1/frostbite.c b/test/battle/status1/frostbite.c index f45508f800..35503b00a3 100644 --- a/test/battle/status1/frostbite.c +++ b/test/battle/status1/frostbite.c @@ -23,7 +23,7 @@ SINGLE_BATTLE_TEST("Frostbite reduces the special attack by 50 percent") } THEN { EXPECT_EQ(reducedDamage * 2, normaleDamage); } } -SINGLE_BATTLE_TEST("Frostbite deals 1/16th (Gen7+) or 1/8th damage to affected pokemon") +SINGLE_BATTLE_TEST("Frostbite deals 1/16th (Gen7+) or 1/8th damage to affected Pokémon") { s16 frostbiteDamage; From 509b4ec5dda96a2b35aa49e14a9c6db3efa20e4e Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 24 Aug 2025 17:31:48 +0200 Subject: [PATCH 254/283] Fixed typo in test name (#7610) Co-authored-by: Hedara --- test/battle/ability/intimidate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/ability/intimidate.c b/test/battle/ability/intimidate.c index cefda4d1b8..c7308bfdaf 100644 --- a/test/battle/ability/intimidate.c +++ b/test/battle/ability/intimidate.c @@ -376,7 +376,7 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second } } -SINGLE_BATTLE_TEST("Intimdate does not lose timing after mega evolution and switch out by a hit escape move") +SINGLE_BATTLE_TEST("Intimidate does not lose timing after mega evolution and switch out by a hit escape move") { GIVEN { ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE); From e3178d3ff695101807fd89c1a58cea30fab8295b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 24 Aug 2025 19:06:13 +0200 Subject: [PATCH 255/283] Fix duplicate switch in after faint (#7600) --- src/battle_ai_switch_items.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index aa7d819a1e..9c8061aabf 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1507,6 +1507,24 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva return bestMonId; } +static u32 GetFirstNonIvalidMon(u32 firstId, u32 lastId, u32 invalidMons, u32 battlerIn1, u32 battlerIn2) +{ + if (!IsDoubleBattle()) + return PARTY_SIZE; + + if (PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn1] + && PARTY_SIZE != gBattleStruct->monToSwitchIntoId[battlerIn2]) + return PARTY_SIZE; + + for (u32 chosenMonId = (lastId-1); chosenMonId >= firstId; chosenMonId--) + { + if ((1 << (chosenMonId)) & invalidMons) + continue; + return chosenMonId; // first non invalid mon found + } + return PARTY_SIZE; +} + bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2) { // List that makes mon not grounded @@ -2045,6 +2063,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 aiMove, hitsToKOAI, maxHitsToKO = 0; u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup; bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1; + u32 invalidMons = 0; // Iterate through mons for (i = firstId; i < lastId; i++) @@ -2056,6 +2075,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, || i == gBattleStruct->monToSwitchIntoId[battlerIn1] || i == gBattleStruct->monToSwitchIntoId[battlerIn2]) { + invalidMons |= 1u << i; continue; } // Save Ace Pokemon for last @@ -2063,6 +2083,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, { aceMonId = i; aceMonCount++; + invalidMons |= 1u << i; continue; } else @@ -2212,6 +2233,11 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) return aceMonId; + // Fallback + u32 bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + if (bestMonId != PARTY_SIZE) + return bestMonId; + return PARTY_SIZE; } @@ -2329,6 +2355,11 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) && (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch)) return aceMonId; + // Fallback + bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + if (bestMonId != PARTY_SIZE) + return bestMonId; + return PARTY_SIZE; } } From 9b5b69ae496f6005b194c3e15c43f76c97814e31 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 25 Aug 2025 05:40:52 -0400 Subject: [PATCH 256/283] switchinabilities also runs ON_WEATHER and ON_TERRAIN (#7612) Co-authored-by: ghoulslash --- src/battle_script_commands.c | 7 +++++++ test/battle/ability/mimicry.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bc97a288d8..0d90a3290d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10639,6 +10639,13 @@ static void Cmd_various(void) gBattlescriptCurrInstr = cmd->nextInstr; AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); + + if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect()) + AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); + + if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); return; } diff --git a/test/battle/ability/mimicry.c b/test/battle/ability/mimicry.c index b9c3bb5fc3..df69e89b71 100644 --- a/test/battle/ability/mimicry.c +++ b/test/battle/ability/mimicry.c @@ -95,3 +95,32 @@ DOUBLE_BATTLE_TEST("Mimicry can trigger multiple times in a turn") } } +DOUBLE_BATTLE_TEST("Mimicry triggers after Skill Swap") +{ + GIVEN { + PLAYER(SPECIES_STUNFISK_GALAR) { Speed(40); Ability(ABILITY_MIMICRY); } + PLAYER(SPECIES_SHIFTRY) { Speed(50); Ability(ABILITY_CHLOROPHYLL); } + OPPONENT(SPECIES_SHUCKLE) { Speed(30); } + OPPONENT(SPECIES_CHANSEY) { Speed(20); } + } WHEN { + TURN { MOVE(playerRight, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(playerRight, MOVE_SKILL_SWAP, target: playerLeft); + MOVE(playerLeft, MOVE_SPLASH); + } + } SCENE { + // turn 1 + MESSAGE("Shiftry used Grassy Terrain!"); + ABILITY_POPUP(playerLeft, ABILITY_MIMICRY); + MESSAGE("Stunfisk's type changed to Grass!"); + // turn 2 + MESSAGE("Shiftry used Skill Swap!"); + ABILITY_POPUP(playerRight, ABILITY_MIMICRY); + MESSAGE("Shiftry's type changed to Grass!"); + MESSAGE("Stunfisk used Splash!"); // make sure popup occurs before the subsequent move + } THEN { + EXPECT_EQ(playerLeft->types[0], TYPE_GRASS); + EXPECT_EQ(playerLeft->types[1], TYPE_GRASS); + EXPECT_EQ(playerRight->types[0], TYPE_GRASS); + EXPECT_EQ(playerRight->types[1], TYPE_GRASS); + } +} From 53e7699649f1352613f2566841a05a5b965e8449 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 25 Aug 2025 11:41:36 +0200 Subject: [PATCH 257/283] Fixes Explosion behavior when 3 mons can endure hit (#7594) --- src/battle_script_commands.c | 20 +++++++++----------- test/battle/spread_moves.c | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0d90a3290d..70540ef275 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2181,7 +2181,7 @@ static void Cmd_adjustdamage(void) u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); - bool32 enduredHit = FALSE; + u32 enduredHit = 0; for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { @@ -2227,30 +2227,30 @@ static void Cmd_adjustdamage(void) if (moveEffect == EFFECT_FALSE_SWIPE) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; } else if (gProtectStructs[battlerDef].endured) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED; } else if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordItemEffectBattle(battlerDef, holdEffect); gLastUsedItem = gBattleMons[battlerDef].item; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; } else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordAbilityBattle(battlerDef, ABILITY_STURDY); gLastUsedAbility = ABILITY_STURDY; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED; } else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; RecordItemEffectBattle(battlerDef, holdEffect); gLastUsedItem = gBattleMons[battlerDef].item; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; @@ -2261,20 +2261,18 @@ static void Cmd_adjustdamage(void) || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) { - enduredHit = TRUE; + enduredHit |= 1u << battlerDef; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; } } // Handle reducing the dmg to 1 hp. - if (enduredHit) + if (enduredHit & 1u << battlerDef) { gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; gSpecialStatuses[battlerDef].enduredDamage = TRUE; - } - - if (gSpecialStatuses[battlerDef].enduredDamage) gProtectStructs[battlerDef].assuranceDoubled = TRUE; + } } if (calcSpreadMoveDamage) diff --git a/test/battle/spread_moves.c b/test/battle/spread_moves.c index 9ea104597a..d5e6b5c26d 100644 --- a/test/battle/spread_moves.c +++ b/test/battle/spread_moves.c @@ -433,3 +433,23 @@ DOUBLE_BATTLE_TEST("Spread Moves: Unless move hits every target user will not in MESSAGE("It's super effective on the opposing Torkoal and Torkoal!"); } } + +DOUBLE_BATTLE_TEST("Spread Moves: Focus Sash activates correctly") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(2); MaxHP(2); Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WOBBUFFET) { HP(2); MaxHP(2); Item(ITEM_FOCUS_SASH); } + OPPONENT(SPECIES_WYNAUT) { HP(2); MaxHP(2); Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(playerRight, MOVE_HYPER_VOICE); MOVE(playerLeft, MOVE_EXPLOSION); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerRight); + MESSAGE("The opposing Wynaut hung on using its Focus Sash!"); + MESSAGE("The opposing Wobbuffet hung on using its Focus Sash!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft); + MESSAGE("The opposing Wobbuffet fainted!"); + MESSAGE("Wynaut hung on using its Focus Sash!"); + MESSAGE("The opposing Wynaut fainted!"); + } +} From ff3e8da00712fead2d13d7dfa54b1d2eda29aa7c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 25 Aug 2025 11:46:23 +0200 Subject: [PATCH 258/283] Minor Clean up in battle_ai_main.c (#7551) --- src/battle_ai_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 95ac1e43b3..b287c53189 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1120,9 +1120,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case MOVE_EFFECT_BURN: ADJUST_SCORE(-5); break; + default: + break; } break; - break; case ABILITY_WONDER_GUARD: if (effectiveness < UQ_4_12(2.0)) RETURN_SCORE_MINUS(20); From 0a3c281cdd97ac5eb20371d6b175b100e14ac91b Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Mon, 25 Aug 2025 05:48:52 -0400 Subject: [PATCH 259/283] Fix terastallization anims flickering (#7613) --- data/battle_anim_scripts.s | 3 ++- src/battle_anim_effects_3.c | 26 ++++++++++++++++++++++++++ src/battle_gfx_sfx_util.c | 7 ------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 50a9b51dc7..19109e190e 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -28732,6 +28732,7 @@ MegaEvolutionSpinEffect: return gBattleAnimGeneral_TeraCharge:: + createvisualtask AnimTask_HideOpponentShadows, 2 @ Hide opponent shadows so they don't flicker between battle anims loadspritegfx ANIM_TAG_TERA_CRYSTAL loadspritegfx ANIM_TAG_TERA_SHATTER loadspritegfx ANIM_TAG_FOCUS_ENERGY @@ -28753,7 +28754,6 @@ gBattleAnimGeneral_TeraCharge:: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 1, 0 call TeraChargeParticles playsewithpan SE_M_BRICK_BREAK, SOUND_PAN_ATTACKER clearmonbg ANIM_ATK_PARTNER @@ -28770,6 +28770,7 @@ TeraChargeParticles: return gBattleAnimGeneral_TeraActivate:: + createvisualtask AnimTask_SetOpponentShadowCallbacks, 2 @ Restore shadows hidden in the charge script createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 5, 14 waitforvisualfinish diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 409244ccac..04be1553bc 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -2515,6 +2515,32 @@ void AnimTask_HideSwapSprite(u8 taskId) } } +void AnimTask_HideOpponentShadows(u8 taskId) +{ + u32 battlerLeft = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerLeft].shadowSpriteIdPrimary].callback = SpriteCB_SetInvisible; + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerLeft].shadowSpriteIdSecondary].callback = SpriteCB_SetInvisible; + if (IsDoubleBattle()) + { + u32 battlerRight = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerRight].shadowSpriteIdPrimary].callback = SpriteCB_SetInvisible; + gSprites[gBattleSpritesDataPtr->healthBoxesData[battlerRight].shadowSpriteIdSecondary].callback = SpriteCB_SetInvisible; + } + DestroyAnimVisualTask(taskId); +} + +void AnimTask_SetOpponentShadowCallbacks(u8 taskId) +{ + u32 battlerLeft = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + SetBattlerShadowSpriteCallback(battlerLeft, gBattleMons[battlerLeft].species); + if (IsDoubleBattle()) + { + u32 battlerRight = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + SetBattlerShadowSpriteCallback(battlerRight, gBattleMons[battlerRight].species); + } + DestroyAnimVisualTask(taskId); +} + void AnimTask_TransformMon(u8 taskId) { int i, j; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 6ca847a272..5b88ec642d 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -1003,13 +1003,6 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); } - // Terastallization's tint - if (GetActiveGimmick(battlerAtk) == GIMMICK_TERA) - { - BlendPalette(paletteOffset, 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battlerAtk))); - CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); - } - gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk); StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], 0); } From 6df3a48ca232068be1e9237f77d77f2275fbbf64 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 25 Aug 2025 15:46:36 +0200 Subject: [PATCH 260/283] Fixes octolock not ending after user switched out (#7556) Co-authored-by: Bassoonian --- asm/macros/battle_script.inc | 5 ++- data/battle_scripts_1.s | 2 +- .../how_to_battle_script_command_macro.md | 33 +++++++++---------- include/battle.h | 2 +- src/battle_main.c | 4 +++ src/battle_script_commands.c | 12 +++---- test/battle/move_effect/octolock.c | 25 ++++++++++++++ test/battle/move_effect/sky_drop.c | 13 ++++++++ 8 files changed, 67 insertions(+), 29 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 721c844554..46581dfab2 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1440,9 +1440,8 @@ callnative BS_TryRevertWeatherForm .endm - .macro trysetoctolock battler:req, failInstr:req + .macro trysetoctolock failInstr:req callnative BS_TrySetOctolock - .byte \battler .4byte \failInstr .endm @@ -1737,7 +1736,7 @@ callnative BS_ActivateTerrainChangeAbilities .byte \battler .endm - + .macro resetterrainabilityflags callnative BS_ResetTerrainAbilityFlags .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bebce183e9..45f5a5babf 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -868,7 +868,7 @@ BattleScript_EffectOctolock:: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - trysetoctolock BS_TARGET, BattleScript_ButItFailed + trysetoctolock BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE diff --git a/docs/tutorials/how_to_battle_script_command_macro.md b/docs/tutorials/how_to_battle_script_command_macro.md index 2bbf503fbe..911da7d09c 100644 --- a/docs/tutorials/how_to_battle_script_command_macro.md +++ b/docs/tutorials/how_to_battle_script_command_macro.md @@ -12,36 +12,33 @@ In general, `gBattlescriptCurrInstr` tracks the current battle script position a ``` `callnative` uses the last battle script command ID in order to pass a native function as an argument. Additional optional arguments are added recursively via a macro, so no need to worry about how they need to align to the amount of instructions to skip. -Now, how might we add a custom `callnative` command? Here are the steps. We will use `BS_TrySetOctolock` as an example. +Now, how might we add a custom `callnative` command? Here are the steps. We will use `BS_JumpIfTerrainAffected` as an example. ### 1. Create a macro in `asm/macros/battle_script.inc`. For example: ```c - .macro trysetoctolock battler:req, failInstr:req - callnative BS_TrySetOctolock + .macro jumpifterrainaffected battler:req, terrainFlags:req, jumpInstr:req + callnative BS_JumpIfTerrainAffected .byte \battler - .4byte \failInstr + .4byte \terrainFlags + .4byte \jumpInstr .endm ``` ### 2. Add your new callnative command ID to `src/battle_script_commands.c`. For example: ```c -void BS_TrySetOctolock(void) +void BS_JumpIfTerrainAffected(void) { - NATIVE_ARGS(u8 battler, const u8 *failInstr); + NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr); u32 battler = GetBattlerForBattleScript(cmd->battler); - if (gDisableStructs[battler].octolock) - { - gBattlescriptCurrInstr = cmd->failInstr; - } + if (IsBattlerTerrainAffected(battler, cmd->flags)) + gBattlescriptCurrInstr = cmd->jumpInstr; else - { - gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; - gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; - } } ``` -Each of the arguments defined in the macro (`battler`, `failInstr`) need to be called at the start of the command using `NATIVE_ARGS`. +Each of the arguments defined in the macro (`battler`, `flags`, `failInstr`) need to be called at the start of the command using `NATIVE_ARGS`. The byte count in the macro should correspond to the type that will be used for the command (eg, `u8` is `byte`, while the pointer are `4byte`). -These arguments can then be accessed as `cmd->battler` and `cmd->battler`. -`gBattlescriptCurrInstr = cmd->nextInstr;` advances to the next instruction. +These arguments can then be accessed as `cmd->battler`, `cmd->flags` and `cmd->failInstr`. +Note that for `cmd->battler` we need to use `GetBattlerForBattleScript` to fetch the correct battler because with the macro we are accessing a scripting command that doesn't corresponds to `gBattlerTarget`, `gBattlerAttacker`, etc. +For the battler argument specifically, most of the time the battler is accessed through `gBattlerAttacker`, `gBattlerTarget` and the battler argument left out. +In the majority of cases, this is fine since the script commands are mostly used for moves and the interaction is usually between an attacker and target. +A script command usually ends with either a jump or next instruction `gBattlescriptCurrInstr = cmd->nextInstr / cmd->nextInstr;` advancing to the next instruction. diff --git a/include/battle.h b/include/battle.h index 179ea47769..d8b9c70102 100644 --- a/include/battle.h +++ b/include/battle.h @@ -133,7 +133,7 @@ struct DisableStruct u8 neutralizingGas:1; u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in - u8 padding:3; + u8 octolockedBy:3; }; // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects diff --git a/src/battle_main.c b/src/battle_main.c index 50e4df8a50..efbe2dd0ff 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3173,6 +3173,8 @@ void SwitchInClearSetData(u32 battler) gBattleMons[i].status2 &= ~STATUS2_WRAPPED; if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) + gDisableStructs[i].octolock = FALSE; } gActionSelectionCursor[battler] = 0; @@ -3291,6 +3293,8 @@ const u8* FaintClearSetData(u32 battler) gBattleMons[i].status2 &= ~STATUS2_WRAPPED; if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler) gStatuses4[i] &= ~STATUS4_SYRUP_BOMB; + if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler) + gDisableStructs[i].octolock = FALSE; } gActionSelectionCursor[battler] = 0; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 70540ef275..a9fc0c6f46 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -17447,18 +17447,18 @@ void BS_TryReflectType(void) void BS_TrySetOctolock(void) { - NATIVE_ARGS(u8 battler, const u8 *failInstr); - u32 battler = GetBattlerForBattleScript(cmd->battler); + NATIVE_ARGS(const u8 *failInstr); - if (gDisableStructs[battler].octolock) + if (gDisableStructs[gBattlerTarget].octolock) { gBattlescriptCurrInstr = cmd->failInstr; } else { - gDisableStructs[battler].octolock = TRUE; - gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION; - gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker; + gDisableStructs[gBattlerTarget].octolock = TRUE; + gDisableStructs[gBattlerTarget].octolockedBy = gBattlerAttacker; + gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION; + gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker; gBattlescriptCurrInstr = cmd->nextInstr; } } diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c index e93f6f29cb..e50e7de514 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -152,3 +152,28 @@ SINGLE_BATTLE_TEST("Octolock triggers Defiant for both stat reductions") MESSAGE("The opposing Bisharp's Attack sharply rose!"); } } + +SINGLE_BATTLE_TEST("Octolock ends after user that set the lock switches out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("The opposing Wobbuffet can no longer escape because of Octolock!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's Defense fell!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's Sp. Def fell!"); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Wobbuffet's Defense fell!"); + MESSAGE("The opposing Wobbuffet's Sp. Def fell!"); + } + + } +} diff --git a/test/battle/move_effect/sky_drop.c b/test/battle/move_effect/sky_drop.c index c2a1e104e1..3790fd4ef3 100644 --- a/test/battle/move_effect/sky_drop.c +++ b/test/battle/move_effect/sky_drop.c @@ -122,3 +122,16 @@ SINGLE_BATTLE_TEST("Sky Drop stops the confusion count until the target is dropp ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player); } } + +SINGLE_BATTLE_TEST("Sky Drop fails if the targe is in a semi-invulnerable state") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_FLY); MOVE(player, MOVE_SKY_DROP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, player); + } +} From 1bb9a1c86b46d87c708e1a9dae97649cbf630c6c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:36:43 +0200 Subject: [PATCH 261/283] Remove unused function (#7617) --- src/battle_script_commands.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a9fc0c6f46..a98fba7408 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6078,28 +6078,6 @@ static inline bool32 IsProtectivePadsProtected(u32 battler, enum ItemHoldEffect return TRUE; } -static inline bool32 IsProtectEffectAffected(u32 battler, u32 move) -{ - enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - if (IsProtectivePadsProtected(battler, holdEffect)) - return TRUE; - - if (holdEffect == HOLD_EFFECT_CLEAR_AMULET) - { - RecordItemEffectBattle(battler, holdEffect); - return TRUE; - } - - u32 ability = GetBattlerAbility(gBattlerAttacker); - if (CanAbilityPreventStatLoss(ability)) - { - RecordAbilityBattle(battler, ability); - return TRUE; - } - - return FALSE; -} - static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_BUTTON From e2f24bbb3ff9811ecefd2314738f349a429f10b6 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:37:57 +0200 Subject: [PATCH 262/283] Prevents a regression for custom abilties (#7616) --- include/constants/battle.h | 17 +++++++++-------- src/battle_script_commands.c | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 0f83eaecae..926023359f 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -363,16 +363,17 @@ enum BattleWeather #define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) +// Explicit numbers until frostbite because those shouldn't be shifted enum __attribute__((packed)) MoveEffect { - MOVE_EFFECT_NONE, - MOVE_EFFECT_SLEEP, - MOVE_EFFECT_POISON, - MOVE_EFFECT_BURN, - MOVE_EFFECT_FREEZE, - MOVE_EFFECT_PARALYSIS, - MOVE_EFFECT_TOXIC, - MOVE_EFFECT_FROSTBITE, + MOVE_EFFECT_NONE = 0, + MOVE_EFFECT_SLEEP = 1, + MOVE_EFFECT_POISON = 2, + MOVE_EFFECT_BURN = 3, + MOVE_EFFECT_FREEZE = 4, + MOVE_EFFECT_PARALYSIS = 5, + MOVE_EFFECT_TOXIC = 6, + MOVE_EFFECT_FROSTBITE = 7, MOVE_EFFECT_CONFUSION, MOVE_EFFECT_FLINCH, MOVE_EFFECT_TRI_ATTACK, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c58b85d187..3d8041966f 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12906,7 +12906,7 @@ static bool32 CanAbilityShieldActivateForBattler(u32 battler) { if (GetBattlerHoldEffectIgnoreAbility(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD) return FALSE; - + RecordItemEffectBattle(battler, HOLD_EFFECT_ABILITY_SHIELD); gBattlerAbility = battler; gLastUsedItem = gBattleMons[battler].item; @@ -14534,7 +14534,7 @@ static void Cmd_setnonvolatilestatus(void) switch (cmd->trigger) { case TRIGGER_ON_ABILITY: - if (gBattleScripting.moveEffect == MOVE_EFFECT_CONFUSION) + if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION) SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); else SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); From 8044255fee5e84b87168c23f904fcce7dc277c25 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Tue, 26 Aug 2025 06:25:18 -0700 Subject: [PATCH 263/283] Fix Vs Seeker Trainer Battle script issue (#7615) --- src/vs_seeker.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 15829c3bd5..1a7dc68c72 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -529,7 +529,6 @@ void ClearRematchMovementByTrainerId(void) TryGetObjectEventIdByLocalIdAndMap(objectEventTemplates[i].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &objEventId); objectEvent = &gObjectEvents[objEventId]; - GetRandomFaceDirectionMovementType(&objectEventTemplates[i]); TryOverrideTemplateCoordsForObjectEvent(objectEvent, sFaceDirectionMovementTypeByFacingDirection[objectEvent->facingDirection]); if (gSelectedObjectEvent == objEventId) @@ -705,22 +704,11 @@ static u8 GetResponseMovementTypeFromTrainerGraphicsId(u8 graphicsId) #endif //FREE_MATCH_CALL static u16 GetTrainerFlagFromScript(const u8 *script) - /* - * The trainer flag is a little-endian short located +2 from - * the script pointer, assuming the trainerbattle command is - * first in the script. Because scripts are unaligned, and - * because the ARM processor requires shorts to be 16-bit - * aligned, this function needs to perform explicit bitwise - * operations to get the correct flag. - * - * 5c XX YY ZZ ... - * -- -- - */ -{ - u16 trainerFlag; - - script += 2; - trainerFlag = script[0]; +{ + // The trainer flag is located 3 bytes (command + flags + localIdA) from the script pointer, assuming the trainerbattle command is first in the script. + // Because scripts are unaligned, and because the ARM processor requires shorts to be 16-bit aligned, this function needs to perform explicit bitwise operations to get the correct flag. + script += 3; + u16 trainerFlag = script[0]; trainerFlag |= script[1] << 8; return trainerFlag; } From a45d36d90f1e8943e33ce1543b57adeba50cf220 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 26 Aug 2025 22:16:57 +0200 Subject: [PATCH 264/283] The original attacker wasn't restored for Doodle (#7620) Co-authored-by: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Co-authored-by: Bassoonian --- data/battle_scripts_1.s | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 45f5a5babf..5f8e768c69 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -221,12 +221,13 @@ BattleScript_EffectDoodle:: attackstring ppreduce trycopyability BS_ATTACKER, BattleScript_ButItFailed + saveattacker attackanimation waitanimation setbyte gBattleCommunication, 0 goto BattleScript_EffectDoodle_AfterCopy BattleScript_EffectDoodle_CopyAbility: - trycopyability BS_ATTACKER, BattleScript_MoveEnd + trycopyability BS_ATTACKER, BattleScript_EffectDoodleMoveEnd BattleScript_EffectDoodle_AfterCopy: .if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerAttacker @@ -238,8 +239,10 @@ BattleScript_EffectDoodle_AfterCopy: switchinabilities BS_ATTACKER jumpifbyte CMP_NOT_EQUAL, gBattleCommunication, 0x0, BattleScript_MoveEnd addbyte gBattleCommunication, 1 - jumpifnoally BS_ATTACKER, BattleScript_MoveEnd + jumpifnoally BS_ATTACKER, BattleScript_EffectDoodleMoveEnd setallytonextattacker BattleScript_EffectDoodle_CopyAbility +BattleScript_EffectDoodleMoveEnd: + restoreattacker goto BattleScript_MoveEnd BattleScript_EffectGlaiveRush:: From 2fbf45d057ba5ead9746d913df95620200508b81 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Tue, 26 Aug 2025 16:17:30 -0400 Subject: [PATCH 265/283] Restore X item friendship increase (#7583) --- include/battle_controllers.h | 1 + include/constants/item_effects.h | 4 +++ include/pokemon.h | 1 + src/battle_controllers.c | 46 +++++++++++++++++++++++++ src/battle_util.c | 6 ++++ src/data/pokemon/item_effects.h | 20 ----------- src/pokemon.c | 3 +- test/battle/item_effect/increase_stat.c | 23 +++++++++++++ test/battle/move_effect/embargo.c | 46 ++++++++++++++----------- 9 files changed, 107 insertions(+), 43 deletions(-) diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 2ce28ca609..b628e69dc1 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -277,6 +277,7 @@ void InitBattleControllers(void); bool32 IsValidForBattle(struct Pokemon *mon); void TryReceiveLinkBattleData(void); void PrepareBufferDataTransferLink(u32 battler, u32 bufferId, u16 size, u8 *data); +void UpdateFriendshipFromXItem(u32 battler); // emitters void BtlController_EmitGetMonData(u32 battler, u32 bufferId, u8 requestId, u8 monToCheck); diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index ac1c7d5c5b..dbe322beac 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -93,4 +93,8 @@ #define ITEM_EFFECT_HEAL_PP 21 #define ITEM_EFFECT_NONE 22 +// Since X item stat increases are now handled by battle scripts, the friendship increase effect is now handled by the battle controller in HandleAction_UseItem. +#define X_ITEM_FRIENDSHIP_INCREASE 1 // The amount of friendship gained by using an X item on a Pokémon in battle. +#define X_ITEM_MAX_FRIENDSHIP 200 // Friendship threshold at which Pokémon stop receiving a friendship increase from using X items on them in battle. + #endif // GUARD_CONSTANTS_ITEM_EFFECTS_H diff --git a/include/pokemon.h b/include/pokemon.h index edc37a1a0b..ebc21441d8 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -830,5 +830,6 @@ uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier) u32 GetRegionalFormByRegion(u32 species, u32 region); bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion); u32 GetTeraTypeFromPersonality(struct Pokemon *mon); +bool8 ShouldSkipFriendshipChange(void); #endif // GUARD_POKEMON_H diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 885b2a922a..da18baee14 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -12,9 +12,11 @@ #include "battle_tv.h" #include "cable_club.h" #include "event_object_movement.h" +#include "item.h" #include "link.h" #include "link_rfu.h" #include "m4a.h" +#include "overworld.h" #include "palette.h" #include "party_menu.h" #include "recorded_battle.h" @@ -25,6 +27,7 @@ #include "util.h" #include "text.h" #include "constants/abilities.h" +#include "constants/item_effects.h" #include "constants/songs.h" #include "pokemon_animation.h" @@ -3260,3 +3263,46 @@ bool32 SwitchIn_TryShinyAnimUtil(u32 battler) return TRUE; } + +void UpdateFriendshipFromXItem(u32 battler) +{ + struct Pokemon *party = GetBattlerParty(battler); + + u8 friendship; + gBattleResources->bufferA[battler][1] = REQUEST_FRIENDSHIP_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &friendship); + + u16 heldItem; + gBattleResources->bufferA[battler][1] = REQUEST_HELDITEM_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], (u8*)&heldItem); + + if (friendship < X_ITEM_MAX_FRIENDSHIP) + { + if (GetItemHoldEffect(heldItem) == HOLD_EFFECT_FRIENDSHIP_UP) + friendship += 150 * X_ITEM_FRIENDSHIP_INCREASE / 100; + else + friendship += X_ITEM_FRIENDSHIP_INCREASE; + + u8 pokeball; + gBattleResources->bufferA[battler][1] = REQUEST_POKEBALL_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &pokeball); + + if (pokeball == BALL_LUXURY) + friendship++; + + u8 metLocation; + gBattleResources->bufferA[battler][1] = REQUEST_MET_LOCATION_BATTLE; + GetBattlerMonData(battler, party, gBattlerPartyIndexes[battler], &metLocation); + + if (metLocation == GetCurrentRegionMapSectionId()) + friendship++; + + if (friendship > MAX_FRIENDSHIP) + friendship = MAX_FRIENDSHIP; + + gBattleMons[battler].friendship = friendship; + gBattleResources->bufferA[battler][3] = friendship; + gBattleResources->bufferA[battler][1] = REQUEST_FRIENDSHIP_BATTLE; + SetBattlerMonData(battler, GetBattlerParty(battler), gBattlerPartyIndexes[battler]); + } +} diff --git a/src/battle_util.c b/src/battle_util.c index 18b8570579..a683ff9989 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -44,6 +44,7 @@ #include "constants/battle_string_ids.h" #include "constants/hold_effects.h" #include "constants/items.h" +#include "constants/item_effects.h" #include "constants/moves.h" #include "constants/songs.h" #include "constants/species.h" @@ -580,6 +581,11 @@ void HandleAction_UseItem(void) ClearVariousBattlerFlags(gBattlerAttacker); gLastUsedItem = gBattleResources->bufferB[gBattlerAttacker][1] | (gBattleResources->bufferB[gBattlerAttacker][2] << 8); + if (X_ITEM_FRIENDSHIP_INCREASE > 0 + && GetItemEffectType(gLastUsedItem) == ITEM_EFFECT_X_ITEM + && !ShouldSkipFriendshipChange()) + UpdateFriendshipFromXItem(gBattlerAttacker); + gBattlescriptCurrInstr = gBattlescriptsForUsingItem[GetItemBattleUsage(gLastUsedItem) - 1]; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } diff --git a/src/data/pokemon/item_effects.h b/src/data/pokemon/item_effects.h index 93ff78ad7c..851424021f 100644 --- a/src/data/pokemon/item_effects.h +++ b/src/data/pokemon/item_effects.h @@ -334,14 +334,8 @@ const u8 gItemEffect_PPMax[9] = { VITAMIN_FRIENDSHIP_CHANGE(6), }; -#define STAT_BOOST_FRIENDSHIP_CHANGE \ - [6] = 1, /* Friendship change, low */ \ - [7] = 1 /* Friendship change, mid */ - const u8 gItemEffect_GuardSpec[8] = { [3] = ITEM3_GUARD_SPEC, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; // The first item effect value for the stat boost items @@ -350,44 +344,30 @@ const u8 gItemEffect_GuardSpec[8] = { const u8 gItemEffect_DireHit[8] = { [0] = 1 << 5, // ITEM0_DIRE_HIT - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XAttack[8] = { [1] = ITEM1_X_ATTACK, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XDefense[8] = { [1] = ITEM1_X_DEFENSE, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XSpeed[8] = { [1] = ITEM1_X_SPEED, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XAccuracy[8] = { [1] = ITEM1_X_ACCURACY, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XSpecialAttack[8] = { [1] = ITEM1_X_SPATK, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_XSpecialDefense[8] = { [1] = ITEM1_X_SPDEF, - [5] = ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID, - STAT_BOOST_FRIENDSHIP_CHANGE, }; const u8 gItemEffect_EvoItem[6] = { diff --git a/src/pokemon.c b/src/pokemon.c index 9b7ce57de1..6e0e7accb8 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -80,7 +80,6 @@ static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 perso static void EncryptBoxMon(struct BoxPokemon *boxMon); static void DecryptBoxMon(struct BoxPokemon *boxMon); static void Task_PlayMapChosenOrBattleBGM(u8 taskId); -static bool8 ShouldSkipFriendshipChange(void); void TrySpecialOverworldEvo(); EWRAM_DATA static u8 sLearningMoveTableID = 0; @@ -6385,7 +6384,7 @@ bool8 HasTwoFramesAnimation(u16 species) && !gTestRunnerHeadless; } -static bool8 ShouldSkipFriendshipChange(void) +bool8 ShouldSkipFriendshipChange(void) { if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) return TRUE; diff --git a/test/battle/item_effect/increase_stat.c b/test/battle/item_effect/increase_stat.c index 3f162ea828..b56f1a2b84 100644 --- a/test/battle/item_effect/increase_stat.c +++ b/test/battle/item_effect/increase_stat.c @@ -1,5 +1,6 @@ #include "global.h" #include "test/battle.h" +#include "constants/item_effects.h" SINGLE_BATTLE_TEST("X Attack sharply raises battler's Attack stat", s16 damage) { @@ -257,3 +258,25 @@ SINGLE_BATTLE_TEST("Max Mushrooms raises battler's Speed stat", s16 damage) } } } + +SINGLE_BATTLE_TEST("Using X items in battle raises Friendship", s16 damage) +{ + u32 startingFriendship; + u8 metLocation = MAPSEC_NONE; + PARAMETRIZE { startingFriendship = 0; } + PARAMETRIZE { startingFriendship = X_ITEM_MAX_FRIENDSHIP; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Friendship(startingFriendship); }; + // Set met location to MAPSEC_NONE to avoid getting the friendship boost + // from being met in the current map section + SetMonData(&PLAYER_PARTY[0], MON_DATA_MET_LOCATION, &metLocation); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { USE_ITEM(player, ITEM_X_ACCURACY); MOVE(opponent, MOVE_CELEBRATE); } + } THEN { + if (startingFriendship == X_ITEM_MAX_FRIENDSHIP) + EXPECT_EQ(player->friendship, X_ITEM_MAX_FRIENDSHIP); + else + EXPECT_EQ(player->friendship, X_ITEM_FRIENDSHIP_INCREASE); + } +} diff --git a/test/battle/move_effect/embargo.c b/test/battle/move_effect/embargo.c index 3e86b60b0b..4b06b92fc1 100644 --- a/test/battle/move_effect/embargo.c +++ b/test/battle/move_effect/embargo.c @@ -114,28 +114,32 @@ SINGLE_BATTLE_TEST("Embargo negates a held item's Speed reduction") } } -WILD_BATTLE_TEST("Embargo doesn't block held item effects that affect friendship") -{ - u32 initialFriendship; - u32 finalFriendship; +// This is a useful test, but under the current circumstances, we can't actually test this without modifying +// X_ITEM_FRIENDSHIP_INCREASE. Since HOLD_EFFECT_FRIENDSHIP_UP applies a 1.5x modifier, and the stock +// Friendship increase is 1, the held item effect actually does not affect the Friendship gained. +// +// WILD_BATTLE_TEST("Embargo doesn't block held item effects that affect friendship") +// { +// u32 initialFriendship; +// u32 finalFriendship; - KNOWN_FAILING; // Pokémon are currently not obtaining Friendship for using items in battle. - GIVEN { - ASSUME(gItemsInfo[ITEM_X_ACCURACY].battleUsage == EFFECT_ITEM_INCREASE_STAT); - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SOOTHE_BELL); }; - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { USE_ITEM(player, ITEM_X_ACCURACY); } - TURN { MOVE(player, MOVE_SING); } - } SCENE { - MESSAGE("Wobbuffet used Sing!"); - MESSAGE("Wild Wobbuffet fell asleep!"); - } THEN { - initialFriendship = GetMonData(&PLAYER_PARTY[0], MON_DATA_FRIENDSHIP); - finalFriendship = GetMonData(&gPlayerParty[0], MON_DATA_FRIENDSHIP); - EXPECT_EQ(finalFriendship, initialFriendship + 2); - } -} +// KNOWN_FAILING; // Pokémon are currently not obtaining Friendship for using items in battle. +// GIVEN { +// ASSUME(gItemsInfo[ITEM_X_ACCURACY].battleUsage == EFFECT_ITEM_INCREASE_STAT); +// PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SOOTHE_BELL); }; +// OPPONENT(SPECIES_WOBBUFFET); +// } WHEN { +// TURN { USE_ITEM(player, ITEM_X_ACCURACY); } +// TURN { MOVE(player, MOVE_SING); } +// } SCENE { +// MESSAGE("Wobbuffet used Sing!"); +// MESSAGE("Wild Wobbuffet fell asleep!"); +// } THEN { +// initialFriendship = GetMonData(&PLAYER_PARTY[0], MON_DATA_FRIENDSHIP); +// finalFriendship = GetMonData(&gPlayerParty[0], MON_DATA_FRIENDSHIP); +// EXPECT_EQ(finalFriendship, initialFriendship + 2); +// } +// } SINGLE_BATTLE_TEST("Embargo doesn't block a held item's form-changing effect, but it does block its other effects", s16 damage) { From f0bd3d544e67a9b4afeddf5705ae144b64668f25 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:16:11 +0100 Subject: [PATCH 266/283] Fixes Wonder Room interactions with Defense/Special Defense boosting effects (#7626) --- src/battle_util.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index a683ff9989..2850b7d23f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8865,6 +8865,14 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u RecordAbilityBattle(battlerDef, ABILITY_THICK_FAT); } break; + case ABILITY_PURIFYING_SALT: + if (moveType == TYPE_GHOST) + { + modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.5)); + if (damageCalcData->updateFlags) + RecordAbilityBattle(battlerDef, ABILITY_PURIFYING_SALT); + } + break; } // ally's abilities @@ -8947,31 +8955,38 @@ static inline u32 CalcDefenseStat(struct DamageCalculationData *damageCalcData, uq4_12_t modifier; u32 battlerDef = damageCalcData->battlerDef; u32 move = damageCalcData->move; - u32 moveType = damageCalcData->moveType; enum BattleMoveEffects moveEffect = GetMoveEffect(move); - if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped - { - def = gBattleMons[battlerDef].spDefense; - spDef = gBattleMons[battlerDef].defense; - } - else - { - def = gBattleMons[battlerDef].defense; - spDef = gBattleMons[battlerDef].spDefense; - } + def = gBattleMons[battlerDef].defense; + spDef = gBattleMons[battlerDef].spDefense; if (moveEffect == EFFECT_PSYSHOCK || IsBattleMovePhysical(move)) // uses defense stat instead of sp.def { - defStat = def; + if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped + { + defStat = spDef; + usesDefStat = FALSE; + } + else + { + defStat = def; + usesDefStat = TRUE; + } defStage = gBattleMons[battlerDef].statStages[STAT_DEF]; - usesDefStat = TRUE; } else // is special { - defStat = spDef; + if (gFieldStatuses & STATUS_FIELD_WONDER_ROOM) // the defense stats are swapped + { + defStat = def; + usesDefStat = TRUE; + } + else + { + defStat = spDef; + usesDefStat = FALSE; + } defStage = gBattleMons[battlerDef].statStages[STAT_SPDEF]; - usesDefStat = FALSE; } // Self-destruct / Explosion cut defense in half @@ -9025,10 +9040,6 @@ static inline u32 CalcDefenseStat(struct DamageCalculationData *damageCalcData, if (gBattleMons[battlerDef].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SUN) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; - case ABILITY_PURIFYING_SALT: - if (moveType == TYPE_GHOST) - modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); - break; } // ally's abilities From de790e481518834dbcca1682337a45defe042c0a Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 28 Aug 2025 07:51:02 -0400 Subject: [PATCH 267/283] Ally Switch attract battler swapping, test for leech seed (#7634) Co-authored-by: ghoulslash --- src/battle_anim_effects_1.c | 28 +++++++++++++ test/battle/move_effect/ally_switch.c | 58 +++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 74444065b8..570b2d1085 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6864,6 +6864,33 @@ static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner) SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp); } +static void TrySwapAttractBattlerIds(u32 battlerAtk, u32 battlerPartner) +{ + u32 attractedTo; + + // our own infatuation handled with gBattleMons struct data swapping + + // if another battler is infatuated with one of us, change to other battler + for (u32 i = 0; i < gBattlersCount; i++) { + if (i == battlerAtk || i == battlerPartner || !(gBattleMons[i].status2 & STATUS2_INFATUATION)) + continue; + + attractedTo = CountTrailingZeroBits((gBattleMons[i].status2 & STATUS2_INFATUATION) >> 0x10); + if (attractedTo == battlerAtk) + { + gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battlerAtk); + gBattleMons[i].status2 |= STATUS2_INFATUATED_WITH(battlerPartner); + break; + } + else if (attractedTo == battlerPartner) + { + gBattleMons[i].status2 &= ~STATUS2_INFATUATED_WITH(battlerPartner); + gBattleMons[i].status2 |= STATUS2_INFATUATED_WITH(battlerAtk); + break; + } + } +} + static void SwapBattlerMoveData(u32 battler1, u32 battler2) { u32 temp; @@ -6936,6 +6963,7 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) TrySwapSkyDropTargets(battlerAtk, battlerPartner); TrySwapStickyWebBattlerId(battlerAtk, battlerPartner); TrySwapWishBattlerIds(battlerAtk, battlerPartner); + TrySwapAttractBattlerIds(battlerAtk, battlerPartner); // For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target. for (i = 0; i < gBattlersCount; i++) diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index b808183fbd..e3f99cb73b 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -348,5 +348,63 @@ DOUBLE_BATTLE_TEST("Ally switch updates last used moves for Mimic") } } +DOUBLE_BATTLE_TEST("Ally Switch does not update leech seed battler") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_SOLOSIS); + OPPONENT(SPECIES_BULBASAUR) { HP(50); MaxHP(100); } + OPPONENT(SPECIES_RALTS) { HP(50); MaxHP(100); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_LEECH_SEED, target: playerLeft); } + TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); } + TURN { ; } + } SCENE { + // turn 1 + MESSAGE("The opposing Bulbasaur used Leech Seed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, opponentLeft); + 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!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_LEECH_SEED_DRAIN, playerLeft); + HP_BAR(playerLeft); + HP_BAR(opponentLeft); // Ralts now gets hp gain + } THEN { + EXPECT_GT(opponentLeft->hp, 50); + EXPECT_GT(opponentRight->hp, 50); + } +} + +DOUBLE_BATTLE_TEST("Ally Switch updates attract battler") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); Gender(MON_MALE); } + PLAYER(SPECIES_SOLOSIS) { Speed(50); } + OPPONENT(SPECIES_CLEFAIRY) { Speed(20); Gender(MON_FEMALE); Ability(ABILITY_CUTE_CHARM); } + OPPONENT(SPECIES_RALTS) { Speed(30); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); } + TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); } + TURN { ; } + } SCENE { + // turn 1 + MESSAGE("Wobbuffet used Tackle!"); + HP_BAR(opponentLeft); + ABILITY_POPUP(opponentLeft, ABILITY_CUTE_CHARM); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_INFATUATION, playerLeft); + MESSAGE("The opposing Clefairy's Cute Charm infatuated Wobbuffet!"); + // turn 2 + MESSAGE("The opposing Ralts used Ally Switch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, opponentRight); + MESSAGE("The opposing Ralts and the opposing Clefairy switched places!"); + // turn 3 + MESSAGE("Wobbuffet is in love with the opposing Clefairy!"); // tracks attract battler + } +} + // Triple Battles required to test //TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle"); From ce77c48142234ee1e355ed14ae3b380885bc094b Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 28 Aug 2025 14:23:44 +0200 Subject: [PATCH 268/283] remove unused var --- src/battle_util.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 0655831db1..de7cec8d58 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8872,7 +8872,6 @@ static inline u32 CalcDefenseStat(struct DamageContext *ctx) uq4_12_t modifier; u32 battlerDef = ctx->battlerDef; u32 move = ctx->move; - u32 moveType = ctx->moveType; enum BattleMoveEffects moveEffect = GetMoveEffect(move); def = gBattleMons[battlerDef].defense; From d812b58064fce57ce74252a688742ee65b1973b3 Mon Sep 17 00:00:00 2001 From: Hedara Date: Thu, 28 Aug 2025 15:49:29 +0200 Subject: [PATCH 269/283] Expansion version 1.12.3 --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 +- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 +- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 +- README.md | 2 +- docs/SUMMARY.md | 1 + docs/changelogs/1.12.x/1.12.3.md | 118 ++++++++++++++++++ include/constants/expansion.h | 4 +- 7 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 docs/changelogs/1.12.x/1.12.3.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index b48cda404c..5c7bf2b5cf 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.2 (Latest release) + - 1.12.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.2 - 1.12.1 - 1.12.0 - 1.11.4 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 95b00ef2d1..ed94c1355e 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.2 (Latest release) + - 1.12.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.2 - 1.12.1 - 1.12.0 - 1.11.4 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index d955d09cbc..a391c6473d 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.2 (Latest release) + - 1.12.3 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.2 - 1.12.1 - 1.12.0 - 1.11.4 diff --git a/README.md b/README.md index 4cd0a5f161..b6a78a3736 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.12.2 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.12.3 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 89767de31b..89b86087c1 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -20,6 +20,7 @@ - [Day/Night System FAQ](tutorials/dns.md) - [Changelog](./CHANGELOG.md) - [1.12.x]() + - [Version 1.12.3](changelogs/1.12.x/1.12.3.md) - [Version 1.12.2](changelogs/1.12.x/1.12.2.md) - [Version 1.12.1](changelogs/1.12.x/1.12.1.md) - [Version 1.12.0](changelogs/1.12.x/1.12.0.md) diff --git a/docs/changelogs/1.12.x/1.12.3.md b/docs/changelogs/1.12.x/1.12.3.md new file mode 100644 index 0000000000..a4deece835 --- /dev/null +++ b/docs/changelogs/1.12.x/1.12.3.md @@ -0,0 +1,118 @@ +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.12.3 +`. +``` + + +## 🧬 General 🧬 +### Changed +* Restore git history check by @ravepossum in [#7463](https://github.com/rh-hideout/pokeemerald-expansion/pull/7463) +* Moved summary screen nature colors to summary_screen.h by @RubyRaven6 in [#7560](https://github.com/rh-hideout/pokeemerald-expansion/pull/7560) +* Added comment in event.inc for simple menus in dynmultichoice by @RubyRaven6 in [#7568](https://github.com/rh-hideout/pokeemerald-expansion/pull/7568) +* Changed default print level for DebugPrintf for mGBA to MGBA_LOG_WARN by @hedara90 in [#7567](https://github.com/rh-hideout/pokeemerald-expansion/pull/7567) +* Fixed Teleport's description not being updated based on `B_TELEPORT_BEHAVIOR` by @AsparagusEduardo in [#7580](https://github.com/rh-hideout/pokeemerald-expansion/pull/7580) +* Minor Clean up in battle_ai_main.c by @AlexOn1ine in [#7551](https://github.com/rh-hideout/pokeemerald-expansion/pull/7551) + +## 🗺️ Overworld 🗺️ +### Changed +* fix: remove unused wild_encounters.json.txt jinja file by @khbsd in [#7581](https://github.com/rh-hideout/pokeemerald-expansion/pull/7581) + +### Fixed +* Bug fix: add handling for forced movements into/after ledge jumps with follower NPCs by @Bivurnum in [#7055](https://github.com/rh-hideout/pokeemerald-expansion/pull/7055) +* Fixed compile issue `OW_TIMES_OF_DAY` is `GEN_3` by @AsparagusEduardo in [#7499](https://github.com/rh-hideout/pokeemerald-expansion/pull/7499) +* Remove shadow and hide follower on stair warp by @cornixsenex in [#7368](https://github.com/rh-hideout/pokeemerald-expansion/pull/7368) +* Fix Form Change Item Task Data and Clean Up Field Use Funcs by @ravepossum in [#7535](https://github.com/rh-hideout/pokeemerald-expansion/pull/7535) +* Fix Vs Seeker Trainer Battle script issue by @pkmnsnfrn in [#7615](https://github.com/rh-hideout/pokeemerald-expansion/pull/7615) + +## ⚔️ Battle General ⚔️ +### Changed +* Remove unused function by @AlexOn1ine in [#7617](https://github.com/rh-hideout/pokeemerald-expansion/pull/7617) + +### Fixed +* Fixes Magnet Rise when user is Rooted/Smacked Down by @PhallenTree in [#7449](https://github.com/rh-hideout/pokeemerald-expansion/pull/7449) +* Fixes Leech Seed recovery not applying behind Sub by @AlexOn1ine in [#7468](https://github.com/rh-hideout/pokeemerald-expansion/pull/7468) +* Fixes Round and Fusion moves doubling power from previous turn's move by @PhallenTree in [#7476](https://github.com/rh-hideout/pokeemerald-expansion/pull/7476) +* Fixes shadows and mon animations for transformed battlers by @AsparagusEduardo in [#7500](https://github.com/rh-hideout/pokeemerald-expansion/pull/7500) +* Fixes Life Orb still activating if move was absorbed by @AlexOn1ine in [#7521](https://github.com/rh-hideout/pokeemerald-expansion/pull/7521) +* Fix Mimicry Only Activating Once per Turn by @ghoulslash in [#7537](https://github.com/rh-hideout/pokeemerald-expansion/pull/7537) +* Fixes Knock Off still activating when there is no Item by @AlexOn1ine in [#7496](https://github.com/rh-hideout/pokeemerald-expansion/pull/7496) +* Fixed `B_PSYWAVE_DMG` by @AsparagusEduardo in [#7557](https://github.com/rh-hideout/pokeemerald-expansion/pull/7557) +* Fixes Counter / Mirror Coat / Metal Burst damage assignment by @AlexOn1ine in [#7538](https://github.com/rh-hideout/pokeemerald-expansion/pull/7538) +* Fix in-game partner battles always causing a whiteout by @ravepossum in [#7587](https://github.com/rh-hideout/pokeemerald-expansion/pull/7587) +* Fix B_ANIMATE_MON_AFTER_KO with a new counter by @hedara90 in [#7531](https://github.com/rh-hideout/pokeemerald-expansion/pull/7531) +* Fixes Rage Fist counter increment by @AlexOn1ine in [#7582](https://github.com/rh-hideout/pokeemerald-expansion/pull/7582) +* Fixes moveend_absorb hitmarker by @AlexOn1ine in [#7591](https://github.com/rh-hideout/pokeemerald-expansion/pull/7591) +* switchinabilities also runs ON_WEATHER and ON_TERRAIN by @ghoulslash in [#7612](https://github.com/rh-hideout/pokeemerald-expansion/pull/7612) +* Fixes Explosion behavior when 3 mons can endure hit by @AlexOn1ine in [#7594](https://github.com/rh-hideout/pokeemerald-expansion/pull/7594) +* Fixes octolock not ending after user switched out by @AlexOn1ine in [#7556](https://github.com/rh-hideout/pokeemerald-expansion/pull/7556) +* The original attacker wasn't restored for Doodle by @AlexOn1ine in [#7620](https://github.com/rh-hideout/pokeemerald-expansion/pull/7620) +* Restore X item friendship increase by @ravepossum in [#7583](https://github.com/rh-hideout/pokeemerald-expansion/pull/7583) +* Fixes Wonder Room interactions with Defense/Special Defense boosting effects by @PhallenTree in [#7626](https://github.com/rh-hideout/pokeemerald-expansion/pull/7626) +* Ally Switch attract battler swapping, test for leech seed by @ghoulslash in [#7634](https://github.com/rh-hideout/pokeemerald-expansion/pull/7634) + +## 🤹 Moves 🤹 +### Fixed +* Clear gScanlineEffect to fix timeout in acid downpour animation by @FosterProgramming in [#7442](https://github.com/rh-hideout/pokeemerald-expansion/pull/7442) +* Fix terastallization anims flickering by @ravepossum in [#7613](https://github.com/rh-hideout/pokeemerald-expansion/pull/7613) + +## 🧶 Items 🧶 +### Changed +* Fix using town map as registered item by @ravepossum in [#7482](https://github.com/rh-hideout/pokeemerald-expansion/pull/7482) + +### Fixed +* Implement using party menu items from field by @ravepossum in [#7481](https://github.com/rh-hideout/pokeemerald-expansion/pull/7481) + +## 🤖 Battle AI 🤖 +### Changed +* Macro-for-AI-Flag-definitions by @grintoul1 in [#7471](https://github.com/rh-hideout/pokeemerald-expansion/pull/7471) + +### Fixed +* Incorrect call in Rest by @surskitty in [#7569](https://github.com/rh-hideout/pokeemerald-expansion/pull/7569) +* Fix duplicate switch in after faint by @AlexOn1ine in [#7600](https://github.com/rh-hideout/pokeemerald-expansion/pull/7600) + +## 🧹 Other Cleanup 🧹 +* Macro-for-AI-Flag-definitions by @grintoul1 in [#7471](https://github.com/rh-hideout/pokeemerald-expansion/pull/7471) +* Moved summary screen nature colors to summary_screen.h by @RubyRaven6 in [#7560](https://github.com/rh-hideout/pokeemerald-expansion/pull/7560) +* fix: remove unused wild_encounters.json.txt jinja file by @khbsd in [#7581](https://github.com/rh-hideout/pokeemerald-expansion/pull/7581) +* Fix Form Change Item Task Data and Clean Up Field Use Funcs by @ravepossum in [#7535](https://github.com/rh-hideout/pokeemerald-expansion/pull/7535) +* Fixed Teleport's description not being updated based on `B_TELEPORT_BEHAVIOR` by @AsparagusEduardo in [#7580](https://github.com/rh-hideout/pokeemerald-expansion/pull/7580) +* Fixed typo in test name by @hedara90 in [#7610](https://github.com/rh-hideout/pokeemerald-expansion/pull/7610) +* Minor Clean up in battle_ai_main.c by @AlexOn1ine in [#7551](https://github.com/rh-hideout/pokeemerald-expansion/pull/7551) +* Remove unused function by @AlexOn1ine in [#7617](https://github.com/rh-hideout/pokeemerald-expansion/pull/7617) +* Fix Vs Seeker Trainer Battle script issue by @pkmnsnfrn in [#7615](https://github.com/rh-hideout/pokeemerald-expansion/pull/7615) + +## 🧪 Test Runner 🧪 +### Changed +* Clean up some Normalize tests to make them make sense by @hedara90 in [#7461](https://github.com/rh-hideout/pokeemerald-expansion/pull/7461) +* Add Synthesis + Utililty Umbrella test by @ghoulslash in [#7472](https://github.com/rh-hideout/pokeemerald-expansion/pull/7472) +* Add test for BoxPokemon integrity by @hedara90 in [#7487](https://github.com/rh-hideout/pokeemerald-expansion/pull/7487) +* Re-order moves in fling test by @hedara90 in [#7559](https://github.com/rh-hideout/pokeemerald-expansion/pull/7559) +* Wrote some tests by @AsparagusEduardo in [#7563](https://github.com/rh-hideout/pokeemerald-expansion/pull/7563) +* Added Ability TODO tests - Volume C by @AsparagusEduardo in [#7562](https://github.com/rh-hideout/pokeemerald-expansion/pull/7562) +* Added missing Move Effect TODO tests - Volume F by @AsparagusEduardo in [#7605](https://github.com/rh-hideout/pokeemerald-expansion/pull/7605) +* Fixed typo in test name by @hedara90 in [#7610](https://github.com/rh-hideout/pokeemerald-expansion/pull/7610) + +### Fixed +* Clear out parties between battle tests by @hedara90 in [#7460](https://github.com/rh-hideout/pokeemerald-expansion/pull/7460) +* Fixed most failed tests with `GEN_LATEST GEN_8` by @AsparagusEduardo in [#7498](https://github.com/rh-hideout/pokeemerald-expansion/pull/7498) +* Corrected Liquid Ooze test by @AsparagusEduardo in [#7527](https://github.com/rh-hideout/pokeemerald-expansion/pull/7527) +* switchinabilities also runs ON_WEATHER and ON_TERRAIN by @ghoulslash in [#7612](https://github.com/rh-hideout/pokeemerald-expansion/pull/7612) +* Ally Switch attract battler swapping, test for leech seed by @ghoulslash in [#7634](https://github.com/rh-hideout/pokeemerald-expansion/pull/7634) + +## 📚 Documentation 📚 +* Update how_to_new_pokemon.md by @kevinwklawrence in [#7440](https://github.com/rh-hideout/pokeemerald-expansion/pull/7440) +* Updating a link to porytiles in INSTALL.md by @ThePeeps191 in [#7490](https://github.com/rh-hideout/pokeemerald-expansion/pull/7490) +* Added comment in event.inc for simple menus in dynmultichoice by @RubyRaven6 in [#7568](https://github.com/rh-hideout/pokeemerald-expansion/pull/7568) + +## New Contributors +* @kevinwklawrence made their first contribution in [#7440](https://github.com/rh-hideout/pokeemerald-expansion/pull/7440) +* @ThePeeps191 made their first contribution in [#7490](https://github.com/rh-hideout/pokeemerald-expansion/pull/7490) +* @cornixsenex made their first contribution in [#7368](https://github.com/rh-hideout/pokeemerald-expansion/pull/7368) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.2...expansion/1.12.3 + + + + diff --git a/include/constants/expansion.h b/include/constants/expansion.h index cdfaa6228e..fffde51959 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,13 +1,13 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.12.2 +// Last version: 1.12.3 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 #define EXPANSION_VERSION_PATCH 3 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE FALSE +#define EXPANSION_TAGGED_RELEASE TRUE #endif From 7056aaba6eda97a83aa22765c8dff3ca39e69920 Mon Sep 17 00:00:00 2001 From: Hedara Date: Thu, 28 Aug 2025 16:15:09 +0200 Subject: [PATCH 270/283] Expansion version 1.13.0 --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 10 +- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 10 +- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 9 +- README.md | 2 +- docs/SUMMARY.md | 2 + docs/changelogs/1.13.x/1.13.0.md | 483 ++++++++++++++++++ include/constants/expansion.h | 2 +- 7 files changed, 496 insertions(+), 22 deletions(-) create mode 100644 docs/changelogs/1.13.x/1.13.0.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 5c7bf2b5cf..0d323435b4 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,18 +43,14 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.3 (Latest release) + - 1.13.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.3 - 1.12.2 - 1.12.1 - 1.12.0 - - 1.11.4 - - 1.11.3 - - 1.11.2 - - 1.11.1 - - 1.11.0 - - pre-1.11.0 + - pre-1.12.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index ed94c1355e..a00d5f4d2c 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,18 +43,14 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.3 (Latest release) + - 1.13.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.3 - 1.12.2 - 1.12.1 - 1.12.0 - - 1.11.4 - - 1.11.3 - - 1.11.2 - - 1.11.1 - - 1.11.0 - - pre-1.11.0 + - pre-1.12.0 validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index a391c6473d..53bf274899 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,17 +43,14 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.3 (Latest release) + - 1.13.0 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.3 - 1.12.2 - 1.12.1 - 1.12.0 - - 1.11.4 - - 1.11.3 - - 1.11.1 - - 1.11.0 - - pre-1.11.0 + - pre-1.12.0 validations: required: true - type: input diff --git a/README.md b/README.md index b6a78a3736..6c91a3ad84 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.12.3 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.13.0 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 89b86087c1..667fcce2a4 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -19,6 +19,8 @@ - [How to add new Trainer Slides](tutorials/how_to_new_trainer_slide.md) - [Day/Night System FAQ](tutorials/dns.md) - [Changelog](./CHANGELOG.md) + - [1.13.x]() + - [Version 1.13.0](changelogs/1.13.x/1.13.0.md) - [1.12.x]() - [Version 1.12.3](changelogs/1.12.x/1.12.3.md) - [Version 1.12.2](changelogs/1.12.x/1.12.2.md) diff --git a/docs/changelogs/1.13.x/1.13.0.md b/docs/changelogs/1.13.x/1.13.0.md new file mode 100644 index 0000000000..52babd0b43 --- /dev/null +++ b/docs/changelogs/1.13.x/1.13.0.md @@ -0,0 +1,483 @@ +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.13.0 +`. +``` + +## 🌋 *REFACTORS* 🌋 +📜 = Uses a migration script. +* Refactor field moves by @cawtds in [#6660](https://github.com/rh-hideout/pokeemerald-expansion/pull/6660) +* Refactors Final Gambit + Tests by @AlexOn1ine in [#7005](https://github.com/rh-hideout/pokeemerald-expansion/pull/7005) +* Combines Super Fang and Guardian of Alola effects by @AlexOn1ine in [#7048](https://github.com/rh-hideout/pokeemerald-expansion/pull/7048) +* Refactor damage calculations aruguments by using a struct context by @AlexOn1ine in [#7108](https://github.com/rh-hideout/pokeemerald-expansion/pull/7108) +* Add damage context to effectiveness multiplier by @AlexOn1ine in [#7111](https://github.com/rh-hideout/pokeemerald-expansion/pull/7111) +* Decouple Status set by ability from SetMoveEffect by @AlexOn1ine in [#7125](https://github.com/rh-hideout/pokeemerald-expansion/pull/7125) +* Converted Relic Song into a proper form change by @AsparagusEduardo in [#7139](https://github.com/rh-hideout/pokeemerald-expansion/pull/7139) + - Added `FORM_CHANGE_BATTLE_AFTER_MOVE` to parametrize Relic Song's form change +* Removed Mind Blown effect in favor of move flag by @AsparagusEduardo in [#7138](https://github.com/rh-hideout/pokeemerald-expansion/pull/7138) +* Volatile status refactoring by @cfmnephrite in [#6983](https://github.com/rh-hideout/pokeemerald-expansion/pull/6983) +* Bag refactor (groundwork for expansion) by @cfmnephrite in [#7018](https://github.com/rh-hideout/pokeemerald-expansion/pull/7018) + - If you're using @ghoulslash's bag sort branch, this PR will break it +* Stat Change (Animation) Refactor by @PhallenTree in [#7144](https://github.com/rh-hideout/pokeemerald-expansion/pull/7144) + `setgraphicalstatchangevalues` and `playstatchangeanimation` have been removed and now Stat Change Animations are handled in `statbuffchange`. + - To update your custom battle scripts: + `setgraphicalstatchangevalues` is often accompanied by `playanimation X, B_ANIM_STATS_CHANGE`. When I refer to deleting `setgraphicalstatchangevalues` below, that command should also be deleted. + 1. If `statbuffchange` is before `setgraphicalstatchangevalues`/`playstatchangeanimation` and there is something in between them (for example, `attackanimation` and `waitanimation`), add the flag `STAT_CHANGE_ONLY_CHECKING` and replace the command (`setgraphicalstatchangevalues`/`playstatchangeanimation`) with a copy of the original `statbuffchange`. + 2. If `statbuffchange` is after `setgraphicalstatchangevalues`/`playstatchangeanimation` or there is nothing in between, you should delete those commands (`setgraphicalstatchangevalues`/`playstatchangeanimation`) and no further changes other than those in _3._ should be required. + 3. If `playstatchangeanimation` had bits assigned to them (`BIT_ATK | BIT_SPATK`, for example), add ", " followed by those bits to the first `statbuffchange`; for the following `statbuffchange`s, remove stats that have already been increased/decreased. +* Untangle `InitBtlControllers` functions by @AsparagusEduardo in [#6748](https://github.com/rh-hideout/pokeemerald-expansion/pull/6748) +* Use battler arguments for SetMoveEffect by @AlexOn1ine in [#7156](https://github.com/rh-hideout/pokeemerald-expansion/pull/7156) +* Easier expandability of debug menu by @AsparagusEduardo in [#6910](https://github.com/rh-hideout/pokeemerald-expansion/pull/6910) +* Use dedicated functions for Mud/Water Sport by @AlexOn1ine in [#7248](https://github.com/rh-hideout/pokeemerald-expansion/pull/7248) +* Expanding and Refactoring Skill Swap and other ability-changing moves by @surskitty in [#7238](https://github.com/rh-hideout/pokeemerald-expansion/pull/7238) +* Refactor move Synchronise by @AlexOn1ine in [#7271](https://github.com/rh-hideout/pokeemerald-expansion/pull/7271) +* Adds hazard queue by @AlexOn1ine in [#7295](https://github.com/rh-hideout/pokeemerald-expansion/pull/7295) +* Changes AccuracyCalcHelper into CanMoveSkipAccuracyCalc by @AlexOn1ine in [#7303](https://github.com/rh-hideout/pokeemerald-expansion/pull/7303) +* battle_interface: overhaul ability pop up by @mudskipper13 in [#7227](https://github.com/rh-hideout/pokeemerald-expansion/pull/7227) + - The layout of the ability pop up's image (`graphics/battle_interface/ability_pop_up.png`) has been changed. +* Bag refactor 2 by @cfmnephrite in [#7166](https://github.com/rh-hideout/pokeemerald-expansion/pull/7166) +* Replaces STATUS2 usage with volatiles in code by @cfmnephrite in [#7262](https://github.com/rh-hideout/pokeemerald-expansion/pull/7262) + - Replaced all references to STATUS2 in the code with volatiles (but left the old bitfield behind for compatibility with downstream users). The list of volatiles is in `include/constants/battle.h` and includes information such as an enum, a field name, type and max size, and whether or not the move is Baton Passable. Users can use VOLATILE_X with any function that previously took STATUS2_X in scripts, and can check/set volatiles in C with `gBattleMons[battler].volatiles.{field name}` syntax instead of checking a flag in a bitfield. +* Refactor battle environment by @fdeblasio in [#4891](https://github.com/rh-hideout/pokeemerald-expansion/pull/4891) +* Convert various to callnatives by @AlexOn1ine in [#7355](https://github.com/rh-hideout/pokeemerald-expansion/pull/7355) +* AI refactor for weather-setting, terrain-setting, Trick Room behaviors; doubles-focused by @surskitty in [#7319](https://github.com/rh-hideout/pokeemerald-expansion/pull/7319) + - AI is more likely to use Trick Room in double battles and Terrains in general. +* Convert Status4 to volatiles by @AlexOn1ine in [#7411](https://github.com/rh-hideout/pokeemerald-expansion/pull/7411) +* Split Sheer Force tests by gen instead of by four by @AlexOn1ine in [#7260](https://github.com/rh-hideout/pokeemerald-expansion/pull/7260) +* Modify move prediction to work in doubles by @AlexOn1ine in [#7087](https://github.com/rh-hideout/pokeemerald-expansion/pull/7087) +* Convert statuses3 to volatiles by @AlexOn1ine in [#7514](https://github.com/rh-hideout/pokeemerald-expansion/pull/7514) +* Added trainerBackPic to Trainer struct to de-couple trainer pic and trainer back pic defines by @grintoul1 in [#7425](https://github.com/rh-hideout/pokeemerald-expansion/pull/7425) + +## 🧬 General 🧬 +### Added +* New sprite compressor by @hedara90, @DizzyEggg Improved performance massively for the instruction decoding., @mrgriffin, SBird and @tertu-m who has done even more optimization and answered questions about the GBA hardware whenever I had them. and @rayrobdod for the better migration script. in [#5627](https://github.com/rh-hideout/pokeemerald-expansion/pull/5627) + - `LZDecompressVram` and `LZDecompressWram` has been deprecated. All calls do decompress LZ compressed data should be using the wrapper functions `DecompressDataWithHeaderVram` or `DecompressDataWithHeaderWram`. + - A new sprite compression format has been introduced. To use it, replace files with `.4bpp.lz` with `.4bpp.smol` or `.4bpp.fastSmol`. + - `.smol` is a compression format utilizing entropy encoding in the form of tabled Asymmetric Numeral Systems (tANS) and a modified LZ style RLE/Dictionary encoding scheme specialized for the sprites used in Pokemon games. This is approximately 25% smaller than the default LZ77 compression. + - `.fastSmol` skips the entropy encoding and is therefore slightly larger than the default LZ77 compression, but decoding sprites is faster than the default LZ77 compression. + - `.smolTM` is a compression scheme for tilemaps. + - Might have unexpected behavior if user introduced decompression during hardware interrupts. + - Has a migration script that handles all files under `src/`, `migration_scripts/1.12/convert_compressed_files.py`. +* Adds FRLG asserts to Alloc/Free by @cawtds in [#7025](https://github.com/rh-hideout/pokeemerald-expansion/pull/7025) +* Debug parties and battles by @SBird1337 in [#6884](https://github.com/rh-hideout/pokeemerald-expansion/pull/6884) + - Adds options to set debug parties and battles using the debug menu +* Added naive line break by @hedara90 in [#7076](https://github.com/rh-hideout/pokeemerald-expansion/pull/7076) +* Disable unowned evo methods by @Bolt-Strike in [#7103](https://github.com/rh-hideout/pokeemerald-expansion/pull/7103) +* lto support by @DizzyEggg in [#7182](https://github.com/rh-hideout/pokeemerald-expansion/pull/7182) +* Improve trainer back pic-related data and code (+ smol documentation) by @mudskipper13 in [#6821](https://github.com/rh-hideout/pokeemerald-expansion/pull/6821) +* Add Set Hidden Nature option to the debug menu by @AlexOn1ine in [#7281](https://github.com/rh-hideout/pokeemerald-expansion/pull/7281) +* Instant Win option in Battle Debug by @AlexOn1ine in [#7333](https://github.com/rh-hideout/pokeemerald-expansion/pull/7333) +* `trainerproc` copy other trainer party by @hedara90 in [#7251](https://github.com/rh-hideout/pokeemerald-expansion/pull/7251) + - Adds the `Copy Pool` command to `trainerproc` which copies the party/pool from another trainer. +* Show chosen move in the battle debug menu by @AlexOn1ine in [#7382](https://github.com/rh-hideout/pokeemerald-expansion/pull/7382) +* Rock climb by ghoulslash by @pokesidv in [#7432](https://github.com/rh-hideout/pokeemerald-expansion/pull/7432) + - Added rock climb field effect + +### Changed +* Restore git history check by @ravepossum in [#7463](https://github.com/rh-hideout/pokeemerald-expansion/pull/7463) +* Moved summary screen nature colors to summary_screen.h by @RubyRaven6 in [#7560](https://github.com/rh-hideout/pokeemerald-expansion/pull/7560) +* Added comment in event.inc for simple menus in dynmultichoice by @RubyRaven6 in [#7568](https://github.com/rh-hideout/pokeemerald-expansion/pull/7568) +* Changed default print level for DebugPrintf for mGBA to MGBA_LOG_WARN by @hedara90 in [#7567](https://github.com/rh-hideout/pokeemerald-expansion/pull/7567) +* Fixed Teleport's description not being updated based on `B_TELEPORT_BEHAVIOR` by @AsparagusEduardo in [#7580](https://github.com/rh-hideout/pokeemerald-expansion/pull/7580) +* Minor Clean up in battle_ai_main.c by @AlexOn1ine in [#7551](https://github.com/rh-hideout/pokeemerald-expansion/pull/7551) +* Refactor field moves by @cawtds in [#6660](https://github.com/rh-hideout/pokeemerald-expansion/pull/6660) +* Replace all usages of lz compression with smol by @hedara90 in [#7032](https://github.com/rh-hideout/pokeemerald-expansion/pull/7032) +* `BtlController_EmitTwoReturnValues` cleanup by @AsparagusEduardo in [#6855](https://github.com/rh-hideout/pokeemerald-expansion/pull/6855) +* Put the gen 1 compression tests behind a config by @hedara90 in [#7033](https://github.com/rh-hideout/pokeemerald-expansion/pull/7033) +* Converts a bunch of defines to enums by @Bassoonian in [#7041](https://github.com/rh-hideout/pokeemerald-expansion/pull/7041) +* chore: remove unused section from credits by @Emiliasky in [#7085](https://github.com/rh-hideout/pokeemerald-expansion/pull/7085) +* Simplify white out messages by @kittenchilly in [#6961](https://github.com/rh-hideout/pokeemerald-expansion/pull/6961) +* Improve music/se macros and fix names by @cawtds in [#7030](https://github.com/rh-hideout/pokeemerald-expansion/pull/7030) +* Bag refactor (groundwork for expansion) by @cfmnephrite in [#7018](https://github.com/rh-hideout/pokeemerald-expansion/pull/7018) + - If you're using @ghoulslash's bag sort branch, this PR will break it +* Converts more defines to enums and name unnamed enums by @Bassoonian in [#7071](https://github.com/rh-hideout/pokeemerald-expansion/pull/7071) +* Add config options for removing bard phoneme audio to save ROM space by @poetahto in [#7155](https://github.com/rh-hideout/pokeemerald-expansion/pull/7155) +* Fix debug text order by @hedara90 in [#7149](https://github.com/rh-hideout/pokeemerald-expansion/pull/7149) +* More battle controller function consolidation. by @AsparagusEduardo in [#6877](https://github.com/rh-hideout/pokeemerald-expansion/pull/6877) +* Easier expandability of debug menu by @AsparagusEduardo in [#6910](https://github.com/rh-hideout/pokeemerald-expansion/pull/6910) +* Update .gitignore to add heal locations by @Bassoonian in [#7050](https://github.com/rh-hideout/pokeemerald-expansion/pull/7050) +* Add 'Give Decoration' function to overworld debug menu by @rayrobdod in [#7219](https://github.com/rh-hideout/pokeemerald-expansion/pull/7219) +* Changes pre-proc to a normal if for Item Desc Header by @AlexOn1ine in [#7231](https://github.com/rh-hideout/pokeemerald-expansion/pull/7231) +* Use compound strings in battle debug menu by @AsparagusEduardo in [#7282](https://github.com/rh-hideout/pokeemerald-expansion/pull/7282) +* Remove competitive syntax config by @hedara90 in [#7154](https://github.com/rh-hideout/pokeemerald-expansion/pull/7154) + - This change can be reverted by doing `git revert 14dbbf63d454073dbb198b941cc3566168c89f11`. +* Turn `OW_FRLG_WHITEOUT` into `OW_WHITEOUT_CUTSCENE` and make it generational by @kittenchilly in [#6962](https://github.com/rh-hideout/pokeemerald-expansion/pull/6962) +* Add `Macro` key to trainerproc by @hedara90 in [#7157](https://github.com/rh-hideout/pokeemerald-expansion/pull/7157) +* preproc: Support __attribute__ in enums by @mrgriffin in [#7344](https://github.com/rh-hideout/pokeemerald-expansion/pull/7344) +* Enum conversion for `enum MoveEffects` and `enum BattleMoveEffects` by @hedara90 in [#7366](https://github.com/rh-hideout/pokeemerald-expansion/pull/7366) + - This enables `-Wenum-conversion`, additional compilation errors can occur +* Get/SetMonData optimisation by @cfmnephrite in [#7313](https://github.com/rh-hideout/pokeemerald-expansion/pull/7313) +* Bag refactor3 + Ghoulslash's sorting feature port by @cfmnephrite in [#7330](https://github.com/rh-hideout/pokeemerald-expansion/pull/7330) +* Replace all usages of rl compression with smol by @rayrobdod in [#7458](https://github.com/rh-hideout/pokeemerald-expansion/pull/7458) +* Bag sorting cleanup by @mrgriffin in [#7489](https://github.com/rh-hideout/pokeemerald-expansion/pull/7489) +* Adds ghouls Rock Climb git history by @AlexOn1ine in [#7493](https://github.com/rh-hideout/pokeemerald-expansion/pull/7493) +* Changed item name/pluralName to a compound string by @cfmnephrite in [#7359](https://github.com/rh-hideout/pokeemerald-expansion/pull/7359) +* Added trainerBackPic to Trainer struct to de-couple trainer pic and trainer back pic defines by @grintoul1 in [#7425](https://github.com/rh-hideout/pokeemerald-expansion/pull/7425) +* Suppress trainerproc compile warning for unused func by @AlexOn1ine in [#7592](https://github.com/rh-hideout/pokeemerald-expansion/pull/7592) + +### Fixed +* Fix .smol compression in debug builds by @hedara90 in [#7090](https://github.com/rh-hideout/pokeemerald-expansion/pull/7090) +* Improve smol compressor by @hedara90 in [#7073](https://github.com/rh-hideout/pokeemerald-expansion/pull/7073) +* Increased heap by 768 bytes by @hedara90 in [#7097](https://github.com/rh-hideout/pokeemerald-expansion/pull/7097) +* Fix healthbox when blending effects happen by @AsparagusEduardo in [#7203](https://github.com/rh-hideout/pokeemerald-expansion/pull/7203) +* Fixed Fake RTC debug menu by @AsparagusEduardo in [#7218](https://github.com/rh-hideout/pokeemerald-expansion/pull/7218) +* Added missing braces by @cfmnephrite in [#7288](https://github.com/rh-hideout/pokeemerald-expansion/pull/7288) +* Fixed Flag Vars menu keeping artifacts from bag menu + cleanup by @AsparagusEduardo in [#7226](https://github.com/rh-hideout/pokeemerald-expansion/pull/7226) +* Fix HGSS dex running out of heap by @hedara90 in [#7317](https://github.com/rh-hideout/pokeemerald-expansion/pull/7317) +* battle intro: fix issues with follower slide-in and wild shiny mon by @mudskipper13 in [#7325](https://github.com/rh-hideout/pokeemerald-expansion/pull/7325) +* Fix sorting bag by type by @mrgriffin in [#7488](https://github.com/rh-hideout/pokeemerald-expansion/pull/7488) +* Hacky support for enums in C asm statements by @mrgriffin in [#7494](https://github.com/rh-hideout/pokeemerald-expansion/pull/7494) +* Fixed compile issue in gcc 11 by @AsparagusEduardo in [#7579](https://github.com/rh-hideout/pokeemerald-expansion/pull/7579) +* Fix overlap between spin evolution and script evolution by @FosterProgramming in [#7593](https://github.com/rh-hideout/pokeemerald-expansion/pull/7593) + +## 🗺️ Overworld 🗺️ +### Added +* Added createfollowernpc macro to make a new follower from a gfx id by @Bivurnum in [#7196](https://github.com/rh-hideout/pokeemerald-expansion/pull/7196) + - Follower NPCs can now be created without using an existing NPC, using the `createfollowernpc` macro. +* feat: separate water and rock smash encounter rate checks by @khbsd in [#7293](https://github.com/rh-hideout/pokeemerald-expansion/pull/7293) + +### Changed +* fix: remove unused wild_encounters.json.txt jinja file by @khbsd in [#7581](https://github.com/rh-hideout/pokeemerald-expansion/pull/7581) +* added Ash Greninja overworld sprites by @wiz1989 in [#6976](https://github.com/rh-hideout/pokeemerald-expansion/pull/6976) +* Update FRLG whiteouts to new pret system by @Bassoonian in [#7040](https://github.com/rh-hideout/pokeemerald-expansion/pull/7040) + - Make sure to migrate your changes to the now deleted `heal_locations_pkm_center.h` to the json file. +* Use CanAbilityAbsorbMove in GetOverworldTypeEffectiveness by @AlexOn1ine in [#7115](https://github.com/rh-hideout/pokeemerald-expansion/pull/7115) +* Add config options for removing bard phoneme audio to save ROM space by @poetahto in [#7155](https://github.com/rh-hideout/pokeemerald-expansion/pull/7155) +* Add debug options for follower NPCs by @Bivurnum in [#7215](https://github.com/rh-hideout/pokeemerald-expansion/pull/7215) +* Better system for Follower NPC running frames by @Bivurnum in [#7222](https://github.com/rh-hideout/pokeemerald-expansion/pull/7222) +* Update follower NPC tutorial doc for createfollowernpc macro by @Bivurnum in [#7230](https://github.com/rh-hideout/pokeemerald-expansion/pull/7230) + +### Fixed +* Bug fix: add handling for forced movements into/after ledge jumps with follower NPCs by @Bivurnum in [#7055](https://github.com/rh-hideout/pokeemerald-expansion/pull/7055) +* Fixed compile issue `OW_TIMES_OF_DAY` is `GEN_3` by @AsparagusEduardo in [#7499](https://github.com/rh-hideout/pokeemerald-expansion/pull/7499) +* Remove shadow and hide follower on stair warp by @cornixsenex in [#7368](https://github.com/rh-hideout/pokeemerald-expansion/pull/7368) +* Fix Form Change Item Task Data and Clean Up Field Use Funcs by @ravepossum in [#7535](https://github.com/rh-hideout/pokeemerald-expansion/pull/7535) +* Fix Vs Seeker Trainer Battle script issue by @pkmnsnfrn in [#7615](https://github.com/rh-hideout/pokeemerald-expansion/pull/7615) +* Fix follower compression by @hedara90 in [#7038](https://github.com/rh-hideout/pokeemerald-expansion/pull/7038) +* Changing P_ONLY_OBTAINABLE_SHINIES to truly be Only Obtainable Shinies by @surskitty in [#7275](https://github.com/rh-hideout/pokeemerald-expansion/pull/7275) + +## 🐉 Pokémon 🐉 +### Added +* 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. +* Added `CRY_MODE_DYNAMAX` by @AsparagusEduardo in [#6933](https://github.com/rh-hideout/pokeemerald-expansion/pull/6933) +* Wild Pokémon animate after breaking out of Poké Ball by @LinathanZel in [#7339](https://github.com/rh-hideout/pokeemerald-expansion/pull/7339) + +### Changed +* Add dedicated getter functions for Pokémon types and abilities by @Bassoonian in [#7043](https://github.com/rh-hideout/pokeemerald-expansion/pull/7043) +* added Ash Greninja overworld sprites by @wiz1989 in [#6976](https://github.com/rh-hideout/pokeemerald-expansion/pull/6976) +* Get/SetMonData optimisation by @cfmnephrite in [#7313](https://github.com/rh-hideout/pokeemerald-expansion/pull/7313) + +### Fixed +* fixes #7129: 'add to full party' feature in the safari zone by @fakuzatsu in [#7147](https://github.com/rh-hideout/pokeemerald-expansion/pull/7147) +* Fix substruct offsets from #7313 by @mrgriffin in [#7431](https://github.com/rh-hideout/pokeemerald-expansion/pull/7431) +* Fixes refusing to replace a move on evolution causing a softlock by @PhallenTree in [#7585](https://github.com/rh-hideout/pokeemerald-expansion/pull/7585) + +## ⚔️ Battle General ⚔️ +### Added +* Add Gen 2 Moonlight, Morning Sun, Synthesis configuration by @i0brendan0 in [#7209](https://github.com/rh-hideout/pokeemerald-expansion/pull/7209) +* Add a heal animation to Hospitality recovery by @AlexOn1ine in [#7426](https://github.com/rh-hideout/pokeemerald-expansion/pull/7426) +* Updated Dream Eater/Liquid Ooze's interaction to Gen 5 standards by @AsparagusEduardo in [#7528](https://github.com/rh-hideout/pokeemerald-expansion/pull/7528) + +### Changed +* Remove unused function by @AlexOn1ine in [#7617](https://github.com/rh-hideout/pokeemerald-expansion/pull/7617) +* Clean up battlescript calls with func BattleScriptCall by @AlexOn1ine in [#6873](https://github.com/rh-hideout/pokeemerald-expansion/pull/6873) +* Refactors Final Gambit + Tests by @AlexOn1ine in [#7005](https://github.com/rh-hideout/pokeemerald-expansion/pull/7005) +* `GetBattlerMon` cleanup by @AsparagusEduardo in [#6967](https://github.com/rh-hideout/pokeemerald-expansion/pull/6967) +* Change GetZMaxMoveAgainstProtectionModifier to prevent regressions by @AlexOn1ine in [#7047](https://github.com/rh-hideout/pokeemerald-expansion/pull/7047) +* Combines Super Fang and Guardian of Alola effects by @AlexOn1ine in [#7048](https://github.com/rh-hideout/pokeemerald-expansion/pull/7048) +* Remove more instances of hard-coded Move IDs by @AsparagusEduardo in [#7056](https://github.com/rh-hideout/pokeemerald-expansion/pull/7056) + - Added `EFFECT_SHEER_COLD` to parametrize Sheer Cold's interactions with Ice types +* Deprecate sStatusFlagsForMoveEffects by @AlexOn1ine in [#7063](https://github.com/rh-hideout/pokeemerald-expansion/pull/7063) +* Removes duplicate AI ability func by @AlexOn1ine in [#7045](https://github.com/rh-hideout/pokeemerald-expansion/pull/7045) +* Deprecate absent member from battlerState by @AlexOn1ine in [#7091](https://github.com/rh-hideout/pokeemerald-expansion/pull/7091) +* Refactor damage calculations aruguments by using a struct context by @AlexOn1ine in [#7108](https://github.com/rh-hideout/pokeemerald-expansion/pull/7108) +* Add damage context to effectiveness multiplier by @AlexOn1ine in [#7111](https://github.com/rh-hideout/pokeemerald-expansion/pull/7111) +* Decouple Status set by ability from SetMoveEffect by @AlexOn1ine in [#7125](https://github.com/rh-hideout/pokeemerald-expansion/pull/7125) +* Removed redundant Damp check by @AsparagusEduardo in [#7134](https://github.com/rh-hideout/pokeemerald-expansion/pull/7134) +* Converted Relic Song into a proper form change by @AsparagusEduardo in [#7139](https://github.com/rh-hideout/pokeemerald-expansion/pull/7139) + - Added `FORM_CHANGE_BATTLE_AFTER_MOVE` to parametrize Relic Song's form change +* Removed Mind Blown effect in favor of move flag by @AsparagusEduardo in [#7138](https://github.com/rh-hideout/pokeemerald-expansion/pull/7138) +* Volatile status refactoring by @cfmnephrite in [#6983](https://github.com/rh-hideout/pokeemerald-expansion/pull/6983) +* Repurposes IsMagicGuardProtected into a general function by @AlexOn1ine in [#7114](https://github.com/rh-hideout/pokeemerald-expansion/pull/7114) +* Stat Change (Animation) Refactor by @PhallenTree in [#7144](https://github.com/rh-hideout/pokeemerald-expansion/pull/7144) + -`setgraphicalstatchangevalues` and `playstatchangeanimation` have been removed and now Stat Change Animations are handled in `statbuffchange`. + - To update your custom battle scripts: + `setgraphicalstatchangevalues` is often accompanied by `playanimation X, B_ANIM_STATS_CHANGE`. When I refer to deleting `setgraphicalstatchangevalues` below, that command should also be deleted. + 1. If `statbuffchange` is before `setgraphicalstatchangevalues`/`playstatchangeanimation` and there is something in between them (for example, `attackanimation` and `waitanimation`), add the flag `STAT_CHANGE_ONLY_CHECKING` and replace the command (`setgraphicalstatchangevalues`/`playstatchangeanimation`) with a copy of the original `statbuffchange`. + 2. If `statbuffchange` is after `setgraphicalstatchangevalues`/`playstatchangeanimation` or there is nothing in between, you should delete those commands (`setgraphicalstatchangevalues`/`playstatchangeanimation`) and no further changes other than those in _3._ should be required. + 3. If `playstatchangeanimation` had bits assigned to them (`BIT_ATK | BIT_SPATK`, for example), add ", " followed by those bits to the first `statbuffchange`; for the following `statbuffchange`s, remove stats that have already been increased/decreased. +* Use `argument.type` for `EFFECT_SOAK` by @AsparagusEduardo in [#7141](https://github.com/rh-hideout/pokeemerald-expansion/pull/7141) +* 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) +* 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) +* Renaming STATUS1_REFRESH and adding more constants for common STATUS1 checks. by @surskitty in [#7284](https://github.com/rh-hideout/pokeemerald-expansion/pull/7284) +* Refactor move Synchronise by @AlexOn1ine in [#7271](https://github.com/rh-hideout/pokeemerald-expansion/pull/7271) +* Adds hazard queue by @AlexOn1ine in [#7295](https://github.com/rh-hideout/pokeemerald-expansion/pull/7295) +* Removed all instances of .chance = 100, SHEER_FORCE_NO_BOOST by @cfmnephrite in [#7300](https://github.com/rh-hideout/pokeemerald-expansion/pull/7300) +* Changes AccuracyCalcHelper into CanMoveSkipAccuracyCalc by @AlexOn1ine in [#7303](https://github.com/rh-hideout/pokeemerald-expansion/pull/7303) +* Replaces STATUS2 usage with volatiles in code by @cfmnephrite in [#7262](https://github.com/rh-hideout/pokeemerald-expansion/pull/7262) + - Replaced all references to STATUS2 in the code with volatiles (but left the old bitfield behind for compatibility with downstream users). The list of volatiles is in `include/constants/battle.h` and includes information such as an enum, a field name, type and max size, and whether or not the move is Baton Passable. Users can use VOLATILE_X with any function that previously took STATUS2_X in scripts, and can check/set volatiles in C with `gBattleMons[battler].volatiles.{field name}` syntax instead of checking a flag in a bitfield. +* Refactor battle environment by @fdeblasio in [#4891](https://github.com/rh-hideout/pokeemerald-expansion/pull/4891) +* Convert various to callnatives by @AlexOn1ine in [#7355](https://github.com/rh-hideout/pokeemerald-expansion/pull/7355) +* Remove leftover code by @AlexOn1ine in [#7397](https://github.com/rh-hideout/pokeemerald-expansion/pull/7397) +* Moved some fields to BattlerState/PartyState by @AsparagusEduardo in [#7409](https://github.com/rh-hideout/pokeemerald-expansion/pull/7409) +* Additional effects tweak by @cfmnephrite in [#7392](https://github.com/rh-hideout/pokeemerald-expansion/pull/7392) +* Clean up noResultString by @AlexOn1ine in [#7408](https://github.com/rh-hideout/pokeemerald-expansion/pull/7408) +* Convert Status4 to volatiles by @AlexOn1ine in [#7411](https://github.com/rh-hideout/pokeemerald-expansion/pull/7411) +* Convert statuses3 to volatiles by @AlexOn1ine in [#7514](https://github.com/rh-hideout/pokeemerald-expansion/pull/7514) +* Prevents a regression for custom abilties by @AlexOn1ine in [#7616](https://github.com/rh-hideout/pokeemerald-expansion/pull/7616) + +### Fixed +* Fixes Magnet Rise when user is Rooted/Smacked Down by @PhallenTree in [#7449](https://github.com/rh-hideout/pokeemerald-expansion/pull/7449) +* Fixes Leech Seed recovery not applying behind Sub by @AlexOn1ine in [#7468](https://github.com/rh-hideout/pokeemerald-expansion/pull/7468) +* Fixes Round and Fusion moves doubling power from previous turn's move by @PhallenTree in [#7476](https://github.com/rh-hideout/pokeemerald-expansion/pull/7476) +* Fixes shadows and mon animations for transformed battlers by @AsparagusEduardo in [#7500](https://github.com/rh-hideout/pokeemerald-expansion/pull/7500) +* Fixes Life Orb still activating if move was absorbed by @AlexOn1ine in [#7521](https://github.com/rh-hideout/pokeemerald-expansion/pull/7521) +* Fix Mimicry Only Activating Once per Turn by @ghoulslash in [#7537](https://github.com/rh-hideout/pokeemerald-expansion/pull/7537) +* Fixes Knock Off still activating when there is no Item by @AlexOn1ine in [#7496](https://github.com/rh-hideout/pokeemerald-expansion/pull/7496) +* Fixed `B_PSYWAVE_DMG` by @AsparagusEduardo in [#7557](https://github.com/rh-hideout/pokeemerald-expansion/pull/7557) +* Fixes Counter / Mirror Coat / Metal Burst damage assignment by @AlexOn1ine in [#7538](https://github.com/rh-hideout/pokeemerald-expansion/pull/7538) +* Fix in-game partner battles always causing a whiteout by @ravepossum in [#7587](https://github.com/rh-hideout/pokeemerald-expansion/pull/7587) +* Fix B_ANIMATE_MON_AFTER_KO with a new counter by @hedara90 in [#7531](https://github.com/rh-hideout/pokeemerald-expansion/pull/7531) +* Fixes Rage Fist counter increment by @AlexOn1ine in [#7582](https://github.com/rh-hideout/pokeemerald-expansion/pull/7582) +* Fixes moveend_absorb hitmarker by @AlexOn1ine in [#7591](https://github.com/rh-hideout/pokeemerald-expansion/pull/7591) +* switchinabilities also runs ON_WEATHER and ON_TERRAIN by @ghoulslash in [#7612](https://github.com/rh-hideout/pokeemerald-expansion/pull/7612) +* Fixes Explosion behavior when 3 mons can endure hit by @AlexOn1ine in [#7594](https://github.com/rh-hideout/pokeemerald-expansion/pull/7594) +* Fixes octolock not ending after user switched out by @AlexOn1ine in [#7556](https://github.com/rh-hideout/pokeemerald-expansion/pull/7556) +* The original attacker wasn't restored for Doodle by @AlexOn1ine in [#7620](https://github.com/rh-hideout/pokeemerald-expansion/pull/7620) +* Restore X item friendship increase by @ravepossum in [#7583](https://github.com/rh-hideout/pokeemerald-expansion/pull/7583) +* Fixes Wonder Room interactions with Defense/Special Defense boosting effects by @PhallenTree in [#7626](https://github.com/rh-hideout/pokeemerald-expansion/pull/7626) +* Ally Switch attract battler swapping, test for leech seed by @ghoulslash in [#7634](https://github.com/rh-hideout/pokeemerald-expansion/pull/7634) +* Fixes Defiant/Competitive not resetting stat change animations and stat change related cleanup by @PhallenTree in [#7004](https://github.com/rh-hideout/pokeemerald-expansion/pull/7004) +* Use battler arguments for SetMoveEffect by @AlexOn1ine in [#7156](https://github.com/rh-hideout/pokeemerald-expansion/pull/7156) +* Fixes Booster Energy timing activation + Clean up by @AlexOn1ine in [#7175](https://github.com/rh-hideout/pokeemerald-expansion/pull/7175) +* Fixes Eject Pack not resolving correctly during switch in effects by @AlexOn1ine in [#7002](https://github.com/rh-hideout/pokeemerald-expansion/pull/7002) +* Adds Ability Shield activation message by @PhallenTree in [#7224](https://github.com/rh-hideout/pokeemerald-expansion/pull/7224) +* Fix incorrect type input by @hedara90 in [#7228](https://github.com/rh-hideout/pokeemerald-expansion/pull/7228) +* Set correct Instruction by @AlexOn1ine in [#7236](https://github.com/rh-hideout/pokeemerald-expansion/pull/7236) +* Fixes Life Dew playing anim when it is not supposed to + tests by @AlexOn1ine in [#7239](https://github.com/rh-hideout/pokeemerald-expansion/pull/7239) +* Fixes instances of battler mutation for abilities by @AlexOn1ine in [#7250](https://github.com/rh-hideout/pokeemerald-expansion/pull/7250) +* Fix Psych Up message and cleanup and don't allow switching to self in tests by @PhallenTree in [#7277](https://github.com/rh-hideout/pokeemerald-expansion/pull/7277) +* Fix incorrect status in beneficial ability Guts check by @grintoul1 in [#7285](https://github.com/rh-hideout/pokeemerald-expansion/pull/7285) +* battle_interface: overhaul ability pop up by @mudskipper13 in [#7227](https://github.com/rh-hideout/pokeemerald-expansion/pull/7227) + - The layout of the ability pop up's image (`graphics/battle_interface/ability_pop_up.png`) has been changed. +* Fixes Status overwrites and Effect Spore wrong func args by @AlexOn1ine in [#7340](https://github.com/rh-hideout/pokeemerald-expansion/pull/7340) +* Fixes various Choice lock issues by @AlexOn1ine in [#7383](https://github.com/rh-hideout/pokeemerald-expansion/pull/7383) +* Fixes draining moves recovering 1 HP when dealing 0 damage by @LinathanZel in [#7523](https://github.com/rh-hideout/pokeemerald-expansion/pull/7523) + +## 🤹 Moves 🤹 +### Changed +* New Attack Animations: 25w20a by @ShinyVolcarona in [#6886](https://github.com/rh-hideout/pokeemerald-expansion/pull/6886) + - Added move animations for multiple moves by @LinathanZel + - Dynamax Cannon, Behemoth Blade, Behemoth Bash, Eternabeam, Glaive Rush, Triple Dive, Doodle, Ruination, Collision Course, Electro Drift, Blazing Torque, Wicked Torque, Noxious Torque, Combat Torque, Magical Torque, Psyblade, Mighty Cleave, Supercell Slam +* Documented usage of `delay X` by @AsparagusEduardo in [#6951](https://github.com/rh-hideout/pokeemerald-expansion/pull/6951) +* Animation documentation by @AsparagusEduardo in [#7052](https://github.com/rh-hideout/pokeemerald-expansion/pull/7052) +* New and polished battle animations by @LinathanZel in [#7074](https://github.com/rh-hideout/pokeemerald-expansion/pull/7074) + +### Fixed +* Clear gScanlineEffect to fix timeout in acid downpour animation by @FosterProgramming in [#7442](https://github.com/rh-hideout/pokeemerald-expansion/pull/7442) +* Fix terastallization anims flickering by @ravepossum in [#7613](https://github.com/rh-hideout/pokeemerald-expansion/pull/7613) + +## 🧶 Items 🧶 +### Changed +* Fix using town map as registered item by @ravepossum in [#7482](https://github.com/rh-hideout/pokeemerald-expansion/pull/7482) +* Compound strings for hold effect names by @AsparagusEduardo in [#7140](https://github.com/rh-hideout/pokeemerald-expansion/pull/7140) +* Untangled TMs and HMs from item ids by @cfmnephrite in [#7173](https://github.com/rh-hideout/pokeemerald-expansion/pull/7173) +* Bag refactor 2 by @cfmnephrite in [#7166](https://github.com/rh-hideout/pokeemerald-expansion/pull/7166) + +### Fixed +* Implement using party menu items from field by @ravepossum in [#7481](https://github.com/rh-hideout/pokeemerald-expansion/pull/7481) +* Fixed TM and Berries disappearing when sorting by @AsparagusEduardo in [#7168](https://github.com/rh-hideout/pokeemerald-expansion/pull/7168) +* Fixed item swapping bug (#7428) by @cfmnephrite in [#7430](https://github.com/rh-hideout/pokeemerald-expansion/pull/7430) +* Fixes some Ability Shield interactions by @PhallenTree in [#7532](https://github.com/rh-hideout/pokeemerald-expansion/pull/7532) +* Fix tossing a stack of berries hiding following berries by @hedara90 in [#7571](https://github.com/rh-hideout/pokeemerald-expansion/pull/7571) + +## 🤖 Battle AI 🤖 +### Added +* AI: Add AI_SMART_TERA flag to make smarter decisions about when to terastalize. by @jfb1337 in [#6705](https://github.com/rh-hideout/pokeemerald-expansion/pull/6705) + - Only single battles are currently supported. +* Haze Boosting AI Followup by @Pawkkie in [#6966](https://github.com/rh-hideout/pokeemerald-expansion/pull/6966) +* Improved logic for Guard Split and Power Split. by @surskitty in [#7298](https://github.com/rh-hideout/pokeemerald-expansion/pull/7298) +* Add AI_FLAG_ASSUME_STAB by @Pawkkie in [#6797](https://github.com/rh-hideout/pokeemerald-expansion/pull/6797) +* AI checks the partner's moves for Flatter, Swagger, and Soak. by @surskitty in [#7306](https://github.com/rh-hideout/pokeemerald-expansion/pull/7306) +* AI uses After You to help set up Trick Room. by @surskitty in [#7310](https://github.com/rh-hideout/pokeemerald-expansion/pull/7310) +* AI assumes Magnitude / Present damage by @Pawkkie in [#7334](https://github.com/rh-hideout/pokeemerald-expansion/pull/7334) +* AI_FLAG_ASSUME_STATUS_MOVES -- AI flag to randomly know some of the player's status moves by @surskitty in [#7324](https://github.com/rh-hideout/pokeemerald-expansion/pull/7324) +* Improve AI's setup logic by @Pawkkie in [#7345](https://github.com/rh-hideout/pokeemerald-expansion/pull/7345) +* Improve AI's ShouldRecover by @Pawkkie in [#7342](https://github.com/rh-hideout/pokeemerald-expansion/pull/7342) +* Switch AI can see weather abilities of switchin candidates during damage calcs by @Pawkkie in [#7373](https://github.com/rh-hideout/pokeemerald-expansion/pull/7373) +* AI refactor for weather-setting, terrain-setting, Trick Room behaviors; doubles-focused by @surskitty in [#7319](https://github.com/rh-hideout/pokeemerald-expansion/pull/7319) + - AI is more likely to use Trick Room in double battles and Terrains in general. +* Improve AI type matchup calcs by @Pawkkie in [#7364](https://github.com/rh-hideout/pokeemerald-expansion/pull/7364) +* Multibattle Partner AI Flags and 2vs1 battler3 AI Flags fix by @grintoul1 in [#7378](https://github.com/rh-hideout/pokeemerald-expansion/pull/7378) +* Improve AI's Sucker Punch handling by @Pawkkie in [#7389](https://github.com/rh-hideout/pokeemerald-expansion/pull/7389) +* Improve AI's priority handling by @Pawkkie in [#7337](https://github.com/rh-hideout/pokeemerald-expansion/pull/7337) +* Fix dynamic move types in switching by @Pawkkie in [#7415](https://github.com/rh-hideout/pokeemerald-expansion/pull/7415) +* Adds AI_FLAG_ASSUMPTIONS as a constant for semi-omniscience by @surskitty in [#7435](https://github.com/rh-hideout/pokeemerald-expansion/pull/7435) +* AI_FLAG_ATTACKS_PARTNER with a config for bloodthirstiness by @surskitty in [#7401](https://github.com/rh-hideout/pokeemerald-expansion/pull/7401) +* Improved Guaranteed Flinch logic (fake out et al) by @surskitty in [#7501](https://github.com/rh-hideout/pokeemerald-expansion/pull/7501) +* AI uses Court Change. by @surskitty in [#7525](https://github.com/rh-hideout/pokeemerald-expansion/pull/7525) +* AI uses Tailwind. by @surskitty in [#7515](https://github.com/rh-hideout/pokeemerald-expansion/pull/7515) +* AI should not use Dark Void or Hyperspace Fury while wrong species by @surskitty in [#7540](https://github.com/rh-hideout/pokeemerald-expansion/pull/7540) +* AI uses Rototiller. by @surskitty in [#7542](https://github.com/rh-hideout/pokeemerald-expansion/pull/7542) +* Helping Hand logic by @surskitty in [#7504](https://github.com/rh-hideout/pokeemerald-expansion/pull/7504) + +### Changed +* Macro-for-AI-Flag-definitions by @grintoul1 in [#7471](https://github.com/rh-hideout/pokeemerald-expansion/pull/7471) +* Remove redundancy for ShouldLowerStat functions by @AlexOn1ine in [#6577](https://github.com/rh-hideout/pokeemerald-expansion/pull/6577) +* Expanding and Refactoring Skill Swap and other ability-changing moves by @surskitty in [#7238](https://github.com/rh-hideout/pokeemerald-expansion/pull/7238) +* Changes AccuracyCalcHelper into CanMoveSkipAccuracyCalc by @AlexOn1ine in [#7303](https://github.com/rh-hideout/pokeemerald-expansion/pull/7303) +* AI Tests + accompanying bugfixes for Skill Swap, Worry Seed, weather setting in double battles, and Discharging into an ally's lightningrod by @surskitty in [#7297](https://github.com/rh-hideout/pokeemerald-expansion/pull/7297) +* Fix AI resisted move scoring by @Pawkkie in [#7350](https://github.com/rh-hideout/pokeemerald-expansion/pull/7350) +* Fiddling with CanLowerStat. by @surskitty in [#7510](https://github.com/rh-hideout/pokeemerald-expansion/pull/7510) +* Improved hazards logic and Mycelium Might ignores ability checks by @surskitty in [#7509](https://github.com/rh-hideout/pokeemerald-expansion/pull/7509) +* AI handling for similar utility moves by @surskitty in [#7513](https://github.com/rh-hideout/pokeemerald-expansion/pull/7513) +* Modify move prediction to work in doubles by @AlexOn1ine in [#7087](https://github.com/rh-hideout/pokeemerald-expansion/pull/7087) +* Uncommenting out No Retreat, Clangorous Soul, and Extreme Evoboost from CheckBadMove by @surskitty in [#7541](https://github.com/rh-hideout/pokeemerald-expansion/pull/7541) +* AI Tailwind singles fix correction. by @surskitty in [#7543](https://github.com/rh-hideout/pokeemerald-expansion/pull/7543) +* Remove funcResult from AiThinkingStruct by @Pawkkie in [#7545](https://github.com/rh-hideout/pokeemerald-expansion/pull/7545) +* AI handling for Autotomize. by @surskitty in [#7550](https://github.com/rh-hideout/pokeemerald-expansion/pull/7550) +* AI uses Stuff Cheeks; treating it simply as a def +2 move for now. by @surskitty in [#7554](https://github.com/rh-hideout/pokeemerald-expansion/pull/7554) +* Slight Purify adjustment for targeting ally; test that AI can use Purify. by @surskitty in [#7553](https://github.com/rh-hideout/pokeemerald-expansion/pull/7553) +* AI handling for Howl. by @surskitty in [#7549](https://github.com/rh-hideout/pokeemerald-expansion/pull/7549) +* Test that AI uses Dragon Cheer. by @surskitty in [#7552](https://github.com/rh-hideout/pokeemerald-expansion/pull/7552) +* Tests to see that the AI uses moves. by @surskitty in [#7555](https://github.com/rh-hideout/pokeemerald-expansion/pull/7555) + +### Fixed +* Incorrect call in Rest by @surskitty in [#7569](https://github.com/rh-hideout/pokeemerald-expansion/pull/7569) +* Fix duplicate switch in after faint by @AlexOn1ine in [#7600](https://github.com/rh-hideout/pokeemerald-expansion/pull/7600) +* Feature/ai/wide guard quick guard singles by @Emiliasky in [#7086](https://github.com/rh-hideout/pokeemerald-expansion/pull/7086) +* Add missing break by @Pawkkie in [#7356](https://github.com/rh-hideout/pokeemerald-expansion/pull/7356) +* fixed-damage-move-ai-calc-fix by @grintoul1 in [#7385](https://github.com/rh-hideout/pokeemerald-expansion/pull/7385) +* Avoid doubling up on status moves in double battles. by @surskitty in [#7452](https://github.com/rh-hideout/pokeemerald-expansion/pull/7452) +* Fix doubles switch AI to use new type matchup system by @Pawkkie in [#7495](https://github.com/rh-hideout/pokeemerald-expansion/pull/7495) +* Fix Bad Odds not seeing damage properly by @Pawkkie in [#7492](https://github.com/rh-hideout/pokeemerald-expansion/pull/7492) +* Fix GetSwitchinHitsToKO one shot heal calcs by @Pawkkie in [#7502](https://github.com/rh-hideout/pokeemerald-expansion/pull/7502) +* Fix AI's KO evaluation getting messed up by priority by @Pawkkie in [#7533](https://github.com/rh-hideout/pokeemerald-expansion/pull/7533) +* Fixing Refresh AI scoring by @surskitty in [#7539](https://github.com/rh-hideout/pokeemerald-expansion/pull/7539) +* Fix switch AI not seeing its own move PP by @Pawkkie in [#7578](https://github.com/rh-hideout/pokeemerald-expansion/pull/7578) +* Fix wrong battler argument in `GetBattleMovePriority` call by @Pawkkie in [#7576](https://github.com/rh-hideout/pokeemerald-expansion/pull/7576) +* Restore AI: Basic Trainer to PARTNER_STEVEN by @grintoul1 in [#7586](https://github.com/rh-hideout/pokeemerald-expansion/pull/7586) + +## 🧹 Other Cleanup 🧹 +* Macro-for-AI-Flag-definitions by @grintoul1 in [#7471](https://github.com/rh-hideout/pokeemerald-expansion/pull/7471) +* Moved summary screen nature colors to summary_screen.h by @RubyRaven6 in [#7560](https://github.com/rh-hideout/pokeemerald-expansion/pull/7560) +* fix: remove unused wild_encounters.json.txt jinja file by @khbsd in [#7581](https://github.com/rh-hideout/pokeemerald-expansion/pull/7581) +* Fix Form Change Item Task Data and Clean Up Field Use Funcs by @ravepossum in [#7535](https://github.com/rh-hideout/pokeemerald-expansion/pull/7535) +* Fixed Teleport's description not being updated based on `B_TELEPORT_BEHAVIOR` by @AsparagusEduardo in [#7580](https://github.com/rh-hideout/pokeemerald-expansion/pull/7580) +* Fixed typo in test name by @hedara90 in [#7610](https://github.com/rh-hideout/pokeemerald-expansion/pull/7610) +* Minor Clean up in battle_ai_main.c by @AlexOn1ine in [#7551](https://github.com/rh-hideout/pokeemerald-expansion/pull/7551) +* Remove unused function by @AlexOn1ine in [#7617](https://github.com/rh-hideout/pokeemerald-expansion/pull/7617) +* Fix Vs Seeker Trainer Battle script issue by @pkmnsnfrn in [#7615](https://github.com/rh-hideout/pokeemerald-expansion/pull/7615) +* Clean up battlescript calls with func BattleScriptCall by @AlexOn1ine in [#6873](https://github.com/rh-hideout/pokeemerald-expansion/pull/6873) +* Replace all usages of lz compression with smol by @hedara90 in [#7032](https://github.com/rh-hideout/pokeemerald-expansion/pull/7032) +* `BtlController_EmitTwoReturnValues` cleanup by @AsparagusEduardo in [#6855](https://github.com/rh-hideout/pokeemerald-expansion/pull/6855) +* `GetBattlerMon` cleanup by @AsparagusEduardo in [#6967](https://github.com/rh-hideout/pokeemerald-expansion/pull/6967) +* Converts a bunch of defines to enums by @Bassoonian in [#7041](https://github.com/rh-hideout/pokeemerald-expansion/pull/7041) +* Change GetZMaxMoveAgainstProtectionModifier to prevent regressions by @AlexOn1ine in [#7047](https://github.com/rh-hideout/pokeemerald-expansion/pull/7047) +* Remove more instances of hard-coded Move IDs by @AsparagusEduardo in [#7056](https://github.com/rh-hideout/pokeemerald-expansion/pull/7056) + - Added `EFFECT_SHEER_COLD` to parametrize Sheer Cold's interactions with Ice types +* Animation documentation by @AsparagusEduardo in [#7052](https://github.com/rh-hideout/pokeemerald-expansion/pull/7052) +* Deprecate sStatusFlagsForMoveEffects by @AlexOn1ine in [#7063](https://github.com/rh-hideout/pokeemerald-expansion/pull/7063) +* chore: remove unused section from credits by @Emiliasky in [#7085](https://github.com/rh-hideout/pokeemerald-expansion/pull/7085) +* Removes duplicate AI ability func by @AlexOn1ine in [#7045](https://github.com/rh-hideout/pokeemerald-expansion/pull/7045) +* Remove redundancy for ShouldLowerStat functions by @AlexOn1ine in [#6577](https://github.com/rh-hideout/pokeemerald-expansion/pull/6577) +* Deprecate absent member from battlerState by @AlexOn1ine in [#7091](https://github.com/rh-hideout/pokeemerald-expansion/pull/7091) +* Use CanAbilityAbsorbMove in GetOverworldTypeEffectiveness by @AlexOn1ine in [#7115](https://github.com/rh-hideout/pokeemerald-expansion/pull/7115) +* Removed redundant Damp check by @AsparagusEduardo in [#7134](https://github.com/rh-hideout/pokeemerald-expansion/pull/7134) +* Improve music/se macros and fix names by @cawtds in [#7030](https://github.com/rh-hideout/pokeemerald-expansion/pull/7030) +* Compound strings for hold effect names by @AsparagusEduardo in [#7140](https://github.com/rh-hideout/pokeemerald-expansion/pull/7140) +* Repurposes IsMagicGuardProtected into a general function by @AlexOn1ine in [#7114](https://github.com/rh-hideout/pokeemerald-expansion/pull/7114) +* Converts more defines to enums and name unnamed enums by @Bassoonian in [#7071](https://github.com/rh-hideout/pokeemerald-expansion/pull/7071) +* Use `argument.type` for `EFFECT_SOAK` by @AsparagusEduardo in [#7141](https://github.com/rh-hideout/pokeemerald-expansion/pull/7141) +* More battle controller function consolidation. by @AsparagusEduardo in [#6877](https://github.com/rh-hideout/pokeemerald-expansion/pull/6877) +* 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) +* 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. +* Script clean up for Flame Burst and Costar by @AlexOn1ine in [#7264](https://github.com/rh-hideout/pokeemerald-expansion/pull/7264) +* Use compound strings in battle debug menu by @AsparagusEduardo in [#7282](https://github.com/rh-hideout/pokeemerald-expansion/pull/7282) +* Renaming STATUS1_REFRESH and adding more constants for common STATUS1 checks. by @surskitty in [#7284](https://github.com/rh-hideout/pokeemerald-expansion/pull/7284) +* Removed all instances of .chance = 100, SHEER_FORCE_NO_BOOST by @cfmnephrite in [#7300](https://github.com/rh-hideout/pokeemerald-expansion/pull/7300) +* AI Tests + accompanying bugfixes for Skill Swap, Worry Seed, weather setting in double battles, and Discharging into an ally's lightningrod by @surskitty in [#7297](https://github.com/rh-hideout/pokeemerald-expansion/pull/7297) +* Turn `OW_FRLG_WHITEOUT` into `OW_WHITEOUT_CUTSCENE` and make it generational by @kittenchilly in [#6962](https://github.com/rh-hideout/pokeemerald-expansion/pull/6962) +* Fix AI resisted move scoring by @Pawkkie in [#7350](https://github.com/rh-hideout/pokeemerald-expansion/pull/7350) +* Convert various to callnatives by @AlexOn1ine in [#7355](https://github.com/rh-hideout/pokeemerald-expansion/pull/7355) +* Remove leftover code by @AlexOn1ine in [#7397](https://github.com/rh-hideout/pokeemerald-expansion/pull/7397) +* Moved some fields to BattlerState/PartyState by @AsparagusEduardo in [#7409](https://github.com/rh-hideout/pokeemerald-expansion/pull/7409) +* Additional effects tweak by @cfmnephrite in [#7392](https://github.com/rh-hideout/pokeemerald-expansion/pull/7392) +* Clean up noResultString by @AlexOn1ine in [#7408](https://github.com/rh-hideout/pokeemerald-expansion/pull/7408) +* Bag sorting cleanup by @mrgriffin in [#7489](https://github.com/rh-hideout/pokeemerald-expansion/pull/7489) +* Convert statuses3 to volatiles by @AlexOn1ine in [#7514](https://github.com/rh-hideout/pokeemerald-expansion/pull/7514) +* Uncommenting out No Retreat, Clangorous Soul, and Extreme Evoboost from CheckBadMove by @surskitty in [#7541](https://github.com/rh-hideout/pokeemerald-expansion/pull/7541) +* AI Tailwind singles fix correction. by @surskitty in [#7543](https://github.com/rh-hideout/pokeemerald-expansion/pull/7543) +* Remove funcResult from AiThinkingStruct by @Pawkkie in [#7545](https://github.com/rh-hideout/pokeemerald-expansion/pull/7545) +* Suppress trainerproc compile warning for unused func by @AlexOn1ine in [#7592](https://github.com/rh-hideout/pokeemerald-expansion/pull/7592) +* Prevents a regression for custom abilties by @AlexOn1ine in [#7616](https://github.com/rh-hideout/pokeemerald-expansion/pull/7616) + +## 🧪 Test Runner 🧪 +### Changed +* Clean up some Normalize tests to make them make sense by @hedara90 in [#7461](https://github.com/rh-hideout/pokeemerald-expansion/pull/7461) +* Add Synthesis + Utililty Umbrella test by @ghoulslash in [#7472](https://github.com/rh-hideout/pokeemerald-expansion/pull/7472) +* Add test for BoxPokemon integrity by @hedara90 in [#7487](https://github.com/rh-hideout/pokeemerald-expansion/pull/7487) +* Re-order moves in fling test by @hedara90 in [#7559](https://github.com/rh-hideout/pokeemerald-expansion/pull/7559) +* Wrote some tests by @AsparagusEduardo in [#7563](https://github.com/rh-hideout/pokeemerald-expansion/pull/7563) +* Added Ability TODO tests - Volume C by @AsparagusEduardo in [#7562](https://github.com/rh-hideout/pokeemerald-expansion/pull/7562) +* Added missing Move Effect TODO tests - Volume F by @AsparagusEduardo in [#7605](https://github.com/rh-hideout/pokeemerald-expansion/pull/7605) +* Fixed typo in test name by @hedara90 in [#7610](https://github.com/rh-hideout/pokeemerald-expansion/pull/7610) +* Add assumes for bag tests by @Bassoonian in [#7188](https://github.com/rh-hideout/pokeemerald-expansion/pull/7188) +* Split Sheer Force tests by gen instead of by four by @AlexOn1ine in [#7260](https://github.com/rh-hideout/pokeemerald-expansion/pull/7260) +* make check TESTS="..." support for filenames and infix matches by @mrgriffin in [#7536](https://github.com/rh-hideout/pokeemerald-expansion/pull/7536) +* Fix shell side arm rng in battle tests moves by @FosterProgramming in [#7548](https://github.com/rh-hideout/pokeemerald-expansion/pull/7548) +* Test that AI uses Dragon Cheer. by @surskitty in [#7552](https://github.com/rh-hideout/pokeemerald-expansion/pull/7552) +* Tests to see that the AI uses moves. by @surskitty in [#7555](https://github.com/rh-hideout/pokeemerald-expansion/pull/7555) + +### Fixed +* Clear out parties between battle tests by @hedara90 in [#7460](https://github.com/rh-hideout/pokeemerald-expansion/pull/7460) +* Fixed most failed tests with `GEN_LATEST GEN_8` by @AsparagusEduardo in [#7498](https://github.com/rh-hideout/pokeemerald-expansion/pull/7498) +* Corrected Liquid Ooze test by @AsparagusEduardo in [#7527](https://github.com/rh-hideout/pokeemerald-expansion/pull/7527) +* switchinabilities also runs ON_WEATHER and ON_TERRAIN by @ghoulslash in [#7612](https://github.com/rh-hideout/pokeemerald-expansion/pull/7612) +* Ally Switch attract battler swapping, test for leech seed by @ghoulslash in [#7634](https://github.com/rh-hideout/pokeemerald-expansion/pull/7634) +* Fixed changed effect for Sheer Cold by @hedara90 in [#7099](https://github.com/rh-hideout/pokeemerald-expansion/pull/7099) +* Fixed Transistor damage calculation test failing when `GEN_LATEST` is less than `GEN_9` by @AsparagusEduardo in [#7577](https://github.com/rh-hideout/pokeemerald-expansion/pull/7577) + +## 📚 Documentation 📚 +* Update how_to_new_pokemon.md by @kevinwklawrence in [#7440](https://github.com/rh-hideout/pokeemerald-expansion/pull/7440) +* Updating a link to porytiles in INSTALL.md by @ThePeeps191 in [#7490](https://github.com/rh-hideout/pokeemerald-expansion/pull/7490) +* Added comment in event.inc for simple menus in dynmultichoice by @RubyRaven6 in [#7568](https://github.com/rh-hideout/pokeemerald-expansion/pull/7568) +* Documented usage of `delay X` by @AsparagusEduardo in [#6951](https://github.com/rh-hideout/pokeemerald-expansion/pull/6951) +* Update follower NPC tutorial doc for createfollowernpc macro by @Bivurnum in [#7230](https://github.com/rh-hideout/pokeemerald-expansion/pull/7230) +* Improve trainer back pic-related data and code (+ smol documentation) by @mudskipper13 in [#6821](https://github.com/rh-hideout/pokeemerald-expansion/pull/6821) +* Update trainer.h usage warning by @hedara90 in [#7439](https://github.com/rh-hideout/pokeemerald-expansion/pull/7439) + +## New Contributors +* @kevinwklawrence made their first contribution in [#7440](https://github.com/rh-hideout/pokeemerald-expansion/pull/7440) +* @ThePeeps191 made their first contribution in [#7490](https://github.com/rh-hideout/pokeemerald-expansion/pull/7490) +* @cornixsenex made their first contribution in [#7368](https://github.com/rh-hideout/pokeemerald-expansion/pull/7368) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.2...expansion/1.12.3 + +## New Contributors +* @ShinyVolcarona made their first contribution in [#6886](https://github.com/rh-hideout/pokeemerald-expansion/pull/6886) +* @Emiliasky made their first contribution in [#7085](https://github.com/rh-hideout/pokeemerald-expansion/pull/7085) +* @poetahto made their first contribution in [#7155](https://github.com/rh-hideout/pokeemerald-expansion/pull/7155) +* @Bolt-Strike made their first contribution in [#7103](https://github.com/rh-hideout/pokeemerald-expansion/pull/7103) +* @kevinwklawrence made their first contribution in [#7440](https://github.com/rh-hideout/pokeemerald-expansion/pull/7440) +* @FosterProgramming made their first contribution in [#7442](https://github.com/rh-hideout/pokeemerald-expansion/pull/7442) +* @ThePeeps191 made their first contribution in [#7490](https://github.com/rh-hideout/pokeemerald-expansion/pull/7490) +* @cornixsenex made their first contribution in [#7368](https://github.com/rh-hideout/pokeemerald-expansion/pull/7368) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.2...expansion/1.13.0 + + + + diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 1ac702a4f8..c604aeabb6 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,7 +1,7 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.12.3 +// Last version: 1.13.0 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 13 #define EXPANSION_VERSION_PATCH 0 From 9ff4c48f7757ca493f6b7c547ef6a3cd2aa8303e Mon Sep 17 00:00:00 2001 From: Hedara Date: Thu, 28 Aug 2025 16:16:40 +0200 Subject: [PATCH 271/283] Start of 1.13.1 cycle --- include/constants/expansion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/expansion.h b/include/constants/expansion.h index c604aeabb6..e4468a82b4 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -4,10 +4,10 @@ // Last version: 1.13.0 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 13 -#define EXPANSION_VERSION_PATCH 0 +#define EXPANSION_VERSION_PATCH 1 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE TRUE +#define EXPANSION_TAGGED_RELEASE FALSE #endif From a4c473e73c4bacc8c60905f98741755455542da9 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Fri, 29 Aug 2025 10:11:32 +0200 Subject: [PATCH 272/283] Update README.md (#7639) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6c91a3ad84..93c6b3a913 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # About `pokeemerald-expansion` -![Gif that shows debugging functionality that is unique to pokeemerald-expansion such as rerolling Trainer Id, Cheat Start, PC from Debug Menu, Debug PC Fill, Pokemon Sprite Visualizer, Debug Warp to Map, and Battle Debug Menu](https://github.com/user-attachments/assets/cf9dfbee-4c6b-4bca-8e0a-07f116ef891c) ![Gif that shows overworld functionality that is unique to pokeemerald-expansion such as indoor running, BW2 style map popups, overworld followers, DNA Splicers, Gen 1 style fishing, OW Item descriptions, Quick Run from Battle, Use Last Ball, Wild Double Battles, and Catch from EXP](https://github.com/user-attachments/assets/383af243-0904-4d41-bced-721492fbc48e) ![Gif that shows off a number of modern Pokemon battle mechanics happening in the pokeemerald-expansion engine: 2 vs 1 battles, modern Pokemon, items, moves, abilities, fully customizable opponents and partners, Trainer Slides, and generational gimmicks](https://github.com/user-attachments/assets/50c576bc-415e-4d66-a38f-ad712f3316be) +![Gif that shows debugging functionality that is unique to pokeemerald-expansion such as rerolling Trainer ID, Cheat Start, PC from Debug Menu, Debug PC Fill, Pokémon Sprite Visualizer, Debug Warp to Map, and Battle Debug Menu](https://github.com/user-attachments/assets/cf9dfbee-4c6b-4bca-8e0a-07f116ef891c) ![Gif that shows overworld functionality that is unique to pokeemerald-expansion such as indoor running, BW2 style map popups, overworld followers, DNA Splicers, Gen 1 style fishing, OW Item descriptions, Quick Run from Battle, Use Last Ball, Wild Double Battles, and Catch from EXP](https://github.com/user-attachments/assets/383af243-0904-4d41-bced-721492fbc48e) ![Gif that shows off a number of modern Pokémon battle mechanics happening in the pokeemerald-expansion engine: 2 vs 1 battles, modern Pokémon, items, moves, abilities, fully customizable opponents and partners, Trainer Slides, and generational gimmicks](https://github.com/user-attachments/assets/50c576bc-415e-4d66-a38f-ad712f3316be) @@ -8,7 +8,7 @@ # [Features](FEATURES.md) -**`pokeemerald-expansion`** offers hundreds of features from various [core series Pokémon games](https://bulbapedia.bulbagarden.net/wiki/Core_series), along with popular quality-of-life enhancements designed to streamline development and improve the player experience. A full list of those featues can be found in [`FEATURES.md`](FEATURES.md). +**`pokeemerald-expansion`** offers hundreds of features from various [core series Pokémon games](https://bulbapedia.bulbagarden.net/wiki/Core_series), along with popular quality-of-life enhancements designed to streamline development and improve the player experience. A full list of those features can be found in [`FEATURES.md`](FEATURES.md). # [Credits](CREDITS.md) @@ -32,7 +32,7 @@ Please consider [crediting all contributors](CREDITS.md) involved in the project ❗❗ **Important**: Do not use GitHub's "Download Zip" option as it will not include commit history. This is necessary if you want to update or merge other feature branches. -If you're new to git and GitHub, [Team Aqua's Asset Repo](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/) has a [guide on forking and cloning the repository](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/wiki/The-Basics-of-GitHub). Then you can follow one of the following guides: +If you're new to git and GitHub, [Team Aqua's Asset Repo](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/) has a [guide to forking and cloning the repository](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/wiki/The-Basics-of-GitHub). Then you can follow one of the following guides: ## 📥 [Installing **`pokeemerald-expansion`**](INSTALL.md) ## 🏗️ [Building **`pokeemerald-expansion`**](INSTALL.md#Building-pokeemerald-expansion) @@ -50,4 +50,4 @@ If you are looking to [report a bug](CONTRIBUTING.md#Bug-Report), [open a pull r [![](https://dcbadge.limes.pink/api/server/6CzjAG6GZk)](https://discord.gg/6CzjAG6GZk) -Our community uses the [Rom Hacking Hideout (RHH) Discord server](https://discord.gg/6CzjAG6GZk) to communicate and organize. Most of our discussions take place there, and we welcome anybody to join us! +Our community uses the [ROM Hacking Hideout (RHH) Discord server](https://discord.gg/6CzjAG6GZk) to communicate and organize. Most of our discussions take place there, and we welcome anybody to join us! From 7302de4209491ed30d214f3d1ed2182b2f58bb47 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 30 Aug 2025 11:22:02 +0200 Subject: [PATCH 273/283] Replace boolean multiplications with ternaries (#7653) Co-authored-by: Hedara --- src/battle_script_commands.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c08324b6e8..6845e760f4 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1630,12 +1630,12 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA } else { - critChance = 2 * (gBattleMons[battlerAtk].volatiles.focusEnergy != 0) - + 1 * (gBattleMons[battlerAtk].volatiles.dragonCheer != 0) + critChance = (gBattleMons[battlerAtk].volatiles.focusEnergy != 0 ? 2 : 0) + + (gBattleMons[battlerAtk].volatiles.dragonCheer != 0 ? 1 : 0) + GetMoveCriticalHitStage(move) + GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk) - + 2 * (B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) - + (abilityAtk == ABILITY_SUPER_LUCK) + + ((B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) ? 2 : 0) + + (abilityAtk == ABILITY_SUPER_LUCK ? 1 : 0) + gBattleStruct->bonusCritStages[gBattlerAttacker]; if (critChance >= ARRAY_COUNT(sCriticalHitOdds)) From 674cd136595cb5cd700c0bc869f0b85c75a227fa Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Sun, 31 Aug 2025 14:53:23 -0400 Subject: [PATCH 274/283] Added sortType to Douse Drive (#7664) --- src/data/items.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/items.h b/src/data/items.h index d86a610eb4..9927191d64 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -5033,6 +5033,7 @@ const struct Item gItemsInfo[] = "Techno Blast to\n" "Water-type."), .pocket = POCKET_ITEMS, + .sortType = ITEM_TYPE_DRIVE, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .secondaryId = TYPE_WATER, From 84f5aa6dae62da212efa2e8de11585bad189a031 Mon Sep 17 00:00:00 2001 From: surskitty Date: Mon, 1 Sep 2025 15:43:04 -0400 Subject: [PATCH 275/283] Helping Hand bugfix; used FOE instead of BATTLE_OPPOSITE. (#7659) --- src/battle_ai_main.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index ebbabf93c8..0623faf864 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1,3 +1,5 @@ +// Note that FOE specifically returns the left-side battler; BATTLE_OPPOSITE is the diagonal. + #include "global.h" #include "main.h" #include "malloc.h" @@ -3098,45 +3100,44 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, FOE(battlerAtk), AI_ATTACKING); - u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, FOE(battlerAtk), AI_ATTACKING); - u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, FOE(battlerAtkPartner), AI_ATTACKING); - u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, FOE(battlerAtkPartner), AI_ATTACKING); + u32 ownHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtk, BATTLE_OPPOSITE(battlerAtk), AI_ATTACKING); + u32 partnerHitsToKOFoe1 = GetBestNoOfHitsToKO(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtk), AI_ATTACKING); + u32 ownHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), AI_ATTACKING); + u32 partnerHitsToKOFoe2 = GetBestNoOfHitsToKO(battlerAtkPartner, BATTLE_OPPOSITE(battlerAtkPartner), AI_ATTACKING); if (hasTwoOpponents) { // Might be about to die - if (CanTargetFaintAi(FOE(battlerAtk), battlerAtk) && CanTargetFaintAi(FOE(battlerAtkPartner), battlerAtk) - && AI_IsSlower(battlerAtk, FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) - && AI_IsSlower(battlerAtk, FOE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) && CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk) + && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY) + && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1 && ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) ADJUST_SCORE(GOOD_EFFECT); } - else if (IsBattlerAlive(FOE(battlerAtk))) + else if (IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk))) { // Might be about to die - if (CanTargetFaintAi(FOE(battlerAtk), battlerAtk) - && AI_IsSlower(battlerAtk, FOE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) + && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe1 > partnerHitsToKOFoe1 && partnerHitsToKOFoe1 > 1) ADJUST_SCORE(GOOD_EFFECT); } - else if (IsBattlerAlive(FOE(battlerAtkPartner))) + else if (IsBattlerAlive(BATTLE_OPPOSITE(battlerAtkPartner))) { // Might be about to die - if (CanTargetFaintAi(FOE(battlerAtkPartner), battlerAtk) - && AI_IsSlower(battlerAtk, FOE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) + if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk) + && AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY)) ADJUST_SCORE(GOOD_EFFECT); if (ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1) ADJUST_SCORE(GOOD_EFFECT); - } - + } } break; case EFFECT_PERISH_SONG: From cfcdd5f776857a28d2b23d6cf26f0ad56a26a0b9 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Tue, 2 Sep 2025 14:59:33 +0200 Subject: [PATCH 276/283] Fix crashing tests duplicating tests from another thread (#7683) Co-authored-by: Hedara --- test/test_runner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_runner.c b/test/test_runner.c index fe9a5eccb6..218061d63f 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -235,6 +235,8 @@ void CB2_TestRunner(void) } else { + // Cost must be assigned to the test that crashed, otherwise tests will be desynched + AssignCostToRunner(); gTestRunnerState.state = STATE_REPORT_RESULT; gTestRunnerState.result = TEST_RESULT_CRASH; } From c252e2256b3e23677162c25164d9b7d0c35a4ec2 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:44:01 +0200 Subject: [PATCH 277/283] Fix Rage Fist test name (#7681) --- test/battle/move_effect/rage_fist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/move_effect/rage_fist.c b/test/battle/move_effect/rage_fist.c index ba8fcecc06..ed21a9097c 100644 --- a/test/battle/move_effect/rage_fist.c +++ b/test/battle/move_effect/rage_fist.c @@ -343,7 +343,7 @@ SINGLE_BATTLE_TEST("Rage Fist doesn't get increased power if Substitute is hit") } } -SINGLE_BATTLE_TEST("Rage Fist - X") +SINGLE_BATTLE_TEST("Rage Fist counter will be updated correctly after absorb move") { s16 timesGotHit[2]; From f39fdf57cfe758ece0177efb3189dfb15602418a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 2 Sep 2025 09:46:48 -0400 Subject: [PATCH 278/283] Fixed disabled cross-evolutions still being possible (#7678) --- .../pokemon/species_info/gen_1_families.h | 94 +++++++++++++++---- .../pokemon/species_info/gen_2_families.h | 30 +++++- .../pokemon/species_info/gen_3_families.h | 20 +++- .../pokemon/species_info/gen_5_families.h | 2 + .../pokemon/species_info/gen_8_families.h | 9 +- 5 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/data/pokemon/species_info/gen_1_families.h b/src/data/pokemon/species_info/gen_1_families.h index 70165414ba..1b0e94aa13 100644 --- a/src/data/pokemon/species_info/gen_1_families.h +++ b/src/data/pokemon/species_info/gen_1_families.h @@ -5730,7 +5730,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sGolbatLevelUpLearnset, .teachableLearnset = sGolbatTeachableLearnset, + #if P_GEN_2_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_CROBAT, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD})}), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -5979,8 +5981,11 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sGloomLevelUpLearnset, .teachableLearnset = sGloomTeachableLearnset, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_LEAF_STONE, SPECIES_VILEPLUME}, - {EVO_ITEM, ITEM_SUN_STONE, SPECIES_BELLOSSOM}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_LEAF_STONE, SPECIES_VILEPLUME} + #if P_GEN_2_CROSS_EVOS + ,{EVO_ITEM, ITEM_SUN_STONE, SPECIES_BELLOSSOM} + #endif + ), }, [SPECIES_VILEPLUME] = @@ -7577,7 +7582,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sPrimeapeLevelUpLearnset, .teachableLearnset = sPrimeapeTeachableLearnset, + #if P_GEN_9_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_ANNIHILAPE, CONDITIONS({IF_USED_MOVE_X_TIMES, MOVE_RAGE_FIST, 20})}), + #endif }, #if P_GEN_9_CROSS_EVOS @@ -8064,9 +8071,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sPoliwhirlLevelUpLearnset, .teachableLearnset = sPoliwhirlTeachableLearnset, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_WATER_STONE, SPECIES_POLIWRATH}, - {EVO_TRADE, 0, SPECIES_POLITOED, CONDITIONS({IF_HOLD_ITEM, ITEM_KINGS_ROCK})}, - {EVO_ITEM, ITEM_KINGS_ROCK, SPECIES_POLITOED}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_WATER_STONE, SPECIES_POLIWRATH} + #if P_GEN_2_CROSS_EVOS + ,{EVO_TRADE, 0, SPECIES_POLITOED, CONDITIONS({IF_HOLD_ITEM, ITEM_KINGS_ROCK})}, + {EVO_ITEM, ITEM_KINGS_ROCK, SPECIES_POLITOED} + #endif + ), }, [SPECIES_POLIWRATH] = @@ -10045,9 +10055,12 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .teachableLearnset = sSlowpokeTeachableLearnset, .eggMoveLearnset = sSlowpokeEggMoveLearnset, .formSpeciesIdTable = sSlowpokeFormSpeciesIdTable, - .evolutions = EVOLUTION({EVO_LEVEL, 37, SPECIES_SLOWBRO}, - {EVO_TRADE, 0, SPECIES_SLOWKING, CONDITIONS({IF_HOLD_ITEM, ITEM_KINGS_ROCK})}, - {EVO_ITEM, ITEM_KINGS_ROCK, SPECIES_SLOWKING}), + .evolutions = EVOLUTION({EVO_LEVEL, 37, SPECIES_SLOWBRO} + #if P_GEN_2_CROSS_EVOS + ,{EVO_TRADE, 0, SPECIES_SLOWKING, CONDITIONS({IF_HOLD_ITEM, ITEM_KINGS_ROCK})}, + {EVO_ITEM, ITEM_KINGS_ROCK, SPECIES_SLOWKING} + #endif + ), }, [SPECIES_SLOWBRO] = @@ -10326,8 +10339,11 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .teachableLearnset = sSlowpokeGalarTeachableLearnset, .eggMoveLearnset = sSlowpokeGalarEggMoveLearnset, .formSpeciesIdTable = sSlowpokeFormSpeciesIdTable, - .evolutions = EVOLUTION({EVO_ITEM, ITEM_GALARICA_CUFF, SPECIES_SLOWBRO_GALAR}, - {EVO_ITEM, ITEM_GALARICA_WREATH, SPECIES_SLOWKING_GALAR}), + .evolutions = EVOLUTION({EVO_ITEM, ITEM_GALARICA_CUFF, SPECIES_SLOWBRO_GALAR} + #if P_GEN_2_CROSS_EVOS + ,{EVO_ITEM, ITEM_GALARICA_WREATH, SPECIES_SLOWKING_GALAR} + #endif + ), }, [SPECIES_SLOWBRO_GALAR] = @@ -10609,8 +10625,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sMagnetonLevelUpLearnset, .teachableLearnset = sMagnetonTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_MAGNEZONE, CONDITIONS({IF_IN_MAPSEC, MAPSEC_NEW_MAUVILLE})}, {EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_MAGNEZONE}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -12107,8 +12125,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sOnixLevelUpLearnset, .teachableLearnset = sOnixTeachableLearnset, .eggMoveLearnset = sOnixEggMoveLearnset, + #if P_GEN_2_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_STEELIX, CONDITIONS({IF_HOLD_ITEM, ITEM_METAL_COAT})}, {EVO_ITEM, ITEM_METAL_COAT, SPECIES_STEELIX}), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -13805,7 +13825,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sLickitungLevelUpLearnset, .teachableLearnset = sLickitungTeachableLearnset, .eggMoveLearnset = sLickitungEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_LICKILICKY, CONDITIONS({IF_KNOWS_MOVE, MOVE_ROLLOUT})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -14274,8 +14296,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sRhydonLevelUpLearnset, .teachableLearnset = sRhydonTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_RHYPERIOR, CONDITIONS({IF_HOLD_ITEM, ITEM_PROTECTOR})}, {EVO_ITEM, ITEM_PROTECTOR, SPECIES_RHYPERIOR}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -14510,7 +14534,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sChanseyLevelUpLearnset, .teachableLearnset = sChanseyTeachableLearnset, .eggMoveLearnset = sChanseyEggMoveLearnset, + #if P_GEN_2_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_BLISSEY, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD})}), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -14655,7 +14681,9 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sTangelaLevelUpLearnset, .teachableLearnset = sTangelaTeachableLearnset, .eggMoveLearnset = sTangelaEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_TANGROWTH, CONDITIONS({IF_KNOWS_MOVE, MOVE_ANCIENT_POWER})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -15037,8 +15065,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sSeadraLevelUpLearnset, .teachableLearnset = sSeadraTeachableLearnset, + #if P_GEN_2_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_KINGDRA, CONDITIONS({IF_HOLD_ITEM, ITEM_DRAGON_SCALE})}, {EVO_ITEM, ITEM_DRAGON_SCALE, SPECIES_KINGDRA}), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -15826,9 +15856,20 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .levelUpLearnset = sScytherLevelUpLearnset, .teachableLearnset = sScytherTeachableLearnset, .eggMoveLearnset = sScytherEggMoveLearnset, - .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_SCIZOR, CONDITIONS({IF_HOLD_ITEM, ITEM_METAL_COAT})}, - {EVO_ITEM, ITEM_BLACK_AUGURITE, SPECIES_KLEAVOR}, - {EVO_ITEM, ITEM_METAL_COAT, SPECIES_SCIZOR}), + #if P_GEN_2_CROSS_EVOS || P_GEN_8_CROSS_EVOS + .evolutions = EVOLUTION( + #if P_GEN_2_CROSS_EVOS + {EVO_TRADE, 0, SPECIES_SCIZOR, CONDITIONS({IF_HOLD_ITEM, ITEM_METAL_COAT})}, + {EVO_ITEM, ITEM_METAL_COAT, SPECIES_SCIZOR} + #if P_GEN_8_CROSS_EVOS + , + #endif + #endif + #if P_GEN_8_CROSS_EVOS + {EVO_ITEM, ITEM_BLACK_AUGURITE, SPECIES_KLEAVOR} + #endif + ), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -16346,8 +16387,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sElectabuzzLevelUpLearnset, .teachableLearnset = sElectabuzzTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_ELECTIVIRE, CONDITIONS({IF_HOLD_ITEM, ITEM_ELECTIRIZER})}, {EVO_ITEM, ITEM_ELECTIRIZER, SPECIES_ELECTIVIRE}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -16567,8 +16610,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sMagmarLevelUpLearnset, .teachableLearnset = sMagmarTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_MAGMORTAR, CONDITIONS({IF_HOLD_ITEM, ITEM_MAGMARIZER})}, {EVO_ITEM, ITEM_MAGMARIZER, SPECIES_MAGMORTAR}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -17609,14 +17654,21 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = .formChangeTable = sEeveeFormChangeTable, .evolutions = EVOLUTION({EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_JOLTEON}, {EVO_ITEM, ITEM_WATER_STONE, SPECIES_VAPOREON}, - {EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON}, - {EVO_LEVEL, 0, SPECIES_SYLVEON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_KNOWS_MOVE_TYPE, TYPE_FAIRY})}, - {EVO_LEVEL, 0, SPECIES_ESPEON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_NOT_TIME, TIME_NIGHT})}, - {EVO_LEVEL, 0, SPECIES_UMBREON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_TIME, TIME_NIGHT})}, - {EVO_LEVEL, 0, SPECIES_LEAFEON, CONDITIONS({IF_IN_MAP, MAP_PETALBURG_WOODS})}, + {EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON} + #if P_GEN_6_CROSS_EVOS + ,{EVO_LEVEL, 0, SPECIES_SYLVEON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_KNOWS_MOVE_TYPE, TYPE_FAIRY})} + #endif + #if P_GEN_2_CROSS_EVOS + ,{EVO_LEVEL, 0, SPECIES_ESPEON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_NOT_TIME, TIME_NIGHT})}, + {EVO_LEVEL, 0, SPECIES_UMBREON, CONDITIONS({IF_MIN_FRIENDSHIP, FRIENDSHIP_EVO_THRESHOLD}, {IF_TIME, TIME_NIGHT})} + #endif + #if P_GEN_4_CROSS_EVOS + ,{EVO_LEVEL, 0, SPECIES_LEAFEON, CONDITIONS({IF_IN_MAP, MAP_PETALBURG_WOODS})}, {EVO_ITEM, ITEM_LEAF_STONE, SPECIES_LEAFEON}, {EVO_LEVEL, 0, SPECIES_GLACEON, CONDITIONS({IF_IN_MAP, MAP_SHOAL_CAVE_LOW_TIDE_ICE_ROOM})}, - {EVO_ITEM, ITEM_ICE_STONE, SPECIES_GLACEON}), + {EVO_ITEM, ITEM_ICE_STONE, SPECIES_GLACEON} + #endif + ), }, #if P_GIGANTAMAX_FORMS @@ -18366,8 +18418,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sPorygonLevelUpLearnset, .teachableLearnset = sPorygonTeachableLearnset, + #if P_GEN_2_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_PORYGON2, CONDITIONS({IF_HOLD_ITEM, ITEM_UPGRADE})}, {EVO_ITEM, ITEM_UPGRADE, SPECIES_PORYGON2}), + #endif }, #if P_GEN_2_CROSS_EVOS @@ -18443,8 +18497,10 @@ const struct SpeciesInfo gSpeciesInfoGen1[] = ) .levelUpLearnset = sPorygon2LevelUpLearnset, .teachableLearnset = sPorygon2TeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_PORYGON_Z, CONDITIONS({IF_HOLD_ITEM, ITEM_DUBIOUS_DISC})}, {EVO_ITEM, ITEM_DUBIOUS_DISC, SPECIES_PORYGON_Z}), + #endif }, #if P_GEN_4_CROSS_EVOS diff --git a/src/data/pokemon/species_info/gen_2_families.h b/src/data/pokemon/species_info/gen_2_families.h index c8143d02f0..f95197332a 100644 --- a/src/data/pokemon/species_info/gen_2_families.h +++ b/src/data/pokemon/species_info/gen_2_families.h @@ -1619,7 +1619,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sTogeticLevelUpLearnset, .teachableLearnset = sTogeticTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_SHINY_STONE, SPECIES_TOGEKISS}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -2868,7 +2870,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sAipomLevelUpLearnset, .teachableLearnset = sAipomTeachableLearnset, .eggMoveLearnset = sAipomEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_AMBIPOM, CONDITIONS({IF_KNOWS_MOVE, MOVE_DOUBLE_HIT})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -3191,7 +3195,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sYanmaLevelUpLearnset, .teachableLearnset = sYanmaTeachableLearnset, .eggMoveLearnset = sYanmaEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_YANMEGA, CONDITIONS({IF_KNOWS_MOVE, MOVE_ANCIENT_POWER})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -3669,7 +3675,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sMurkrowLevelUpLearnset, .teachableLearnset = sMurkrowTeachableLearnset, .eggMoveLearnset = sMurkrowEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_DUSK_STONE, SPECIES_HONCHKROW}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -3819,7 +3827,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sMisdreavusLevelUpLearnset, .teachableLearnset = sMisdreavusTeachableLearnset, .eggMoveLearnset = sMisdreavusEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_DUSK_STONE, SPECIES_MISMAGIUS}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -4239,7 +4249,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sGirafarigLevelUpLearnset, .teachableLearnset = sGirafarigTeachableLearnset, .eggMoveLearnset = sGirafarigEggMoveLearnset, + #if P_GEN_9_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_FARIGIRAF, CONDITIONS({IF_KNOWS_MOVE, MOVE_TWIN_BEAM})}), + #endif }, #if P_GEN_9_CROSS_EVOS @@ -4527,8 +4539,10 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sDunsparceLevelUpLearnset, .teachableLearnset = sDunsparceTeachableLearnset, .eggMoveLearnset = sDunsparceEggMoveLearnset, + #if P_GEN_9_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_DUDUNSPARCE_TWO_SEGMENT, CONDITIONS({IF_KNOWS_MOVE, MOVE_HYPER_DRILL}, {IF_PID_MODULO_100_GT, 0})}, {EVO_LEVEL, 0, SPECIES_DUDUNSPARCE_THREE_SEGMENT, CONDITIONS({IF_KNOWS_MOVE, MOVE_HYPER_DRILL}, {IF_PID_MODULO_100_EQ, 0})}), + #endif }, #if P_GEN_9_CROSS_EVOS @@ -4742,8 +4756,10 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sGligarLevelUpLearnset, .teachableLearnset = sGligarTeachableLearnset, .eggMoveLearnset = sGligarEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_GLISCOR, CONDITIONS({IF_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_FANG})}, + #if P_GEN_4_CROSS_EVOS + .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_GLISCOR, CONDITIONS({IF_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_FANG})}, {EVO_ITEM, ITEM_RAZOR_FANG, SPECIES_GLISCOR, CONDITIONS({IF_TIME, TIME_NIGHT})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -5506,8 +5522,10 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .teachableLearnset = sSneaselTeachableLearnset, .eggMoveLearnset = sSneaselEggMoveLearnset, .formSpeciesIdTable = sSneaselFormSpeciesIdTable, - .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_WEAVILE, CONDITIONS({IF_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_CLAW})}, + #if P_GEN_4_CROSS_EVOS + .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_WEAVILE, CONDITIONS({IF_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_CLAW})}, {EVO_ITEM, ITEM_RAZOR_CLAW, SPECIES_WEAVILE, CONDITIONS({IF_TIME, TIME_NIGHT})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -5672,7 +5690,7 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sSneaselHisuiLevelUpLearnset, .teachableLearnset = sSneaselHisuiTeachableLearnset, .formSpeciesIdTable = sSneaselFormSpeciesIdTable, - .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_SNEASLER, CONDITIONS({IF_NOT_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_CLAW})}, + .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_SNEASLER, CONDITIONS({IF_NOT_TIME, TIME_NIGHT}, {IF_HOLD_ITEM, ITEM_RAZOR_CLAW})}, {EVO_ITEM, ITEM_RAZOR_CLAW, SPECIES_SNEASLER, CONDITIONS({IF_NOT_TIME, TIME_NIGHT})}), }, @@ -5897,8 +5915,10 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sUrsaringLevelUpLearnset, .teachableLearnset = sUrsaringTeachableLearnset, + #if P_GEN_8_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_PEAT_BLOCK, SPECIES_URSALUNA, CONDITIONS({IF_TIME, TIME_NIGHT})}, {EVO_NONE, 0, SPECIES_URSALUNA_BLOODMOON}), + #endif }, #if P_GEN_8_CROSS_EVOS @@ -6330,7 +6350,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = ) .levelUpLearnset = sPiloswineLevelUpLearnset, .teachableLearnset = sPiloswineTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_MAMOSWINE, CONDITIONS({IF_KNOWS_MOVE, MOVE_ANCIENT_POWER})}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -7534,7 +7556,9 @@ const struct SpeciesInfo gSpeciesInfoGen2[] = .levelUpLearnset = sStantlerLevelUpLearnset, .teachableLearnset = sStantlerTeachableLearnset, .eggMoveLearnset = sStantlerEggMoveLearnset, + #if P_GEN_8_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_WYRDEER, CONDITIONS({IF_USED_MOVE_X_TIMES, MOVE_PSYSHIELD_BASH, 20})}), + #endif }, #if P_GEN_8_CROSS_EVOS diff --git a/src/data/pokemon/species_info/gen_3_families.h b/src/data/pokemon/species_info/gen_3_families.h index 272c57668e..6ad30646cf 100644 --- a/src/data/pokemon/species_info/gen_3_families.h +++ b/src/data/pokemon/species_info/gen_3_families.h @@ -2801,8 +2801,11 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = ) .levelUpLearnset = sKirliaLevelUpLearnset, .teachableLearnset = sKirliaTeachableLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 30, SPECIES_GARDEVOIR}, - {EVO_ITEM, ITEM_DAWN_STONE, SPECIES_GALLADE, CONDITIONS({IF_GENDER, MON_MALE})}), + .evolutions = EVOLUTION({EVO_LEVEL, 30, SPECIES_GARDEVOIR} + #if P_GEN_4_CROSS_EVOS + ,{EVO_ITEM, ITEM_DAWN_STONE, SPECIES_GALLADE, CONDITIONS({IF_GENDER, MON_MALE})} + #endif + ), }, [SPECIES_GARDEVOIR] = @@ -4314,8 +4317,10 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .levelUpLearnset = sNosepassLevelUpLearnset, .teachableLearnset = sNosepassTeachableLearnset, .eggMoveLearnset = sNosepassEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_PROBOPASS, CONDITIONS({IF_IN_MAPSEC, MAPSEC_NEW_MAUVILLE})}, {EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_PROBOPASS}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -6069,7 +6074,9 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .levelUpLearnset = sRoseliaLevelUpLearnset, .teachableLearnset = sRoseliaTeachableLearnset, .eggMoveLearnset = sRoseliaEggMoveLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_SHINY_STONE, SPECIES_ROSERADE}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -9900,8 +9907,10 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = ) .levelUpLearnset = sDusclopsLevelUpLearnset, .teachableLearnset = sDusclopsTeachableLearnset, + #if P_GEN_4_CROSS_EVOS .evolutions = EVOLUTION({EVO_TRADE, 0, SPECIES_DUSKNOIR, CONDITIONS({IF_HOLD_ITEM, ITEM_REAPER_CLOTH})}, {EVO_ITEM, ITEM_REAPER_CLOTH, SPECIES_DUSKNOIR}), + #endif }, #if P_GEN_4_CROSS_EVOS @@ -10459,8 +10468,11 @@ const struct SpeciesInfo gSpeciesInfoGen3[] = .levelUpLearnset = sSnoruntLevelUpLearnset, .teachableLearnset = sSnoruntTeachableLearnset, .eggMoveLearnset = sSnoruntEggMoveLearnset, - .evolutions = EVOLUTION({EVO_LEVEL, 42, SPECIES_GLALIE}, - {EVO_ITEM, ITEM_DAWN_STONE, SPECIES_FROSLASS, CONDITIONS({IF_GENDER, MON_FEMALE})}), + .evolutions = EVOLUTION({EVO_LEVEL, 42, SPECIES_GLALIE} + #if P_GEN_4_CROSS_EVOS + ,{EVO_ITEM, ITEM_DAWN_STONE, SPECIES_FROSLASS, CONDITIONS({IF_GENDER, MON_FEMALE})} + #endif + ), }, [SPECIES_GLALIE] = diff --git a/src/data/pokemon/species_info/gen_5_families.h b/src/data/pokemon/species_info/gen_5_families.h index 9e906e8f85..6b46006a58 100644 --- a/src/data/pokemon/species_info/gen_5_families.h +++ b/src/data/pokemon/species_info/gen_5_families.h @@ -11107,7 +11107,9 @@ const struct SpeciesInfo gSpeciesInfoGen5[] = ) .levelUpLearnset = sBisharpLevelUpLearnset, .teachableLearnset = sBisharpTeachableLearnset, + #if P_GEN_9_CROSS_EVOS .evolutions = EVOLUTION({EVO_LEVEL, 0, SPECIES_KINGAMBIT, CONDITIONS({IF_DEFEAT_X_WITH_ITEMS, SPECIES_BISHARP, ITEM_LEADERS_CREST, 3})}), + #endif }, #if P_GEN_9_CROSS_EVOS diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index 8495287bf7..6ba7fed676 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -2466,8 +2466,11 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .teachableLearnset = sApplinTeachableLearnset, .eggMoveLearnset = sApplinEggMoveLearnset, .evolutions = EVOLUTION({EVO_ITEM, ITEM_TART_APPLE, SPECIES_FLAPPLE}, - {EVO_ITEM, ITEM_SWEET_APPLE, SPECIES_APPLETUN}, - {EVO_ITEM, ITEM_SYRUPY_APPLE, SPECIES_DIPPLIN}), + {EVO_ITEM, ITEM_SWEET_APPLE, SPECIES_APPLETUN} + #if P_GEN_9_CROSS_EVOS + ,{EVO_ITEM, ITEM_SYRUPY_APPLE, SPECIES_DIPPLIN} + #endif + ), }, [SPECIES_FLAPPLE] = @@ -6405,7 +6408,9 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .eggMoveLearnset = sDuraludonEggMoveLearnset, .formSpeciesIdTable = sDuraludonFormSpeciesIdTable, .formChangeTable = sDuraludonFormChangeTable, + #if P_GEN_9_CROSS_EVOS .evolutions = EVOLUTION({EVO_ITEM, ITEM_METAL_ALLOY, SPECIES_ARCHALUDON}), + #endif }, #if P_GIGANTAMAX_FORMS From c1b1fb4cdc19bc7b6bb685229074020a86f6ef55 Mon Sep 17 00:00:00 2001 From: Hedara Date: Tue, 2 Sep 2025 16:17:05 +0200 Subject: [PATCH 279/283] 1.13.1 Release version --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 +- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 +- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 +- README.md | 2 +- docs/SUMMARY.md | 1 + docs/changelogs/1.13.x/1.13.1.md | 44 +++++++++++++++++++ include/constants/expansion.h | 4 +- 7 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 docs/changelogs/1.13.x/1.13.1.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 0d323435b4..a06bfb5247 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.0 (Latest release) + - 1.13.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.13.0 - 1.12.3 - 1.12.2 - 1.12.1 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index a00d5f4d2c..505cd5e6c4 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.0 (Latest release) + - 1.13.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.13.0 - 1.12.3 - 1.12.2 - 1.12.1 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 53bf274899..4abed5dbb5 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.13.0 (Latest release) + - 1.13.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.13.0 - 1.12.3 - 1.12.2 - 1.12.1 diff --git a/README.md b/README.md index 93c6b3a913..21de8f622d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.13.0 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.13.1 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 667fcce2a4..8fd400844d 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -20,6 +20,7 @@ - [Day/Night System FAQ](tutorials/dns.md) - [Changelog](./CHANGELOG.md) - [1.13.x]() + - [Version 1.13.1](changelogs/1.13.x/1.13.1.md) - [Version 1.13.0](changelogs/1.13.x/1.13.0.md) - [1.12.x]() - [Version 1.12.3](changelogs/1.12.x/1.12.3.md) diff --git a/docs/changelogs/1.13.x/1.13.1.md b/docs/changelogs/1.13.x/1.13.1.md new file mode 100644 index 0000000000..97b33e931d --- /dev/null +++ b/docs/changelogs/1.13.x/1.13.1.md @@ -0,0 +1,44 @@ +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.13.1 +`. +``` + + +## 🧬 General 🧬 +### Fixed +* Added sortType to Douse Drive by @fdeblasio in [#7664](https://github.com/rh-hideout/pokeemerald-expansion/pull/7664) + +## 🐉 Pokémon 🐉 +### Fixed +* Fixed disabled cross-evolutions still being possible by @AsparagusEduardo in [#7678](https://github.com/rh-hideout/pokeemerald-expansion/pull/7678) + +## ⚔️ Battle General ⚔️ +### Changed +* Replace boolean multiplications with ternaries by @hedara90 in [#7653](https://github.com/rh-hideout/pokeemerald-expansion/pull/7653) + +## 🤖 Battle AI 🤖 +### Fixed +* Helping Hand bugfix; used FOE instead of BATTLE_OPPOSITE. by @surskitty in [#7659](https://github.com/rh-hideout/pokeemerald-expansion/pull/7659) + +## 🧹 Other Cleanup 🧹 +* Replace boolean multiplications with ternaries by @hedara90 in [#7653](https://github.com/rh-hideout/pokeemerald-expansion/pull/7653) +* Fix Rage Fist test name by @AlexOn1ine in [#7681](https://github.com/rh-hideout/pokeemerald-expansion/pull/7681) + +## 🧪 Test Runner 🧪 +### Changed +* Fix Rage Fist test name by @AlexOn1ine in [#7681](https://github.com/rh-hideout/pokeemerald-expansion/pull/7681) + +### Fixed +* Fix crashing tests duplicating tests from another thread by @hedara90 in [#7683](https://github.com/rh-hideout/pokeemerald-expansion/pull/7683) + +## 📚 Documentation 📚 +* Update README.md by @Bassoonian in [#7639](https://github.com/rh-hideout/pokeemerald-expansion/pull/7639) + + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.13.0...expansion/1.13.1 + + + + diff --git a/include/constants/expansion.h b/include/constants/expansion.h index e4468a82b4..27845d8e5e 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,13 +1,13 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.13.0 +// Last version: 1.13.1 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 13 #define EXPANSION_VERSION_PATCH 1 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE FALSE +#define EXPANSION_TAGGED_RELEASE TRUE #endif From 601f8887f954d9aa8218afc930c900788384b5ed Mon Sep 17 00:00:00 2001 From: Ruby Date: Thu, 4 Sep 2025 03:53:45 +0800 Subject: [PATCH 280/283] added a list of mons that the player has access to --- list of mons.txt | 632 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 632 insertions(+) create mode 100644 list of mons.txt diff --git a/list of mons.txt b/list of mons.txt new file mode 100644 index 0000000000..817bdb889c --- /dev/null +++ b/list of mons.txt @@ -0,0 +1,632 @@ +== GEN ONE == +{{lop/base|0003|Venusaur|80|82|83|100|100|80}} +{{lop/base|0006|Charizard|78|84|78|109|85|100}} +{{lop/base|0009|Blastoise|79|83|100|85|105|78}} +{{lop/base|0012|Butterfree|60|45|50|90|80|70}} +{{lop/base|0015|Beedrill|65|90|40|45|80|75}} +{{lop/base|0018|Pidgeot|83|80|75|70|70|101}} +{{lop/base|0020|Raticate|55|81|60|50|70|97}} +{{lop/base|0020|form=-Alola|Raticate|75|71|70|40|80|77|Alolan Raticate}} +{{lop/base|0022|Fearow|65|90|65|61|61|100}} +{{lop/base|0024|Arbok|60|95|69|65|79|80}} +{{lop/base|0025|form=-Partner|Pikachu|45|80|50|75|60|120|Partner Pikachu}} //the one with a cap +{{lop/base|0026|Raichu|60|90|55|90|80|110}} +{{lop/base|0026|form=-Alola|Raichu|60|85|50|95|85|110|Alolan Raichu}} +{{lop/base|0028|Sandslash|75|100|110|45|55|65}} +{{lop/base|0028|form=-Alola|Sandslash|75|100|120|25|65|65|Alolan Sandslash}} +{{lop/base|0031|Nidoqueen|90|92|87|75|85|76}} +{{lop/base|0034|Nidoking|81|102|77|85|75|85}} +{{lop/base|0036|Clefable|95|70|73|95|90|60}} +{{lop/base|0038|Ninetales|73|76|75|81|100|100}} +{{lop/base|0038|form=-Alola|Ninetales|73|67|75|81|100|109|Alolan Ninetales}} +{{lop/base|0040|Wigglytuff|140|70|45|85|50|45}} +{{lop/base|0045|Vileplume|75|80|85|110|90|50}} +{{lop/base|0047|Parasect|60|95|80|60|80|30}} +{{lop/base|0049|Venomoth|70|65|60|90|75|90}} +{{lop/base|0051|Dugtrio|35|100|50|50|70|120}} +{{lop/base|0051|form=-Alola|Dugtrio|35|100|60|50|70|110|Alolan Dugtrio}} +{{lop/base|0053|Persian|65|70|60|65|65|115}} +{{lop/base|0053|form=-Alola|Persian|65|60|60|75|65|115|Alolan Persian}} +{{lop/base|0055|Golduck|80|82|78|95|80|85}} +{{lop/base|0059|Arcanine|90|110|80|100|80|95}} +{{lop/base|0059|form=-Hisui|Arcanine|95|115|80|95|80|90|Hisuian Arcanine}} +{{lop/base|0062|Poliwrath|90|95|95|70|90|70}} +{{lop/base|0065|Alakazam|55|50|45|135|95|120}} +{{lop/base|0068|Machamp|90|130|80|65|85|55}} +{{lop/base|0071|Victreebel|80|105|65|100|70|70}} +{{lop/base|0073|Tentacruel|80|70|65|80|120|100}} +{{lop/base|0076|Golem|80|120|130|55|65|45}} +{{lop/base|0076|form=-Alola|Golem|80|120|130|55|65|45|Alolan Golem}} +{{lop/base|0078|Rapidash|65|100|70|80|80|105}} +{{lop/base|0078|form=-Galar|Rapidash|65|100|70|80|80|105|Galarian Rapidash}} +{{lop/base|0080|Slowbro|95|75|110|100|80|30}} +{{lop/base|0080|form=-Galar|Slowbro|95|100|95|100|70|30|Galarian Slowbro}} +{{lop/base|0083|Farfetch'd|52|90|55|58|62|60}} +{{lop/base|0085|Dodrio|60|110|70|60|60|110}} +{{lop/base|0087|Dewgong|90|70|80|70|95|70}} +{{lop/base|0089|Muk|105|105|75|65|100|50}} +{{lop/base|0089|form=-Alola|Muk|105|105|75|65|100|50|Alolan Muk}} +{{lop/base|0091|Cloyster|50|95|180|85|45|70}} +{{lop/base|0094|Gengar|60|65|60|130|75|110}} +{{lop/base|0097|Hypno|85|73|70|73|115|67}} +{{lop/base|0099|Kingler|55|130|115|50|50|75}} +{{lop/base|0101|Electrode|60|50|70|80|80|150}} +{{lop/base|0101|form=-Hisui|Electrode|60|50|70|80|80|150|Hisuian Electrode}} +{{lop/base|0103|Exeggutor|95|95|85|125|75|55}} +{{lop/base|0103|form=-Alola|Exeggutor|95|105|85|125|75|45|Alolan Exeggutor}} +{{lop/base|0105|Marowak|60|80|110|50|80|45}} +{{lop/base|0105|form=-Alola|Marowak|60|80|110|50|80|45|Alolan Marowak}} +{{lop/base|0106|Hitmonlee|50|120|53|35|110|87}} +{{lop/base|0107|Hitmonchan|50|105|79|35|110|76}} +{{lop/base|0110|Weezing|65|90|120|85|70|60}} +{{lop/base|0110|form=-Galar|Weezing|65|90|120|85|70|60|Galarian Weezing}} +{{lop/base|0115|Kangaskhan|105|95|80|40|80|90}} +{{lop/base|0119|Seaking|80|92|65|65|80|68}} +{{lop/base|0121|Starmie|60|75|85|100|85|115}} +{{lop/base|0122|Mr. Mime|40|45|65|100|120|90}} +{{lop/base|0124|Jynx|65|50|35|115|95|95}} +{{lop/base|0127|Pinsir|65|125|100|55|70|85}} +{{lop/base|0128|Tauros|75|100|95|40|70|110}} +{{lop/base|0128|form=-Paldea_Combat|Tauros|75|110|105|30|70|100|Paldean Tauros
(Combat Breed)}} +{{lop/base|0128|form=-Paldea_Blaze|Tauros|75|110|105|30|70|100|Paldean Tauros
(Blaze Breed)}} +{{lop/base|0128|form=-Paldea_Aqua|Tauros|75|110|105|30|70|100|Paldean Tauros
(Aqua Breed)}} +{{lop/base|0130|Gyarados|95|125|79|60|100|81}} +{{lop/base|0131|Lapras|130|85|80|85|95|60}} +{{lop/base|0132|Ditto|48|48|48|48|48|48}} +{{lop/base|0134|Vaporeon|130|65|60|110|95|65}} +{{lop/base|0135|Jolteon|65|65|60|110|95|130}} +{{lop/base|0136|Flareon|65|130|60|95|110|65}} +{{lop/base|0139|Omastar|70|60|125|115|70|55}} +{{lop/base|0141|Kabutops|60|115|105|65|70|80}} +{{lop/base|0142|Aerodactyl|80|105|65|60|75|130}} +{{lop/base|0143|Snorlax|160|110|65|65|110|30}} +{{lop/base|0144|Articuno|90|85|100|95|125|85}} +{{lop/base|0144|form=-Galar|Articuno|90|85|85|125|100|95|Galarian Articuno}} +{{lop/base|0145|Zapdos|90|90|85|125|90|100}} +{{lop/base|0145|form=-Galar|Zapdos|90|125|90|85|90|100|Galarian Zapdos}} +{{lop/base|0146|Moltres|90|100|90|125|85|90}} +{{lop/base|0146|form=-Galar|Moltres|90|85|90|100|125|90|Galarian Moltres}} +{{lop/base|0149|Dragonite|91|134|95|100|100|80}} +{{lop/base|0150|Mewtwo|106|110|90|154|90|130}} +{{lop/base|0151|Mew|100|100|100|100|100|100}} + +== GEN TWO == +{{lop/base|0154|Meganium|80|82|100|83|100|80}} +{{lop/base|0157|Typhlosion|78|84|78|109|85|100}} +{{lop/base|0157|form=-Hisui|Typhlosion|73|84|78|119|85|95|Hisuian Typhlosion}} +{{lop/base|0160|Feraligatr|85|105|100|79|83|78}} +{{lop/base|0162|Furret|85|76|64|45|55|90}} +{{lop/base|0164|Noctowl|100|50|50|86|96|70}} +{{lop/base|0166|Ledian|55|35|50|55|110|85}} +{{lop/base|0168|Ariados|70|90|70|60|70|40}} +{{lop/base|0169|Crobat|85|90|80|70|80|130}} +{{lop/base|0171|Lanturn|125|58|58|76|76|67}} +{{lop/base|0178|Xatu|65|75|70|95|70|95}} +{{lop/base|0181|Ampharos|90|75|85|115|90|55}} +{{lop/base|0182|Bellossom|75|80|95|90|100|50}} +{{lop/base|0184|Azumarill|100|50|80|60|80|50}} +{{lop/base|0185|Sudowoodo|70|100|115|30|65|30}} +{{lop/base|0186|Politoed|90|75|75|90|100|70}} +{{lop/base|0189|Jumpluff|75|55|70|55|95|110}} +{{lop/base|0192|Sunflora|75|75|55|105|85|30}} +{{lop/base|0195|Quagsire|95|85|85|65|65|35}} +{{lop/base|0196|Espeon|65|65|60|130|95|110}} +{{lop/base|0197|Umbreon|95|65|110|60|130|65}} +{{lop/base|0199|Slowking|95|75|80|100|110|30}} +{{lop/base|0199|form=-Galar|Slowking|95|65|80|110|110|30|Galarian Slowking}} +{{lop/base|0201|Unown|48|72|48|72|48|48}} +{{lop/base|0202|Wobbuffet|190|33|58|33|58|33}} +{{lop/base|0205|Forretress|75|90|140|60|60|40}} +{{lop/base|0208|Steelix|75|85|200|55|65|30}} +{{lop/base|0210|Granbull|90|120|75|60|60|45}} +{{lop/base|0211|Qwilfish|65|95|85|55|55|85}} +{{lop/base|0212|Scizor|70|130|100|55|80|65}} +{{lop/base|0213|Shuckle|20|10|230|10|230|5}} +{{lop/base|0214|Heracross|80|125|75|40|95|85}} +{{lop/base|0219|Magcargo|60|50|120|90|80|30}} +{{lop/base|0222|Corsola|65|55|95|65|95|35}} +{{lop/base|0224|Octillery|75|105|75|105|75|45}} +{{lop/base|0225|Delibird|45|55|45|65|45|75}} +{{lop/base|0226|Mantine|85|40|70|80|140|70}} +{{lop/base|0227|Skarmory|65|80|140|40|70|70}} +{{lop/base|0229|Houndoom|75|90|50|110|80|95}} +{{lop/base|0230|Kingdra|75|95|95|95|95|85}} +{{lop/base|0232|Donphan|90|120|120|60|60|50}} +{{lop/base|0235|Smeargle|55|20|35|20|45|75}} +{{lop/base|0237|Hitmontop|50|95|95|35|110|70}} +{{lop/base|0241|Miltank|95|80|105|40|70|100}} +{{lop/base|0242|Blissey|255|10|10|75|135|55}} +{{lop/base|0243|Raikou|90|85|75|115|100|115}} +{{lop/base|0244|Entei|115|115|85|90|75|100}} +{{lop/base|0245|Suicune|100|75|115|90|115|85}} +{{lop/base|0248|Tyranitar|100|134|110|95|100|61}} +{{lop/base|0249|Lugia|106|90|130|90|154|110}} +{{lop/base|0250|Ho-Oh|106|130|90|110|154|90}} +{{lop/base|0251|Celebi|100|100|100|100|100|100}} + +== GEN THREE == +{{lop/base|0254|Sceptile|70|85|65|105|85|120}} +{{lop/base|0257|Blaziken|80|120|70|110|70|80}} +{{lop/base|0260|Swampert|100|110|90|85|90|60}} +{{lop/base|0262|Mightyena|70|90|70|60|60|70}} +{{lop/base|0264|Linoone|78|70|61|50|61|100}} +{{lop/base|0267|Beautifly|60|70|50|100|50|65}} +{{lop/base|0269|Dustox|60|50|70|50|90|65}} +{{lop/base|0272|Ludicolo|80|70|70|90|100|70}} +{{lop/base|0275|Shiftry|90|100|60|90|60|80}} +{{lop/base|0277|Swellow|60|85|60|75|50|125}} +{{lop/base|0279|Pelipper|60|50|100|95|70|65}} +{{lop/base|0282|Gardevoir|68|65|65|125|115|80}} +{{lop/base|0284|Masquerain|70|60|62|100|82|80}} +{{lop/base|0286|Breloom|60|130|80|60|60|70}} +{{lop/base|0289|Slaking|150|160|100|95|65|100}} +{{lop/base|0291|Ninjask|61|90|45|50|50|160}} +{{lop/base|0292|Shedinja|1|90|45|30|30|40}} +{{lop/base|0295|Exploud|104|91|63|91|73|68}} +{{lop/base|0297|Hariyama|144|120|60|40|60|50}} +{{lop/base|0301|Delcatty|70|65|65|55|55|90}} +{{lop/base|0302|Sableye|50|75|75|65|65|50}} +{{lop/base|0303|Mawile|50|85|85|55|55|50}} +{{lop/base|0306|Aggron|70|110|180|60|60|50}} +{{lop/base|0308|Medicham|60|60|75|60|75|80}} +{{lop/base|0310|Manectric|70|75|60|105|60|105}} +{{lop/base|0311|Plusle|60|50|40|85|75|95}} +{{lop/base|0312|Minun|60|40|50|75|85|95}} +{{lop/base|0313|Volbeat|65|73|75|47|85|85}} +{{lop/base|0314|Illumise|65|47|75|73|85|85}} +{{lop/base|0317|Swalot|100|73|83|73|83|55}} +{{lop/base|0319|Sharpedo|70|120|40|95|40|95}} +{{lop/base|0321|Wailord|170|90|45|90|45|60}} +{{lop/base|0323|Camerupt|70|100|70|105|75|40}} +{{lop/base|0324|Torkoal|70|85|140|85|70|20}} +{{lop/base|0326|Grumpig|80|45|65|90|110|80}} +{{lop/base|0327|Spinda|60|60|60|60|60|60}} +{{lop/base|0330|Flygon|80|100|80|80|80|100}} +{{lop/base|0332|Cacturne|70|115|60|115|60|55}} +{{lop/base|0334|Altaria|75|70|90|70|105|80}} +{{lop/base|0335|Zangoose|73|115|60|60|60|90}} +{{lop/base|0336|Seviper|73|100|60|100|60|65}} +{{lop/base|0337|Lunatone|90|55|65|95|85|70}} +{{lop/base|0338|Solrock|90|95|85|55|65|70}} +{{lop/base|0340|Whiscash|110|78|73|76|71|60}} +{{lop/base|0342|Crawdaunt|63|120|85|90|55|55}} +{{lop/base|0344|Claydol|60|70|105|70|120|75}} +{{lop/base|0346|Cradily|86|81|97|81|107|43}} +{{lop/base|0348|Armaldo|75|125|100|70|80|45}} +{{lop/base|0350|Milotic|95|60|79|100|125|81}} +{{lop/base|0351|Castform|70|70|70|70|70|70}} +{{lop/base|0352|Kecleon|60|90|70|60|120|40}} +{{lop/base|0354|Banette|64|115|65|83|63|65}} +{{lop/base|0357|Tropius|99|68|83|72|87|51}} +{{lop/base|0358|Chimecho|75|50|80|95|90|65}} +{{lop/base|0359|Absol|65|130|60|75|60|75}} +{{lop/base|0362|Glalie|80|80|80|80|80|80}} +{{lop/base|0365|Walrein|110|80|90|95|90|65}} +{{lop/base|0367|Huntail|55|104|105|94|75|52}} +{{lop/base|0368|Gorebyss|55|84|105|114|75|52}} +{{lop/base|0369|Relicanth|100|90|130|45|65|55}} +{{lop/base|0370|Luvdisc|43|30|55|40|65|97}} +{{lop/base|0373|Salamence|95|135|80|110|80|100}} +{{lop/base|0376|Metagross|80|135|130|95|90|70}} +{{lop/base|0377|Regirock|80|100|200|50|100|50}} +{{lop/base|0378|Regice|80|50|100|100|200|50}} +{{lop/base|0379|Registeel|80|75|150|75|150|50}} +{{lop/base|0380|Latias|80|80|90|110|130|110}} +{{lop/base|0381|Latios|80|90|80|130|110|110}} +{{lop/base|0382|Kyogre|100|100|90|150|140|90}} +{{lop/base|0383|Groudon|100|150|140|100|90|90}} +{{lop/base|0384|Rayquaza|105|150|90|150|90|95}} +{{lop/base|0385|Jirachi|100|100|100|100|100|100}} +{{lop/base|0386|Deoxys|50|150|50|150|50|150|Normal Forme}} +{{lop/base|0389|Torterra|95|109|105|75|85|56}} + +== GEN FOUR == +{{lop/base|0392|Infernape|76|104|71|104|71|108}} +{{lop/base|0395|Empoleon|84|86|88|111|101|60}} +{{lop/base|0398|Staraptor|85|120|70|50|60|100}} +{{lop/base|0400|Bibarel|79|85|60|55|60|71}} +{{lop/base|0402|Kricketune|77|85|51|55|51|65}} +{{lop/base|0405|Luxray|80|120|79|95|79|70}} +{{lop/base|0407|Roserade|60|70|65|125|105|90}} +{{lop/base|0409|Rampardos|97|165|60|65|50|58}} +{{lop/base|0411|Bastiodon|60|52|168|47|138|30}} +{{lop/base|0413|form=-Plant|Wormadam|60|59|85|79|105|36|Plant Cloak}} +{{lop/base|0413|form=-Sandy|Wormadam|60|79|105|59|85|36|Sandy Cloak}} +{{lop/base|0413|form=-Trash|Wormadam|60|69|95|69|95|36|Trash Cloak}} +{{lop/base|0414|Mothim|70|94|50|94|50|66}} +{{lop/base|0416|Vespiquen|70|80|102|80|102|40}} +{{lop/base|0417|Pachirisu|60|45|70|45|90|95}} +{{lop/base|0419|Floatzel|85|105|55|85|50|115}} +{{lop/base|0421|Cherrim|70|60|70|87|78|85}} +{{lop/base|0423|Gastrodon|111|83|68|92|82|39}} +{{lop/base|0424|Ambipom|75|100|66|60|66|115}} +{{lop/base|0426|Drifblim|150|80|44|90|54|80}} +{{lop/base|0428|Lopunny|65|76|84|54|96|105}} +{{lop/base|0429|Mismagius|60|60|60|105|105|105}} +{{lop/base|0430|Honchkrow|100|125|52|105|52|71}} +{{lop/base|0432|Purugly|71|82|64|64|59|112}} +{{lop/base|0435|Skuntank|103|93|67|71|61|84}} +{{lop/base|0437|Bronzong|67|89|116|79|116|33}} +{{lop/base|0441|Chatot|76|65|45|92|42|91}} +{{lop/base|0442|Spiritomb|50|92|108|92|108|35}} +{{lop/base|0445|Garchomp|108|130|95|80|85|102}} +{{lop/base|0448|Lucario|70|110|70|115|70|90}} +{{lop/base|0450|Hippowdon|108|112|118|68|72|47}} +{{lop/base|0452|Drapion|70|90|110|60|75|95}} +{{lop/base|0454|Toxicroak|83|106|65|86|65|85}} +{{lop/base|0455|Carnivine|74|100|72|90|72|46}} +{{lop/base|0457|Lumineon|69|69|76|69|86|91}} +{{lop/base|0460|Abomasnow|90|92|75|92|85|60}} +{{lop/base|0461|Weavile|70|120|65|45|85|125}} +{{lop/base|0462|Magnezone|70|70|115|130|90|60}} +{{lop/base|0463|Lickilicky|110|85|95|80|95|50}} +{{lop/base|0464|Rhyperior|115|140|130|55|55|40}} +{{lop/base|0465|Tangrowth|100|100|125|110|50|50}} +{{lop/base|0466|Electivire|75|123|67|95|85|95}} +{{lop/base|0467|Magmortar|75|95|67|125|95|83}} +{{lop/base|0468|Togekiss|85|50|95|120|115|80}} +{{lop/base|0469|Yanmega|86|76|86|116|56|95}} +{{lop/base|0470|Leafeon|65|110|130|60|65|95}} +{{lop/base|0471|Glaceon|65|60|110|130|95|65}} +{{lop/base|0472|Gliscor|75|95|125|45|75|95}} +{{lop/base|0473|Mamoswine|110|130|80|70|60|80}} +{{lop/base|0474|Porygon-Z|85|80|70|135|75|90}} +{{lop/base|0475|Gallade|68|125|65|65|115|80}} +{{lop/base|0476|Probopass|60|55|145|75|150|40}} +{{lop/base|0477|Dusknoir|45|100|135|65|135|45}} +{{lop/base|0478|Froslass|70|80|70|80|70|110}} +{{lop/base|0479|Rotom|50|50|77|95|77|91}} +{{lop/base|0480|Uxie|75|75|130|75|130|95}} +{{lop/base|0481|Mesprit|80|105|105|105|105|80}} +{{lop/base|0482|Azelf|75|125|70|125|70|115}} +{{lop/base|0483|Dialga|100|120|120|150|100|90}} +{{lop/base|0484|Palkia|90|120|100|150|120|100}} +{{lop/base|0485|Heatran|91|90|106|130|106|77}} +{{lop/base|0486|Regigigas|110|160|110|80|110|100}} +{{lop/base|0487|Giratina|150|100|120|100|120|90|Altered Forme}} +{{lop/base|0488|Cresselia|120|70|110|75|120|85}} +{{lop/base|0489|Phione|80|80|80|80|80|80}} +{{lop/base|0490|Manaphy|100|100|100|100|100|100}} +{{lop/base|0491|Darkrai|70|90|90|135|90|125}} +{{lop/base|0492|Shaymin|100|100|100|100|100|100|Land Forme}} +{{lop/base|0492|form=-Sky|Shaymin|100|103|75|120|75|127|Sky Forme}} +{{lop/base|0493|Arceus|120|120|120|120|120|120}} + +== GEN FIVE == +{{lop/base|0494|Victini|100|100|100|100|100|100}} +{{lop/base|0497|Serperior|75|75|95|75|95|113}} +{{lop/base|0500|Emboar|110|123|65|100|65|65}} +{{lop/base|0503|Samurott|95|100|85|108|70|70}} +{{lop/base|0503|form=-Hisui|Samurott|90|108|80|100|65|85|Hisuian Samurott}} +{{lop/base|0505|Watchog|60|85|69|60|69|77}} +{{lop/base|0508|Stoutland|85|110|90|45|90|80}} +{{lop/base|0510|Liepard|64|88|50|88|50|106}} +{{lop/base|0512|Simisage|75|98|63|98|63|101}} +{{lop/base|0514|Simisear|75|98|63|98|63|101}} +{{lop/base|0516|Simipour|75|98|63|98|63|101}} +{{lop/base|0518|Musharna|116|55|85|107|95|29}} +{{lop/base|0521|Unfezant|80|115|80|65|55|93}} +{{lop/base|0523|Zebstrika|75|100|63|80|63|116}} +{{lop/base|0526|Gigalith|85|135|130|60|80|25}} +{{lop/base|0528|Swoobat|67|57|55|77|55|114}} +{{lop/base|0530|Excadrill|110|135|60|50|65|88}} +{{lop/base|0531|Audino|103|60|86|60|86|50}} +{{lop/base|0534|Conkeldurr|105|140|95|55|65|45}} +{{lop/base|0537|Seismitoad|105|95|75|85|75|74}} +{{lop/base|0538|Throh|120|100|85|30|85|45}} +{{lop/base|0539|Sawk|75|125|75|30|75|85}} +{{lop/base|0542|Leavanny|75|103|80|70|80|92}} +{{lop/base|0545|Scolipede|60|100|89|55|69|112}} +{{lop/base|0547|Whimsicott|60|67|85|77|75|116}} +{{lop/base|0549|Lilligant|70|60|75|110|75|90}} +{{lop/base|0549|form=-Hisui|Lilligant|70|105|75|50|75|105|Hisuian Lilligant}} +{{lop/base|0550|Basculin|70|92|65|80|55|98}} +{{lop/base|0553|Krookodile|95|117|80|65|70|92}} +{{lop/base|0555|Darmanitan|105|140|55|30|55|95|Standard Mode}} +{{lop/base|0555|form=-Zen|Darmanitan|105|30|105|140|105|55|Zen Mode}} +{{lop/base|0555|form=-Galar|Darmanitan|105|140|55|30|55|95|Galarian Standard Mode}} +{{lop/base|0555|form=-Galar-Zen|Darmanitan|105|160|55|30|55|135|Galarian Zen Mode}} +{{lop/base|0556|Maractus|75|86|67|106|67|60}} +{{lop/base|0558|Crustle|70|105|125|65|75|45}} +{{lop/base|0560|Scrafty|65|90|115|45|115|58}} +{{lop/base|0561|Sigilyph|72|58|80|103|80|97}} +{{lop/base|0563|Cofagrigus|58|50|145|95|105|30}} +{{lop/base|0565|Carracosta|74|108|133|83|65|32}} +{{lop/base|0567|Archeops|75|140|65|112|65|110}} +{{lop/base|0569|Garbodor|80|95|82|60|82|75}} +{{lop/base|0571|Zoroark|60|105|60|120|60|105}} +{{lop/base|0571|form=-Hisui|Zoroark|55|100|60|125|60|110|Hisuian Zoroark}} +{{lop/base|0573|Cinccino|75|95|60|65|60|115}} +{{lop/base|0576|Gothitelle|70|55|95|95|110|65}} +{{lop/base|0579|Reuniclus|110|65|75|125|85|30}} +{{lop/base|0581|Swanna|75|87|63|87|63|98}} +{{lop/base|0584|Vanilluxe|71|95|85|110|95|79}} +{{lop/base|0586|Sawsbuck|80|100|70|60|70|95}} +{{lop/base|0587|Emolga|55|75|60|75|60|103}} +{{lop/base|0589|Escavalier|70|135|105|60|105|20}} +{{lop/base|0591|Amoonguss|114|85|70|85|80|30}} +{{lop/base|0593|Jellicent|100|60|70|85|105|60}} +{{lop/base|0594|Alomomola|165|75|80|40|45|65}} +{{lop/base|0596|Galvantula|70|77|60|97|60|108}} +{{lop/base|0598|Ferrothorn|74|94|131|54|116|20}} +{{lop/base|0601|Klinklang|60|100|115|70|85|90}} +{{lop/base|0604|Eelektross|85|115|80|105|80|50}} +{{lop/base|0606|Beheeyem|75|75|75|125|95|40}} +{{lop/base|0609|Chandelure|60|55|90|145|90|80}} +{{lop/base|0612|Haxorus|76|147|90|60|70|97}} +{{lop/base|0614|Beartic|95|130|80|70|80|50}} +{{lop/base|0615|Cryogonal|80|50|50|95|135|105}} +{{lop/base|0617|Accelgor|80|70|40|100|60|145}} +{{lop/base|0618|Stunfisk|109|66|84|81|99|32}} +{{lop/base|0618|form=-Galar|Stunfisk|109|81|99|66|84|32|Galarian Stunfisk}} +{{lop/base|0620|Mienshao|65|125|60|95|60|105}} +{{lop/base|0621|Druddigon|77|120|90|60|90|48}} +{{lop/base|0623|Golurk|89|124|80|55|80|55}} +{{lop/base|0626|Bouffalant|95|110|95|40|95|55}} +{{lop/base|0628|Braviary|100|123|75|57|75|80}} +{{lop/base|0628|form=-Hisui|Braviary|110|83|70|112|70|65|Hisuian Braviary}} +{{lop/base|0630|Mandibuzz|110|65|105|55|95|80}} +{{lop/base|0631|Heatmor|85|97|66|105|66|65}} +{{lop/base|0632|Durant|58|109|112|48|48|109}} +{{lop/base|0635|Hydreigon|92|105|90|125|90|98}} +{{lop/base|0637|Volcarona|85|60|65|135|105|100}} +{{lop/base|0638|Cobalion|91|90|129|90|72|108}} +{{lop/base|0639|Terrakion|91|129|90|72|90|108}} +{{lop/base|0640|Virizion|91|90|72|90|129|108}} +{{lop/base|0641|Tornadus|79|115|70|125|80|111|Incarnate Forme}} +{{lop/base|0642|Thundurus|79|115|70|125|80|111|Incarnate Forme}} +{{lop/base|0643|Reshiram|100|120|100|150|120|90}} +{{lop/base|0644|Zekrom|100|150|120|120|100|90}} +{{lop/base|0645|Landorus|89|125|90|115|80|101|Incarnate Forme}} +{{lop/base|0646|Kyurem|125|130|90|130|90|95}} +{{lop/base|0647|Keldeo|91|72|90|129|90|108}} +{{lop/base|0648|Meloetta|100|77|77|128|128|90|Aria Forme}} +{{lop/base|0649|Genesect|71|120|95|120|95|99}} +{{lop/base|0652|Chesnaught|88|107|122|74|75|64}} +{{lop/base|0655|Delphox|75|69|72|114|100|104}} +{{lop/base|0658|Greninja|72|95|67|103|71|122}} +{{lop/base|0660|Diggersby|85|56|77|50|77|78}} +{{lop/base|0663|Talonflame|78|81|71|74|69|126}} +{{lop/base|0666|Vivillon|80|52|50|90|50|89}} +{{lop/base|0668|Pyroar|86|68|72|109|66|106}} +{{lop/base|0671|Florges|78|65|68|112|154|75}} +{{lop/base|0673|Gogoat|123|100|62|97|81|68}} +{{lop/base|0675|Pangoro|95|124|78|69|71|58}} +{{lop/base|0676|Furfrou|75|80|60|65|90|102}} +{{lop/base|0678|Meowstic|74|48|76|83|81|104}} +{{lop/base|0681|form=-Shield|Aegislash|60|50|140|50|140|60|Shield Forme}} +{{lop/base|0683|Aromatisse|101|72|72|99|89|29}} +{{lop/base|0685|Slurpuff|82|80|86|85|75|72}} +{{lop/base|0687|Malamar|86|92|88|68|75|73}} +{{lop/base|0689|Barbaracle|72|105|115|54|86|68}} +{{lop/base|0691|Dragalge|65|75|90|97|123|44}} +{{lop/base|0693|Clawitzer|71|73|88|120|89|59}} +{{lop/base|0695|Heliolisk|62|55|52|109|94|109}} +{{lop/base|0697|Tyrantrum|82|121|119|69|59|71}} +{{lop/base|0699|Aurorus|123|77|72|99|92|58}} +{{lop/base|0700|Sylveon|95|65|65|110|130|60}} +{{lop/base|0701|Hawlucha|78|92|75|74|63|118}} +{{lop/base|0702|Dedenne|67|58|57|81|67|101}} +{{lop/base|0703|Carbink|50|50|150|50|150|50}} +{{lop/base|0706|Goodra|90|100|70|110|150|80}} +{{lop/base|0706|form=-Hisui|Goodra|80|100|100|110|150|60|Hisuian Goodra}} +{{lop/base|0707|Klefki|57|80|91|80|87|75}} +{{lop/base|0709|Trevenant|85|110|76|65|82|56}} +{{lop/base|0711|Gourgeist|55|85|122|58|75|99|Small Size}} +{{lop/base|0711|Gourgeist|65|90|122|58|75|84|Average Size}} +{{lop/base|0711|Gourgeist|75|95|122|58|75|69|Large Size}} +{{lop/base|0711|Gourgeist|85|100|122|58|75|54|Super Size}} +{{lop/base|0713|Avalugg|95|117|184|44|46|28}} +{{lop/base|0713|form=-Hisui|Avalugg|95|127|184|34|36|38|Hisuian Avalugg}} +{{lop/base|0715|Noivern|85|70|80|97|80|123}} +{{lop/base|0716|Xerneas|126|131|95|131|98|99}} +{{lop/base|0717|Yveltal|126|131|95|131|98|99}} +{{lop/base|0718|Zygarde|108|100|121|81|95|95|50% Forme}} +{{lop/base|0719|Diancie|50|100|150|100|150|50}} +{{lop/base|0720|Hoopa|80|110|60|150|130|70|Hoopa Confined}} +{{lop/base|0721|Volcanion|80|110|120|130|90|70}} +{{lop/base|0724|Decidueye|78|107|75|100|100|70}} +{{lop/base|0724|form=-Hisui|Decidueye|88|112|80|95|95|60|Hisuian Decidueye}} +{{lop/base|0727|Incineroar|95|115|90|80|90|60}} +{{lop/base|0730|Primarina|80|74|74|126|116|60}} +{{lop/base|0733|Toucannon|80|120|75|75|75|60}} +{{lop/base|0735|Gumshoos|88|110|60|55|60|45}} +{{lop/base|0738|Vikavolt|77|70|90|145|75|43}} +{{lop/base|0740|Crabominable|97|132|77|62|67|43}} +{{lop/base|0741|Oricorio|75|70|70|98|70|93}} +{{lop/base|0743|Ribombee|60|55|60|95|70|124}} +{{lop/base|0745|Lycanroc|75|115|65|55|65|112|Midday Form}} +{{lop/base|0745|form=-Midnight|Lycanroc|85|115|75|55|75|82|Midnight Form}} +{{lop/base|0745|form=-Dusk|Lycanroc|75|117|65|55|65|110|Dusk Form}} +{{lop/base|0746|Wishiwashi|45|20|20|25|25|40|Solo Form}} +{{lop/base|0748|Toxapex|50|63|152|53|142|35}} +{{lop/base|0750|Mudsdale|100|125|100|55|85|35}} +{{lop/base|0752|Araquanid|68|70|92|50|132|42}} +{{lop/base|0754|Lurantis|70|105|90|80|90|45}} +{{lop/base|0756|Shiinotic|60|45|80|90|100|30}} +{{lop/base|0758|Salazzle|68|64|60|111|60|117}} +{{lop/base|0760|Bewear|120|125|80|55|60|60}} +{{lop/base|0763|Tsareena|72|120|98|50|98|72}} +{{lop/base|0764|Comfey|51|52|90|82|110|100}} +{{lop/base|0765|Oranguru|90|60|80|90|110|60}} +{{lop/base|0766|Passimian|100|120|90|40|60|80}} +{{lop/base|0768|Golisopod|75|125|140|60|90|40}} +{{lop/base|0770|Palossand|85|75|110|100|75|35}} +{{lop/base|0771|Pyukumuku|55|60|130|30|130|5}} +{{lop/base|0773|Silvally|95|95|95|95|95|95}} +{{lop/base|0774|Minior|60|60|100|60|100|60|Meteor Form}} +{{lop/base|0775|Komala|65|115|65|75|95|65}} +{{lop/base|0776|Turtonator|60|78|135|91|85|36}} +{{lop/base|0777|Togedemaru|65|98|63|40|73|96}} +{{lop/base|0778|Mimikyu|55|90|80|50|105|96}} +{{lop/base|0779|Bruxish|68|105|70|70|70|92}} +{{lop/base|0780|Drampa|78|60|85|135|91|36}} +{{lop/base|0781|Dhelmise|70|131|100|86|90|40}} +{{lop/base|0784|Kommo-o|75|110|125|100|105|85}} +{{lop/base|0785|Tapu Koko|70|115|85|95|75|130}} +{{lop/base|0786|Tapu Lele|70|85|75|130|115|95}} +{{lop/base|0787|Tapu Bulu|70|130|115|85|95|75}} +{{lop/base|0788|Tapu Fini|70|75|115|95|130|85}} +{{lop/base|0791|Solgaleo|137|137|107|113|89|97}} +{{lop/base|0792|Lunala|137|113|89|137|107|97}} +{{lop/base|0793|Nihilego|109|53|47|127|131|103}} +{{lop/base|0794|Buzzwole|107|139|139|53|53|79}} +{{lop/base|0795|Pheromosa|71|137|37|137|37|151}} +{{lop/base|0796|Xurkitree|83|89|71|173|71|83}} +{{lop/base|0797|Celesteela|97|101|103|107|101|61}} +{{lop/base|0798|Kartana|59|181|131|59|31|109}} +{{lop/base|0799|Guzzlord|223|101|53|97|53|43}} +{{lop/base|0800|Necrozma|97|107|101|127|89|79}} +{{lop/base|0801|Magearna|80|95|115|130|115|65}} +{{lop/base|0802|Marshadow|90|125|80|90|90|125}} +{{lop/base|0804|Naganadel|73|73|73|127|73|121}} +{{lop/base|0805|Stakataka|61|131|211|53|101|13}} +{{lop/base|0806|Blacephalon|53|127|53|151|79|107}} +{{lop/base|0807|Zeraora|88|112|75|102|80|143}} +{{lop/base|0809|Melmetal|135|143|143|80|65|34}} +{{lop/base|0812|Rillaboom|100|125|90|60|70|85}} +{{lop/base|0815|Cinderace|80|116|75|65|75|119}} +{{lop/base|0818|Inteleon|70|85|65|125|65|120}} +{{lop/base|0820|Greedent|120|95|95|55|75|20}} +{{lop/base|0823|Corviknight|98|87|105|53|85|67}} +{{lop/base|0826|Orbeetle|60|45|110|80|120|90}} +{{lop/base|0828|Thievul|70|58|58|87|92|90}} +{{lop/base|0830|Eldegoss|60|50|90|80|120|60}} +{{lop/base|0832|Dubwool|72|80|100|60|90|88}} +{{lop/base|0834|Drednaw|90|115|90|48|68|74}} +{{lop/base|0836|Boltund|69|90|60|90|60|121}} +{{lop/base|0839|Coalossal|110|80|120|80|90|30}} +{{lop/base|0841|Flapple|70|110|80|95|60|70}} +{{lop/base|0842|Appletun|110|85|80|100|80|30}} +{{lop/base|0844|Sandaconda|72|107|125|65|70|71}} +{{lop/base|0845|Cramorant|70|85|55|85|95|85}} +{{lop/base|0847|Barraskewda|61|123|60|60|50|136}} +{{lop/base|0849|Toxtricity|75|98|70|114|70|75}} +{{lop/base|0851|Centiskorch|100|115|65|90|90|65}} +{{lop/base|0853|Grapploct|80|118|90|70|80|42}} +{{lop/base|0855|Polteageist|60|65|65|134|114|70}} +{{lop/base|0858|Hatterene|57|90|95|136|103|29}} +{{lop/base|0861|Grimmsnarl|95|120|65|95|75|60}} +{{lop/base|0862|Obstagoon|93|90|101|60|81|95}} +{{lop/base|0863|Perrserker|70|110|100|50|60|50}} +{{lop/base|0864|Cursola|60|95|50|145|130|30}} +{{lop/base|0865|Sirfetch'd|62|135|95|68|82|65}} +{{lop/base|0866|Mr. Rime|80|85|75|110|100|70}} +{{lop/base|0867|Runerigus|58|95|145|50|105|30}} +{{lop/base|0869|Alcremie|65|60|75|110|121|64}} +{{lop/base|0870|Falinks|65|100|100|70|60|75}} +{{lop/base|0871|Pincurchin|48|101|95|91|85|15}} +{{lop/base|0873|Frosmoth|70|65|60|125|90|65}} +{{lop/base|0874|Stonjourner|100|125|135|20|20|70}} +{{lop/base|0875|Eiscue|75|80|110|65|90|50|Ice Face}} +{{lop/base|0876|form=-Male|Indeedee|60|65|55|105|95|95|Male}} +{{lop/base|0876|form=-Female|Indeedee|70|55|65|95|105|85|Female}} +{{lop/base|0877|Morpeko|58|95|58|70|58|97}} +{{lop/base|0879|Copperajah|122|130|69|80|69|30}} +{{lop/base|0880|Dracozolt|90|100|90|80|70|75}} +{{lop/base|0881|Arctozolt|90|100|90|90|80|55}} +{{lop/base|0882|Dracovish|90|90|100|70|80|75}} +{{lop/base|0883|Arctovish|90|90|100|80|90|55}} +{{lop/base|0887|Dragapult|88|120|75|100|75|142}} +{{lop/base|0888|Zacian|92|150|115|80|115|148|Crowned Sword}} +{{lop/base|0889|Zamazenta|92|120|140|80|140|128|Crowned Shield}} +{{lop/base|0890|Eternatus|140|85|95|145|95|130}} +{{lop/base|0892|Urshifu|100|130|100|63|60|97}} +{{lop/base|0893|Zarude|105|120|105|70|95|105}} +{{lop/base|0894|Regieleki|80|100|50|100|50|200}} +{{lop/base|0895|Regidrago|200|100|50|100|50|80}} +{{lop/base|0896|Glastrier|100|145|130|65|110|30}} +{{lop/base|0897|Spectrier|100|65|60|145|80|130}} +{{lop/base|0898|Calyrex|100|80|80|80|80|80}} +{{lop/base|0899|Wyrdeer|103|105|72|105|75|65}} +{{lop/base|0900|Kleavor|70|135|95|45|70|85}} +{{lop/base|0901|Ursaluna|130|140|105|45|80|50}} +{{lop/base|0901|form=-Bloodmoon|Ursaluna|113|70|120|135|65|52|Bloodmoon}} +{{lop/base|0902|form=-Male|Basculegion|120|112|65|80|75|78|Male}} +{{lop/base|0902|form=-Female|Basculegion|120|92|65|100|75|78|Female}} +{{lop/base|0903|Sneasler|80|130|60|40|80|120}} +{{lop/base|0904|Overqwil|85|115|95|65|65|85}} +{{lop/base|0905|Enamorus|74|115|70|135|80|106|Incarnate Forme}} +{{lop/base|0908|Meowscarada|76|110|70|81|70|123}} +{{lop/base|0911|Skeledirge|104|75|100|110|75|66}} +{{lop/base|0914|Quaquaval|85|120|80|85|75|85}} +{{lop/base|0916|form=-Male|Oinkologne|110|100|75|59|80|65|Male}} +{{lop/base|0916|form=-Female|Oinkologne|115|90|70|59|90|65|Female}} +{{lop/base|0918|Spidops|60|79|92|52|86|35}} +{{lop/base|0920|Lokix|71|102|78|52|55|92}} +{{lop/base|0923|Pawmot|70|115|70|70|60|105}} +{{lop/base|0925|Maushold|74|75|70|65|75|111}} +{{lop/base|0927|Dachsbun|57|80|115|50|80|95}} +{{lop/base|0930|Arboliva|78|69|90|125|109|39}} +{{lop/base|0931|Squawkabilly|82|96|51|45|51|92}} +{{lop/base|0934|Garganacl|100|100|130|45|90|35}} +{{lop/base|0936|Armarouge|85|60|100|125|80|75}} +{{lop/base|0937|Ceruledge|75|125|80|60|100|85}} +{{lop/base|0939|Bellibolt|109|64|91|103|83|45}} +{{lop/base|0941|Kilowattrel|70|70|60|105|60|125}} +{{lop/base|0943|Mabosstiff|80|120|90|60|70|85}} +{{lop/base|0945|Grafaiai|63|95|65|80|72|110}} +{{lop/base|0947|Brambleghast|55|115|70|80|70|90}} +{{lop/base|0949|Toedscruel|80|70|65|80|120|100}} +{{lop/base|0950|Klawf|70|100|115|35|55|75}} +{{lop/base|0952|Scovillain|65|108|65|108|65|75}} +{{lop/base|0954|Rabsca|75|50|85|115|100|45}} +{{lop/base|0956|Espathra|95|60|60|101|60|105}} +{{lop/base|0959|Tinkaton|85|75|77|70|105|94}} +{{lop/base|0961|Wugtrio|35|100|50|50|70|120}} +{{lop/base|0962|Bombirdier|70|103|85|60|85|82}} +{{lop/base|0964|Palafin|100|70|72|53|62|100|Zero Form}} +{{lop/base|0966|Revavroom|80|119|90|54|67|90}} +{{lop/base|0967|Cyclizar|70|95|65|85|65|121}} +{{lop/base|0968|Orthworm|70|85|145|60|55|65}} +{{lop/base|0970|Glimmora|83|55|90|130|81|86}} +{{lop/base|0972|Houndstone|72|101|100|50|97|68}} +{{lop/base|0973|Flamigo|82|115|74|75|64|90}} +{{lop/base|0975|Cetitan|170|113|65|45|55|73}} +{{lop/base|0976|Veluza|90|102|73|78|65|70}} +{{lop/base|0977|Dondozo|150|100|115|65|65|35}} +{{lop/base|0978|Tatsugiri|68|50|60|120|95|82}} //Curly +{{lop/base|0978|Tatsugiri|68|50|60|120|95|82}} //Droopy +{{lop/base|0978|Tatsugiri|68|50|60|120|95|82}} //Stretchy +{{lop/base|0979|Annihilape|110|115|80|50|90|90}} +{{lop/base|0980|Clodsire|130|75|60|45|100|20}} +{{lop/base|0981|Farigiraf|120|90|70|110|70|60}} +{{lop/base|0982|Dudunsparce|125|100|80|85|75|55}} +{{lop/base|0983|Kingambit|100|135|120|60|85|50}} +{{lop/base|0984|Great Tusk|115|131|131|53|53|87}} +{{lop/base|0985|Scream Tail|115|65|99|65|115|111}} +{{lop/base|0986|Brute Bonnet|111|127|99|79|99|55}} +{{lop/base|0987|Flutter Mane|55|55|55|135|135|135}} +{{lop/base|0988|Slither Wing|85|135|79|85|105|81}} +{{lop/base|0989|Sandy Shocks|85|81|97|121|85|101}} +{{lop/base|0990|Iron Treads|90|112|120|72|70|106}} +{{lop/base|0991|Iron Bundle|56|80|114|124|60|136}} +{{lop/base|0992|Iron Hands|154|140|108|50|68|50}} +{{lop/base|0993|Iron Jugulis|94|80|86|122|80|108}} +{{lop/base|0994|Iron Moth|80|70|60|140|110|110}} +{{lop/base|0995|Iron Thorns|100|134|110|70|84|72}} +{{lop/base|0998|Baxcalibur|115|145|92|75|86|87}} +{{lop/base|1000|Gholdengo|87|60|95|133|91|84}} +{{lop/base|1001|Wo-Chien|85|85|100|95|135|70}} +{{lop/base|1002|Chien-Pao|80|120|80|90|65|135}} +{{lop/base|1003|Ting-Lu|155|110|125|55|80|45}} +{{lop/base|1004|Chi-Yu|55|80|80|135|120|100}} +{{lop/base|1005|Roaring Moon|105|139|71|55|101|119}} +{{lop/base|1006|Iron Valiant|74|130|90|120|60|116}} +{{lop/base|1007|Koraidon|100|135|115|85|100|135}} +{{lop/base|1008|Miraidon|100|85|100|135|115|135}} +{{lop/base|1009|Walking Wake|99|83|91|125|83|109}} +{{lop/base|1010|Iron Leaves|90|130|88|70|108|104}} +{{lop/base|1013|Sinistcha|71|60|106|121|80|70}} +{{lop/base|1014|Okidogi|88|128|115|58|86|80}} +{{lop/base|1015|Munkidori|88|75|66|130|90|106}} +{{lop/base|1016|Fezandipiti|88|91|82|70|125|99}} +{{lop/base|1017|Ogerpon|80|120|84|60|96|110}} +{{lop/base|1018|Archaludon|90|105|130|125|65|85}} +{{lop/base|1019|Hydrapple|106|80|110|120|80|44}} +{{lop/base|1020|Gouging Fire|105|115|121|65|93|91}} +{{lop/base|1021|Raging Bolt|125|73|91|137|89|75}} +{{lop/base|1022|Iron Boulder|90|120|80|68|108|124}} +{{lop/base|1023|Iron Crown|90|72|100|122|108|98}} +{{lop/base|1024|Terapagos|90|65|85|65|85|60|Normal Form}} +{{lop/base|1025|Pecharunt|88|88|160|88|88|88}} \ No newline at end of file From a3f44d080572e9c23a5d63df110624b8b40f6aa2 Mon Sep 17 00:00:00 2001 From: Ruby Date: Thu, 4 Sep 2025 03:58:56 +0800 Subject: [PATCH 281/283] added gen separations --- list of mons.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/list of mons.txt b/list of mons.txt index 817bdb889c..810fe88f76 100644 --- a/list of mons.txt +++ b/list of mons.txt @@ -382,6 +382,8 @@ {{lop/base|0647|Keldeo|91|72|90|129|90|108}} {{lop/base|0648|Meloetta|100|77|77|128|128|90|Aria Forme}} {{lop/base|0649|Genesect|71|120|95|120|95|99}} + +== GEN SIX == {{lop/base|0652|Chesnaught|88|107|122|74|75|64}} {{lop/base|0655|Delphox|75|69|72|114|100|104}} {{lop/base|0658|Greninja|72|95|67|103|71|122}} @@ -425,6 +427,8 @@ {{lop/base|0719|Diancie|50|100|150|100|150|50}} {{lop/base|0720|Hoopa|80|110|60|150|130|70|Hoopa Confined}} {{lop/base|0721|Volcanion|80|110|120|130|90|70}} + +== GEN SEVEN == {{lop/base|0724|Decidueye|78|107|75|100|100|70}} {{lop/base|0724|form=-Hisui|Decidueye|88|112|80|95|95|60|Hisuian Decidueye}} {{lop/base|0727|Incineroar|95|115|90|80|90|60}} @@ -484,6 +488,8 @@ {{lop/base|0806|Blacephalon|53|127|53|151|79|107}} {{lop/base|0807|Zeraora|88|112|75|102|80|143}} {{lop/base|0809|Melmetal|135|143|143|80|65|34}} + +== GEN EIGHT == {{lop/base|0812|Rillaboom|100|125|90|60|70|85}} {{lop/base|0815|Cinderace|80|116|75|65|75|119}} {{lop/base|0818|Inteleon|70|85|65|125|65|120}} @@ -547,6 +553,8 @@ {{lop/base|0903|Sneasler|80|130|60|40|80|120}} {{lop/base|0904|Overqwil|85|115|95|65|65|85}} {{lop/base|0905|Enamorus|74|115|70|135|80|106|Incarnate Forme}} + +== GEN NINE == {{lop/base|0908|Meowscarada|76|110|70|81|70|123}} {{lop/base|0911|Skeledirge|104|75|100|110|75|66}} {{lop/base|0914|Quaquaval|85|120|80|85|75|85}} From 1339403d907602a7abefe83f193325e36763df02 Mon Sep 17 00:00:00 2001 From: Ruby Date: Thu, 4 Sep 2025 04:07:53 +0800 Subject: [PATCH 282/283] fixed sheer force for moves --- src/data/moves_info.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 1faef253d6..613979aed3 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -21148,7 +21148,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_INFATUATED, .chance = 30, - .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_RockBlast, }, @@ -21172,7 +21171,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .moveEffect = MOVE_EFFECT_SPD_PLUS_2, .self = TRUE, .chance = 100, - .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_Waterfall, }, @@ -21195,7 +21193,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_ELECTRIC_TERRAIN, .chance = 100, - .sheerForceBoost = SHEER_FORCE_NO_BOOST, + .sheerForceOverride = TRUE, }), .parentalBondBanned = TRUE, .battleAnimScript = gBattleAnimMove_Explosion, @@ -21220,7 +21218,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .additionalEffects = ADDITIONAL_EFFECTS({ .moveEffect = MOVE_EFFECT_GRASSPIERCER, .chance = 50, - .sheerForceBoost = SHEER_FORCE_BOOST, }), .battleAnimScript = gBattleAnimMove_VineWhip, }, From c45ef41eafb717ccff092d88a1c3d228c8ea922c Mon Sep 17 00:00:00 2001 From: Ruby Date: Thu, 4 Sep 2025 04:12:59 +0800 Subject: [PATCH 283/283] removed some .ymls --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 71 ------------------- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 71 ------------------- .../ISSUE_TEMPLATE/03_feature_requests.yaml | 38 ---------- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 71 ------------------- .github/pull_request_template.md | 41 ----------- .github/workflows/build.yml | 11 +-- .github/workflows/docs.yml | 48 ------------- 7 files changed, 1 insertion(+), 350 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml delete mode 100644 .github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml delete mode 100644 .github/ISSUE_TEMPLATE/03_feature_requests.yaml delete mode 100644 .github/ISSUE_TEMPLATE/04_other_errors.yaml delete mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/docs.yml diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml deleted file mode 100644 index a06bfb5247..0000000000 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: ⚔️ Battle Engine mechanical bugs 🐛 -description: File a bug report related to battle mechanic, be it moves, abilities and/or items. -labels: ["bug", "status: unconfirmed", "category: battle-mechanic"] -body: - - type: markdown - attributes: - value: | - Please fill in all fields with as many details as possible. - Once your bug is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even reporting bugs! - - type: textarea - id: description - attributes: - label: Description - description: | - What behavior are you expecting to happen? What behavior are you observing instead? - placeholder: | - Please be as descriptive as possible. - validations: - required: true - - type: textarea - id: reproduction - attributes: - label: Reproduction Steps - description: | - What exact steps can somebody else follow in order to recreate the issue on their own? - placeholder: | - Provide as much context as possible as to what was done to create the issue. - validations: - required: true - - type: textarea - id: media - attributes: - label: Images / Video - description: | - Do you have images or videos to show the problem happen? - placeholder: | - Here you can also attach logs, screenshots, gifs or a video. - validations: - required: false - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using? - options: - - 1.13.1 (Latest release) - - master (default, unreleased bugfixes) - - upcoming (Edge) - - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming/master Version - description: If you're using the `upcoming` or `master` branches directly, please use the following command to give us the commit hash that you are on. `git log --merges RHH/upcoming -1 --format=%H` Replace `upcoming` with `master` if you're using `master`. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Discussion around **`pokeemerald-expansion`** happens in our [Discord server](https://discord.gg/6CzjAG6GZk). - placeholder: ex. Lunos#4026 - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml deleted file mode 100644 index 505cd5e6c4..0000000000 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: 🧠 Battle AI bugs 🐛 -description: File a bug report related to battle AI. -labels: ["bug", "status: unconfirmed", "category: battle-ai"] -body: - - type: markdown - attributes: - value: | - Please fill in all fields with as many details as possible. - Once your bug is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even reporting bugs! - - type: textarea - id: description - attributes: - label: Description - description: | - What behavior are you expecting to happen? What behavior are you observing instead? - placeholder: | - Please be as descriptive as possible. - validations: - required: true - - type: textarea - id: reproduction - attributes: - label: Reproduction Steps - description: | - What exact steps can somebody else follow in order to recreate the issue on their own? - placeholder: | - Provide as much context as possible as to what was done to create the issue. - validations: - required: true - - type: textarea - id: media - attributes: - label: Images / Video - description: | - Do you have images or videos to show the problem happen? - placeholder: | - Here you can also attach logs, screenshots, gifs or a video. - validations: - required: false - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using? - options: - - 1.13.1 (Latest release) - - master (default, unreleased bugfixes) - - upcoming (Edge) - - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming/master Version - description: If you're using the `upcoming` or `master` branches directly, please use the following command to give us the commit hash that you are on. `git log --merges RHH/upcoming -1 --format=%H` Replace `upcoming` with `master` if you're using `master`. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Discussion around **`pokeemerald-expansion`** happens in our [Discord server](https://discord.gg/6CzjAG6GZk). - placeholder: ex. Lunos#4026 - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/03_feature_requests.yaml b/.github/ISSUE_TEMPLATE/03_feature_requests.yaml deleted file mode 100644 index 347e782660..0000000000 --- a/.github/ISSUE_TEMPLATE/03_feature_requests.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: 🙏 Feature Request 🙏 -description: Do you want a feature to be added to the Expansion? Let us know! -labels: ["feature-request"] -body: - - type: markdown - attributes: - value: | - Please fill in all fields with as many details as possible. - Once your feature request is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even requesting issues! - - - type: textarea - id: behavior - attributes: - label: Behavior Description - description: | - What is the current behavior? What behavior would you expect your feature request to provide? What other information can you provide to help your feature get implemented? - placeholder: | - Provide as much context as possible. - validations: - required: true - - type: textarea - id: media - attributes: - label: Images / Video - description: | - Have other projects or games solved this problem? Do you have images or video to show this happening? - placeholder: | - Here you can also attach logs, screenshots, gifs or a video. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Discussion around **pokeemerald-expansion** happens in our [Discord server](https://discord.gg/6CzjAG6GZk). - placeholder: ex. Lunos#4026 - validations: - required: false diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml deleted file mode 100644 index 4abed5dbb5..0000000000 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ /dev/null @@ -1,71 +0,0 @@ -name: 💾 Other errors 🖥️ -description: Everything else that doesn't fit in the above categories. -labels: ["bug", "status: unconfirmed"] -body: - - type: markdown - attributes: - value: | - Please fill in all fields with as many details as possible. - Once your bug is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even creating issues! - - type: textarea - id: description - attributes: - label: Description - description: | - What behavior are you expecting to happen? What behavior are you observing instead? - placeholder: | - Please be as descriptive as possible. - validations: - required: true - - type: textarea - id: reproduction - attributes: - label: Reproduction Steps - description: | - What exact steps can somebody else follow in order to recreate the issue on their own? - placeholder: | - Provide as much context as possible as to what was done to create the issue. - validations: - required: false - - type: textarea - id: media - attributes: - label: Images / Video - description: | - Do you have images or videos to show the problem happen? - placeholder: | - Here you can also attach logs, screenshots, gifs or a video. - validations: - required: false - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using? - options: - - 1.13.1 (Latest release) - - master (default, unreleased bugfixes) - - upcoming (Edge) - - 1.13.0 - - 1.12.3 - - 1.12.2 - - 1.12.1 - - 1.12.0 - - pre-1.12.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming/master Version - description: If you're using the `upcoming` or `master` branches directly, please use the following command to give us the commit hash that you are on. `git log --merges RHH/upcoming -1 --format=%H` Replace `upcoming` with `master` if you're using `master`. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Discussion around **`pokeemerald-expansion`** happens in our [Discord server](https://discord.gg/6CzjAG6GZk). - placeholder: ex. Lunos#4026 - validations: - required: false diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index dc900e224e..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - -## Description - - -## Media - - -## Issue(s) that this PR fixes - - - - - - - - -## Feature(s) this PR does NOT handle: - - - -## Things to note in the release changelog: - - - -## Discord contact info - - - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8126850bb3..22aa2af321 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,6 @@ on: jobs: build: - if: github.actor != 'allcontributors[bot]' runs-on: ubuntu-latest env: GAME_VERSION: EMERALD @@ -56,12 +55,4 @@ jobs: env: TEST: 1 run: | - make -j${nproc} check - allcontributors: - if: github.actor == 'allcontributors[bot]' - runs-on: ubuntu-latest - needs: [] - steps: - - name: Automatically pass for allcontributors - run: echo "CI automatically passes for allcontributors" && exit 0 - + make -j${nproc} check \ No newline at end of file diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 874ebdd590..0000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Docs -on: - push: - branches: - - master - -jobs: - deploy: - runs-on: ubuntu-latest - permissions: - contents: write - pages: write - id-token: write - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install latest mdbook - run: | - tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') - url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" - mkdir mdbook - curl -sSL $url | tar -xz --directory=./mdbook - echo `pwd`/mdbook >> $GITHUB_PATH - - name: Build Book - run: | - cd docs - mdbook build - - name: Check if Pages is enabled - uses: octokit/request-action@v2.x - id: check_pages - continue-on-error: true - with: - route: GET /repos/{repo}/pages - repo: ${{ github.repository }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Setup Pages - uses: actions/configure-pages@v4 - if: steps.check_pages.outcome == 'success' - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: 'docs/book' - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 - if: steps.check_pages.outcome == 'success'