diff --git a/Makefile b/Makefile index 80ee5303d3..fb48be1841 100644 --- a/Makefile +++ b/Makefile @@ -119,7 +119,7 @@ LIBPATH := -L ../../tools/agbcc/lib LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall else CC1 = $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 +override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias ifeq ($(ANALYZE),1) override CFLAGS += -fanalyzer endif diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 636435f0e6..b2cd95ca27 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -19482,8 +19482,8 @@ Move_MILK_DRINK: Move_MAGNITUDE: createvisualtask AnimTask_IsPowerOver99, 2 waitforvisualfinish - jumpargeq 15, FALSE, MagnitudeRegular - jumpargeq 15, TRUE, MagnitudeIntense + jumpreteq FALSE, MagnitudeRegular + jumpreteq TRUE, MagnitudeIntense MagnitudeEnd: end MagnitudeRegular: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5fdd44f2f7..dab321a2d8 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -439,8 +439,51 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectSaltCure @ EFFECT_SALT_CURE .4byte BattleScript_EffectMaxMove @ EFFECT_MAX_MOVE + .4byte BattleScript_EffectMatchaGotcha @ EFFECT_MATCHA_GOTCHA + .4byte BattleScript_EffectSyrupBomb @ EFFECT_SYRUP_BOMB + .4byte BattleScript_EffectHit @ EFFECT_IVY_CUDGEL + +BattleScript_EffectSyrupBomb:: + setmoveeffect MOVE_EFFECT_SYRUP_BOMB + call BattleScript_EffectHit_Ret + seteffectwithchance + tryfaintmon BS_TARGET + printstring STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd + +BattleScript_SyrupBombEndTurn:: + setbyte sSTAT_ANIM_PLAYED, FALSE + copybyte sBATTLER, gBattlerTarget + jumpifholdeffect BS_TARGET, HOLD_EFFECT_CLEAR_AMULET, BattleScript_SyrupBombItemNoStatLoss + jumpifability BS_TARGET, ABILITY_CLEAR_BODY, BattleScript_SyrupBombAbilityNoStatLoss + jumpifability BS_TARGET, ABILITY_FULL_METAL_BODY, BattleScript_SyrupBombAbilityNoStatLoss + jumpifability BS_TARGET, ABILITY_WHITE_SMOKE, BattleScript_SyrupBombAbilityNoStatLoss + jumpifstat BS_TARGET, CMP_GREATER_THAN, BIT_SPEED, MIN_STAT_STAGE, BattleScript_SyrupBombLowerSpeed + goto BattleScript_SyrupBombEnd2 +BattleScript_SyrupBombLowerSpeed: + playstatchangeanimation BS_ATTACKER, BIT_SPEED, STAT_CHANGE_NEGATIVE + setbyte sSTAT_ANIM_PLAYED, TRUE + setstatchanger STAT_SPEED, 1, TRUE + statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_SyrupBombEnd2 + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_SyrupBombEnd2 + printfromtable gStatDownStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_SyrupBombItemNoStatLoss:: + call BattleScript_ItemNoStatLoss + goto BattleScript_SyrupBombEnd2 +BattleScript_SyrupBombAbilityNoStatLoss:: + call BattleScript_AbilityNoStatLoss +BattleScript_SyrupBombEnd2:: + end2 + +BattleScript_EffectMatchaGotcha:: + setmoveeffect MOVE_EFFECT_BURN + goto BattleScript_EffectAbsorb + BattleScript_EffectSaltCure: call BattleScript_EffectHit_Ret + tryfaintmon BS_TARGET jumpiffainted BS_TARGET, TRUE, BattleScript_EffectSaltCure_End applysaltcure BS_TARGET printstring STRINGID_TARGETISBEINGSALTCURED @@ -3338,6 +3381,7 @@ BattleScript_EffectPoisonHit: BattleScript_EffectAbsorb:: call BattleScript_EffectHit_Ret + seteffectwithchance jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_AbsorbHealBlock setdrainedhp manipulatedamage DMG_BIG_ROOT @@ -3864,6 +3908,7 @@ BattleScript_EffectRest:: jumpifuproarwakes BattleScript_RestCantSleep jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_InsomniaProtects jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_InsomniaProtects + jumpifability BS_ATTACKER, ABILITY_PURIFYING_SALT, BattleScript_InsomniaProtects .if B_LEAF_GUARD_PREVENTS_REST >= GEN_5 jumpifleafguardprotected BS_TARGET, BattleScript_LeafGuardPreventsRest .endif @@ -7984,9 +8029,10 @@ BattleScript_DoTurnDmgEnd: end2 BattleScript_PoisonHealActivates:: + copybyte gBattlerAbility, gBattlerAttacker + call BattleScript_AbilityPopUp printstring STRINGID_POISONHEALHPUP waitmessage B_WAIT_TIME_LONG - recordability BS_ATTACKER statusanimation BS_ATTACKER orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_ATTACKER @@ -8736,28 +8782,6 @@ BattleScript_ActivateTerrainEffects_Increment: restoretarget return -BattleScript_ActivateSwitchInAbilities: - copybyte sBATTLER, gBattlerAttacker - setbyte gBattlerAttacker, 0 -BattleScript_ActivateSwitchInAbilities_Loop: - switchinabilities BS_ATTACKER -BattleScript_ActivateSwitchInAbilities_Increment: - addbyte gBattlerAttacker, 1 - jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateSwitchInAbilities_Loop - copybyte gBattlerAttacker, sBATTLER - return - -BattleScript_ActivateTerrainAbilities: - savetarget - setbyte gBattlerTarget, 0 -BattleScript_ActivateTerrainAbilities_Loop: - activateterrainchangeabilities BS_ATTACKER -BattleScript_ActivateTerrainAbilities_Increment: - addbyte gBattlerTarget, 1 - jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateTerrainAbilities_Loop - restoretarget - return - BattleScript_ElectricSurgeActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -9926,6 +9950,14 @@ BattleScript_MirrorHerbCopyStatChange:: copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe return +BattleScript_OpportunistCopyStatChange:: + call BattleScript_AbilityPopUp + printstring STRINGID_OPPORTUNISTCOPIED + waitmessage B_WAIT_TIME_LONG + call BattleScript_TotemVar_Ret + copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe + end3 + BattleScript_TotemVar:: call BattleScript_TotemVar_Ret end2 diff --git a/gflib/malloc.c b/gflib/malloc.c index dcfac6ee81..b3191e30b6 100644 --- a/gflib/malloc.c +++ b/gflib/malloc.c @@ -1,5 +1,8 @@ #include "global.h" #include "malloc.h" +#if TESTING +#include "test/test.h" +#endif static void *sHeapStart; static u32 sHeapSize; @@ -71,7 +74,27 @@ void *AllocInternal(void *heapStart, u32 size, const char *location) } if (pos->next == head) + { +#if TESTING + const struct MemBlock *head = HeapHead(); + const struct MemBlock *block = head; + do + { + if (block->allocated) + { + const char *location = MemBlockLocation(block); + if (location) + MgbaPrintf_("%s: %d bytes allocated", location, block->size); + else + MgbaPrintf_(": %d bytes allocated", block->size); + } + block = block->next; + } + while (block != head); + Test_ExitWithResult(TEST_RESULT_ERROR, "%s: OOM allocating %d bytes", location, size); +#endif return NULL; + } pos = pos->next; } diff --git a/gflib/sprite.c b/gflib/sprite.c index d75f6f7271..ee20ab675b 100644 --- a/gflib/sprite.c +++ b/gflib/sprite.c @@ -324,7 +324,7 @@ void AnimateSprites(void) void BuildOamBuffer(void) { bool32 oamLoadDisabled; - u32 i, stride; + u32 i; u8 oamIndex; // All attributes which affect sorting packed into a single u32: diff --git a/graphics/pokemon/pikachu/world_cap/icon.png b/graphics/pokemon/pikachu/world_cap/icon.png new file mode 100644 index 0000000000..260e29cda2 Binary files /dev/null and b/graphics/pokemon/pikachu/world_cap/icon.png differ diff --git a/include/battle.h b/include/battle.h index 64c00b2255..90a392e15c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -105,6 +105,7 @@ struct DisableStruct u8 toxicSpikesDone:1; u8 stickyWebDone:1; u8 stealthRockDone:1; + u8 syrupBombTimer; u8 steelSurgeDone:1; }; @@ -153,6 +154,7 @@ struct ProtectStruct u16 maxGuarded:1; u16 silkTrapped:1; u16 eatMirrorHerb:1; + u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; @@ -927,7 +929,7 @@ struct MonSpritesGfx u16 *buffer; }; -struct TotemBoost +struct QueuedStatBoost { u8 stats; // bitfield for each battle stat that is set if the stat changes s8 statChanges[NUM_BATTLE_STATS - 1]; // highest bit being set decreases the stat @@ -946,7 +948,7 @@ extern u16 gBattle_WIN0H; extern u16 gBattle_WIN0V; extern u16 gBattle_WIN1H; extern u16 gBattle_WIN1V; -extern u8 gDisplayedStringBattle[400]; +extern u8 gDisplayedStringBattle[425]; extern u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT]; extern u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT]; extern u8 gBattleTextBuff3[30]; //to handle stupidly large z move names @@ -1040,7 +1042,7 @@ extern u32 gFieldStatuses; extern struct FieldTimer gFieldTimers; extern u8 gBattlerAbility; extern u16 gPartnerSpriteId; -extern struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT]; +extern struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT]; extern void (*gPreBattleCallback1)(void); extern void (*gBattleMainFunc)(void); diff --git a/include/battle_ai_main.h b/include/battle_ai_main.h index 5b6807ab37..24bc6943aa 100644 --- a/include/battle_ai_main.h +++ b/include/battle_ai_main.h @@ -24,6 +24,13 @@ score += val; \ } while (0) \ +#define ADJUST_SCORE_PTR(val) \ + do \ + { \ + TestRunner_Battle_AIAdjustScore(__FILE__, __LINE__, sBattler_AI, AI_THINKING_STRUCT->movesetIndex, val); \ + (*score) += val; \ + } while (0) \ + #define RETURN_SCORE_PLUS(val) \ { \ ADJUST_SCORE(val); \ diff --git a/include/battle_scripts.h b/include/battle_scripts.h index ace1fa68ba..3cfc9ace16 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -1,6 +1,7 @@ #ifndef GUARD_BATTLE_SCRIPTS_H #define GUARD_BATTLE_SCRIPTS_H +extern const u8 BattleScript_OpportunistCopyStatChange[]; extern const u8 BattleScript_MirrorHerbCopyStatChange[]; extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[]; extern const u8 BattleScript_NotAffected[]; @@ -479,6 +480,7 @@ extern const u8 BattleScript_UltraBurst[]; extern const u8 BattleScript_SelectingNotAllowedCurrentMove[]; extern const u8 BattleScript_SelectingNotAllowedCurrentMoveInPalace[]; extern const u8 BattleScript_SaltCureExtraDamage[]; +extern const u8 BattleScript_SyrupBombEndTurn[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/battle_util.h b/include/battle_util.h index 62e7d1a2a3..ec7fa42800 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -33,14 +33,15 @@ #define ABILITYEFFECT_TRACE2 10 #define ABILITYEFFECT_MOVE_END_OTHER 11 #define ABILITYEFFECT_NEUTRALIZINGGAS 12 -#define ABILITYEFFECT_FIELD_SPORT 13 // Only used if B_SPORT_TURNS < GEN_6 +#define ABILITYEFFECT_FIELD_SPORT 13 // Only used if B_SPORT_TURNS >= GEN_6 #define ABILITYEFFECT_ON_WEATHER 14 #define ABILITYEFFECT_ON_TERRAIN 15 #define ABILITYEFFECT_SWITCH_IN_TERRAIN 16 #define ABILITYEFFECT_SWITCH_IN_WEATHER 17 +#define ABILITYEFFECT_OPPORTUNIST 18 // Special cases -#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS < GEN_6 -#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS < GEN_6 +#define ABILITYEFFECT_MUD_SPORT 252 // Only used if B_SPORT_TURNS >= GEN_6 +#define ABILITYEFFECT_WATER_SPORT 253 // Only used if B_SPORT_TURNS >= GEN_6 // For the first argument of ItemBattleEffects, to deteremine which block of item effects to try #define ITEMEFFECT_ON_SWITCH_IN 0 @@ -248,6 +249,7 @@ bool32 ChangeTypeBasedOnTerrain(u32 battler); void RemoveConfusionStatus(u32 battler); u8 GetBattlerGender(u32 battler); bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2); +bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2); u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance); u8 GetBattlerType(u32 battler, u8 typeIndex); diff --git a/include/config/battle.h b/include/config/battle.h index a5c16d2591..ca995e3271 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -25,7 +25,7 @@ #define B_RECALCULATE_STATS GEN_LATEST // In Gen5+, the stats of the Pokémon who participate in battle are recalculated at the end of each battle. // Damage settings -#define B_BURN_DAMAGE GEN_LATEST // In Gen7+, burn damage is 1/16th of max HP instead of 1/8th. +#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. @@ -128,16 +128,17 @@ #define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases. #define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight. #define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail. +#define B_TRANSISTOR_BOOST GEN_LATEST // In Gen9+, Transistor will only boost Electric-type moves by 1.3x as opposed to 1.5x. // Item settings -#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. +#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. #define B_BERRIES_INSTANT GEN_LATEST // In Gen4+, most berries activate on battle start/switch-in if applicable. In Gen3, they only activate either at the move end or turn end. #define B_CONFUSE_BERRIES_HEAL GEN_LATEST // Before Gen7, Figy and similar berries restore 1/8th of HP and trigger at half HP. In Gen7 they restore half HP, triggering at 25% HP. In Gen8 they heal 1/3rd of HP. #define B_X_ITEMS_BUFF GEN_LATEST // In Gen7+, the X Items raise a stat by 2 stages instead of 1. #define B_MENTAL_HERB GEN_LATEST // In Gen5+, the Mental Herb cures Taunt, Encore, Torment, Heal Block, and Disable in addition to Infatuation from before. #define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items. #define B_RESTORE_HELD_BATTLE_ITEMS TRUE // In Gen9 all non berry items are restored after battle. -#define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Lati@s' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. +#define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Latis' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead. #define B_NET_BALL_MODIFIER GEN_LATEST // In Gen7+, Net Ball's catch multiplier is x5 instead of x3. #define B_DIVE_BALL_MODIFIER GEN_LATEST // In Gen4+, Dive Ball's effectiveness increases by when Surfing or Fishing. #define B_NEST_BALL_MODIFIER GEN_LATEST // Nest Ball's formula varies depending on the Gen. See Cmd_handleballthrow. diff --git a/include/config/item.h b/include/config/item.h index 08e5e4d3bb..55de3fdb60 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -19,6 +19,8 @@ #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. // Exp. Share config +// To use this feature, replace the 0 with the flag ID you're assigning it to. +// Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. #define I_EXP_SHARE_FLAG 0 // If this flag is set, every Pokémon in the party will gain experience, regardless if they participated in the battle or not. #define I_EXP_SHARE_ITEM GEN_5 // In Gen6+, the Exp. Share was changed from a held item to a Key item that toggles the effect described above. diff --git a/include/constants/battle.h b/include/constants/battle.h index b7b59dd240..05c0d1b037 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -188,6 +188,7 @@ #define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6 #define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene #define STATUS4_SALT_CURE (1 << 5) +#define STATUS4_SYRUP_BOMB (1 << 6) #define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked. #define HITMARKER_SKIP_DMG_TRACK (1 << 5) @@ -386,8 +387,9 @@ #define MOVE_EFFECT_STEALTH_ROCK 76 #define MOVE_EFFECT_SPIKES 77 #define MOVE_EFFECT_TRIPLE_ARROWS 78 +#define MOVE_EFFECT_SYRUP_BOMB 79 -#define NUM_MOVE_EFFECTS 79 +#define NUM_MOVE_EFFECTS 80 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index c97dab6337..421a191043 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -414,8 +414,11 @@ #define EFFECT_MORTAL_SPIN 408 #define EFFECT_GIGATON_HAMMER 409 #define EFFECT_SALT_CURE 410 -#define EFFECT_MAX_MOVE 411 +#define EFFECT_MATCHA_GOTCHA 411 +#define EFFECT_SYRUP_BOMB 412 +#define EFFECT_IVY_CUDGEL 413 +#define EFFECT_MAX_MOVE 414 -#define NUM_BATTLE_MOVE_EFFECTS 412 +#define NUM_BATTLE_MOVE_EFFECTS 415 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index ee98bccec7..1775b9528e 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -323,8 +323,9 @@ #define MOVEEND_DANCER 31 #define MOVEEND_EMERGENCY_EXIT 32 #define MOVEEND_SYMBIOSIS 33 -#define MOVEEND_CLEAR_BITS 34 -#define MOVEEND_COUNT 35 +#define MOVEEND_OPPORTUNIST 34 // Occurs after other stat change items/abilities to try and copy the boosts +#define MOVEEND_CLEAR_BITS 35 +#define MOVEEND_COUNT 36 // switch cases #define B_SWITCH_NORMAL 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index c9f9b2bde5..1f5539dc62 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -670,21 +670,23 @@ #define STRINGID_CURRENTMOVECANTSELECT 668 #define STRINGID_TARGETISBEINGSALTCURED 669 #define STRINGID_TARGETISHURTBYSALTCURE 670 -#define STRINGID_SHARPSTEELFLOATS 671 -#define STRINGID_SHARPSTEELDMG 672 -#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 673 -#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 674 -#define STRINGID_TEAMTRAPPEDWITHVINES 675 -#define STRINGID_PKMNHURTBYVINES 676 -#define STRINGID_TEAMCAUGHTINVORTEX 677 -#define STRINGID_PKMNHURTBYVORTEX 678 -#define STRINGID_TEAMSURROUNDEDBYFIRE 679 -#define STRINGID_PKMNBURNINGUP 680 -#define STRINGID_TEAMSURROUNDEDBYROCKS 681 -#define STRINGID_PKMNHURTBYROCKSTHROWN 682 -#define STRINGID_MOVEBLOCKEDBYDYNAMAX 683 +#define STRINGID_OPPORTUNISTCOPIED 671 +#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 672 +#define STRINGID_SHARPSTEELFLOATS 673 +#define STRINGID_SHARPSTEELDMG 674 +#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 675 +#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 676 +#define STRINGID_TEAMTRAPPEDWITHVINES 677 +#define STRINGID_PKMNHURTBYVINES 678 +#define STRINGID_TEAMCAUGHTINVORTEX 679 +#define STRINGID_PKMNHURTBYVORTEX 680 +#define STRINGID_TEAMSURROUNDEDBYFIRE 681 +#define STRINGID_PKMNBURNINGUP 682 +#define STRINGID_TEAMSURROUNDEDBYROCKS 683 +#define STRINGID_PKMNHURTBYROCKSTHROWN 684 +#define STRINGID_MOVEBLOCKEDBYDYNAMAX 685 -#define BATTLESTRINGS_COUNT 684 +#define BATTLESTRINGS_COUNT 686 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 9f877cffa8..a54f569cd2 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -160,9 +160,10 @@ #define HOLD_EFFECT_COVERT_CLOAK 179 #define HOLD_EFFECT_LOADED_DICE 180 #define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented. +#define HOLD_EFFECT_MASK 183 // Gen2 hold effect -#define HOLD_EFFECT_BERSERK_GENE 182 +#define HOLD_EFFECT_BERSERK_GENE 184 #define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 933c75970a..49272691c6 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -163,7 +163,7 @@ #define LEVEL_UP_MOVE_ID 0x01FF #define LEVEL_UP_MOVE_LV 0xFE00 -#define LEVEL_UP_END 0xFFFF +#define LEVEL_UP_MOVE_END 0xFFFF #define MAX_LEVEL_UP_MOVES 20 diff --git a/include/field_weather.h b/include/field_weather.h index 8ce0cc9e50..b354d500e3 100644 --- a/include/field_weather.h +++ b/include/field_weather.h @@ -132,7 +132,7 @@ struct Weather s16 droughtTimer; s16 droughtState; u8 droughtUnused[9]; - s8 loadDroughtPalsIndex; + u8 loadDroughtPalsIndex; u8 loadDroughtPalsOffset; }; diff --git a/include/fieldmap.h b/include/fieldmap.h index 47072bd1be..ecb1e49c4d 100644 --- a/include/fieldmap.h +++ b/include/fieldmap.h @@ -22,6 +22,7 @@ #include "main.h" extern struct BackupMapLayout gBackupMapLayout; +extern u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE]; u32 MapGridGetMetatileIdAt(int, int); u32 MapGridGetMetatileBehaviorAt(int, int); diff --git a/include/graphics.h b/include/graphics.h index ba84769f22..7a44592d26 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -6257,6 +6257,7 @@ extern const u8 gMonIcon_PikachuUnovaCap[]; extern const u8 gMonIcon_PikachuKalosCap[]; extern const u8 gMonIcon_PikachuAlolaCap[]; extern const u8 gMonIcon_PikachuPartnerCap[]; +extern const u8 gMonIcon_PikachuWorldCap[]; extern const u8 gMonIcon_PichuSpikyEared[]; extern const u8 gMonIcon_UnownB[]; extern const u8 gMonIcon_UnownC[]; diff --git a/include/random.h b/include/random.h index 16f58136f5..8d801ebe74 100644 --- a/include/random.h +++ b/include/random.h @@ -96,6 +96,7 @@ enum RandomTag RNG_TRI_ATTACK, RNG_TRIPLE_ARROWS_DEFENSE_DOWN, RNG_TRIPLE_ARROWS_FLINCH, + RNG_QUICK_DRAW, }; #define RandomWeighted(tag, ...) \ diff --git a/include/test/battle.h b/include/test/battle.h index b2001174ab..616c81964a 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -504,8 +504,8 @@ enum { BATTLE_TEST_SINGLES, BATTLE_TEST_DOUBLES, BATTLE_TEST_WILD, BATTLE_TEST_AI_SINGLES, BATTLE_TEST_AI_DOUBLES }; -typedef void (*SingleBattleTestFunction)(void *, u32, struct BattlePokemon *, struct BattlePokemon *); -typedef void (*DoubleBattleTestFunction)(void *, u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); +typedef void (*SingleBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *); +typedef void (*DoubleBattleTestFunction)(void *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); struct BattleTest { @@ -712,7 +712,7 @@ struct BattleTestRunnerState }; extern const struct TestRunner gBattleTestRunner; -extern struct BattleTestRunnerState *gBattleTestRunnerState; +extern struct BattleTestRunnerState *const gBattleTestRunnerState; #define MEMBERS(...) VARARG_8(MEMBERS_, __VA_ARGS__) #define MEMBERS_0() @@ -746,7 +746,7 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState; #define BATTLE_TEST_ARGS_SINGLE(_name, _type, ...) \ struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \ - static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, u32, struct BattlePokemon *, struct BattlePokemon *); \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *); \ __attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \ { \ .name = _name, \ @@ -760,11 +760,11 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState; .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ }, \ }; \ - static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, u32 i, struct BattlePokemon *player, struct BattlePokemon *opponent) + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *player, struct BattlePokemon *opponent) #define BATTLE_TEST_ARGS_DOUBLE(_name, _type, ...) \ struct CAT(Result, __LINE__) { MEMBERS(__VA_ARGS__) }; \ - static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *, const u32, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *, struct BattlePokemon *); \ __attribute__((section(".tests"))) static const struct Test CAT(sTest, __LINE__) = \ { \ .name = _name, \ @@ -778,7 +778,7 @@ extern struct BattleTestRunnerState *gBattleTestRunnerState; .resultsSize = sizeof(struct CAT(Result, __LINE__)), \ }, \ }; \ - static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) + static void CAT(Test, __LINE__)(struct CAT(Result, __LINE__) *results, const u32 i, struct BattlePokemon *playerLeft, struct BattlePokemon *opponentLeft, struct BattlePokemon *playerRight, struct BattlePokemon *opponentRight) #define SINGLE_BATTLE_TEST(_name, ...) BATTLE_TEST_ARGS_SINGLE(_name, BATTLE_TEST_SINGLES, __VA_ARGS__) @@ -894,8 +894,8 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define EXPECT_MOVE(battler, ...) ExpectMove(__LINE__, battler, (struct MoveContext) { APPEND_TRUE(__VA_ARGS__) }) #define NOT_EXPECT_MOVE(battler, _move) ExpectMove(__LINE__, battler, (struct MoveContext) { .move = _move, .explicitMove = TRUE, .notExpected = TRUE, .explicitNotExpected = TRUE, }) -#define EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, FALSE, (struct FourMoves) { __VA_ARGS__ }) -#define NOT_EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, TRUE, (struct FourMoves) { __VA_ARGS__ }) +#define EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, FALSE, (struct FourMoves) {{ __VA_ARGS__ }}) +#define NOT_EXPECT_MOVES(battler, ...) ExpectMoves(__LINE__, battler, TRUE, (struct FourMoves) {{ __VA_ARGS__ }}) #define EXPECT_SEND_OUT(battler, partyIndex) ExpectSendOut(__LINE__, battler, partyIndex) #define EXPECT_SWITCH(battler, partyIndex) ExpectSwitch(__LINE__, battler, partyIndex) #define SCORE_EQ(battler, ...) Score(__LINE__, battler, CMP_EQUAL, FALSE, (struct TestAIScoreStruct) { APPEND_TRUE(__VA_ARGS__) } ) diff --git a/src/apprentice.c b/src/apprentice.c index 2142a91f71..e7d67a43e2 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -351,7 +351,7 @@ static u16 GetRandomAlternateMove(u8 monId) else // == APPRENTICE_LVL_MODE_OPEN level = 60; // Despite being open level, level up moves are only read up to level 60 - for (j = 0; learnset[j].move != LEVEL_UP_END; j++) + for (j = 0; learnset[j].move != LEVEL_UP_MOVE_END; j++) { if (learnset[j].level > level) break; @@ -468,7 +468,7 @@ static void GetLatestLearnedMoves(u16 species, u16 *moves) level = 60; learnset = gLevelUpLearnsets[species]; - for (i = 0; learnset[i].move != LEVEL_UP_END; i++) + for (i = 0; learnset[i].move != LEVEL_UP_MOVE_END; i++) { if (learnset[i].level > level) break; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 94d67401a9..b31f66ec1e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -118,7 +118,7 @@ void BattleAI_SetupItems(void) static u32 GetWildAiFlags(void) { u32 avgLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL); - u32 flags; + u32 flags = 0; if (IsDoubleBattle()) avgLevel = (GetMonData(&gEnemyParty[0], MON_DATA_LEVEL) + GetMonData(&gEnemyParty[1], MON_DATA_LEVEL)) / 2; @@ -174,7 +174,7 @@ void BattleAI_SetupFlags(void) // sBattler_AI set in ComputeBattleAiScores void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) { - s32 i, move, dmg; + s32 i; u8 moveLimitations; // Clear AI data but preserve the flags. @@ -492,7 +492,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi) u8 currentMoveArray[MAX_MON_MOVES]; u8 consideredMoveArray[MAX_MON_MOVES]; u32 numOfBestMoves; - s32 i, id; + s32 i; u32 flags = AI_THINKING_STRUCT->aiFlags; AI_DATA->partnerMove = 0; // no ally @@ -721,7 +721,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) u32 moveEffect = gBattleMoves[move].effect; s32 moveType; u32 moveTarget = AI_GetBattlerMoveTargetType(battlerAtk, move); - u32 accuracy = AI_DATA->moveAccuracy[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; struct AiLogicData *aiData = AI_DATA; u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); @@ -938,11 +937,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // ignore def ability check // gen7+ dark type mons immune to priority->elevated moves from prankster - #if B_PRANKSTER_DARK_TYPES >= GEN_7 - if (aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && IS_MOVE_STATUS(move) + if (B_PRANKSTER_DARK_TYPES >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) + && aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IS_MOVE_STATUS(move) && !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) RETURN_SCORE_MINUS(10); - #endif // terrain & effect checks if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) @@ -1126,10 +1124,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-20); else if (!HasMoveWithType(battlerAtk, TYPE_ELECTRIC)) ADJUST_SCORE(-10); - #if B_CHARGE_SPDEF_RAISE >= GEN_5 - else if (!BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) + else if (B_CHARGE_SPDEF_RAISE >= GEN_5 + && !BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) ADJUST_SCORE(-5); - #endif break; case EFFECT_QUIVER_DANCE: case EFFECT_GEOMANCY: @@ -1416,10 +1413,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_OHKO: - #if B_SHEER_COLD_IMMUNITY >= GEN_7 - if (move == MOVE_SHEER_COLD && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) + if (B_SHEER_COLD_IMMUNITY >= GEN_7 && move == MOVE_SHEER_COLD && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) return 0; - #endif if (!ShouldTryOHKO(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move)) ADJUST_SCORE(-10); break; @@ -1447,10 +1442,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-8); else if (aiData->hpPercents[battlerAtk] <= 25) ADJUST_SCORE(-10); - #if B_SOUND_SUBSTITUTE >= GEN_6 - else if (HasSoundMove(battlerDef)) + else if (B_SOUND_SUBSTITUTE >= GEN_6 && HasSoundMove(battlerDef)) ADJUST_SCORE(-8); - #endif break; case EFFECT_LEECH_SEED: if (gStatuses3[battlerDef] & STATUS3_LEECHSEED @@ -1462,9 +1455,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_DISABLE: if (gDisableStructs[battlerDef].disableTimer == 0 - #if B_MENTAL_HERB >= GEN_5 - && aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB - #endif + && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker should go first @@ -1484,9 +1475,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_ENCORE: if (gDisableStructs[battlerDef].encoreTimer == 0 - #if B_MENTAL_HERB >= GEN_5 - && aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB - #endif + && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB) && !DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) { if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // Attacker should go first @@ -1715,10 +1704,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; } - #if B_MENTAL_HERB >= GEN_5 - if (aiData->holdEffects[battlerDef] == HOLD_EFFECT_MENTAL_HERB) + if (B_MENTAL_HERB >= GEN_5 && aiData->holdEffects[battlerDef] == HOLD_EFFECT_MENTAL_HERB) ADJUST_SCORE(-6); - #endif break; case EFFECT_WILL_O_WISP: if (!AI_CanBurn(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) @@ -3153,26 +3140,13 @@ static u32 CompareMoveAccuracies(u32 battlerAtk, u32 battlerDef, u32 moveSlot1, return 2; } -static u32 GetAIMostDamagingMoveId(u32 battlerAtk, u32 battlerDef) -{ - u32 i, id = 0; - u32 mostDmg = 0; - - for (i = 0; i < MAX_MON_MOVES; i++) - { - if (AI_DATA->simulatedDmg[battlerAtk][battlerDef][i] > mostDmg) - id = i, mostDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i]; - } - return id; -} - static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) { u32 i; bool32 multipleBestMoves = FALSE; s32 noOfHits[MAX_MON_MOVES]; s32 score = 0; - s32 leastHits = 1000, leastHitsId = 0; + s32 leastHits = 1000; u16 *moves = GetMovesArray(battlerAtk); bool8 isPowerfulIgnoredEffect[MAX_MON_MOVES]; @@ -3184,7 +3158,6 @@ static s32 AI_CompareDamagingMoves(u32 battlerAtk, u32 battlerDef, u32 currId) if (noOfHits[i] < leastHits) { leastHits = noOfHits[i]; - leastHitsId = i; } isPowerfulIgnoredEffect[i] = IsInIgnoredPowerfulMoveEffects(gBattleMoves[moves[i]].effect); } @@ -3832,10 +3805,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score break; case EFFECT_DISABLE: if (gDisableStructs[battlerDef].disableTimer == 0 - #if B_MENTAL_HERB >= GEN_5 - && aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB // mental herb - #endif - ) + && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)) { if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER) // AI goes first { @@ -3856,10 +3826,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score break; case EFFECT_ENCORE: if (gDisableStructs[battlerDef].encoreTimer == 0 - #if B_MENTAL_HERB >= GEN_5 - && aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB // mental herb - #endif - ) + && (B_MENTAL_HERB < GEN_5 || aiData->holdEffects[battlerDef] != HOLD_EFFECT_MENTAL_HERB)) { if (IsEncoreEncouragedEffect(gBattleMoves[gLastMoves[battlerDef]].effect)) ADJUST_SCORE(3); @@ -3908,9 +3875,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score { bool32 canSteal = FALSE; - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE + if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE) canSteal = TRUE; - #endif if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) canSteal = TRUE; @@ -4366,9 +4332,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score case EFFECT_CHARGE: if (HasDamagingMoveOfType(battlerAtk, TYPE_ELECTRIC)) ADJUST_SCORE(2); - #if B_CHARGE_SPDEF_RAISE >= GEN_5 - IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score); - #endif + if (B_CHARGE_SPDEF_RAISE >= GEN_5) + IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score); break; case EFFECT_TAUNT: if (IS_MOVE_STATUS(predictedMove)) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index b2f56326f7..5d77dca70b 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -420,7 +420,6 @@ static bool8 ShouldSwitchIfGameStatePrompt(u32 battler) static bool8 ShouldSwitchIfAbilityBenefit(u32 battler) { - s32 monToSwitchId; s32 moduloChance = 4; //25% Chance Default s32 chanceReducer = 1; //No Reduce default. Increase to reduce @@ -894,7 +893,7 @@ static u32 GetBestMonTypeMatchup(struct Pokemon *party, int firstId, int lastId, static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 invalidMons, u32 battler, u32 opposingBattler) { - int i, j; + int i; int dmg, bestDmg = 0; int bestMonId = PARTY_SIZE; @@ -926,7 +925,7 @@ u8 GetMostSuitableMonToSwitchInto(u32 battler) s32 firstId = 0; s32 lastId = 0; // + 1 struct Pokemon *party; - s32 i, j, aliveCount = 0; + s32 i, aliveCount = 0; u32 invalidMons = 0, aceMonId = PARTY_SIZE; if (*(gBattleStruct->monToSwitchIntoId + battler) != PARTY_SIZE) @@ -1004,8 +1003,6 @@ u8 GetMostSuitableMonToSwitchInto(u32 battler) static bool32 AiExpectsToFaintPlayer(u32 battler) { - bool32 canFaintPlayer; - u32 i; u8 target = gBattleStruct->aiChosenTarget[battler]; if (gBattleStruct->aiMoveOrAction[battler] > 3) @@ -1059,7 +1056,6 @@ static bool8 ShouldUseItem(u32 battler) { u16 item; const u8 *itemEffects; - u8 paramOffset; u8 battlerSide; item = gBattleResources->battleHistory->trainerItems[i]; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index cbda89d66e..64936e0b98 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -616,10 +616,8 @@ bool32 IsBattlerTrapped(u32 battler, bool32 checkSwitch) { u32 holdEffect = AI_DATA->holdEffects[battler]; -#if B_GHOSTS_ESCAPE >= GEN_6 - if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) + if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return FALSE; -#endif if (checkSwitch && holdEffect == HOLD_EFFECT_SHED_SHELL) return FALSE; else if (!checkSwitch && GetBattlerAbility(battler) == ABILITY_RUN_AWAY) @@ -667,9 +665,7 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) bool32 IsAffectedByPowder(u32 battler, u32 ability, u32 holdEffect) { if (ability == ABILITY_OVERCOAT - #if B_POWDER_GRASS >= GEN_6 - || IS_BATTLER_OF_TYPE(battler, TYPE_GRASS) - #endif + || (B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) return FALSE; return TRUE; @@ -706,7 +702,7 @@ s32 AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, u8 *type { SaveBattlerData(battlerAtk); SaveBattlerData(battlerDef); - AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA)); + return AI_CalcDamage(move, battlerAtk, battlerDef, typeEffectiveness, considerZPower, AI_GetWeather(AI_DATA)); } static inline s32 LowestRollDmg(s32 dmg) @@ -811,8 +807,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes case EFFECT_FINAL_GAMBIT: dmg = gBattleMons[battlerAtk].hp; break; - #if B_BEAT_UP >= GEN_5 case EFFECT_BEAT_UP: + if (B_BEAT_UP >= GEN_5) { u32 partyCount = CalculatePartyCount(GetBattlerParty(battlerAtk)); u32 i; @@ -824,7 +820,6 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes gBattleStruct->beatUpSlot = 0; } break; - #endif } // Handle other multi-strike moves @@ -1230,7 +1225,6 @@ u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered) { u32 fasterAI = 0, fasterPlayer = 0, i; s8 prioAI = 0; - s8 prioPlayer = 0; s8 prioBattler2 = 0; u16 *battler2Moves = GetMovesArray(battler2); @@ -1276,7 +1270,7 @@ u32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered) // Check if target has means to faint ai mon. bool32 CanTargetFaintAi(u32 battlerDef, u32 battlerAtk) { - s32 i, dmg; + s32 i; u32 unusable = AI_DATA->moveLimitations[battlerDef]; u16 *moves = GetMovesArray(battlerDef); @@ -1465,8 +1459,6 @@ bool32 AI_IsBattlerGrounded(u32 battlerId) bool32 DoesBattlerIgnoreAbilityChecks(u32 atkAbility, u32 move) { - u32 i; - if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE) return FALSE; // AI handicap flag: doesn't understand ability suppression concept @@ -1495,8 +1487,6 @@ u32 AI_GetWeather(struct AiLogicData *aiData) u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move) { - u32 target; - if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && AI_IsTerrainAffected(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN)) return MOVE_TARGET_BOTH; else @@ -1505,8 +1495,6 @@ u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move) bool32 IsAromaVeilProtectedMove(u32 move) { - u32 i; - switch (move) { case MOVE_DISABLE: @@ -1631,10 +1619,8 @@ bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move) if (AI_DATA->abilities[battlerDef] == ABILITY_NO_GUARD || AI_DATA->abilities[battlerAtk] == ABILITY_NO_GUARD) return TRUE; -#if B_TOXIC_NEVER_MISS >= GEN_6 - if (gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) + if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON)) return TRUE; -#endif // discouraged from hitting weather = AI_GetWeather(AI_DATA); @@ -1646,9 +1632,7 @@ bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move) if ((((weather & B_WEATHER_RAIN) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE)) || (((weather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && move == MOVE_BLIZZARD))) || (gBattleMoves[move].effect == EFFECT_VITAL_THROW) - #if B_MINIMIZE_DMG_ACC >= GEN_6 - || ((gStatuses3[battlerDef] & STATUS3_MINIMIZED) && gBattleMoves[move].minimizeDoubleDamage) - #endif + || (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && gBattleMoves[move].minimizeDoubleDamage) || (gBattleMoves[move].accuracy == 0)) { return TRUE; @@ -1681,10 +1665,8 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil else // test the odds { u32 odds = accuracy + (gBattleMons[battlerAtk].level - gBattleMons[battlerDef].level); - #if B_SHEER_COLD_ACC >= GEN_7 - if (move == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) + if (B_SHEER_COLD_ACC >= GEN_7 && move == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) odds -= 10; - #endif if (Random() % 100 + 1 < odds && gBattleMons[battlerAtk].level >= gBattleMons[battlerDef].level) return TRUE; } @@ -1808,42 +1790,40 @@ bool32 ShouldSetSnow(u32 battler, u32 ability, u32 holdEffect) void ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove, s32 *score) { // TODO more sophisticated logic - u32 predictedEffect = gBattleMoves[predictedMove].effect; - u32 defAbility = AI_DATA->abilities[battlerDef]; u32 uses = gDisableStructs[battlerAtk].protectUses; /*if (GetMoveResultFlags(predictedMove) & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_MISSED)) { - (*score) -= 5; + ADJUST_SCORE_PTR(-5); return; }*/ if (uses == 0) { if (predictedMove != MOVE_NONE && predictedMove != 0xFFFF && !IS_MOVE_STATUS(predictedMove)) - (*score) += 2; + ADJUST_SCORE_PTR(2); else if (Random() % 256 < 100) - (*score)++; + ADJUST_SCORE_PTR(1); } else { if (IsDoubleBattle()) - (*score) -= 2 * min(uses, 3); + ADJUST_SCORE_PTR(-(2 * min(uses, 3))); else - (*score) -= min(uses, 3); + ADJUST_SCORE_PTR(-(min(uses, 3))); } if (gBattleMons[battlerAtk].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_FROSTBITE) || gBattleMons[battlerAtk].status2 & (STATUS2_CURSED | STATUS2_INFATUATION) || gStatuses3[battlerAtk] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN)) { - (*score)--; + ADJUST_SCORE_PTR(-1); } if (gBattleMons[battlerDef].status1 & STATUS1_TOXIC_POISON || gBattleMons[battlerDef].status2 & (STATUS2_CURSED | STATUS2_INFATUATION) || gStatuses3[battlerDef] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN)) - (*score) += 2; + ADJUST_SCORE_PTR(2); } // stat stages @@ -2299,9 +2279,6 @@ bool32 IsStatRaisingEffect(u32 effect) case EFFECT_EVASION_UP_2: case EFFECT_MINIMIZE: case EFFECT_DEFENSE_CURL: - #if B_CHARGE_SPDEF_RAISE >= GEN_5 - case EFFECT_CHARGE: - #endif case EFFECT_CALM_MIND: case EFFECT_COSMIC_POWER: case EFFECT_DRAGON_DANCE: @@ -2318,6 +2295,8 @@ bool32 IsStatRaisingEffect(u32 effect) case EFFECT_STOCKPILE: case EFFECT_VICTORY_DANCE: return TRUE; + case EFFECT_CHARGE: + return B_CHARGE_SPDEF_RAISE >= GEN_5; default: return FALSE; } @@ -2457,15 +2436,10 @@ static u32 GetTrapDamage(u32 battlerId) if (gBattleMons[battlerId].status2 & STATUS2_WRAPPED) { if (holdEffect == HOLD_EFFECT_BINDING_BAND) - #if B_BINDING_DAMAGE >= GEN_6 - damage = gBattleMons[battlerId].maxHP / 6; + damage = gBattleMons[battlerId].maxHP / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else - damage = gBattleMons[battlerId].maxHP / 8; - #else - damage = gBattleMons[battlerId].maxHP / 8; - else - damage = gBattleMons[battlerId].maxHP / 16; - #endif + damage = gBattleMons[battlerId].maxHP / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); + if (damage == 0) damage = 1; } @@ -2705,9 +2679,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 if (!IS_MOVE_STATUS(move) && (shouldSwitch || (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH - #if B_STURDY >= GEN_5 - || defAbility == ABILITY_STURDY - #endif + || (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD)))) return PIVOT; // pivot to break sash/sturdy/multiscale @@ -2715,9 +2687,7 @@ bool32 ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 else if (!hasStatBoost) { if (!IS_MOVE_STATUS(move) && (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH - #if B_STURDY >= GEN_5 - || (defAbility == ABILITY_STURDY) - #endif + || (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD))) return PIVOT; // pivot to break sash/sturdy/multiscale @@ -2858,9 +2828,7 @@ bool32 CanKnockOffItem(u32 battler, u32 item) | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_SECRET_BASE - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE - | BATTLE_TYPE_TRAINER - #endif + | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) )) && GetBattlerSide(battler) == B_SIDE_PLAYER) return FALSE; @@ -3411,7 +3379,7 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move) { u32 i; - u32 firstId, lastId; + s32 firstId, lastId; struct Pokemon* party; bool32 hasStatus = FALSE; bool32 needHealing = FALSE; @@ -3494,7 +3462,7 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons) // party logic s32 AI_CalcPartyMonBestMoveDamage(u32 battlerAtk, u32 battlerDef, struct Pokemon *attackerMon, struct Pokemon *targetMon) { - s32 i, move, bestDmg, dmg; + s32 i, move, bestDmg, dmg = 0; u8 effectiveness; struct BattlePokemon *savedBattleMons = AllocSaveBattleMons(); @@ -3582,7 +3550,6 @@ bool32 IsPartyFullyHealedExceptBattler(u32 battlerId) bool32 PartyHasMoveSplit(u32 battlerId, u32 split) { - u32 firstId, lastId; struct Pokemon *party = GetBattlerParty(battlerId); u32 i, j; @@ -3718,39 +3685,39 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) if (HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL) && AI_DATA->hpPercents[battlerAtk] > 40) { if (gBattleMons[battlerAtk].statStages[STAT_ATK] < STAT_UP_2_STAGE) - *score += 2; + ADJUST_SCORE_PTR(2); else if (gBattleMons[battlerAtk].statStages[STAT_ATK] < STAT_UP_STAGE) - *(score)++; + ADJUST_SCORE_PTR(1); } if (HasMoveEffect(battlerAtk, EFFECT_FOUL_PLAY)) - *(score)++; + ADJUST_SCORE_PTR(1); break; case STAT_DEF: if ((HasMoveWithSplit(battlerDef, SPLIT_PHYSICAL)|| IS_MOVE_PHYSICAL(gLastMoves[battlerDef])) && AI_DATA->hpPercents[battlerAtk] > 70) { if (gBattleMons[battlerAtk].statStages[STAT_DEF] < STAT_UP_2_STAGE) - *score += 2; // seems better to raise def at higher HP + ADJUST_SCORE_PTR(2); // seems better to raise def at higher HP else if (gBattleMons[battlerAtk].statStages[STAT_DEF] < STAT_UP_STAGE) - *(score)++; + ADJUST_SCORE_PTR(1); } break; case STAT_SPEED: if (!AI_STRIKES_FIRST(battlerAtk, battlerDef, AI_THINKING_STRUCT->moveConsidered)) { if (gBattleMons[battlerAtk].statStages[STAT_SPEED] < STAT_UP_2_STAGE) - *score += 2; + ADJUST_SCORE_PTR(2); else if (gBattleMons[battlerAtk].statStages[STAT_SPEED] < STAT_UP_STAGE) - *(score)++; + ADJUST_SCORE_PTR(1); } break; case STAT_SPATK: if (HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL) && AI_DATA->hpPercents[battlerAtk] > 40) { if (gBattleMons[battlerAtk].statStages[STAT_SPATK] < STAT_UP_2_STAGE) - *score += 2; + ADJUST_SCORE_PTR(2); else if (gBattleMons[battlerAtk].statStages[STAT_SPATK] < STAT_UP_STAGE) - *(score)++; + ADJUST_SCORE_PTR(1); } break; case STAT_SPDEF: @@ -3758,24 +3725,24 @@ void IncreaseStatUpScore(u32 battlerAtk, u32 battlerDef, u32 statId, s32 *score) && AI_DATA->hpPercents[battlerAtk] > 70) { if (gBattleMons[battlerAtk].statStages[STAT_SPDEF] < STAT_UP_2_STAGE) - *score += 2; // seems better to raise spdef at higher HP + ADJUST_SCORE_PTR(2); // seems better to raise spdef at higher HP else if (gBattleMons[battlerAtk].statStages[STAT_SPDEF] < STAT_UP_STAGE) - *(score)++; + ADJUST_SCORE_PTR(1); } break; case STAT_ACC: if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 80, TRUE, AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef], AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef])) - *score += 2; // has moves with less than 80% accuracy + ADJUST_SCORE_PTR(2); // has moves with less than 80% accuracy else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, TRUE, AI_DATA->abilities[battlerAtk], AI_DATA->abilities[battlerDef], AI_DATA->holdEffects[battlerAtk], AI_DATA->holdEffects[battlerDef])) - *(score)++; + ADJUST_SCORE_PTR(1); break; case STAT_EVASION: if (!BattlerWillFaintFromWeather(battlerAtk, AI_DATA->abilities[battlerAtk])) { if (!GetBattlerSecondaryDamage(battlerAtk) && !(gStatuses3[battlerAtk] & STATUS3_ROOTED)) - *score += 2; + ADJUST_SCORE_PTR(2); else - *(score)++; + ADJUST_SCORE_PTR(1); } break; } @@ -3790,18 +3757,18 @@ void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (AI_CanPoison(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove) && AI_DATA->hpPercents[battlerDef] > 20) { if (!HasDamagingMove(battlerDef)) - *score += 2; + ADJUST_SCORE_PTR(2); if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT)) - (*score)++; // stall tactic + ADJUST_SCORE_PTR(1); // stall tactic if (HasMoveEffect(battlerAtk, EFFECT_VENOSHOCK) || HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH) || AI_DATA->abilities[battlerAtk] == ABILITY_MERCILESS) - *(score) += 2; + ADJUST_SCORE_PTR(2); else - *(score)++; + ADJUST_SCORE_PTR(1); } } @@ -3813,15 +3780,15 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) if (AI_CanBurn(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) { - (*score)++; // burning is good + ADJUST_SCORE_PTR(1); // burning is good if (HasMoveWithSplit(battlerDef, SPLIT_PHYSICAL)) { if (CanTargetFaintAi(battlerDef, battlerAtk)) - *score += 2; // burning the target to stay alive is cool + ADJUST_SCORE_PTR(2); // burning the target to stay alive is cool } if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX)) - (*score)++; + ADJUST_SCORE_PTR(1); } } @@ -3841,9 +3808,9 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) || HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT) || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION || gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) - *score += 4; + ADJUST_SCORE_PTR(4); else - *score += 2; + ADJUST_SCORE_PTR(2); } } @@ -3854,16 +3821,16 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) return; if (AI_CanPutToSleep(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) - *score += 2; + ADJUST_SCORE_PTR(2); else return; if ((HasMoveEffect(battlerAtk, EFFECT_DREAM_EATER) || HasMoveEffect(battlerAtk, EFFECT_NIGHTMARE)) && !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK))) - (*score)++; + ADJUST_SCORE_PTR(1); if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX)) - (*score)++; + ADJUST_SCORE_PTR(1); } void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) @@ -3879,9 +3846,9 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score if (gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS || gBattleMons[battlerDef].status2 & STATUS2_INFATUATION || (AI_DATA->abilities[battlerAtk] == ABILITY_SERENE_GRACE && HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT))) - *score += 3; + ADJUST_SCORE_PTR(3); else - *score += 2; + ADJUST_SCORE_PTR(2); } } @@ -3892,15 +3859,15 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score if (AI_CanGiveFrostbite(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) { - (*score)++; // frostbite is good + ADJUST_SCORE_PTR(1); // frostbite is good if (HasMoveWithSplit(battlerDef, SPLIT_SPECIAL)) { if (CanTargetFaintAi(battlerDef, battlerAtk)) - *score += 2; // frostbiting the target to stay alive is cool + ADJUST_SCORE_PTR(2); // frostbiting the target to stay alive is cool } if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX)) - (*score)++; + ADJUST_SCORE_PTR(1); } } diff --git a/src/battle_anim.c b/src/battle_anim.c index 8caa2850cb..c46c5cee4c 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -248,6 +248,7 @@ void LaunchBattleAnimation(u32 animType, u32 animId) switch (animType) { case ANIM_TYPE_GENERAL: + default: animsTable = gBattleAnims_General; break; case ANIM_TYPE_MOVE: @@ -1468,10 +1469,8 @@ static void LoadDefaultBg(void) { if (IsContest()) LoadContestBgAfterMoveAnim(); -#if B_TERRAIN_BG_CHANGE == TRUE - else if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + else if (B_TERRAIN_BG_CHANGE == TRUE && gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) DrawTerrainTypeBattleBackground(); -#endif else DrawMainBattleBackground(); } diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c old mode 100755 new mode 100644 index 822adc1733..2c8572cc8c --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -721,8 +721,6 @@ const struct SpriteTemplate gSweetScentPetalSpriteTemplate = .callback = AnimSweetScentPetal, }; -static const u16 sUnusedPalette[] = INCBIN_U16("graphics/battle_anims/unused/unknown.gbapal"); - const union AnimCmd gPainSplitAnimCmds[] = { ANIMCMD_FRAME(0, 5), diff --git a/src/battle_anim_ghost.c b/src/battle_anim_ghost.c index e49d2411de..7bd6a0268e 100644 --- a/src/battle_anim_ghost.c +++ b/src/battle_anim_ghost.c @@ -1447,7 +1447,6 @@ static void AnimPoltergeistItem(struct Sprite *sprite) void AnimTask_PulverizingPancakeWhiteShadow(u8 taskId) { struct Task *task; - s16 battler; u8 spriteId; s16 baseX, baseY; s16 x, y; diff --git a/src/battle_anim_ground.c b/src/battle_anim_ground.c index a89800492f..6119371757 100644 --- a/src/battle_anim_ground.c +++ b/src/battle_anim_ground.c @@ -750,7 +750,7 @@ static void SetBattlersXOffsetForShake(struct Task *task) void AnimTask_IsPowerOver99(u8 taskId) { - gBattleAnimArgs[15] = gAnimMovePower > 99; + gBattleAnimArgs[ARG_RET_ID] = gAnimMovePower > 99; DestroyAnimVisualTask(taskId); } diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index bdb7e50649..f150afb799 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -81,8 +81,6 @@ static void SpriteCB_HorizontalSliceStep(struct Sprite *sprite); static void SpriteCB_HorizontalSlice(struct Sprite *sprite); static void SpriteCB_LashOutStrike(struct Sprite* sprite); static void AnimTask_TwinkleTackleLaunchStep(u8 taskId); -static void SpriteCB_ShellSmashShell(struct Sprite* sprite); -static void SpriteCB_ShellSmashShell_DestroyDuringFadeOut(struct Sprite* sprite); static void SpriteCB_AnimSpriteOnTargetSideCentre(struct Sprite *sprite); static void SpriteCB_SpriteOnMonUntilAffineAnimEnds(struct Sprite* sprite); static void SpriteCB_MoveSpriteUpwardsForDurationStep(struct Sprite* sprite); @@ -8726,6 +8724,7 @@ static void SpriteCB_LashOutStrike(struct Sprite* sprite) sprite->callback = AnimKnockOffStrike_Step; } +/* TODO - Use the ShellSmash Anim //Moves the shells towards the attacker and leaves them there until they fade out //arg 0: Initial x-pos //arg 1: Final x-pos @@ -8753,6 +8752,7 @@ static void SpriteCB_ShellSmashShell_DestroyDuringFadeOut(struct Sprite* sprite) if (GetGpuReg(REG_OFFSET_BLDALPHA) >= BLDALPHA_BLEND(0, 8)) //Fade out 1/2 done DestroyAnimSprite(sprite); } +*/ static void SpriteCB_AnimSpriteOnTargetSideCentre(struct Sprite *sprite) { diff --git a/src/battle_anim_rock.c b/src/battle_anim_rock.c index c1dc754c1f..6811c857b3 100644 --- a/src/battle_anim_rock.c +++ b/src/battle_anim_rock.c @@ -351,8 +351,7 @@ const struct SpriteTemplate gSeedFlareGreenWavesTemplate = static void AnimStealthRock(struct Sprite *sprite) { - u16 x; - u16 y; + s16 x, y; InitSpritePosToAnimAttacker(sprite, TRUE); SetAverageBattlerPositions(gBattleAnimTarget, FALSE, &x, &y); diff --git a/src/battle_anim_water.c b/src/battle_anim_water.c index 961f154baa..e4044efe65 100644 --- a/src/battle_anim_water.c +++ b/src/battle_anim_water.c @@ -57,9 +57,6 @@ static void AnimAquaTail(struct Sprite *sprite); static void AnimKnockOffAquaTail(struct Sprite *sprite); static void AnimKnockOffAquaTailStep(struct Sprite *sprite); -static const u8 sUnusedWater_Gfx[] = INCBIN_U8("graphics/battle_anims/unused/water_gfx.4bpp"); -static const u8 sUnusedWater[] = INCBIN_U8("graphics/battle_anims/unused/water.bin"); - static const union AnimCmd sAnim_RainDrop[] = { ANIMCMD_FRAME(0, 2), diff --git a/src/battle_bg.c b/src/battle_bg.c index efc021951d..1da5d5c65e 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -859,11 +859,10 @@ void LoadBattleTextboxAndBackground(void) CopyBgTilemapBufferToVram(0); LoadCompressedPalette(gBattleTextboxPalette, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); LoadBattleMenuWindowGfx(); -#if B_TERRAIN_BG_CHANGE == TRUE - DrawTerrainTypeBattleBackground(); -#else - DrawMainBattleBackground(); -#endif + if (B_TERRAIN_BG_CHANGE == TRUE) + DrawTerrainTypeBattleBackground(); + else + DrawMainBattleBackground(); } static void DrawLinkBattleParticipantPokeballs(u8 taskId, u8 multiplayerId, u8 bgId, u8 destX, u8 destY) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index f0dfaf5865..703d66105b 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -595,9 +595,8 @@ static void OpponentHandleChooseMove(u32 battler) target = GetBattlerAtPosition(Random() & 2); } while (!CanTargetBattler(battler, target, move)); - #if B_WILD_NATURAL_ENEMIES == TRUE // Don't bother to loop through table if the move can't attack ally - if (!(gBattleMoves[move].target & MOVE_TARGET_BOTH)) + if (B_WILD_NATURAL_ENEMIES == TRUE && !(gBattleMoves[move].target & MOVE_TARGET_BOTH)) { u16 i, speciesAttacker, speciesTarget, isPartnerEnemy = FALSE; static const u16 naturalEnemies[][2] = @@ -627,8 +626,9 @@ static void OpponentHandleChooseMove(u32 battler) BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (target << 8)); } else - #endif + { BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (target << 8)); + } } else BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) << 8)); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 0c7eacdf24..feabb2863a 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -202,7 +202,7 @@ static void CompleteOnBattlerSpritePosX_0(u32 battler) static u16 GetPrevBall(u16 ballId) { u16 ballPrev; - u32 i, j; + s32 i, j; CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]); for (i = 0; i < gBagPockets[BALLS_POCKET].capacity; i++) { @@ -218,28 +218,29 @@ static u16 GetPrevBall(u16 ballId) } } i--; - return gBagPockets[BALLS_POCKET].itemSlots[i].itemId; + break; } } + return gBagPockets[BALLS_POCKET].itemSlots[i].itemId; } static u16 GetNextBall(u16 ballId) { - u16 ballNext; - u32 i; + u16 ballNext = 0; + s32 i; CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]); for (i = 0; i < gBagPockets[BALLS_POCKET].capacity; i++) { if (ballId == gBagPockets[BALLS_POCKET].itemSlots[i].itemId) { - i++; ballNext = gBagPockets[BALLS_POCKET].itemSlots[i].itemId; - if (ballNext == ITEM_NONE) - return gBagPockets[BALLS_POCKET].itemSlots[0].itemId; // Zeroth slot - else - return ballNext; + break; } } + if (ballNext == ITEM_NONE) + return gBagPockets[BALLS_POCKET].itemSlots[0].itemId; // Zeroth slot + else + return ballNext; } static void HandleInputChooseAction(u32 battler) @@ -729,25 +730,26 @@ static void HandleInputChooseMove(u32 battler) canSelectTarget = 0; } - #if B_SHOW_TARGETS == TRUE - // Show all available targets for multi-target moves - if ((moveTarget & MOVE_TARGET_ALL_BATTLERS) == MOVE_TARGET_ALL_BATTLERS) + if (B_SHOW_TARGETS == TRUE) { - u32 i = 0; - for (i = 0; i < gBattlersCount; i++) - TryShowAsTarget(i); + // Show all available targets for multi-target moves + if ((moveTarget & MOVE_TARGET_ALL_BATTLERS) == MOVE_TARGET_ALL_BATTLERS) + { + u32 i = 0; + for (i = 0; i < gBattlersCount; i++) + TryShowAsTarget(i); - canSelectTarget = 3; + canSelectTarget = 3; + } + else if (moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + { + TryShowAsTarget(gMultiUsePlayerCursor); + TryShowAsTarget(BATTLE_PARTNER(gMultiUsePlayerCursor)); + if (moveTarget & MOVE_TARGET_FOES_AND_ALLY) + TryShowAsTarget(BATTLE_PARTNER(battler)); + canSelectTarget = 2; + } } - else if (moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) - { - TryShowAsTarget(gMultiUsePlayerCursor); - TryShowAsTarget(BATTLE_PARTNER(gMultiUsePlayerCursor)); - if (moveTarget & MOVE_TARGET_FOES_AND_ALLY) - TryShowAsTarget(BATTLE_PARTNER(battler)); - canSelectTarget = 2; - } - #endif } switch (canSelectTarget) @@ -1839,7 +1841,7 @@ static void PlayerHandleDrawTrainerPic(u32 battler) { bool32 isFrontPic; s16 xPos, yPos; - u32 trainerPicId, gender; + u32 trainerPicId; trainerPicId = PlayerGetTrainerBackPicId(); if (gBattleTypeFlags & BATTLE_TYPE_MULTI) diff --git a/src/battle_debug.c b/src/battle_debug.c index 87095e4bbc..cf7c9c4235 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -844,7 +844,7 @@ static const u8 *const sAiInfoItemNames[] = static void PutAiInfoText(struct BattleDebugMenu *data) { - u32 i, j, count; + u32 i; u8 *text = Alloc(0x50); FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); diff --git a/src/battle_dome.c b/src/battle_dome.c index ad7c60dd1c..313d7289d9 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -2796,7 +2796,6 @@ static int SelectOpponentMonsFromParty(int *partyMovePoints, bool8 allowRandom) static int GetTypeEffectivenessPoints(int move, int targetSpecies, int mode) { int defType1, defType2, defAbility, moveType; - int i = 0; int typePower = TYPE_x1; if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || IS_MOVE_STATUS(move)) diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 3ac4ff05b4..d66d2592c4 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -591,13 +591,16 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) else { species = gBattleSpritesDataPtr->battlerData[battler].transformSpecies; - #if B_TRANSFORM_SHINY >= GEN_4 + if (B_TRANSFORM_SHINY >= GEN_4) + { currentPersonality = gTransformedPersonalities[battler]; currentOtId = gTransformedOtIds[battler]; - #else + } + else + { currentPersonality = monsPersonality; currentOtId = otId; - #endif + } } position = GetBattlerPosition(battler); @@ -894,14 +897,12 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo if (GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) { - #if B_TRANSFORM_SHINY >= GEN_4 - if (trackEnemyPersonality) + if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); } else - #endif { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); @@ -915,15 +916,13 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo } else { - #if B_TRANSFORM_SHINY >= GEN_4 - if (trackEnemyPersonality) + if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); } else - #endif { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); diff --git a/src/battle_interface.c b/src/battle_interface.c index da2d234f1e..139bcc1603 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -754,12 +754,6 @@ static const struct SpriteTemplate sSpriteTemplate_BurstTrigger = #define hBar_HealthBoxSpriteId data[5] #define hBar_Data6 data[6] -static void InitLastUsedBallAssets(void) -{ - gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; - gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; -} - // This function is here to cover a specific case - one player's mon in a 2 vs 1 double battle. In this scenario - display singles layout. // The same goes for a 2 vs 1 where opponent has only one pokemon. u32 WhichBattleCoords(u32 battlerId) // 0 - singles, 1 - doubles @@ -780,7 +774,7 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId) { s16 data6 = 0; u8 healthboxLeftSpriteId, healthboxRightSpriteId; - u8 healthbarSpriteId, megaIndicatorSpriteId; + u8 healthbarSpriteId; struct Sprite *healthBarSpritePtr; if (WhichBattleCoords(battlerId) == 0) // Singles @@ -1002,10 +996,8 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) MegaIndicator_UpdateOamPriority(healthboxLeftSpriteId, priority); DynamaxIndicator_UpdateOamPriority(healthboxLeftSpriteId, priority); - #if B_HIDE_HEALTHBOX_IN_ANIMS - if (hideHPBoxes && IsBattlerAlive(i)) + if (B_HIDE_HEALTHBOX_IN_ANIMS == TRUE && hideHPBoxes && IsBattlerAlive(i)) TryToggleHealboxVisibility(priority, healthboxLeftSpriteId, healthboxRightSpriteId, healthbarSpriteId); - #endif } } @@ -1099,7 +1091,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) static void PrintHpOnHealthbox(u32 spriteId, s16 currHp, s16 maxHp, u32 bgColor, u32 rightTile, u32 leftTile) { u8 *windowTileData; - u32 windowId, tilesCount, x, healthboxTileNum; + u32 windowId, tilesCount, x; u8 text[28], *txtPtr; void *objVram = (void *)(OBJ_VRAM0) + gSprites[spriteId].oam.tileNum * TILE_SIZE_4BPP; @@ -1702,7 +1694,6 @@ void MegaIndicator_LoadSpritesGfx(void) static bool32 MegaIndicator_ShouldBeInvisible(u32 battlerId, struct Sprite *sprite) { - u32 side = GetBattlerSide(battlerId); bool32 megaEvolved = IsBattlerMegaEvolved(battlerId); bool32 primalReverted = IsBattlerPrimalReverted(battlerId); @@ -1749,7 +1740,6 @@ static void MegaIndicator_UpdateOamPriority(u32 healthboxId, u32 oamPriority) static void MegaIndicator_UpdateLevel(u32 healthboxId, u32 level) { - u32 i; s16 xDelta = 0; u8 *spriteId = MegaIndicator_GetSpriteId(healthboxId); @@ -1764,7 +1754,7 @@ static void MegaIndicator_UpdateLevel(u32 healthboxId, u32 level) static void MegaIndicator_CreateSprite(u32 battlerId, u32 healthboxSpriteId) { struct SpriteTemplate sprTemplate; - u32 position, level; + u32 position; u8 *spriteId; s16 xHealthbox = 0, y = 0; s32 x = 0; @@ -2624,15 +2614,12 @@ s32 MoveBattleBar(u8 battlerId, u8 healthboxSpriteId, u8 whichBar, u8 unused) if (whichBar == HEALTH_BAR) // health bar { + u16 hpFraction = B_FAST_HP_DRAIN == FALSE ? 1 : max(gBattleSpritesDataPtr->battleBars[battlerId].maxValue / B_HEALTHBAR_PIXELS, 1); currentBarValue = CalcNewBarValue(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, gBattleSpritesDataPtr->battleBars[battlerId].oldValue, gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, &gBattleSpritesDataPtr->battleBars[battlerId].currValue, - #if B_FAST_HP_DRAIN == TRUE - B_HEALTHBAR_PIXELS / 8, max(gBattleSpritesDataPtr->battleBars[battlerId].maxValue / B_HEALTHBAR_PIXELS, 1)); - #else - B_HEALTHBAR_PIXELS / 8, 1); - #endif + B_HEALTHBAR_PIXELS / 8, hpFraction); } else // exp bar { @@ -3249,10 +3236,12 @@ static void RestoreOverwrittenPixels(u8 *tiles) void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle) { -#if B_ABILITY_POP_UP == TRUE const s16 (*coords)[2]; u8 spriteId1, spriteId2, battlerPosition, taskId; + if (B_ABILITY_POP_UP == FALSE) + return; + if (gTestRunnerEnabled) { TestRunner_Battle_RecordAbilityPopUp(battlerId, ability); @@ -3322,7 +3311,6 @@ void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle) PrintBattlerOnAbilityPopUp(battlerId, spriteId1, spriteId2); PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); -#endif } void UpdateAbilityPopup(u8 battlerId) @@ -3405,18 +3393,10 @@ static const struct OamData sOamData_LastUsedBall = .objMode = 0, .mosaic = 0, .bpp = 0, -#if B_LAST_USED_BALL_CYCLE == TRUE - .shape = SPRITE_SHAPE(32x64), -#else - .shape = SPRITE_SHAPE(32x32), -#endif + .shape = (B_LAST_USED_BALL_CYCLE == TRUE ? SPRITE_SHAPE(32x64) : SPRITE_SHAPE(32x32)), .x = 0, .matrixNum = 0, -#if B_LAST_USED_BALL_CYCLE == TRUE - .size = SPRITE_SIZE(32x64), -#else - .size = SPRITE_SIZE(32x32), -#endif + .size = (B_LAST_USED_BALL_CYCLE == TRUE ? SPRITE_SIZE(32x64) : SPRITE_SIZE(32x32)), .tileNum = 0, .priority = 1, .paletteNum = 0, @@ -3467,9 +3447,8 @@ static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = bool32 CanThrowLastUsedBall(void) { -#if B_LAST_USED_BALL == FALSE - return FALSE; -#else + if (B_LAST_USED_BALL == FALSE) + return FALSE; if (!CanThrowBall()) return FALSE; if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FRONTIER)) @@ -3478,12 +3457,12 @@ bool32 CanThrowLastUsedBall(void) return FALSE; return TRUE; -#endif } void TryAddLastUsedBallItemSprites(void) { -#if B_LAST_USED_BALL == TRUE + if (B_LAST_USED_BALL == FALSE) + return; if (gLastThrownBall == 0 || (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1))) { @@ -3520,10 +3499,8 @@ void TryAddLastUsedBallItemSprites(void) gSprites[gBattleStruct->ballSpriteIds[1]].sHide = FALSE; // restore gLastUsedBallMenuPresent = TRUE; } -#if B_LAST_USED_BALL_CYCLE == TRUE - ArrowsChangeColorLastBallCycle(0); //Default the arrows to be invisible -#endif -#endif + if (B_LAST_USED_BALL_CYCLE == TRUE) + ArrowsChangeColorLastBallCycle(0); //Default the arrows to be invisible } static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) @@ -3581,7 +3558,8 @@ static void SpriteCB_LastUsedBall(struct Sprite *sprite) static void TryHideOrRestoreLastUsedBall(u8 caseId) { -#if B_LAST_USED_BALL == TRUE + if (B_LAST_USED_BALL == FALSE) + return; if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) return; @@ -3602,27 +3580,25 @@ static void TryHideOrRestoreLastUsedBall(u8 caseId) gLastUsedBallMenuPresent = TRUE; break; } -#if B_LAST_USED_BALL_CYCLE == TRUE - ArrowsChangeColorLastBallCycle(0); //Default the arrows to be invisible -#endif -#endif + if (B_LAST_USED_BALL_CYCLE == TRUE) + ArrowsChangeColorLastBallCycle(0); //Default the arrows to be invisible } void TryHideLastUsedBall(void) { -#if B_LAST_USED_BALL == TRUE - TryHideOrRestoreLastUsedBall(0); -#endif + if (B_LAST_USED_BALL == TRUE) + TryHideOrRestoreLastUsedBall(0); } void TryRestoreLastUsedBall(void) { -#if B_LAST_USED_BALL == TRUE + if (B_LAST_USED_BALL == FALSE) + return; + if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) TryHideOrRestoreLastUsedBall(1); else TryAddLastUsedBallItemSprites(); -#endif } static void SpriteCB_LastUsedBallBounce(struct Sprite *sprite) @@ -3682,13 +3658,13 @@ static void Task_BounceBall(u8 taskId) sprite->callback = SpriteCB_LastUsedBallBounce; //Show and bounce down task->sState++; } - break; + break; case 4: // Destroy Task if(!sprite->sMoving) { sprite->callback = SpriteCB_LastUsedBall; DestroyTask(taskId); - } + } } if (!gLastUsedBallMenuPresent) { diff --git a/src/battle_intro.c b/src/battle_intro.c index d26c7efa2b..537edebb71 100644 --- a/src/battle_intro.c +++ b/src/battle_intro.c @@ -587,7 +587,6 @@ static void BattleIntroSlidePartner(u8 taskId) void DrawBattlerOnBg(int bgId, u8 x, u8 y, u8 battlerPosition, u8 paletteId, u8 *tiles, u16 *tilemap, u16 tilesOffset) { int i, j; - u8 battler = GetBattlerAtPosition(battlerPosition); int offset = tilesOffset; CpuCopy16(gMonSpritesGfxPtr->sprites.ptr[battlerPosition], tiles, BG_SCREEN_SIZE); LoadBgTiles(bgId, tiles, 0x1000, tilesOffset); diff --git a/src/battle_main.c b/src/battle_main.c index c9f149b439..a6db696400 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -87,7 +87,6 @@ static void AskRecordBattle(void); static void SpriteCB_MoveWildMonToRight(struct Sprite *sprite); static void SpriteCB_WildMonShowHealthbox(struct Sprite *sprite); static void SpriteCB_WildMonAnimate(struct Sprite *sprite); -static void SpriteCB_Flicker(struct Sprite *sprite); static void SpriteCB_AnimFaintOpponent(struct Sprite *sprite); static void SpriteCB_BlinkVisible(struct Sprite *sprite); static void SpriteCB_Idle(struct Sprite *sprite); @@ -103,7 +102,6 @@ static void SetActionsAndBattlersTurnOrder(void); static void UpdateBattlerPartyOrdersOnSwitch(u32 battler); static bool8 AllAtActionConfirmed(void); static void TryChangeTurnOrder(void); -static void CheckChosenMoveForEffectsBeforeTurnStarts(void); static void CheckQuickClaw_CustapBerryActivation(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); @@ -133,16 +131,10 @@ EWRAM_DATA u16 gBattle_WIN0H = 0; EWRAM_DATA u16 gBattle_WIN0V = 0; EWRAM_DATA u16 gBattle_WIN1H = 0; EWRAM_DATA u16 gBattle_WIN1V = 0; -EWRAM_DATA u8 gDisplayedStringBattle[400] = {0}; +EWRAM_DATA u8 gDisplayedStringBattle[425] = {0}; // Increased in size to fit Juan's defeat text (SootopolisCity_Gym_1F_Text_JuanDefeat) EWRAM_DATA u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT] = {0}; EWRAM_DATA u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT] = {0}; -EWRAM_DATA u8 gBattleTextBuff3[30] = {0}; //expanded for stupidly long z move names -// The below array is never intentionally used. However, Juan's -// defeat text (SootopolisCity_Gym_1F_Text_JuanDefeat) is too long -// for gDisplayedStringBattle and overflows into this array. If it -// is removed (and none of the buffers above are increased in size) -// it will instead overflow into useful data. -EWRAM_DATA static u32 sFlickerArray[25] = {0}; +EWRAM_DATA u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT + 13] = {0}; // expanded for stupidly long z move names EWRAM_DATA u32 gBattleTypeFlags = 0; EWRAM_DATA u8 gBattleTerrain = 0; EWRAM_DATA u32 gUnusedFirstBattleVar1 = 0; // Never read @@ -235,7 +227,7 @@ EWRAM_DATA u32 gFieldStatuses = 0; EWRAM_DATA struct FieldTimer gFieldTimers = {0}; EWRAM_DATA u8 gBattlerAbility = 0; EWRAM_DATA u16 gPartnerSpriteId = 0; -EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA bool8 gHasFetchedBall = FALSE; EWRAM_DATA u8 gLastUsedBall = 0; EWRAM_DATA u16 gLastThrownBall = 0; @@ -508,7 +500,6 @@ void CB2_InitBattle(void) static void CB2_InitBattleInternal(void) { s32 i; - u16 targetSpecies; SetHBlankCallback(NULL); SetVBlankCallback(NULL); @@ -605,14 +596,11 @@ static void CB2_InitBattleInternal(void) gSaveBlock2Ptr->frontier.disableRecordBattle = FALSE; for (i = 0; i < PARTY_SIZE; i++) + { AdjustFriendship(&gPlayerParty[i], FRIENDSHIP_EVENT_LEAGUE_BATTLE); - // Apply party-wide start-of-battle form changes - for (i = 0; i < PARTY_SIZE; i++) - { - // Player's side + // Apply party-wide start-of-battle form changes for both sides. TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BEGIN_BATTLE); - // Opponent's side TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } @@ -1940,7 +1928,6 @@ void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags) { u32 personalityValue; - u8 fixedIV; s32 i, j; u8 monsCount; if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER @@ -2696,29 +2683,6 @@ void SpriteCallbackDummy_2(struct Sprite *sprite) } -#define sNumFlickers data[3] -#define sDelay data[4] - -static void SpriteCB_Flicker(struct Sprite *sprite) -{ - sprite->sDelay--; - if (sprite->sDelay == 0) - { - sprite->sDelay = 8; - sprite->invisible ^= 1; - sprite->sNumFlickers--; - if (sprite->sNumFlickers == 0) - { - sprite->invisible = FALSE; - sprite->callback = SpriteCallbackDummy_2; - // sFlickerArray[0] = 0; - } - } -} - -#undef sNumFlickers -#undef sDelay - extern const struct MonCoords gMonFrontPicCoords[]; void SpriteCB_FaintOpponentMon(struct Sprite *sprite) @@ -3249,6 +3213,7 @@ void SwitchInClearSetData(u32 battler) gSelectedMonPartyId = PARTY_SIZE; // Allow for illegal abilities within tests. + #if TESTING if (gTestRunnerEnabled) { u32 side = GetBattlerSide(battler); @@ -3256,6 +3221,7 @@ void SwitchInClearSetData(u32 battler) if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex); } + #endif // TESTING Ai_UpdateSwitchInData(battler); } @@ -3521,11 +3487,10 @@ static void DoBattleIntro(void) } else // Skip party summary since it is a wild battle. { - #if B_FAST_INTRO == TRUE - *state = 7; // Don't wait for sprite, print message at the same time. - #else - *state = 6; // Wait for sprite to load. - #endif + if (B_FAST_INTRO == TRUE) + *state = 7; // Don't wait for sprite, print message at the same time. + else + *state = 6; // Wait for sprite to load. } break; case 5: // draw party summary in trainer battles @@ -3594,11 +3559,10 @@ static void DoBattleIntro(void) } else { - #if B_FAST_INTRO == TRUE - *state = 15; // Wait for text to be printed. - #else - *state = 14; // Wait for text and sprite. - #endif + if (B_FAST_INTRO == TRUE) + *state = 15; // Wait for text to be printed. + else + *state = 14; // Wait for text and sprite. } } break; @@ -3636,11 +3600,10 @@ static void DoBattleIntro(void) BtlController_EmitIntroTrainerBallThrow(battler, BUFFER_A); MarkBattlerForControllerExec(battler); } - #if B_FAST_INTRO == TRUE - if (!(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK))) + if (B_FAST_INTRO == TRUE + && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK))) *state = 15; // Print at the same time as trainer sends out second mon. else - #endif (*state)++; break; case 14: // wait for opponent 2 send out @@ -3660,14 +3623,13 @@ static void DoBattleIntro(void) battler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); // A hack that makes fast intro work in trainer battles too. - #if B_FAST_INTRO == TRUE - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER + if (B_FAST_INTRO == TRUE + && gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK)) && gSprites[gHealthboxSpriteIds[battler ^ BIT_SIDE]].callback == SpriteCallbackDummy) { return; } - #endif PrepareStringBattle(STRINGID_INTROSENDOUT, battler); } @@ -3755,6 +3717,7 @@ static void TryDoEventsBeforeFirstTurn(void) } // Allow for illegal abilities within tests. + #if TESTING if (gTestRunnerEnabled && gBattleStruct->switchInAbilitiesCounter == 0) { for (i = 0; i < gBattlersCount; ++i) @@ -3765,6 +3728,7 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex); } } + #endif // TESTING if (gBattleStruct->switchInAbilitiesCounter == 0) { @@ -3795,14 +3759,13 @@ static void TryDoEventsBeforeFirstTurn(void) // Totem boosts for (i = 0; i < gBattlersCount; i++) { - if (gTotemBoosts[i].stats != 0) + if (gQueuedStatBoosts[i].stats != 0 && !gProtectStructs[i].eatMirrorHerb && gProtectStructs[i].activateOpportunist == 0) { gBattlerAttacker = i; BattleScriptExecute(BattleScript_TotemVar); return; } } - memset(gTotemBoosts, 0, sizeof(gTotemBoosts)); // erase all totem boosts just to be safe // Check neutralizing gas if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) @@ -3827,6 +3790,9 @@ static void TryDoEventsBeforeFirstTurn(void) return; } + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) + return; + for (i = 0; i < MAX_BATTLERS_COUNT; i++) { *(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE; @@ -3860,6 +3826,8 @@ static void TryDoEventsBeforeFirstTurn(void) gRandomTurnNumber = Random(); + memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts just to be safe + SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers if (gBattleTypeFlags & BATTLE_TYPE_ARENA) @@ -3999,10 +3967,8 @@ u8 IsRunningFromBattleImpossible(u32 battler) if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN) return BATTLE_RUN_SUCCESS; - #if B_GHOSTS_ESCAPE >= GEN_6 - if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) - return BATTLE_RUN_SUCCESS; - #endif + if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) + return BATTLE_RUN_SUCCESS; if (gBattleTypeFlags & BATTLE_TYPE_LINK) return BATTLE_RUN_SUCCESS; if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY) @@ -4680,11 +4646,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect) // paralysis drop if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && ability != ABILITY_QUICK_FEET) - #if B_PARALYSIS_SPEED >= GEN_7 - speed /= 2; - #else - speed /= 4; - #endif + speed /= B_PARALYSIS_SPEED >= GEN_7 ? 2 : 4; return speed; } @@ -4721,9 +4683,7 @@ s8 GetMovePriority(u32 battler, u16 move) return gBattleMoves[MOVE_MAX_GUARD].priority; if (ability == ABILITY_GALE_WINGS - #if B_GALE_WINGS >= GEN_7 - && BATTLER_MAX_HP(battler) - #endif + && (B_GALE_WINGS < GEN_7 || BATTLER_MAX_HP(battler)) && gBattleMoves[move].type == TYPE_FLYING) { priority++; @@ -4773,7 +4733,7 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Battler 1 // Quick Draw - if (!ignoreChosenMoves && ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && Random() % 100 < 30) + if (!ignoreChosenMoves && ability1 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler1]) && RandomPercentage(RNG_QUICK_DRAW, 30)) gProtectStructs[battler1].quickDraw = TRUE; // Quick Claw and Custap Berry if (!gProtectStructs[battler1].quickDraw @@ -4783,7 +4743,7 @@ u32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Battler 2 // Quick Draw - if (!ignoreChosenMoves && ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && Random() % 100 < 30) + if (!ignoreChosenMoves && ability2 == ABILITY_QUICK_DRAW && !IS_MOVE_STATUS(gChosenMoveByBattler[battler2]) && RandomPercentage(RNG_QUICK_DRAW, 30)) gProtectStructs[battler2].quickDraw = TRUE; // Quick Claw and Custap Berry if (!gProtectStructs[battler2].quickDraw @@ -4992,6 +4952,7 @@ static void TurnValuesCleanUp(bool8 var0) gProtectStructs[i].kingsShielded = FALSE; gProtectStructs[i].banefulBunkered = FALSE; gProtectStructs[i].quash = FALSE; + gProtectStructs[i].usedCustapBerry = FALSE; } else { @@ -5038,8 +4999,6 @@ static bool32 TryDoGimmicksBeforeMoves(void) && (gBattleStruct->mega.toEvolve || gBattleStruct->burst.toBurst || gBattleStruct->dynamax.toDynamax)) { u32 i, battler; - struct Pokemon *party; - struct Pokemon *mon; u8 order[MAX_BATTLERS_COUNT]; PopulateArrayWithBattlers(order); @@ -5063,8 +5022,6 @@ static bool32 TryDoGimmicksBeforeMoves(void) gBattlerAttacker = order[i]; gBattleStruct->mega.toEvolve &= ~(gBitTable[gBattlerAttacker]); gLastUsedItem = gBattleMons[gBattlerAttacker].item; - party = GetBattlerParty(gBattlerAttacker); - mon = &party[gBattlerPartyIndexes[gBattlerAttacker]]; if (GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) BattleScriptExecute(BattleScript_WishMegaEvolution); else @@ -5078,17 +5035,14 @@ static bool32 TryDoGimmicksBeforeMoves(void) battler = gBattlerAttacker = order[i]; gBattleStruct->burst.toBurst &= ~(gBitTable[battler]); gLastUsedItem = gBattleMons[battler].item; - party = GetBattlerParty(battler); - mon = &party[gBattlerPartyIndexes[battler]]; BattleScriptExecute(BattleScript_UltraBurst); return TRUE; } } } - #if B_MEGA_EVO_TURN_ORDER >= GEN_7 + if (B_MEGA_EVO_TURN_ORDER >= GEN_7) TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved. - #endif return FALSE; } @@ -5097,7 +5051,6 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) if (!(gHitMarker & HITMARKER_RUN)) { u32 i; - struct Pokemon *mon; u8 battlers[MAX_BATTLERS_COUNT]; PopulateArrayWithBattlers(battlers); @@ -5170,7 +5123,6 @@ static void CheckQuickClaw_CustapBerryActivation(void) { if (gProtectStructs[battler].usedCustapBerry) { - gProtectStructs[battler].usedCustapBerry = FALSE; gLastUsedItem = gBattleMons[battler].item; PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem); if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_CUSTAP_BERRY) @@ -5440,14 +5392,15 @@ static void HandleEndTurn_FinishBattle(void) TestRunner_Battle_AfterLastTurn(); BeginFastPaletteFade(3); FadeOutMapMusic(5); - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE || B_RESTORE_HELD_BATTLE_ITEMS == TRUE + if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE || B_RESTORE_HELD_BATTLE_ITEMS == TRUE) TryRestoreHeldItems(); - #endif // Undo Dynamax HP multiplier before recalculating stats. for (i = 0; i < gBattlersCount; ++i) + { if (IsDynamaxed(i)) UndoDynamax(i); + } for (i = 0; i < PARTY_SIZE; i++) { @@ -5464,11 +5417,9 @@ static void HandleEndTurn_FinishBattle(void) gBattleStruct->changedSpecies[B_SIDE_PLAYER][i] = SPECIES_NONE; gBattleStruct->changedSpecies[B_SIDE_OPPONENT][i] = SPECIES_NONE; - #if B_RECALCULATE_STATS >= GEN_5 // Recalculate the stats of every party member before the end - if (!changedForm) + if (!changedForm && B_RECALCULATE_STATS >= GEN_5) CalculateMonStats(&gPlayerParty[i]); - #endif } // Clear battle mon species to avoid a bug on the next battle that causes // healthboxes loading incorrectly due to it trying to create a Mega Indicator @@ -5501,10 +5452,9 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void) | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_WALLY_TUTORIAL)) - #if B_EVOLUTION_AFTER_WHITEOUT <= GEN_5 - && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT) - #endif - ) + && (B_EVOLUTION_AFTER_WHITEOUT >= GEN_6 + || gBattleOutcome == B_OUTCOME_WON + || gBattleOutcome == B_OUTCOME_CAUGHT)) { gBattleMainFunc = TrySpecialEvolution; } @@ -5682,6 +5632,10 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk) if (holdEffect == gBattleMoves[move].argument) gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | F_DYNAMIC_TYPE_2; } + else if (gBattleMoves[move].effect == EFFECT_IVY_CUDGEL && holdEffect == HOLD_EFFECT_MASK) + { + gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | F_DYNAMIC_TYPE_2; + } else if (gBattleMoves[move].effect == EFFECT_REVELATION_DANCE) { if (gBattleMons[battlerAtk].type1 != TYPE_MYSTERY) @@ -5781,9 +5735,9 @@ void SetTotemBoost(void) { if (*(&gSpecialVar_0x8001 + i)) { - gTotemBoosts[battler].stats |= (1 << i); - gTotemBoosts[battler].statChanges[i] = *(&gSpecialVar_0x8001 + i); - gTotemBoosts[battler].stats |= 0x80; // used as a flag for the "totem flared to life" script + gQueuedStatBoosts[battler].stats |= (1 << i); + gQueuedStatBoosts[battler].statChanges[i] = *(&gSpecialVar_0x8001 + i); + gQueuedStatBoosts[battler].stats |= 0x80; // used as a flag for the "totem flared to life" script } } } diff --git a/src/battle_message.c b/src/battle_message.c index 563fe85eaa..116a42d6bc 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -532,12 +532,12 @@ static const u8 sText_TwoInGameTrainersDefeated[]; static const u8 sText_Trainer2LoseText[]; // New battle strings. -static const s8 sText_EnduredViaSturdy[] = _("{B_DEF_NAME_WITH_PREFIX} endured\nthe hit using {B_DEF_ABILITY}!"); -static const s8 sText_PowerHerbActivation[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its {B_LAST_ITEM}!"); -static const s8 sText_HurtByItem[] = _("{B_ATK_NAME_WITH_PREFIX} was hurt\nby its {B_LAST_ITEM}!"); -static const s8 sText_BadlyPoisonedByItem[] = _("{B_EFF_NAME_WITH_PREFIX} was badly\npoisoned by the {B_LAST_ITEM}!"); -static const s8 sText_BurnedByItem[] = _("{B_EFF_NAME_WITH_PREFIX} was burned\nby the {B_LAST_ITEM}!"); -static const s8 sText_TargetAbilityActivates[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} activates!"); +static const u8 sText_EnduredViaSturdy[] = _("{B_DEF_NAME_WITH_PREFIX} endured\nthe hit using {B_DEF_ABILITY}!"); +static const u8 sText_PowerHerbActivation[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its {B_LAST_ITEM}!"); +static const u8 sText_HurtByItem[] = _("{B_ATK_NAME_WITH_PREFIX} was hurt\nby its {B_LAST_ITEM}!"); +static const u8 sText_BadlyPoisonedByItem[] = _("{B_EFF_NAME_WITH_PREFIX} was badly\npoisoned by the {B_LAST_ITEM}!"); +static const u8 sText_BurnedByItem[] = _("{B_EFF_NAME_WITH_PREFIX} was burned\nby the {B_LAST_ITEM}!"); +static const u8 sText_TargetAbilityActivates[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} activates!"); static const u8 sText_GravityIntensified[] = _("Gravity intensified!"); static const u8 sText_TargetIdentified[] = _("{B_DEF_NAME_WITH_PREFIX} was\nidentified!"); static const u8 sText_TargetWokeUp[] = _("{B_DEF_NAME_WITH_PREFIX} woke up!"); @@ -820,10 +820,13 @@ static const u8 sText_TeamGainedEXP[] = _("The rest of your team gained EXP.\nPo static const u8 sText_CurrentMoveCantSelect[] = _("{B_BUFF1} cannot be used!\p"); static const u8 sText_TargetIsBeingSaltCured[] = _("{B_DEF_NAME_WITH_PREFIX} is being salt cured!"); static const u8 sText_TargetIsHurtBySaltCure[] = _("{B_DEF_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!"); +static const u8 sText_OpportunistCopied[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} copied its\nopponent's stat changes!"); +static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PREFIX} got covered\nin sticky syrup!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { [STRINGID_MOVEBLOCKEDBYDYNAMAX - BATTLESTRINGS_TABLE_START] = sText_MoveBlockedByDynamax, + [STRINGID_OPPORTUNISTCOPIED - BATTLESTRINGS_TABLE_START] = sText_OpportunistCopied, [STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure, [STRINGID_TARGETISBEINGSALTCURED - BATTLESTRINGS_TABLE_START] = sText_TargetIsBeingSaltCured, [STRINGID_CURRENTMOVECANTSELECT - BATTLESTRINGS_TABLE_START] = sText_CurrentMoveCantSelect, @@ -1495,6 +1498,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_ULTRABURSTREACTING - BATTLESTRINGS_TABLE_START] = sText_UltraBurstReacting, [STRINGID_ULTRABURSTCOMPLETED - BATTLESTRINGS_TABLE_START] = sText_UltraBurstCompleted, [STRINGID_TEAMGAINEDEXP - BATTLESTRINGS_TABLE_START] = sText_TeamGainedEXP, + [STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP - BATTLESTRINGS_TABLE_START] = sText_TargetCoveredInStickyCandySyrup, }; const u16 gTrainerUsedItemStringIds[] = @@ -1878,11 +1882,7 @@ const u16 gWeatherStartsStringIds[] = [WEATHER_SUNNY_CLOUDS] = STRINGID_ITISRAINING, [WEATHER_SUNNY] = STRINGID_ITISRAINING, [WEATHER_RAIN] = STRINGID_ITISRAINING, -#if B_OVERWORLD_SNOW >= GEN_9 - [WEATHER_SNOW] = STRINGID_STARTEDSNOW, -#else - [WEATHER_SNOW] = STRINGID_STARTEDHAIL, -#endif + [WEATHER_SNOW] = (B_OVERWORLD_SNOW >= GEN_9 ? STRINGID_STARTEDSNOW : STRINGID_STARTEDHAIL), [WEATHER_RAIN_THUNDERSTORM] = STRINGID_ITISRAINING, [WEATHER_FOG_HORIZONTAL] = STRINGID_ITISRAINING, [WEATHER_VOLCANIC_ASH] = STRINGID_ITISRAINING, @@ -2999,7 +2999,7 @@ void BufferStringBattle(u16 stringID, u32 battler) u32 BattleStringExpandPlaceholdersToDisplayedString(const u8 *src) { - BattleStringExpandPlaceholders(src, gDisplayedStringBattle); + return BattleStringExpandPlaceholders(src, gDisplayedStringBattle); } static const u8 *TryGetStatusString(u8 *src) @@ -3067,7 +3067,7 @@ static void GetBattlerNick(u32 battler, u8 *dst) static const u8 *BattleStringGetOpponentNameByTrainerId(u16 trainerId, u8 *text, u8 multiplayerId, u8 battler) { - const u8 *toCpy; + const u8 *toCpy = NULL; if (gBattleTypeFlags & BATTLE_TYPE_SECRET_BASE) { @@ -3119,7 +3119,7 @@ static const u8 *BattleStringGetOpponentNameByTrainerId(u16 trainerId, u8 *text, static const u8 *BattleStringGetOpponentName(u8 *text, u8 multiplayerId, u8 battler) { - const u8 *toCpy; + const u8 *toCpy = NULL; switch (GetBattlerPosition(battler)) { @@ -3139,7 +3139,7 @@ static const u8 *BattleStringGetOpponentName(u8 *text, u8 multiplayerId, u8 batt static const u8 *BattleStringGetPlayerName(u8 *text, u8 battler) { - const u8 *toCpy; + const u8 *toCpy = NULL; switch (GetBattlerPosition(battler)) { @@ -3215,7 +3215,6 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) // This buffer may hold either the name of a trainer, pokemon, or item. u8 text[max(max(max(32, TRAINER_NAME_LENGTH + 1), POKEMON_NAME_LENGTH + 1), ITEM_NAME_LENGTH)]; u8 multiplayerId; - s32 i; if (gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK) multiplayerId = gRecordedBattleMultiplayerId; @@ -3796,7 +3795,7 @@ void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) // unused, since the value loaded into the buffer is not read; it loaded one of // two particles (either "?" or "?") which works in tandem with ChooseTypeOfMoveUsedString // below to effect changes in the meaning of the line. -static void ChooseMoveUsedParticle(u8 *textBuff) +static void UNUSED ChooseMoveUsedParticle(u8 *textBuff) { s32 counter = 0; u32 i = 0; @@ -3836,7 +3835,7 @@ static void ChooseMoveUsedParticle(u8 *textBuff) // // sText_ExclamationMark5 was " ????!" This resulted in a translation of // "'s attack!". -static void ChooseTypeOfMoveUsedString(u8 *dst) +static void UNUSED ChooseTypeOfMoveUsedString(u8 *dst) { s32 counter = 0; s32 i = 0; @@ -4079,9 +4078,8 @@ u32 BattlerHPPercentage(u32 battler, u32 operation, u32 threshold) case GREATER_THAN_OR_EQUAL: return gBattleMons[battler].hp >= (gBattleMons[battler].maxHP / threshold); case NOT_EQUAL: - return gBattleMons[battler].hp != (gBattleMons[battler].maxHP / threshold); default: - break; + return gBattleMons[battler].hp != (gBattleMons[battler].maxHP / threshold); } } diff --git a/src/battle_pike.c b/src/battle_pike.c index 9070fb6595..0692b68063 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -861,10 +861,7 @@ static bool8 DoesTypePreventStatus(u16 species, u32 status) break; case STATUS1_PARALYSIS: if (gSpeciesInfo[species].types[0] == TYPE_GROUND || gSpeciesInfo[species].types[1] == TYPE_GROUND - #if B_PARALYZE_ELECTRIC >= GEN_6 - || gSpeciesInfo[species].types[0] == TYPE_ELECTRIC || gSpeciesInfo[species].types[1] == TYPE_ELECTRIC - #endif - ) + || (B_PARALYZE_ELECTRIC >= GEN_6 && (gSpeciesInfo[species].types[0] == TYPE_ELECTRIC || gSpeciesInfo[species].types[1] == TYPE_ELECTRIC))) ret = TRUE; break; case STATUS1_BURN: @@ -916,11 +913,7 @@ static bool8 TryInflictRandomStatus(void) if (rand < 35) sStatusFlags = STATUS1_TOXIC_POISON; else if (rand < 60) - #if B_USE_FROSTBITE == TRUE - sStatusFlags = STATUS1_FROSTBITE; - #else - sStatusFlags = STATUS1_FREEZE; - #endif + sStatusFlags = B_USE_FROSTBITE ? STATUS1_FROSTBITE : STATUS1_FREEZE; else if (rand < 80) sStatusFlags = STATUS1_PARALYSIS; else if (rand < 90) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 46023c5475..21e1c6e713 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -79,7 +79,7 @@ // // The arguments can be accessed as cmd->failInstr and cmd->move. // gBattlescriptCurrInstr = cmd->nextInstr; advances to the next instruction. -#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; MEMBERS(__VA_ARGS__) const u8 nextInstr[0]; } *const cmd = (const void *)gBattlescriptCurrInstr +#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; MEMBERS(__VA_ARGS__) const u8 nextInstr[0]; } *const cmd UNUSED = (const void *)gBattlescriptCurrInstr #define VARIOUS_ARGS(...) CMD_ARGS(u8 battler, u8 id, ##__VA_ARGS__) #define NATIVE_ARGS(...) CMD_ARGS(void (*func)(void), ##__VA_ARGS__) @@ -338,7 +338,6 @@ static const u16 sWhiteOutBadgeMoney[9] = { 8, 16, 24, 36, 48, 64, 80, 100, 120 static bool8 IsTwoTurnsMove(u16 move); static void TrySetDestinyBondToHappen(void); -static u8 AttacksThisTurn(u8 battler, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2. static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr); static bool32 IsMonGettingExpSentOut(void); static void InitLevelUpBanner(void); @@ -1120,16 +1119,8 @@ static const u8 sTerrainToType[BATTLE_TERRAIN_COUNT] = [BATTLE_TERRAIN_DISTORTION_WORLD] = TYPE_NORMAL, [BATTLE_TERRAIN_SPACE] = TYPE_DRAGON, [BATTLE_TERRAIN_ULTRA_SPACE] = TYPE_PSYCHIC, -#if B_CAMOUFLAGE_TYPES >= GEN_5 - [BATTLE_TERRAIN_MOUNTAIN] = TYPE_GROUND, - [BATTLE_TERRAIN_PLAIN] = TYPE_GROUND, -#elif B_CAMOUFLAGE_TYPES == GEN_4 - [BATTLE_TERRAIN_MOUNTAIN] = TYPE_ROCK, - [BATTLE_TERRAIN_PLAIN] = TYPE_GROUND, -#else - [BATTLE_TERRAIN_MOUNTAIN] = TYPE_ROCK, - [BATTLE_TERRAIN_PLAIN] = TYPE_NORMAL, -#endif + [BATTLE_TERRAIN_MOUNTAIN] = (B_CAMOUFLAGE_TYPES >= GEN_5 ? TYPE_GROUND : TYPE_ROCK), + [BATTLE_TERRAIN_PLAIN] = (B_CAMOUFLAGE_TYPES >= GEN_4 ? TYPE_GROUND : TYPE_NORMAL), }; // In Battle Palace, moves are chosen based on the pokemons nature rather than by the player @@ -1292,10 +1283,8 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } -#if B_STANCE_CHANGE_FAIL <= GEN_6 - if (TryAegiFormChange()) + if (B_STANCE_CHANGE_FAIL < GEN_7 && TryAegiFormChange()) return; -#endif if (AtkCanceller_UnableToUseMove(moveType)) return; @@ -1353,10 +1342,8 @@ static void Cmd_attackcanceler(void) gMoveResultFlags |= MOVE_RESULT_MISSED; return; } -#if B_STANCE_CHANGE_FAIL >= GEN_7 - if (TryAegiFormChange()) + if (B_STANCE_CHANGE_FAIL >= GEN_7 && TryAegiFormChange()) return; -#endif gHitMarker &= ~HITMARKER_ALLOW_NO_PP; @@ -1551,13 +1538,11 @@ static bool32 AccuracyCalcHelper(u16 move) JumpIfMoveFailed(7, move); return TRUE; } -#if B_TOXIC_NEVER_MISS >= GEN_6 - else if (gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)) + else if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)) { JumpIfMoveFailed(7, move); return TRUE; } -#endif // 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 && (move != MOVE_SKY_DROP || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)) { @@ -1597,14 +1582,12 @@ static bool32 AccuracyCalcHelper(u16 move) JumpIfMoveFailed(7, move); return TRUE; } - #if B_BLIZZARD_HAIL >= GEN_4 - else if ((gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && move == MOVE_BLIZZARD) + else if (B_BLIZZARD_HAIL >= GEN_4 && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && move == MOVE_BLIZZARD) { - // thunder/hurricane ignore acc checks in rain unless target is holding utility umbrella + // Blizzard ignores acc checks in Hail in Gen4+ JumpIfMoveFailed(7, move); return TRUE; } - #endif } if (gBattleMoves[move].effect == EFFECT_VITAL_THROW) @@ -1613,13 +1596,13 @@ static bool32 AccuracyCalcHelper(u16 move) return TRUE; } -#if B_MINIMIZE_DMG_ACC >= GEN_6 - if ((gStatuses3[gBattlerTarget] & STATUS3_MINIMIZED) && gBattleMoves[move].minimizeDoubleDamage) + if (B_MINIMIZE_DMG_ACC >= GEN_6 + && (gStatuses3[gBattlerTarget] & STATUS3_MINIMIZED) + && gBattleMoves[move].minimizeDoubleDamage) { JumpIfMoveFailed(7, move); return TRUE; } -#endif if (gBattleMoves[move].accuracy == 0) { @@ -1744,12 +1727,10 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u if (gFieldStatuses & STATUS_FIELD_GRAVITY) calc = (calc * 5) / 3; // 1.66 Gravity acc boost -#if B_AFFECTION_MECHANICS == TRUE // With high affection/friendship there's a chance to evade a move by substracting 10% of its accuracy. // I can't find exact information about that chance, so I'm just gonna write it as a 20% chance for now. - if (GetBattlerFriendshipScore(battlerDef) >= FRIENDSHIP_150_TO_199 && (Random() % 100) <= 20) + if (B_AFFECTION_MECHANICS == TRUE && GetBattlerFriendshipScore(battlerDef) >= FRIENDSHIP_150_TO_199 && (Random() % 100) <= 20) calc = (calc * 90) / 100; -#endif return calc; } @@ -1936,9 +1917,7 @@ s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec + (holdEffectAtk == HOLD_EFFECT_SCOPE_LENS) + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[battlerAtk].species == SPECIES_CHANSEY) + 2 * BENEFITS_FROM_LEEK(battlerAtk, holdEffectAtk) - #if B_AFFECTION_MECHANICS == TRUE - + 2 * (GetBattlerFriendshipScore(battlerAtk) >= FRIENDSHIP_200_TO_254) - #endif + + 2 * (B_AFFECTION_MECHANICS == TRUE && GetBattlerFriendshipScore(battlerAtk) >= FRIENDSHIP_200_TO_254) + (abilityAtk == ABILITY_SUPER_LUCK) + gBattleStruct->bonusCritStages[gBattlerAttacker]; @@ -2047,20 +2026,17 @@ static void Cmd_adjustdamage(void) RecordItemEffectBattle(gBattlerTarget, holdEffect); gSpecialStatuses[gBattlerTarget].focusBanded = TRUE; } - #if B_STURDY >= GEN_5 - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STURDY && BATTLER_MAX_HP(gBattlerTarget)) + else if (B_STURDY >= GEN_5 && GetBattlerAbility(gBattlerTarget) == ABILITY_STURDY && BATTLER_MAX_HP(gBattlerTarget)) { RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY); gSpecialStatuses[gBattlerTarget].sturdied = TRUE; } - #endif else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget)) { RecordItemEffectBattle(gBattlerTarget, holdEffect); gSpecialStatuses[gBattlerTarget].focusSashed = TRUE; } -#if B_AFFECTION_MECHANICS == TRUE - else if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && friendshipScore >= FRIENDSHIP_100_TO_149) + else if (B_AFFECTION_MECHANICS == TRUE && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && friendshipScore >= FRIENDSHIP_100_TO_149) { if ((friendshipScore == FRIENDSHIP_MAX && rand < 25) || (friendshipScore == FRIENDSHIP_200_TO_254 && rand < 20) @@ -2068,15 +2044,12 @@ static void Cmd_adjustdamage(void) || (friendshipScore == FRIENDSHIP_100_TO_149 && rand < 10)) gSpecialStatuses[gBattlerTarget].affectionEndured = TRUE; } -#endif if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBattlerTarget].endured && !gSpecialStatuses[gBattlerTarget].focusBanded && !gSpecialStatuses[gBattlerTarget].focusSashed -#if B_AFFECTION_MECHANICS == TRUE - && !gSpecialStatuses[gBattlerTarget].affectionEndured -#endif + && (B_AFFECTION_MECHANICS == FALSE || !gSpecialStatuses[gBattlerTarget].affectionEndured) && !gSpecialStatuses[gBattlerTarget].sturdied) goto END; @@ -2097,12 +2070,10 @@ static void Cmd_adjustdamage(void) gMoveResultFlags |= MOVE_RESULT_STURDIED; gLastUsedAbility = ABILITY_STURDY; } -#if B_AFFECTION_MECHANICS == TRUE - else if (gSpecialStatuses[gBattlerTarget].affectionEndured) + else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[gBattlerTarget].affectionEndured) { gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION; } -#endif END: gBattlescriptCurrInstr = cmd->nextInstr; @@ -2295,18 +2266,11 @@ static void Cmd_datahpupdate(void) { CMD_ARGS(u8 battler); - u32 battler, moveType; + u32 battler; if (gBattleControllerExecFlags) return; - if (gBattleStruct->dynamicMoveType == 0) - moveType = gBattleMoves[gCurrentMove].type; - else if (!(gBattleStruct->dynamicMoveType & F_DYNAMIC_TYPE_1)) - moveType = gBattleStruct->dynamicMoveType & DYNAMIC_TYPE_MASK; - else - moveType = gBattleMoves[gCurrentMove].type; - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) || (gHitMarker & HITMARKER_PASSIVE_DAMAGE)) { battler = GetBattlerForBattleScript(cmd->battler); @@ -2591,8 +2555,7 @@ static void Cmd_resultmessage(void) { stringId = STRINGID_BUTITFAILED; } - #if B_AFFECTION_MECHANICS == TRUE - else if (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION) + else if (B_AFFECTION_MECHANICS == TRUE && (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION)) { gSpecialStatuses[gBattlerTarget].affectionEndured = FALSE; gMoveResultFlags &= ~MOVE_RESULT_FOE_ENDURED_AFFECTION; @@ -2600,7 +2563,6 @@ static void Cmd_resultmessage(void) gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance; return; } - #endif else { gBattleCommunication[MSG_DISPLAY] = 0; @@ -2762,7 +2724,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) void SetMoveEffect(bool32 primary, u32 certain) { - s32 i, byTwo, affectsUser = 0; + s32 i, affectsUser = 0; bool32 statusChanged = FALSE; bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR); u32 flags = 0; @@ -3045,13 +3007,16 @@ void SetMoveEffect(bool32 primary, u32 certain) BattleScriptPush(gBattlescriptCurrInstr + 1); if (sStatusFlagsForMoveEffects[gBattleScripting.moveEffect] == STATUS1_SLEEP) - #if B_SLEEP_TURNS >= GEN_5 - gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3)); - #else - gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5)); - #endif + { + if (B_SLEEP_TURNS >= GEN_5) + gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3)); + else + gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5)); + } else + { gBattleMons[gEffectBattler].status1 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]; + } gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; @@ -3144,11 +3109,7 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS; gLockedMoves[gEffectBattler] = gCurrentMove; - #if B_UPROAR_TURNS >= GEN_5 - gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN(3); - #else - gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN((Random() & 3) + 2); - #endif + gBattleMons[gEffectBattler].status2 |= STATUS2_UPROAR_TURN(B_UPROAR_TURNS >= GEN_5 ? 3 : (Random() & 3) + 2); BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect]; @@ -3190,11 +3151,12 @@ void SetMoveEffect(bool32 primary, u32 certain) } else { - #if B_USE_FROSTBITE == TRUE - static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FROSTBITE, MOVE_EFFECT_PARALYSIS }; - #else - static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FREEZE, MOVE_EFFECT_PARALYSIS }; - #endif + static const u8 sTriAttackEffects[] = + { + MOVE_EFFECT_BURN, + B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE, + MOVE_EFFECT_PARALYSIS + }; gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); SetMoveEffect(FALSE, 0); } @@ -3214,15 +3176,9 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) - #if B_BINDING_TURNS >= GEN_5 - gDisableStructs[gEffectBattler].wrapTurns = 7; + gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5; else - gDisableStructs[gEffectBattler].wrapTurns = (Random() % 2) + 4; - #else - gDisableStructs[gEffectBattler].wrapTurns = 5; - else - gDisableStructs[gEffectBattler].wrapTurns = (Random() % 4) + 2; - #endif + gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2; gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove; gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker; @@ -3514,6 +3470,8 @@ void SetMoveEffect(bool32 primary, u32 certain) { if (gBattleMons[gBattlerTarget].statStages[i] > DEFAULT_STAT_STAGE && gBattleMons[gBattlerAttacker].statStages[i] != MAX_STAT_STAGE) { + bool32 byTwo = FALSE; + gBattleStruct->stolenStats[0] |= gBitTable[i]; // Store by how many stages to raise the stat. gBattleStruct->stolenStats[i] = gBattleMons[gBattlerTarget].statStages[i] - DEFAULT_STAT_STAGE; @@ -3569,10 +3527,7 @@ void SetMoveEffect(bool32 primary, u32 certain) break; case MOVE_EFFECT_INCINERATE: if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX) - #if B_INCINERATE_GEMS >= GEN_6 - || (GetBattlerHoldEffect(gEffectBattler, FALSE) == HOLD_EFFECT_GEMS) - #endif - ) + || (B_INCINERATE_GEMS >= GEN_6 && GetBattlerHoldEffect(gEffectBattler, FALSE) == HOLD_EFFECT_GEMS)) { gLastUsedItem = gBattleMons[gEffectBattler].item; gBattleMons[gEffectBattler].item = 0; @@ -3685,6 +3640,19 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattlescriptCurrInstr++; } } + + break; + case MOVE_EFFECT_SYRUP_BOMB: + if (gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB) + { + gBattlescriptCurrInstr++; + } + else + { + gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB; + gDisableStructs[gBattlerTarget].syrupBombTimer = 3; + gBattlescriptCurrInstr++; + } break; } } @@ -4119,16 +4087,17 @@ static void Cmd_getexp(void) if (orderId < PARTY_SIZE) gBattleStruct->expGettersOrder[orderId] = PARTY_SIZE; - #if (B_SCALED_EXP >= GEN_5) && (B_SCALED_EXP != GEN_6) - calculatedExp = gSpeciesInfo[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level / 5; - #else - calculatedExp = gSpeciesInfo[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level / 7; - #endif + calculatedExp = gSpeciesInfo[gBattleMons[gBattlerFainted].species].expYield * gBattleMons[gBattlerFainted].level; + if (B_SCALED_EXP >= GEN_5 && B_SCALED_EXP != GEN_6) + calculatedExp /= 5; + else + calculatedExp /= 7; if (B_TRAINER_EXP_MULTIPLIER <= GEN_7 && gBattleTypeFlags & BATTLE_TYPE_TRAINER) calculatedExp = (calculatedExp * 150) / 100; - #if B_SPLIT_EXP < GEN_6 + if (B_SPLIT_EXP < GEN_6) + { if (viaExpShare) // at least one mon is getting exp via exp share { *exp = SAFE_DIV(calculatedExp / 2, viaSentIn); @@ -4146,12 +4115,14 @@ static void Cmd_getexp(void) *exp = 1; gBattleStruct->expShareExpValue = 0; } - #else + } + else + { *exp = calculatedExp; gBattleStruct->expShareExpValue = calculatedExp / 2; if (gBattleStruct->expShareExpValue == 0) gBattleStruct->expShareExpValue = 1; - #endif + } gBattleScripting.getexpState++; gBattleStruct->expOrderId = 0; @@ -4176,9 +4147,8 @@ static void Cmd_getexp(void) { gBattleScripting.getexpState = 5; gBattleMoveDamage = 0; // used for exp - #if B_MAX_LEVEL_EV_GAINS >= GEN_5 - MonGainEVs(&gPlayerParty[*expMonId], gBattleMons[gBattlerFainted].species); - #endif + if (B_MAX_LEVEL_EV_GAINS >= GEN_5) + MonGainEVs(&gPlayerParty[*expMonId], gBattleMons[gBattlerFainted].species); } else { @@ -4202,11 +4172,7 @@ static void Cmd_getexp(void) gBattleMoveDamage = 0; if ((holdEffect == HOLD_EFFECT_EXP_SHARE || IsGen6ExpShareEnabled()) -#if B_SPLIT_EXP >= GEN_6 - // only give exp share bonus in later gens if the mon wasn't sent out - && gBattleMoveDamage == 0 -#endif - ) + && (B_SPLIT_EXP < GEN_6 || gBattleMoveDamage == 0)) // only give exp share bonus in later gens if the mon wasn't sent out { gBattleMoveDamage += gBattleStruct->expShareExpValue; } @@ -4359,7 +4325,6 @@ static void Cmd_getexp(void) } } -#if B_MULTI_BATTLE_WHITEOUT >= GEN_4 static bool32 NoAliveMonsForPlayerAndPartner(void) { u32 i; @@ -4379,7 +4344,6 @@ static bool32 NoAliveMonsForPlayerAndPartner(void) return (HP_count == 0); } -#endif static bool32 NoAliveMonsForPlayer(void) { @@ -4444,8 +4408,7 @@ static void Cmd_checkteamslost(void) if (gBattleControllerExecFlags) return; -#if B_MULTI_BATTLE_WHITEOUT >= GEN_4 - if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) + if (B_MULTI_BATTLE_WHITEOUT >= GEN_4 && gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) { if (NoAliveMonsForPlayerAndPartner()) gBattleOutcome |= B_OUTCOME_LOST; @@ -4455,10 +4418,6 @@ static void Cmd_checkteamslost(void) if (NoAliveMonsForPlayer()) gBattleOutcome |= B_OUTCOME_LOST; } -#else - if (NoAliveMonsForPlayer()) - gBattleOutcome |= B_OUTCOME_LOST; -#endif if (NoAliveMonsForOpponent()) gBattleOutcome |= B_OUTCOME_WON; @@ -4952,14 +4911,12 @@ static void Cmd_endselectionscript(void) static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *nextInstr) { -#if B_TERRAIN_BG_CHANGE == FALSE - if (animId == B_ANIM_RESTORE_BG) + if (B_TERRAIN_BG_CHANGE == FALSE && animId == B_ANIM_RESTORE_BG) { // workaround for .if not working gBattlescriptCurrInstr = nextInstr; return; } -#endif if (animId == B_ANIM_STATS_CHANGE || animId == B_ANIM_SNATCH_MOVE @@ -5277,11 +5234,10 @@ static void Cmd_moveend(void) i = gBattlerAttacker; gBattlerAttacker = gBattlerTarget; gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable - #if B_KINGS_SHIELD_LOWER_ATK >= GEN_8 - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; - #else - gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_2; - #endif + if (B_KINGS_SHIELD_LOWER_ATK >= GEN_8) + gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1; + else + gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_2; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; effect = 1; @@ -5355,10 +5311,7 @@ static void Cmd_moveend(void) && gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget && (moveType == TYPE_FIRE - #if B_BURN_HIT_THAW >= GEN_6 - || gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT - #endif - ) + || (B_BURN_HIT_THAW >= GEN_6 && gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT)) && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) { gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; @@ -5434,6 +5387,12 @@ static void Cmd_moveend(void) effect = TRUE; 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_STATUS_IMMUNITY_ABILITIES: // status immunities if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0)) effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers @@ -6040,19 +5999,17 @@ static void Cmd_moveend(void) BattleScriptPushCursor(); if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || GetBattlerSide(i) == B_SIDE_PLAYER) { - #if B_ABILITY_POP_UP == TRUE - gBattlescriptCurrInstr = BattleScript_EmergencyExit; - #else - gBattlescriptCurrInstr = BattleScript_EmergencyExitNoPopUp; - #endif + if (B_ABILITY_POP_UP == TRUE) + gBattlescriptCurrInstr = BattleScript_EmergencyExit; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitNoPopUp; } else { - #if B_ABILITY_POP_UP == TRUE - gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; - #else - gBattlescriptCurrInstr = BattleScript_EmergencyExitWildNoPopUp; - #endif + if (B_ABILITY_POP_UP == TRUE) + gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitWildNoPopUp; } return; } @@ -6063,10 +6020,8 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { if ((gSpecialStatuses[i].berryReduced - #if B_SYMBIOSIS_GEMS >= GEN_7 - || gSpecialStatuses[i].gemBoost - #endif - ) && SYMBIOSIS_CHECK(i, BATTLE_PARTNER(i))) + || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) + && SYMBIOSIS_CHECK(i, BATTLE_PARTNER(i))) { BestowItem(BATTLE_PARTNER(i), i); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; @@ -6085,12 +6040,11 @@ static void Cmd_moveend(void) if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget) *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3; - #if B_RAMPAGE_CANCELLING >= GEN_5 - if (gBattleMoves[gCurrentMove].effect == EFFECT_RAMPAGE // If we're rampaging + if (B_RAMPAGE_CANCELLING >= GEN_5 + && gBattleMoves[gCurrentMove].effect == EFFECT_RAMPAGE // If we're rampaging && (gMoveResultFlags & 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 CancelMultiTurnMoves(gBattlerAttacker); // Cancel it - #endif gBattleStruct->targetsDone[gBattlerAttacker] = 0; gProtectStructs[gBattlerAttacker].usesBouncedMove = FALSE; @@ -6981,6 +6935,8 @@ static void Cmd_switchineffects(void) { if (DoSwitchInAbilitiesItems(battler)) return; + else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) + return; } gDisableStructs[battler].stickyWebDone = FALSE; @@ -7662,9 +7618,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId) && gBattleStruct->changedItems[battler] == ITEM_NONE && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK - #if B_SYMBIOSIS_GEMS >= GEN_7 - && !(gSpecialStatuses[battler].gemBoost) - #endif + && (B_SYMBIOSIS_GEMS < GEN_7 || !(gSpecialStatuses[battler].gemBoost)) && gCurrentMove != MOVE_FLING //Fling and damage-reducing berries are handled separately. && !gSpecialStatuses[battler].berryReduced && SYMBIOSIS_CHECK(battler, BATTLE_PARTNER(battler))) @@ -8229,15 +8183,13 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) 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 B_DEFOG_CLEARS_TERRAIN >= GEN_8 - if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + if (B_DEFOG_CLEARS_TERRAIN >= GEN_8 && (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) { RemoveAllTerrains(); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TerrainEnds_Ret; return TRUE; } - #endif // B_DEFOG_CLEARS_TERRAIN } return FALSE; @@ -8385,7 +8337,7 @@ static bool32 IsTeatimeAffected(u32 battler) sideTimerOpp->structField = BATTLE_OPPOSITE(temp); \ } \ -static bool32 CourtChangeSwapSideStatuses(void) +static void CourtChangeSwapSideStatuses(void) { struct SideTimer *sideTimerPlayer = &gSideTimers[B_SIDE_PLAYER]; struct SideTimer *sideTimerOpp = &gSideTimers[B_SIDE_OPPONENT]; @@ -8512,7 +8464,7 @@ static void Cmd_various(void) CMD_ARGS(u8 battler, u8 id); struct Pokemon *mon; - s32 i, j; + s32 i; u8 data[10]; u32 side, battler, bits; @@ -9086,6 +9038,7 @@ static void Cmd_various(void) AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_TRACE2, battler, 0, 0, 0); + AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); return; } case VARIOUS_SAVE_TARGET: @@ -9252,11 +9205,7 @@ static void Cmd_various(void) && !NoAliveMonsForEitherParty() && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { - #if B_FELL_STINGER_STAT_RAISE >= GEN_7 - SET_STATCHANGER(STAT_ATK, 3, FALSE); - #else - SET_STATCHANGER(STAT_ATK, 2, FALSE); - #endif + SET_STATCHANGER(STAT_ATK, (B_FELL_STINGER_STAT_RAISE >= GEN_7 ? 3 : 2), FALSE); PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_FellStingerRaisesStat; @@ -9504,8 +9453,10 @@ static void Cmd_various(void) // Change species. if (cmd->case_ == 0) { + /* What was the idea here? if (!gBattleTextBuff1) PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battler].species); + */ BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battler]], sizeof(gBattleMons[battler].species), &gBattleMons[battler].species); MarkBattlerForControllerExec(battler); } @@ -9799,7 +9750,7 @@ static void Cmd_various(void) { VARIOUS_ARGS(const u8 *jumpInstr); if (!IsBattlerGrounded(battler)) - gBattlescriptCurrInstr = gBattlescriptCurrInstr = cmd->jumpInstr; + gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; return; @@ -9911,7 +9862,7 @@ static void Cmd_various(void) { VARIOUS_ARGS(const u8 *jumpInstr); battler = gBattlerAttacker; - if (gTotemBoosts[battler].stats == 0) + if (gQueuedStatBoosts[battler].stats == 0) { gBattlescriptCurrInstr = cmd->nextInstr; // stats done, exit } @@ -9919,19 +9870,19 @@ static void Cmd_various(void) { for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) { - if (gTotemBoosts[battler].stats & (1 << i)) + if (gQueuedStatBoosts[battler].stats & (1 << i)) { - if (gTotemBoosts[battler].statChanges[i] <= -1) - SET_STATCHANGER(i + 1, abs(gTotemBoosts[battler].statChanges[i]), TRUE); + if (gQueuedStatBoosts[battler].statChanges[i] <= -1) + SET_STATCHANGER(i + 1, abs(gQueuedStatBoosts[battler].statChanges[i]), TRUE); else - SET_STATCHANGER(i + 1, gTotemBoosts[battler].statChanges[i], FALSE); + SET_STATCHANGER(i + 1, gQueuedStatBoosts[battler].statChanges[i], FALSE); - gTotemBoosts[battler].stats &= ~(1 << i); + gQueuedStatBoosts[battler].stats &= ~(1 << i); gBattleScripting.battler = battler; gBattlerTarget = battler; - if (gTotemBoosts[battler].stats & 0x80) + if (gQueuedStatBoosts[battler].stats & 0x80) { - gTotemBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag + gQueuedStatBoosts[battler].stats &= ~0x80; // set 'aura flared to life' flag gBattlescriptCurrInstr = BattleScript_TotemFlaredToLife; } else @@ -11086,14 +11037,19 @@ static void Cmd_manipulatedamage(void) gBattleMoveDamage *= -1; break; case DMG_RECOIL_FROM_MISS: - #if B_RECOIL_IF_MISS_DMG >= GEN_5 - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; - #elif B_RECOIL_IF_MISS_DMG == GEN_4 - if ((gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage) - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2; - #else - gBattleMoveDamage /= 2; - #endif + if (B_RECOIL_IF_MISS_DMG >= GEN_5) + { + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; + } + else if (B_RECOIL_IF_MISS_DMG == GEN_4) + { + if ((gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage) + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerTarget) / 2; + } + else + { + gBattleMoveDamage /= 2; + } if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; break; @@ -11217,11 +11173,8 @@ static void Cmd_jumpifuproarwakes(void) { CMD_ARGS(const u8 *jumpInstr); - const u8 *jumpInstr = cmd->jumpInstr; - u32 ability = GetBattlerAbility(gBattlerTarget); - if (UproarWakeUpCheck(gBattlerTarget)) - gBattlescriptCurrInstr = jumpInstr; + gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; } @@ -11396,6 +11349,8 @@ static u16 ReverseStatChangeMoveEffect(u16 moveEffect) return MOVE_EFFECT_ACC_PLUS_2; case MOVE_EFFECT_EVS_MINUS_2: return MOVE_EFFECT_EVS_PLUS_2; + default: + return 0; } } @@ -11650,12 +11605,19 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { if (GetBattlerSide(index) == GetBattlerSide(battler)) continue; // Only triggers on opposing side - if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB + 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 + gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk + gQueuedStatBoosts[index].statChanges[statId - 1] += statValue; // cumulative in case of multiple opponent boosts + } + else if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB && gBattleMons[index].statStages[statId] < MAX_STAT_STAGE) { gProtectStructs[index].eatMirrorHerb = 1; - gTotemBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk - gTotemBoosts[index].statChanges[statId - 1] = statValue; + gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk + gQueuedStatBoosts[index].statChanges[statId - 1] = statValue; } } } @@ -11713,7 +11675,7 @@ static void Cmd_normalisebuffs(void) { CMD_ARGS(); - s32 i, j; + s32 i; for (i = 0; i < gBattlersCount; i++) TryResetBattlerStatChanges(i); @@ -11760,13 +11722,12 @@ static void Cmd_setmultihitcounter(void) else { // WARNING: These seem to be unused, see SetRandomMultiHitCounter. - #if B_MULTI_HIT_CHANCE >= GEN_5 + if (B_MULTI_HIT_CHANCE >= GEN_5) // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); - #else + else // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); - #endif } } @@ -11792,7 +11753,6 @@ static void Cmd_forcerandomswitch(void) s32 firstMonId; s32 lastMonId = 0; // + 1 - s32 monsCount; struct Pokemon *party = NULL; u8 validMons[PARTY_SIZE]; s32 validMonsCount = 0; @@ -11848,7 +11808,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = 6; - monsCount = 6; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11866,7 +11825,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE / 2; } - monsCount = PARTY_SIZE / 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11883,7 +11841,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE / 2; } - monsCount = PARTY_SIZE / 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11893,7 +11850,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = PARTY_SIZE; - monsCount = PARTY_SIZE; } else { @@ -11907,7 +11863,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE / 2; } - monsCount = PARTY_SIZE / 2; } battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; @@ -11916,7 +11871,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = PARTY_SIZE; - monsCount = PARTY_SIZE; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11924,7 +11878,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = PARTY_SIZE; - monsCount = PARTY_SIZE; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; // there is only one pokemon out in single battles battler1PartyId = gBattlerPartyIndexes[gBattlerTarget]; } @@ -11983,68 +11936,44 @@ static void Cmd_tryconversiontypechange(void) CMD_ARGS(const u8 *failInstr); u8 validMoves = 0; - u8 moveChecked; - u8 moveType; + u8 moveChecked = 0; + u8 moveType = 0; -#if B_UPDATED_CONVERSION >= GEN_6 - // Changes user's type to its first move's type - for (moveChecked = 0; moveChecked < MAX_MON_MOVES; moveChecked++) + if (B_UPDATED_CONVERSION >= GEN_6) { - if (gBattleMons[gBattlerAttacker].moves[moveChecked] != MOVE_NONE) + // Changes user's type to its first move's type + for (moveChecked = 0; moveChecked < MAX_MON_MOVES; moveChecked++) { - moveType = gBattleMoves[gBattleMons[gBattlerAttacker].moves[moveChecked]].type; - break; + if (gBattleMons[gBattlerAttacker].moves[moveChecked] != MOVE_NONE) + { + moveType = gBattleMoves[gBattleMons[gBattlerAttacker].moves[moveChecked]].type; + 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; } - } - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType)) - { - gBattlescriptCurrInstr = cmd->failInstr; } else { - SET_BATTLER_TYPE(gBattlerAttacker, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); - gBattlescriptCurrInstr = cmd->nextInstr; - } -#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; - - validMoves++; - } - - for (moveChecked = 0; moveChecked < validMoves; moveChecked++) - { - moveType = gBattleMoves[gBattleMons[gBattlerAttacker].moves[moveChecked]].type; - - if (moveType == TYPE_MYSTERY) + // Randomly changes user's type to one of its moves' type + while (validMoves < MAX_MON_MOVES) { - if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) - moveType = TYPE_GHOST; - else - moveType = TYPE_NORMAL; + if (gBattleMons[gBattlerAttacker].moves[validMoves] == MOVE_NONE) + break; + + validMoves++; } - if (moveType != gBattleMons[gBattlerAttacker].type1 - && moveType != gBattleMons[gBattlerAttacker].type2 - && moveType != gBattleMons[gBattlerAttacker].type3) - { - break; - } - } - if (moveChecked == validMoves) - { - gBattlescriptCurrInstr = cmd->failInstr; - } - else - { - do + for (moveChecked = 0; moveChecked < validMoves; moveChecked++) { - while ((moveChecked = MOD(Random(), MAX_MON_MOVES)) >= validMoves); - moveType = gBattleMoves[gBattleMons[gBattlerAttacker].moves[moveChecked]].type; if (moveType == TYPE_MYSTERY) @@ -12054,15 +11983,42 @@ static void Cmd_tryconversiontypechange(void) else moveType = TYPE_NORMAL; } + if (moveType != gBattleMons[gBattlerAttacker].type1 + && moveType != gBattleMons[gBattlerAttacker].type2 + && moveType != gBattleMons[gBattlerAttacker].type3) + { + break; + } } - while (moveType == gBattleMons[gBattlerAttacker].type1 || moveType == gBattleMons[gBattlerAttacker].type2 || moveType == gBattleMons[gBattlerAttacker].type3); - SET_BATTLER_TYPE(gBattlerAttacker, moveType); - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + if (moveChecked == validMoves) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + do + { + while ((moveChecked = MOD(Random(), MAX_MON_MOVES)) >= validMoves); - gBattlescriptCurrInstr = cmd->nextInstr; + moveType = gBattleMoves[gBattleMons[gBattlerAttacker].moves[moveChecked]].type; + + if (moveType == TYPE_MYSTERY) + { + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) + moveType = TYPE_GHOST; + else + moveType = TYPE_NORMAL; + } + } + while (moveType == gBattleMons[gBattlerAttacker].type1 || moveType == gBattleMons[gBattlerAttacker].type2 || moveType == gBattleMons[gBattlerAttacker].type3); + + SET_BATTLER_TYPE(gBattlerAttacker, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); + + gBattlescriptCurrInstr = cmd->nextInstr; + } } -#endif } static void Cmd_givepaydaymoney(void) @@ -12162,10 +12118,8 @@ static void Cmd_tryKO(void) else { u16 odds = gBattleMoves[gCurrentMove].accuracy + (gBattleMons[gBattlerAttacker].level - gBattleMons[gBattlerTarget].level); - #if B_SHEER_COLD_ACC >= GEN_7 - if (gCurrentMove == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) + if (B_SHEER_COLD_ACC >= GEN_7 && gCurrentMove == MOVE_SHEER_COLD && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE)) odds -= 10; - #endif if (RandomPercentage(RNG_ACCURACY, odds) && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) lands = TRUE; } @@ -12183,13 +12137,11 @@ static void Cmd_tryKO(void) gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON; gLastUsedItem = gBattleMons[gBattlerTarget].item; } - #if B_AFFECTION_MECHANICS == TRUE - else if (gSpecialStatuses[gBattlerTarget].affectionEndured) + else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[gBattlerTarget].affectionEndured) { gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1; gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED_AFFECTION; } - #endif else { gBattleMoveDamage = gBattleMons[gBattlerTarget].hp; @@ -12572,12 +12524,7 @@ static void Cmd_psywavedamageeffect(void) { CMD_ARGS(); - s32 randDamage; -#if B_PSYWAVE_DMG >= GEN_6 - randDamage = (Random() % 101); -#else - randDamage = (Random() % 11) * 10; -#endif + s32 randDamage = B_PSYWAVE_DMG >= GEN_6 ? (Random() % 101) : ((Random() % 11) * 10); gBattleMoveDamage = gBattleMons[gBattlerAttacker].level * (randDamage + 50) / 100; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12654,13 +12601,12 @@ static void Cmd_disablelastusedattack(void) PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].moves[i]) gDisableStructs[gBattlerTarget].disabledMove = gBattleMons[gBattlerTarget].moves[i]; - #if B_DISABLE_TURNS == GEN_3 - gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 2; - #elif B_DISABLE_TURNS == GEN_4 - gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 4; - #else - gDisableStructs[gBattlerTarget].disableTimer = 4; - #endif + 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 @@ -12708,7 +12654,6 @@ static void Cmd_trysetencore(void) gDisableStructs[gBattlerTarget].encoredMove = gBattleMons[gBattlerTarget].moves[i]; gDisableStructs[gBattlerTarget].encoredMovePos = i; gDisableStructs[gBattlerTarget].encoreTimer = 3; - gDisableStructs[gBattlerTarget].encoreTimer; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -12876,26 +12821,6 @@ static bool8 IsTwoTurnsMove(u16 move) return FALSE; } -// unused -static u8 AttacksThisTurn(u8 battler, u16 move) // Note: returns 1 if it's a charging turn, otherwise 2 -{ - // first argument is unused - if (gBattleMoves[move].effect == EFFECT_SOLAR_BEAM - && IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) - return 2; - - if (gBattleMoves[move].effect == EFFECT_SKULL_BASH - || gBattleMoves[move].effect == EFFECT_TWO_TURNS_ATTACK - || gBattleMoves[move].effect == EFFECT_SOLAR_BEAM - || gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE - || gBattleMoves[move].effect == EFFECT_BIDE) - { - if ((gHitMarker & HITMARKER_CHARGING)) - return 1; - } - return 2; -} - static void Cmd_trychoosesleeptalkmove(void) { CMD_ARGS(const u8 *failInstr); @@ -12969,11 +12894,7 @@ static void Cmd_settailwind(void) { gSideStatuses[side] |= SIDE_STATUS_TAILWIND; gSideTimers[side].tailwindBattlerId = gBattlerAttacker; - #if B_TAILWIND_TURNS >= GEN_5 - gSideTimers[side].tailwindTimer = 4; - #else - gSideTimers[side].tailwindTimer = 3; - #endif + gSideTimers[side].tailwindTimer = B_TAILWIND_TURNS >= GEN_5 ? 4 : 3; gBattlescriptCurrInstr = cmd->nextInstr; } else @@ -13009,17 +12930,9 @@ static void Cmd_tryspiteppreduce(void) } } - #if B_CAN_SPITE_FAIL <= GEN_3 - if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] > 1) - #else - if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] != 0) - #endif + if (i != MAX_MON_MOVES && gBattleMons[gBattlerTarget].pp[i] > (B_CAN_SPITE_FAIL >= GEN_4 ? 0 : 1)) { - #if B_PP_REDUCED_BY_SPITE <= GEN_3 - s32 ppToDeduct = (Random() & 3) + 2; - #else - s32 ppToDeduct = 4; - #endif + s32 ppToDeduct = B_PP_REDUCED_BY_SPITE >= GEN_4 ? 4 : (Random() & 3) + 2; // G-Max Depletion only deducts 2 PP. if (IsMaxMove(gCurrentMove) && gBattleMoves[gCurrentMove].argument == MAX_EFFECT_SPITE) ppToDeduct = 2; @@ -13815,16 +13728,19 @@ static void Cmd_trymemento(void) { CMD_ARGS(const u8 *failInstr); - #if B_MEMENTO_FAIL == GEN_3 - if (gBattleMons[gBattlerTarget].statStages[STAT_ATK] == MIN_STAT_STAGE + if (B_MEMENTO_FAIL >= GEN_4 + && (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED + || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE + || IsBattlerProtected(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) - #else - if (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED - || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE - || IsBattlerProtected(gBattlerTarget, gCurrentMove) - || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) - #endif { // Failed, unprotected target already has minimum Attack and Special Attack. gBattlescriptCurrInstr = cmd->failInstr; @@ -13937,26 +13853,29 @@ static void Cmd_settaunt(void) { CMD_ARGS(const u8 *failInstr); -#if B_OBLIVIOUS_TAUNT >= GEN_6 - if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) + if (B_OBLIVIOUS_TAUNT >= GEN_6 && GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) { gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; gLastUsedAbility = ABILITY_OBLIVIOUS; RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); } - else -#endif - if (gDisableStructs[gBattlerTarget].tauntTimer == 0) + else if (gDisableStructs[gBattlerTarget].tauntTimer == 0) { - #if B_TAUNT_TURNS >= GEN_5 - u8 turns = 4; + u8 turns; + if (B_TAUNT_TURNS >= GEN_5) + { + 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) - #elif B_TAUNT_TURNS == GEN_4 - u8 turns = (Random() & 2) + 3; - #else - u8 turns = 2; - #endif + } + else if (B_TAUNT_TURNS >= GEN_4) + { + turns = (Random() & 2) + 3; + } + else + { + turns = 2; + } gDisableStructs[gBattlerTarget].tauntTimer = turns; gBattlescriptCurrInstr = cmd->nextInstr; @@ -14000,9 +13919,7 @@ static void Cmd_tryswapitems(void) | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_RECORDED_LINK - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE - | BATTLE_TYPE_TRAINER - #endif + | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) )))) { gBattlescriptCurrInstr = cmd->failInstr; @@ -14141,14 +14058,17 @@ static void Cmd_trywish(void) break; case 1: // heal effect PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattlerTarget, gWishFutureKnock.wishPartyId[gBattlerTarget]) - #if B_WISH_HP_SOURCE >= GEN_5 - if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) - gBattleMoveDamage = max(1, GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[gBattlerTarget]], MON_DATA_MAX_HP) / 2); + if (B_WISH_HP_SOURCE >= GEN_5) + { + if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) + gBattleMoveDamage = max(1, GetMonData(&gPlayerParty[gWishFutureKnock.wishPartyId[gBattlerTarget]], MON_DATA_MAX_HP) / 2); + else + gBattleMoveDamage = max(1, GetMonData(&gEnemyParty[gWishFutureKnock.wishPartyId[gBattlerTarget]], MON_DATA_MAX_HP) / 2); + } else - gBattleMoveDamage = max(1, GetMonData(&gEnemyParty[gWishFutureKnock.wishPartyId[gBattlerTarget]], MON_DATA_MAX_HP) / 2); - #else - gBattleMoveDamage = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 2); - #endif + { + gBattleMoveDamage = max(1, GetNonDynamaxMaxHP(gBattlerAttacker) / 2); + } gBattleMoveDamage *= -1; if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) @@ -14569,31 +14489,26 @@ u16 GetSecretPowerMoveEffect(void) { switch (gBattleTerrain) { - #if B_SECRET_POWER_EFFECT >= GEN_6 - case BATTLE_TERRAIN_GRASS: moveEffect = MOVE_EFFECT_SLEEP; break; - case BATTLE_TERRAIN_UNDERWATER: moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; - case BATTLE_TERRAIN_POND: moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; - case BATTLE_TERRAIN_MOUNTAIN: moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; - case BATTLE_TERRAIN_PUDDLE: moveEffect = MOVE_EFFECT_SPD_MINUS_1; break; - #elif B_SECRET_POWER_EFFECT >= GEN_5 - case BATTLE_TERRAIN_GRASS: moveEffect = MOVE_EFFECT_SLEEP; break; - case BATTLE_TERRAIN_UNDERWATER: moveEffect = MOVE_EFFECT_DEF_MINUS_1; break; - case BATTLE_TERRAIN_POND: moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; - case BATTLE_TERRAIN_MOUNTAIN: moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; - case BATTLE_TERRAIN_PUDDLE: moveEffect = MOVE_EFFECT_SPD_MINUS_1; break; - #elif B_SECRET_POWER_EFFECT >= GEN_4 - case BATTLE_TERRAIN_GRASS: moveEffect = MOVE_EFFECT_SLEEP; break; - case BATTLE_TERRAIN_UNDERWATER: moveEffect = MOVE_EFFECT_DEF_MINUS_1; break; - case BATTLE_TERRAIN_POND: moveEffect = MOVE_EFFECT_ATK_MINUS_1; break; - case BATTLE_TERRAIN_MOUNTAIN: moveEffect = MOVE_EFFECT_FLINCH; break; - case BATTLE_TERRAIN_PUDDLE: moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; - #else - case BATTLE_TERRAIN_GRASS: moveEffect = MOVE_EFFECT_POISON; break; - case BATTLE_TERRAIN_UNDERWATER: moveEffect = MOVE_EFFECT_DEF_MINUS_1; break; - case BATTLE_TERRAIN_POND: moveEffect = MOVE_EFFECT_SPD_MINUS_1; break; - case BATTLE_TERRAIN_MOUNTAIN: moveEffect = MOVE_EFFECT_CONFUSION; break; - case BATTLE_TERRAIN_PUDDLE: moveEffect = MOVE_EFFECT_ACC_MINUS_1; break; - #endif + case BATTLE_TERRAIN_GRASS: + moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON); + break; + case BATTLE_TERRAIN_UNDERWATER: + moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1); + break; + case BATTLE_TERRAIN_POND: + moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1); + break; + case BATTLE_TERRAIN_MOUNTAIN: + if (B_SECRET_POWER_EFFECT >= GEN_5) + moveEffect = MOVE_EFFECT_ACC_MINUS_1; + else if (B_SECRET_POWER_EFFECT >= GEN_4) + moveEffect = MOVE_EFFECT_FLINCH; + else + moveEffect = MOVE_EFFECT_CONFUSION; + break; + case BATTLE_TERRAIN_PUDDLE: + moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1); + break; case BATTLE_TERRAIN_LONG_GRASS: moveEffect = MOVE_EFFECT_SLEEP; break; @@ -14616,11 +14531,7 @@ u16 GetSecretPowerMoveEffect(void) break; case BATTLE_TERRAIN_SNOW: case BATTLE_TERRAIN_ICE: - #if B_USE_FROSTBITE == TRUE - moveEffect = MOVE_EFFECT_FROSTBITE; - #else - moveEffect = MOVE_EFFECT_FREEZE; - #endif + moveEffect = (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE); break; case BATTLE_TERRAIN_VOLCANO: moveEffect = MOVE_EFFECT_BURN; @@ -14727,7 +14638,8 @@ static void Cmd_settypebasedhalvers(void) if (gBattleMoves[gCurrentMove].effect == EFFECT_MUD_SPORT) { - #if B_SPORT_TURNS >= GEN_6 + if (B_SPORT_TURNS >= GEN_6) + { if (!(gFieldStatuses & STATUS_FIELD_MUDSPORT)) { gFieldStatuses |= STATUS_FIELD_MUDSPORT; @@ -14735,18 +14647,21 @@ static void Cmd_settypebasedhalvers(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; worked = TRUE; } - #else + } + else + { if (!(gStatuses4[gBattlerAttacker] & STATUS4_MUD_SPORT)) { gStatuses4[gBattlerAttacker] |= STATUS4_MUD_SPORT; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC; worked = TRUE; } - #endif + } } else // Water Sport { - #if B_SPORT_TURNS >= GEN_6 + if (B_SPORT_TURNS >= GEN_6) + { if (!(gFieldStatuses & STATUS_FIELD_WATERSPORT)) { gFieldStatuses |= STATUS_FIELD_WATERSPORT; @@ -14754,14 +14669,16 @@ static void Cmd_settypebasedhalvers(void) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; worked = TRUE; } - #else + } + else + { if (!(gStatuses4[gBattlerAttacker] & STATUS4_WATER_SPORT)) { gStatuses4[gBattlerAttacker] |= STATUS4_WATER_SPORT; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE; worked = TRUE; } - #endif + } } if (worked) @@ -14774,10 +14691,8 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) { if (!(gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE)) return FALSE; -#if B_SOUND_SUBSTITUTE >= GEN_6 - else if (gBattleMoves[move].soundMove) + else if (B_SOUND_SUBSTITUTE >= GEN_6 && gBattleMoves[move].soundMove) return FALSE; -#endif else if (gBattleMoves[move].ignoresSubstitute) return FALSE; else if (GetBattlerAbility(battlerAtk) == ABILITY_INFILTRATOR) @@ -14924,18 +14839,15 @@ static void Cmd_removelightscreenreflect(void) u8 side; bool32 failed; -#if B_BRICK_BREAK >= GEN_4 -// From Gen 4 onwards, Brick Break can remove screens on the user's side if used on an ally - side = GetBattlerSide(gBattlerTarget); -#else - side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; -#endif + 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; -#if B_BRICK_BREAK >= GEN_5 - failed = (gMoveResultFlags & MOVE_RESULT_NO_EFFECT); -#else - failed = FALSE; -#endif + if (B_BRICK_BREAK >= GEN_5) + failed = (gMoveResultFlags & MOVE_RESULT_NO_EFFECT); + else + failed = FALSE; if (!failed && (gSideTimers[side].reflectTimer @@ -15018,81 +14930,60 @@ static void Cmd_handleballthrow(void) case ITEM_ULTRA_BALL: ballMultiplier = 200; break; - #if B_SPORT_BALL_MODIFIER <= GEN_7 case ITEM_SPORT_BALL: - #endif + if (B_SPORT_BALL_MODIFIER <= GEN_7) + ballMultiplier = 150; case ITEM_GREAT_BALL: case ITEM_SAFARI_BALL: ballMultiplier = 150; break; case ITEM_NET_BALL: if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG)) - #if B_NET_BALL_MODIFIER >= GEN_7 - ballMultiplier = 350; - #else - ballMultiplier = 300; - #endif + ballMultiplier = B_NET_BALL_MODIFIER >= GEN_7 ? 350 : 300; break; case ITEM_DIVE_BALL: if (GetCurrentMapType() == MAP_TYPE_UNDERWATER - #if B_DIVE_BALL_MODIFIER >= GEN_4 - || gIsFishingEncounter || gIsSurfingEncounter - #endif - ) + || (B_DIVE_BALL_MODIFIER >= GEN_4 && (gIsFishingEncounter || gIsSurfingEncounter))) ballMultiplier = 350; break; case ITEM_NEST_BALL: - #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); - #elif 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 - //((40 - Pokémon's level) ÷ 10)×, minimum 1× - if (gBattleMons[gBattlerTarget].level < 40) + 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; } - #endif break; case ITEM_REPEAT_BALL: - if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT)) - #if B_REPEAT_BALL_MODIFIER >= GEN_7 - ballMultiplier = 350; - #else - ballMultiplier = 300; - #endif - break; + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), FLAG_GET_CAUGHT)) + ballMultiplier = (B_REPEAT_BALL_MODIFIER >= GEN_7 ? 350 : 300); + break; case ITEM_TIMER_BALL: - #if B_TIMER_BALL_MODIFIER >= GEN_5 - ballMultiplier = (gBattleResults.battleTurnCounter * 30) + 100; - #else - ballMultiplier = (gBattleResults.battleTurnCounter * 10) + 100; - #endif + ballMultiplier = 100 + (gBattleResults.battleTurnCounter * (B_TIMER_BALL_MODIFIER >= GEN_5 ? 30 : 10)); if (ballMultiplier > 400) ballMultiplier = 400; break; case ITEM_DUSK_BALL: RtcCalcLocalTime(); if ((gLocalTime.hours >= 20 && gLocalTime.hours <= 3) || gMapHeader.cave || gMapHeader.mapType == MAP_TYPE_UNDERGROUND) - #if B_DUSK_BALL_MODIFIER >= GEN_7 - ballMultiplier = 300; - #else - ballMultiplier = 350; - #endif + ballMultiplier = (B_DUSK_BALL_MODIFIER >= GEN_7 ? 300 : 350); break; case ITEM_QUICK_BALL: if (gBattleResults.battleTurnCounter == 0) - #if B_QUICK_BALL_MODIFIER >= GEN_5 - ballMultiplier = 500; - #else - ballMultiplier = 400; - #endif + ballMultiplier = (B_QUICK_BALL_MODIFIER >= GEN_5 ? 500 : 400); break; case ITEM_LEVEL_BALL: if (gBattleMons[gBattlerAttacker].level >= 4 * gBattleMons[gBattlerTarget].level) @@ -15104,11 +14995,7 @@ static void Cmd_handleballthrow(void) break; case ITEM_LURE_BALL: if (gIsFishingEncounter) - #if B_LURE_BALL_MODIFIER >= GEN_7 - ballMultiplier = 500; - #else - ballMultiplier = 300; - #endif + ballMultiplier = (B_LURE_BALL_MODIFIER >= GEN_7 ? 500 : 300); break; case ITEM_MOON_BALL: for (i = 0; i < EVOS_PER_MON; i++) @@ -15134,44 +15021,45 @@ static void Cmd_handleballthrow(void) break; case ITEM_HEAVY_BALL: i = GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), 1); - #if B_HEAVY_BALL_MODIFIER >= GEN_7 - if (i < 1000) - ballAddition = -20; - else if (i < 2000) - ballAddition = 0; - else if (i < 3000) - ballAddition = 20; + 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 - ballAddition = 30; - #elif 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; - #endif + { + 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 ITEM_DREAM_BALL: - #if B_DREAM_BALL_MODIFIER >= GEN_8 - if (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP || GetBattlerAbility(gBattlerTarget) == ABILITY_COMATOSE) + if (B_DREAM_BALL_MODIFIER >= GEN_8 && (gBattleMons[gBattlerTarget].status1 & STATUS1_SLEEP || GetBattlerAbility(gBattlerTarget) == ABILITY_COMATOSE)) ballMultiplier = 400; - #else - ballMultiplier = 100; - #endif break; case ITEM_BEAST_BALL: ballMultiplier = 10; @@ -15551,17 +15439,14 @@ static void Cmd_removeattackerstatus1(void) gBattlescriptCurrInstr = cmd->nextInstr; } +// CMD_ARGS is not needed for these functions as they end the script execution. static void Cmd_finishaction(void) { - CMD_ARGS(); - gCurrentActionFuncId = B_ACTION_FINISHED; } static void Cmd_finishturn(void) { - CMD_ARGS(); - gCurrentActionFuncId = B_ACTION_FINISHED; gCurrentTurnActionNumber = gBattlersCount; } @@ -15797,8 +15682,12 @@ void BS_DoStockpileStatChangesWearOff(void) static bool32 CriticalCapture(u32 odds) { -#if B_CRITICAL_CAPTURE == TRUE - u32 numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); + u32 numCaught; + + if (B_CRITICAL_CAPTURE == FALSE) + return FALSE; + + numCaught = GetNationalPokedexCount(FLAG_GET_CAUGHT); if (numCaught <= (NATIONAL_DEX_COUNT * 30) / 650) odds = 0; @@ -15821,9 +15710,6 @@ static bool32 CriticalCapture(u32 odds) return TRUE; return FALSE; -#else - return FALSE; -#endif } static const u16 sParentalBondBannedEffects[] = @@ -15852,7 +15738,7 @@ bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler) { if (move != MOVE_NONE && move != MOVE_STRUGGLE && gBattleMoves[move].split != SPLIT_STATUS - && !gBattleMoves[move].strikeCount > 2) + && gBattleMoves[move].strikeCount <= 2) { u32 i; for (i = 0; i < ARRAY_COUNT(sParentalBondBannedEffects); i++) @@ -15957,7 +15843,7 @@ static void TryUpdateRoundTurnOrder(void) u32 i; u32 j = 0; u32 k = 0; - u32 currRounder; + u32 currRounder = 0; u8 roundUsers[3] = {0xFF, 0xFF, 0xFF}; u8 nonRoundUsers[3] = {0xFF, 0xFF, 0xFF}; for (i = 0; i < gBattlersCount; i++) diff --git a/src/battle_tower.c b/src/battle_tower.c index edacc53a98..c30406f798 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -3004,7 +3004,7 @@ void TryHideBattleTowerReporter(void) static void FillPartnerParty(u16 trainerId) { s32 i, j; - u32 ivs, level; + u32 ivs, level, personality; u32 friendship; u16 monId; u32 otID; @@ -3054,22 +3054,22 @@ static void FillPartnerParty(u16 trainerId) u32 otIdType = OT_ID_RANDOM_NO_SHINY; do { - j = Random32(); - } while (IsShinyOtIdPersonality(otID, j)); + personality = Random32(); + } while (IsShinyOtIdPersonality(otID, personality)); if (partyData[i].gender == TRAINER_MON_MALE) - j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species); + personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species); else if (partyData[i].gender == TRAINER_MON_FEMALE) - j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species); + personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species); if (partyData[i].nature != 0) - ModifyPersonalityForNature(&j, partyData[i].nature - 1); + ModifyPersonalityForNature(&personality, partyData[i].nature - 1); if (partyData[i].isShiny) { otIdType = OT_ID_PRESET; - otID = HIHALF(j) ^ LOHALF(j); + otID = HIHALF(personality) ^ LOHALF(personality); } - CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, j, otIdType, otID); + CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, personality, otIdType, otID); SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem); CustomTrainerPartyAssignMoves(&gPlayerParty[i+3], &partyData[i]); diff --git a/src/battle_transition.c b/src/battle_transition.c index 11f9cddf4b..ae42db1fef 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -1196,7 +1196,7 @@ static bool8 Swirl_Init(struct Task *task) InitTransitionData(); ScanlineEffect_Clear(); BeginNormalPaletteFade(PALETTES_ALL, 4, 0, 16, RGB_BLACK); - SetSinWave(gScanlineEffectRegBuffers[1], sTransitionData->cameraX, 0, 2, 0, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[1], sTransitionData->cameraX, 0, 2, 0, DISPLAY_HEIGHT); SetVBlankCallback(VBlankCB_Swirl); SetHBlankCallback(HBlankCB_Swirl); @@ -1213,7 +1213,7 @@ static bool8 Swirl_End(struct Task *task) task->tSinIndex += 4; task->tAmplitude += 8; - SetSinWave(gScanlineEffectRegBuffers[0], sTransitionData->cameraX, task->tSinIndex, 2, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], sTransitionData->cameraX, task->tSinIndex, 2, task->tAmplitude, DISPLAY_HEIGHT); if (!gPaletteFade.active) { @@ -1468,7 +1468,7 @@ static bool8 BigPokeball_SetGfx(struct Task *task) SET_TILE(tilemap, i, j, *bigPokeballMap); } - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return TRUE; @@ -1480,7 +1480,7 @@ static bool8 Aqua_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LZ77UnCompVram(sTeamAqua_Tilemap, tilemap); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return FALSE; @@ -1492,7 +1492,7 @@ static bool8 Magma_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LZ77UnCompVram(sTeamMagma_Tilemap, tilemap); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return FALSE; @@ -1505,7 +1505,7 @@ static bool8 Regice_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LoadPalette(sRegice_Palette, BG_PLTT_ID(15), sizeof(sRegice_Palette)); CpuCopy16(sRegice_Tilemap, tilemap, 0x500); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return FALSE; @@ -1518,7 +1518,7 @@ static bool8 Registeel_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LoadPalette(sRegisteel_Palette, BG_PLTT_ID(15), sizeof(sRegisteel_Palette)); CpuCopy16(sRegisteel_Tilemap, tilemap, 0x500); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return FALSE; @@ -1531,7 +1531,7 @@ static bool8 Regirock_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LoadPalette(sRegirock_Palette, BG_PLTT_ID(15), sizeof(sRegirock_Palette)); CpuCopy16(sRegirock_Tilemap, tilemap, 0x500); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return FALSE; @@ -1623,7 +1623,7 @@ static bool8 PatternWeave_Blend1(struct Task *task) task->tSinIndex += 8; task->tAmplitude -= 256; - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); sTransitionData->VBlank_DMA++; return FALSE; @@ -1643,7 +1643,7 @@ static bool8 PatternWeave_Blend2(struct Task *task) task->tSinIndex += 8; task->tAmplitude -= 256; - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); sTransitionData->VBlank_DMA++; return FALSE; @@ -1655,7 +1655,7 @@ static bool8 PatternWeave_FinishAppear(struct Task *task) task->tSinIndex += 8; task->tAmplitude -= 256; - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude >> 8, DISPLAY_HEIGHT); if (task->tAmplitude <= 0) { @@ -4253,7 +4253,7 @@ static bool8 FrontierLogoWiggle_SetGfx(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); LZ77UnCompVram(sFrontierLogo_Tilemap, tilemap); - SetSinWave(gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); + SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; return TRUE; diff --git a/src/battle_util.c b/src/battle_util.c index 44890cd139..c2adc6b199 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -62,7 +62,6 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler); static u32 GetFlingPowerFromItemId(u32 itemId); static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); -static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier); static uq4_12_t GetSupremeOverlordModifier(u32 battler); static bool32 CanBeInfinitelyConfused(u32 battler); @@ -584,12 +583,10 @@ bool32 TryRunFromBattle(u32 battler) gProtectStructs[battler].fleeType = FLEE_ITEM; effect++; } - #if B_GHOSTS_ESCAPE >= GEN_6 - else if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) + else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) { effect++; } - #endif else if (GetBattlerAbility(battler) == ABILITY_RUN_AWAY) { if (InBattlePyramid()) @@ -835,10 +832,8 @@ void HandleAction_NothingIsFainted(void) void HandleAction_ActionFinished(void) { - #if B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 u32 i, j; bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou; - #endif *(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE; gCurrentTurnActionNumber++; gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; @@ -863,8 +858,7 @@ void HandleAction_ActionFinished(void) gBattleResources->battleScriptsStack->size = 0; gBattleStruct->dynamax.usingMaxMove[gBattlerAttacker] = 0; - #if B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 - if (!afterYouActive) + if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action @@ -894,7 +888,6 @@ void HandleAction_ActionFinished(void) } } } - #endif } static const u8 sAbilitiesAffectedByMoldBreaker[] = @@ -1350,7 +1343,6 @@ void MarkBattlerReceivedLinkData(u32 battler) void CancelMultiTurnMoves(u32 battler) { - u8 i; gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE); gBattleMons[battler].status2 &= ~(STATUS2_UPROAR); @@ -1583,11 +1575,6 @@ bool32 IsHealBlockPreventingMove(u32 battler, u32 move) switch (gBattleMoves[move].effect) { -#if B_HEAL_BLOCKING >= GEN_6 - case EFFECT_ABSORB: - case EFFECT_STRENGTH_SAP: - case EFFECT_DREAM_EATER: -#endif case EFFECT_MORNING_SUN: case EFFECT_SYNTHESIS: case EFFECT_MOONLIGHT: @@ -1599,6 +1586,10 @@ bool32 IsHealBlockPreventingMove(u32 battler, u32 move) case EFFECT_HEAL_PULSE: case EFFECT_JUNGLE_HEALING: return TRUE; + case EFFECT_ABSORB: + case EFFECT_STRENGTH_SAP: + case EFFECT_DREAM_EATER: + return B_HEAL_BLOCKING >= GEN_6; default: return FALSE; } @@ -2463,25 +2454,21 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WATER_SPORT: - #if B_SPORT_TURNS >= GEN_6 - if (gFieldStatuses & STATUS_FIELD_WATERSPORT && --gFieldTimers.waterSportTimer == 0) - { - gFieldStatuses &= ~STATUS_FIELD_WATERSPORT; - BattleScriptExecute(BattleScript_WaterSportEnds); - effect++; - } - #endif + if (gFieldStatuses & STATUS_FIELD_WATERSPORT && --gFieldTimers.waterSportTimer == 0) + { + gFieldStatuses &= ~STATUS_FIELD_WATERSPORT; + BattleScriptExecute(BattleScript_WaterSportEnds); + effect++; + } gBattleStruct->turnCountersTracker++; break; case ENDTURN_MUD_SPORT: - #if B_SPORT_TURNS >= GEN_6 - if (gFieldStatuses & STATUS_FIELD_MUDSPORT && --gFieldTimers.mudSportTimer == 0) - { - gFieldStatuses &= ~STATUS_FIELD_MUDSPORT; - BattleScriptExecute(BattleScript_MudSportEnds); - effect++; - } - #endif + if (gFieldStatuses & STATUS_FIELD_MUDSPORT && --gFieldTimers.mudSportTimer == 0) + { + gFieldStatuses &= ~STATUS_FIELD_MUDSPORT; + BattleScriptExecute(BattleScript_MudSportEnds); + effect++; + } gBattleStruct->turnCountersTracker++; break; case ENDTURN_GRAVITY: @@ -2526,8 +2513,8 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) { - #if B_AFFECTION_MECHANICS == TRUE - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER + if (B_AFFECTION_MECHANICS == TRUE + && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && GetBattlerFriendshipScore(gBattlerAttacker) >= FRIENDSHIP_150_TO_199 && (Random() % 100 < 20)) { @@ -2535,7 +2522,6 @@ u8 DoFieldEndTurnEffects(void) BattleScriptExecute(BattleScript_AffectionBasedStatusHeal); break; } - #endif } gBattleStruct->turnCountersTracker++; break; @@ -2588,6 +2574,7 @@ enum ENDTURN_CUD_CHEW, ENDTURN_TORMENT, // supposedly this goes after Taunt, before Encore, but Encore is first right now? ENDTURN_SALT_CURE, + ENDTURN_SYRUP_BOMB, ENDTURN_DYNAMAX, ENDTURN_BATTLER_COUNT }; @@ -2757,11 +2744,7 @@ u8 DoBattlerEndTurnEffects(void) && gBattleMons[battler].hp != 0) { MAGIC_GUARD_CHECK; - #if B_BURN_DAMAGE >= GEN_7 - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; - #else - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8; - #endif + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (ability == ABILITY_HEATPROOF) { if (gBattleMoveDamage > (gBattleMoveDamage / 2) + 1) // Record ability if the burn takes less damage than it normally would. @@ -2780,11 +2763,7 @@ u8 DoBattlerEndTurnEffects(void) && gBattleMons[battler].hp != 0) { MAGIC_GUARD_CHECK; - #if B_BURN_DAMAGE >= GEN_7 - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; - #else - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8; - #endif + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; BattleScriptExecute(BattleScript_FrostbiteTurnDmg); @@ -2839,15 +2818,9 @@ u8 DoBattlerEndTurnEffects(void) PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[battler]); gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[battler], TRUE) == HOLD_EFFECT_BINDING_BAND) - #if B_BINDING_DAMAGE >= GEN_6 - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 6; + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8; - #else - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8; - else - gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; - #endif + gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; @@ -3038,11 +3011,11 @@ u8 DoBattlerEndTurnEffects(void) } else { - #if B_SLEEP_TURNS >= GEN_5 - gBattleMons[battler].status1 |= ((Random() % 3) + 2); - #else - gBattleMons[battler].status1 |= ((Random() % 4) + 3); - #endif + if (B_SLEEP_TURNS >= GEN_5) + gBattleMons[battler].status1 |= ((Random() % 3) + 2); + else + gBattleMons[battler].status1 |= ((Random() % 4) + 3); + BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); BattleScriptExecute(BattleScript_YawnMakesAsleep); @@ -3164,6 +3137,27 @@ u8 DoBattlerEndTurnEffects(void) } gBattleStruct->turnEffectsTracker++; break; + case ENDTURN_SYRUP_BOMB: + if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (gBattleMons[battler].hp != 0)) + { + gDisableStructs[battler].syrupBombTimer--; + if (gDisableStructs[battler].syrupBombTimer == 0) + { + gStatuses4[battler] &= ~STATUS4_SYRUP_BOMB; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); + gBattlescriptCurrInstr = BattleScript_WrapEnds; + } + else if (gDisableStructs[battler].syrupBombTimer != 0) + { + gBattlerTarget = battler; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB); + gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn; + } + BattleScriptExecute(gBattlescriptCurrInstr); + effect++; + } + gBattleStruct->turnEffectsTracker++; + break; case ENDTURN_TORMENT: if (gDisableStructs[battler].tormentTimer != PERMANENT_TORMENT && --gDisableStructs[battler].tormentTimer == 0) @@ -3341,27 +3335,25 @@ bool32 HandleFaintedMonActions(void) gBattleStruct->faintedActionsState = 3; else gBattleStruct->faintedActionsState = 1; - #if B_FAINT_SWITCH_IN >= GEN_4 // Don't switch mons until all pokemon performed their actions or the battle's over. - if (gBattleOutcome == 0 + if (B_FAINT_SWITCH_IN >= GEN_4 + && gBattleOutcome == 0 && !NoAliveMonsForEitherParty() && gCurrentTurnActionNumber != gBattlersCount) { gAbsentBattlerFlags |= gBitTable[gBattlerFainted]; return FALSE; } - #endif break; case 3: - #if B_FAINT_SWITCH_IN >= GEN_4 // Don't switch mons until all pokemon performed their actions or the battle's over. - if (gBattleOutcome == 0 + if (B_FAINT_SWITCH_IN >= GEN_4 + && gBattleOutcome == 0 && !NoAliveMonsForEitherParty() && gCurrentTurnActionNumber != gBattlersCount) { return FALSE; } - #endif gBattleStruct->faintedActionsBattlerId = 0; gBattleStruct->faintedActionsState++; // fall through @@ -3615,11 +3607,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION) { // confusion dmg - #if B_CONFUSION_SELF_DMG_CHANCE >= GEN_7 - if (RandomWeighted(RNG_CONFUSION, 2, 1)) - #else - if (RandomWeighted(RNG_CONFUSION, 1, 1)) - #endif + if (RandomWeighted(RNG_CONFUSION, (B_CONFUSION_SELF_DMG_CHANCE >= GEN_7 ? 2 : 1), 1)) { gBattleCommunication[MULTISTRING_CHOOSER] = TRUE; gBattlerTarget = gBattlerAttacker; @@ -3733,11 +3721,8 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) case CANCELLER_POWDER_MOVE: if ((gBattleMoves[gCurrentMove].powderMove) && (gBattlerAttacker != gBattlerTarget)) { - #if B_POWDER_GRASS >= GEN_6 - if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) || GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT) - #else - if (GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT) - #endif + if (B_POWDER_GRASS >= GEN_6 + && (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) || GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT)) { gBattlerAbility = gBattlerTarget; effect = 1; @@ -3842,8 +3827,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 3, 0) } } - #if B_BEAT_UP >= GEN_5 - else if (gBattleMoves[gCurrentMove].effect == EFFECT_BEAT_UP) + else if (B_BEAT_UP >= GEN_5 && gBattleMoves[gCurrentMove].effect == EFFECT_BEAT_UP) { struct Pokemon* party = GetBattlerParty(gBattlerAttacker); int i; @@ -3860,7 +3844,6 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gBattleStruct->beatUpSlot = 0; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } - #endif gBattleStruct->atkCancellerTracker++; break; case CANCELLER_END: @@ -4090,14 +4073,12 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) { return FALSE; } -#if B_ABILITY_WEATHER <= GEN_5 - else if (viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) + else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) { gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]); ShouldChangeFormInWeather(battler); return TRUE; } -#endif else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]))) { gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0]); @@ -4232,7 +4213,6 @@ static uq4_12_t GetSupremeOverlordModifier(u32 battler) u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg) { u32 effect = 0; - u32 speciesAtk, speciesDef; u32 moveType, move; u32 i, j; @@ -4242,9 +4222,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gBattlerAttacker >= gBattlersCount) gBattlerAttacker = battler; - speciesAtk = gBattleMons[gBattlerAttacker].species; - speciesDef = gBattleMons[gBattlerTarget].species; - if (special) gLastUsedAbility = special; else @@ -4268,24 +4245,25 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 switch (VarGet(VAR_TERRAIN) & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_ELECTRIC_TERRAIN: - gBattleCommunication[MULTISTRING_CHOOSER] = 2; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC; break; case STATUS_FIELD_MISTY_TERRAIN: - gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY; break; case STATUS_FIELD_GRASSY_TERRAIN: - gBattleCommunication[MULTISTRING_CHOOSER] = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY; break; case STATUS_FIELD_PSYCHIC_TERRAIN: - gBattleCommunication[MULTISTRING_CHOOSER] = 3; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; } BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); effect++; } - #if B_THUNDERSTORM_TERRAIN == TRUE - else if (GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)) + else if (B_THUNDERSTORM_TERRAIN == TRUE + && GetCurrentWeather() == WEATHER_RAIN_THUNDERSTORM + && !(gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN)) { // overworld weather started rain, so just do electric terrain anim gFieldStatuses = (STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); @@ -4293,16 +4271,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); effect++; } - #endif - #if B_FOG_TERRAIN == TRUE - else if ((GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) + else if (B_FOG_TERRAIN == TRUE + && (GetCurrentWeather() == WEATHER_FOG_HORIZONTAL || GetCurrentWeather() == WEATHER_FOG_DIAGONAL) + && !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN)) { gFieldStatuses = (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); gBattleCommunication[MULTISTRING_CHOOSER] = 0; BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain); effect++; } - #endif break; case ABILITYEFFECT_SWITCH_IN_WEATHER: gBattleScripting.battler = battler; @@ -4339,16 +4316,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case WEATHER_SNOW: if (!(gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) { - #if B_OVERWORLD_SNOW >= GEN_9 + if (B_OVERWORLD_SNOW >= GEN_9) + { gBattleWeather = B_WEATHER_SNOW; gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; - effect++; - #else + } + else + { gBattleWeather = B_WEATHER_HAIL; gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; - effect++; - #endif - + } + effect++; } break; } @@ -4436,7 +4414,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)) && TryResetBattlerStatChanges(BATTLE_PARTNER(battler))) { - u32 i; gEffectBattler = BATTLE_PARTNER(battler); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_CURIOUS_MEDICINE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -4633,19 +4610,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SNOW_WARNING: - #if B_SNOW_WARNING >= GEN_9 - if (TryChangeBattleWeather(battler, ENUM_WEATHER_SNOW, TRUE)) + if (B_SNOW_WARNING >= GEN_9 && TryChangeBattleWeather(battler, ENUM_WEATHER_SNOW, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow); effect++; } - #else - if (TryChangeBattleWeather(battler, ENUM_WEATHER_HAIL, TRUE)) + else if (B_SNOW_WARNING < GEN_9 && TryChangeBattleWeather(battler, ENUM_WEATHER_HAIL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail); effect++; } - #endif else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT && !gSpecialStatuses[battler].switchInAbilityDone) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; @@ -4907,11 +4881,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (gDisableStructs[battler].isFirstTurn != 2) { u32 validToRaise = 0, validToLower = 0; - #if B_MOODY_ACC_EVASION < GEN_8 - u32 statsNum = NUM_BATTLE_STATS; - #else - u32 statsNum = NUM_STATS; - #endif + u32 statsNum = B_MOODY_ACC_EVASION >= GEN_8 ? NUM_STATS : NUM_BATTLE_STATS; for (i = STAT_ATK; i < statsNum; i++) { @@ -5106,10 +5076,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_FLASH_FIRE: if (moveType == TYPE_FIRE - #if B_FLASH_FIRE_FROZEN <= GEN_4 - && !(gBattleMons[battler].status1 & STATUS1_FREEZE) - #endif - ) + && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battler].status1 & STATUS1_FREEZE))) { if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) { @@ -5150,11 +5117,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (effect == 1) // Drain Hp ability. { -#if B_HEAL_BLOCKING >= GEN_5 - if (BATTLER_MAX_HP(battler) || gStatuses3[battler] & STATUS3_HEAL_BLOCK) -#else - if (BATTLER_MAX_HP(battler)) -#endif + if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; @@ -5191,9 +5154,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss; SET_STATCHANGER(statId, statAmount, FALSE); - #if B_ABSORBING_ABILITY_STRING < GEN_5 - PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); - #endif + if (B_ABSORBING_ABILITY_STRING < GEN_5) + PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); } } } @@ -5458,11 +5420,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && TARGET_TURN_DAMAGED && IsMoveMakingContact(move, gBattlerAttacker)) { - #if B_ROUGH_SKIN_DMG >= GEN_4 - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - #else - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 16; - #endif + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -5809,9 +5767,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && RandomWeighted(RNG_STENCH, 9, 1) && !IS_MOVE_STATUS(move) - && !gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_HIT - && !gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_STATUS - && !gBattleMoves[gCurrentMove].effect != EFFECT_TRIPLE_ARROWS) + && gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_HIT + && gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_STATUS + && gBattleMoves[gCurrentMove].effect != EFFECT_TRIPLE_ARROWS) { gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; BattleScriptPushCursor(); @@ -5860,6 +5818,27 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; } break; + case ABILITYEFFECT_OPPORTUNIST: + /* Similar to ABILITYEFFECT_IMMUNITY in that it loops through all battlers. + * Is called after ABILITYEFFECT_ON_SWITCHIN to copy any boosts + * from switch in abilities e.g. intrepid sword, as + */ + for (battler = 0; battler < gBattlersCount; battler++) + { + switch (GetBattlerAbility(battler)) + { + case ABILITY_OPPORTUNIST: + if (gProtectStructs[battler].activateOpportunist == 2) { + gBattleScripting.savedBattler = gBattlerAttacker; + gBattleScripting.battler = gBattlerAttacker = gBattlerAbility = battler; + gProtectStructs[battler].activateOpportunist--; + BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChange); + effect = 1; + } + break; + } + } + break; case ABILITYEFFECT_IMMUNITY: // 5 for (battler = 0; battler < gBattlersCount; battler++) { @@ -5918,6 +5897,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect = 4; break; } + if (effect != 0) { switch (effect) @@ -5959,10 +5939,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)) { gBattleStruct->synchronizeMoveEffect &= ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN); - #if B_SYNCHRONIZE_TOXIC < GEN_5 - if (gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) - gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; - #endif + if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER; gBattleScripting.battler = gBattlerAbility = gBattlerTarget; @@ -6308,15 +6286,10 @@ u32 IsAbilityOnFieldExcept(u32 battler, u32 ability) u32 IsAbilityPreventingEscape(u32 battler) { u32 id; -#if B_GHOSTS_ESCAPE >= GEN_6 - if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) + if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return 0; -#endif -#if B_SHADOW_TAG_ESCAPE >= GEN_4 - if ((id = IsAbilityOnOpposingSide(battler, ABILITY_SHADOW_TAG)) && GetBattlerAbility(battler) != ABILITY_SHADOW_TAG) -#else - if ((id = IsAbilityOnOpposingSide(battler, ABILITY_SHADOW_TAG))) -#endif + if ((id = IsAbilityOnOpposingSide(battler, ABILITY_SHADOW_TAG)) + && (B_SHADOW_TAG_ESCAPE < GEN_4 && GetBattlerAbility(battler) != ABILITY_SHADOW_TAG)) return id; if ((id = IsAbilityOnOpposingSide(battler, ABILITY_ARENA_TRAP)) && IsBattlerGrounded(battler)) return id; @@ -6330,10 +6303,8 @@ bool32 CanBattlerEscape(u32 battler) // no ability check { if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SHED_SHELL) return TRUE; -#if B_GHOSTS_ESCAPE >= GEN_6 - else if (IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) + else if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GHOST)) return TRUE; -#endif else if (gBattleMons[battler].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)) return FALSE; else if (gStatuses3[battler] & STATUS3_ROOTED) @@ -6432,11 +6403,8 @@ bool32 CanBeBurned(u32 battler) bool32 CanBeParalyzed(u32 battler) { u16 ability = GetBattlerAbility(battler); - if ( - #if B_PARALYZE_ELECTRIC >= GEN_6 - IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC) || - #endif - gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD + if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC)) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || ability == ABILITY_LIMBER || ability == ABILITY_COMATOSE || gBattleMons[battler].status1 & STATUS1_ANY @@ -6509,19 +6477,10 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) return FALSE; } -#if B_CONFUSE_BERRIES_HEAL >= GEN_7 - #define CONFUSE_BERRY_HP_FRACTION 4 -#else - #define CONFUSE_BERRY_HP_FRACTION 2 -#endif - static u8 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, bool32 end2) { - if (HasEnoughHpToEatBerry(battler, CONFUSE_BERRY_HP_FRACTION, itemId) -#if B_HEAL_BLOCKING >= GEN_5 - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) -#endif - ) + if (HasEnoughHpToEatBerry(battler, (B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2), itemId) + && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId); @@ -6557,8 +6516,6 @@ static u8 HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, bool32 end2) return 0; } -#undef CONFUSE_BERRY_HP_FRACTION - static u8 StatRaiseBerry(u32 battler, u32 itemId, u32 statId, bool32 end2) { if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, itemId), itemId)) @@ -6664,9 +6621,7 @@ static u8 TrySetEnigmaBerry(u32 battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && ((TARGET_TURN_DAMAGED && gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) -#if B_HEAL_BLOCKING >= GEN_5 - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) -#endif + && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { gBattleScripting.battler = battler; gBattleMoveDamage = (gBattleMons[battler].maxHP * 25 / 100) * -1; @@ -6698,6 +6653,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 split) else SET_STATCHANGER(statId, 1, FALSE); + gBattleScripting.battler = battler; gBattleScripting.animArg1 = 14 + statId; gBattleScripting.animArg2 = 0; BattleScriptPushCursor(); @@ -6781,9 +6737,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, bool32 execute) static u8 ItemHealHp(u32 battler, u32 itemId, bool32 end2, bool32 percentHeal) { if (!(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) - #if B_HEAL_BLOCKING >= GEN_5 - && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) - #endif + && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) && HasEnoughHpToEatBerry(battler, 2, itemId)) { if (percentHeal) @@ -6829,46 +6783,47 @@ static bool32 GetMentalHerbEffect(u32 battler) StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); ret = TRUE; } -#if B_MENTAL_HERB >= GEN_5 - // Check taunt - if (gDisableStructs[battler].tauntTimer != 0) + if (B_MENTAL_HERB >= GEN_5) { - gDisableStructs[battler].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - ret = TRUE; + // Check taunt + if (gDisableStructs[battler].tauntTimer != 0) + { + gDisableStructs[battler].tauntTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + ret = TRUE; + } + // Check encore + if (gDisableStructs[battler].encoreTimer != 0) + { + gDisableStructs[battler].encoredMove = 0; + gDisableStructs[battler].encoreTimer = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED + ret = TRUE; + } + // Check torment + if (gBattleMons[battler].status2 & STATUS2_TORMENT) + { + gBattleMons[battler].status2 &= ~STATUS2_TORMENT; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; + ret = TRUE; + } + // Check heal block + if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) + { + gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; + ret = TRUE; + } + // Check disable + if (gDisableStructs[battler].disableTimer != 0) + { + gDisableStructs[battler].disableTimer = 0; + gDisableStructs[battler].disabledMove = 0; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; + ret = TRUE; + } } - // Check encore - if (gDisableStructs[battler].encoreTimer != 0) - { - gDisableStructs[battler].encoredMove = 0; - gDisableStructs[battler].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - ret = TRUE; - } - // Check torment - if (gBattleMons[battler].status2 & STATUS2_TORMENT) - { - gBattleMons[battler].status2 &= ~STATUS2_TORMENT; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; - ret = TRUE; - } - // Check heal block - if (gStatuses3[battler] & STATUS3_HEAL_BLOCK) - { - gStatuses3[battler] &= ~STATUS3_HEAL_BLOCK; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; - ret = TRUE; - } - // Check disable - if (gDisableStructs[battler].disableTimer != 0) - { - gDisableStructs[battler].disableTimer = 0; - gDisableStructs[battler].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; - ret = TRUE; - } -#endif return ret; } @@ -6899,64 +6854,78 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect) switch (holdEffect) { -#if B_HP_BERRIES >= GEN_4 case HOLD_EFFECT_MICLE_BERRY: - effect = TrySetMicleBerry(battler, gLastUsedItem, FALSE); + if (B_HP_BERRIES >= GEN_4) + effect = TrySetMicleBerry(battler, gLastUsedItem, FALSE); break; case HOLD_EFFECT_RESTORE_HP: - effect = ItemHealHp(battler, gLastUsedItem, FALSE, FALSE); + if (B_HP_BERRIES >= GEN_4) + effect = ItemHealHp(battler, gLastUsedItem, FALSE, FALSE); break; -#endif -#if B_BERRIES_INSTANT >= GEN_4 case HOLD_EFFECT_RESTORE_PCT_HP: - effect = ItemHealHp(battler, gLastUsedItem, FALSE, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = ItemHealHp(battler, gLastUsedItem, FALSE, TRUE); break; case HOLD_EFFECT_RESTORE_PP: - effect = ItemRestorePp(battler, gLastUsedItem, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = ItemRestorePp(battler, gLastUsedItem, FALSE); break; case HOLD_EFFECT_CONFUSE_SPICY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, FALSE); break; case HOLD_EFFECT_CONFUSE_DRY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, FALSE); break; case HOLD_EFFECT_CONFUSE_SWEET: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, FALSE); break; case HOLD_EFFECT_CONFUSE_BITTER: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, FALSE); break; case HOLD_EFFECT_CONFUSE_SOUR: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, FALSE); break; case HOLD_EFFECT_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, FALSE); break; case HOLD_EFFECT_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, FALSE); break; case HOLD_EFFECT_SPEED_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, FALSE); break; case HOLD_EFFECT_SP_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, FALSE); break; case HOLD_EFFECT_SP_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, FALSE); break; case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move - effect = TrySetEnigmaBerry(battler); + if (B_BERRIES_INSTANT >= GEN_4) + effect = TrySetEnigmaBerry(battler); break; case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move - effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, SPLIT_PHYSICAL); + if (B_BERRIES_INSTANT >= GEN_4) + effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, SPLIT_PHYSICAL); break; case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move - effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, SPLIT_SPECIAL); + if (B_BERRIES_INSTANT >= GEN_4) + effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, SPLIT_SPECIAL); break; case HOLD_EFFECT_RANDOM_STAT_UP: - effect = RandomStatRaiseBerry(battler, gLastUsedItem, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = RandomStatRaiseBerry(battler, gLastUsedItem, FALSE); break; -#endif case HOLD_EFFECT_CURE_PAR: if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem)) { @@ -7119,8 +7088,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) { int i = 0, moveType; u8 effect = ITEM_NO_EFFECT; - u8 changedPP = 0; - u32 battlerHoldEffect, atkHoldEffect; + u32 battlerHoldEffect = 0, atkHoldEffect; u8 atkHoldEffectParam; u16 atkItem; @@ -7164,39 +7132,50 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) BattleScriptExecute(BattleScript_WhiteHerbEnd2); } break; - #if B_BERRIES_INSTANT >= GEN_4 case HOLD_EFFECT_CONFUSE_SPICY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SPICY, TRUE); break; case HOLD_EFFECT_CONFUSE_DRY: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_DRY, TRUE); break; case HOLD_EFFECT_CONFUSE_SWEET: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SWEET, TRUE); break; case HOLD_EFFECT_CONFUSE_BITTER: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_BITTER, TRUE); break; case HOLD_EFFECT_CONFUSE_SOUR: - effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = HealConfuseBerry(battler, gLastUsedItem, FLAVOR_SOUR, TRUE); break; case HOLD_EFFECT_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_ATK, TRUE); break; case HOLD_EFFECT_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_DEF, TRUE); break; case HOLD_EFFECT_SPEED_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPEED, TRUE); break; case HOLD_EFFECT_SP_ATTACK_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPATK, TRUE); break; case HOLD_EFFECT_SP_DEFENSE_UP: - effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, TRUE); break; case HOLD_EFFECT_CRITICAL_UP: - if (!(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY) && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && !(gBattleMons[battler].status2 & STATUS2_FOCUS_ENERGY) + && HasEnoughHpToEatBerry(battler, GetBattlerItemHoldEffectParam(battler, gLastUsedItem), gLastUsedItem)) { gBattleMons[battler].status2 |= STATUS2_FOCUS_ENERGY; gBattleScripting.battler = battler; @@ -7205,10 +7184,13 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_RANDOM_STAT_UP: - effect = RandomStatRaiseBerry(battler, gLastUsedItem, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = RandomStatRaiseBerry(battler, gLastUsedItem, TRUE); break; case HOLD_EFFECT_CURE_PAR: - if (gBattleMons[battler].status1 & STATUS1_PARALYSIS && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && gBattleMons[battler].status1 & STATUS1_PARALYSIS + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; BattleScriptExecute(BattleScript_BerryCurePrlzEnd2); @@ -7216,7 +7198,9 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CURE_PSN: - if (gBattleMons[battler].status1 & STATUS1_PSN_ANY && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_PSN_ANY) + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); BattleScriptExecute(BattleScript_BerryCurePsnEnd2); @@ -7224,7 +7208,9 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CURE_BRN: - if (gBattleMons[battler].status1 & STATUS1_BURN && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_BURN) + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_BURN; BattleScriptExecute(BattleScript_BerryCureBrnEnd2); @@ -7232,13 +7218,17 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CURE_FRZ: - if (gBattleMons[battler].status1 & STATUS1_FREEZE && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_FREEZE) + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_FREEZE; BattleScriptExecute(BattleScript_BerryCureFrzEnd2); effect = ITEM_STATUS_CHANGE; } - if (gBattleMons[battler].status1 & STATUS1_FROSTBITE && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_FROSTBITE) + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_FROSTBITE; BattleScriptExecute(BattleScript_BerryCureFsbEnd2); @@ -7246,7 +7236,9 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CURE_SLP: - if (gBattleMons[battler].status1 & STATUS1_SLEEP && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_SLEEP) + && !UnnerveOn(battler, gLastUsedItem)) { gBattleMons[battler].status1 &= ~STATUS1_SLEEP; gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE; @@ -7255,7 +7247,9 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_CURE_STATUS: - if ((gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) && !UnnerveOn(battler, gLastUsedItem)) + if (B_BERRIES_INSTANT >= GEN_4 + && (gBattleMons[battler].status1 & STATUS1_ANY || gBattleMons[battler].status2 & STATUS2_CONFUSION) + && !UnnerveOn(battler, gLastUsedItem)) { i = 0; if (gBattleMons[battler].status1 & STATUS1_PSN_ANY) @@ -7300,12 +7294,13 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_RESTORE_HP: - effect = ItemHealHp(battler, gLastUsedItem, TRUE, FALSE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = ItemHealHp(battler, gLastUsedItem, TRUE, FALSE); break; case HOLD_EFFECT_RESTORE_PCT_HP: - effect = ItemHealHp(battler, gLastUsedItem, TRUE, TRUE); + if (B_BERRIES_INSTANT >= GEN_4) + effect = ItemHealHp(battler, gLastUsedItem, TRUE, TRUE); break; - #endif case HOLD_EFFECT_AIR_BALLOON: effect = ITEM_EFFECT_OTHER; gBattleScripting.battler = battler; @@ -7437,11 +7432,8 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_LEFTOVERS: LEFTOVERS: -#if B_HEAL_BLOCKING >= GEN_5 - if (gBattleMons[battler].hp < gBattleMons[battler].maxHP && !moveTurn && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) -#else - if (gBattleMons[battler].hp < gBattleMons[battler].maxHP && !moveTurn) -#endif + if (gBattleMons[battler].hp < gBattleMons[battler].maxHP && !moveTurn + && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 16; if (gBattleMoveDamage == 0) @@ -7690,10 +7682,8 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) case HOLD_EFFECT_FLINCH: { u16 ability = GetBattlerAbility(gBattlerAttacker); - #if B_SERENE_GRACE_BOOST >= GEN_5 - if (ability == ABILITY_SERENE_GRACE) + if (B_SERENE_GRACE_BOOST >= GEN_5 && ability == ABILITY_SERENE_GRACE) atkHoldEffectParam *= 2; - #endif if (gBattleMoveDamage != 0 // Need to have done damage && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED @@ -7716,7 +7706,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) { gBattleStruct->blunderPolicy = FALSE; gLastUsedItem = atkItem; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPEED, 2, FALSE); + SET_STATCHANGER(STAT_SPEED, 2, FALSE); effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; @@ -7732,11 +7722,8 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) if (gSpecialStatuses[gBattlerAttacker].damagedMons // Need to have done damage && gBattlerAttacker != gBattlerTarget && gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP -#if B_HEAL_BLOCKING >= GEN_5 - && gBattleMons[gBattlerAttacker].hp != 0 && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) -#else - && gBattleMons[gBattlerAttacker].hp != 0) -#endif + && gBattleMons[gBattlerAttacker].hp != 0 + && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { gLastUsedItem = atkItem; gPotentialItemEffectBattler = gBattlerAttacker; @@ -7774,7 +7761,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) { gLastUsedItem = atkItem; gBattleScripting.battler = gBattlerAttacker; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); + SET_STATCHANGER(STAT_SPATK, 1, FALSE); effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise; @@ -7830,7 +7817,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_ATK, 1, FALSE); + SET_STATCHANGER(STAT_ATK, 1, FALSE); } break; case HOLD_EFFECT_LUMINOUS_MOSS: @@ -7841,7 +7828,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPDEF, 1, FALSE); + SET_STATCHANGER(STAT_SPDEF, 1, FALSE); } break; case HOLD_EFFECT_CELL_BATTERY: @@ -7852,7 +7839,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_ATK, 1, FALSE); + SET_STATCHANGER(STAT_ATK, 1, FALSE); } break; case HOLD_EFFECT_ABSORB_BULB: @@ -7863,7 +7850,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn) effect = ITEM_STATS_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_TargetItemStatRaise; - gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE); + SET_STATCHANGER(STAT_SPATK, 1, FALSE); } break; case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move @@ -8027,7 +8014,7 @@ u32 SetRandomTarget(u32 battler) u32 GetMoveTarget(u16 move, u8 setTarget) { u8 targetBattler = 0; - u32 i, moveTarget, side; + u32 moveTarget, side; if (setTarget != NO_TARGET_OVERRIDE) moveTarget = setTarget - 1; @@ -8132,10 +8119,8 @@ u8 IsMonDisobedient(void) return 0; if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) return 0; - #if B_OBEDIENCE_MECHANICS < GEN_8 - if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) + if (B_OBEDIENCE_MECHANICS < GEN_8 && !IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) return 0; - #endif if (FlagGet(FLAG_BADGE08_GET)) return 0; @@ -8149,11 +8134,10 @@ u8 IsMonDisobedient(void) obedienceLevel = 70; } -#if B_OBEDIENCE_MECHANICS >= GEN_8 - if (!IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) + if (B_OBEDIENCE_MECHANICS >= GEN_8 + && !IsOtherTrainer(gBattleMons[gBattlerAttacker].otId, gBattleMons[gBattlerAttacker].otName)) levelReferenced = gBattleMons[gBattlerAttacker].metLevel; else -#endif levelReferenced = gBattleMons[gBattlerAttacker].level; if (levelReferenced <= obedienceLevel) @@ -8369,10 +8353,8 @@ static bool32 IsBattlerGrounded2(u32 battler, bool32 considerInverse) return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY) return TRUE; -#if B_ROOTED_GROUNDING >= GEN_4 - if (gStatuses3[battler] & STATUS3_ROOTED) + if (B_ROOTED_GROUNDING >= GEN_4 && gStatuses3[battler] & STATUS3_ROOTED) return TRUE; -#endif if (gStatuses3[battler] & STATUS3_SMACKED_DOWN) return TRUE; if (gStatuses3[battler] & STATUS3_TELEKINESIS) @@ -8765,10 +8747,7 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 break; case EFFECT_PAYBACK: if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef) - #if B_PAYBACK_SWITCH_BOOST >= GEN_5 - && (gDisableStructs[battlerDef].isFirstTurn != 2) - #endif - ) + && (B_PAYBACK_SWITCH_BOOST < GEN_5 || gDisableStructs[battlerDef].isFirstTurn != 2)) basePower *= 2; break; case EFFECT_BOLT_BEAK: @@ -8804,18 +8783,17 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 break; case EFFECT_HIDDEN_POWER: { - #if B_HIDDEN_POWER_DMG < GEN_6 - u8 powerBits; + if (B_HIDDEN_POWER_DMG < GEN_6) + { + u8 powerBits = ((gBattleMons[battlerAtk].hpIV & 2) >> 1) + | ((gBattleMons[battlerAtk].attackIV & 2) << 0) + | ((gBattleMons[battlerAtk].defenseIV & 2) << 1) + | ((gBattleMons[battlerAtk].speedIV & 2) << 2) + | ((gBattleMons[battlerAtk].spAttackIV & 2) << 3) + | ((gBattleMons[battlerAtk].spDefenseIV & 2) << 4); - powerBits = ((gBattleMons[battlerAtk].hpIV & 2) >> 1) - | ((gBattleMons[battlerAtk].attackIV & 2) << 0) - | ((gBattleMons[battlerAtk].defenseIV & 2) << 1) - | ((gBattleMons[battlerAtk].speedIV & 2) << 2) - | ((gBattleMons[battlerAtk].spAttackIV & 2) << 3) - | ((gBattleMons[battlerAtk].spDefenseIV & 2) << 4); - - basePower = (40 * powerBits) / 63 + 30; - #endif + basePower = (40 * powerBits) / 63 + 30; + } break; } case EFFECT_GRAV_APPLE: @@ -8836,9 +8814,8 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3 basePower *= 2; break; case EFFECT_BEAT_UP: - #if B_BEAT_UP >= GEN_5 - basePower = CalcBeatUpPower(); - #endif + if (B_BEAT_UP >= GEN_5) + basePower = CalcBeatUpPower(); break; case EFFECT_PSYBLADE: if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) @@ -8907,20 +8884,13 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_KNOCK_OFF: - #if B_KNOCK_OFF_DMG >= GEN_6 - if (gBattleMons[battlerDef].item != ITEM_NONE + if (B_KNOCK_OFF_DMG >= GEN_6 + && gBattleMons[battlerDef].item != ITEM_NONE && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); - #endif break; } -#if B_TERRAIN_TYPE_BOOST >= GEN_8 - #define TERRAIN_TYPE_BOOST UQ_4_12(1.3) -#else - #define TERRAIN_TYPE_BOOST UQ_4_12(1.5) -#endif - // various effects if (gProtectStructs[battlerAtk].helpingHand) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); @@ -8931,25 +8901,19 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_GRASSY_TERRAIN) && moveType == TYPE_GRASS) - modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); + modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN) && moveType == TYPE_DRAGON) modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN) && moveType == TYPE_ELECTRIC) - modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); + modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && moveType == TYPE_PSYCHIC) - modifier = uq4_12_multiply(modifier, TERRAIN_TYPE_BOOST); - #if B_SPORT_TURNS >= GEN_6 - if ((moveType == TYPE_ELECTRIC && gFieldStatuses & STATUS_FIELD_MUDSPORT) - || (moveType == TYPE_FIRE && gFieldStatuses & STATUS_FIELD_WATERSPORT)) - #else - if ((moveType == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_MUD_SPORT, 0)) - || (moveType == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0))) - #endif - #if B_SPORT_DMG_REDUCTION >= GEN_5 - modifier = uq4_12_multiply(modifier, UQ_4_12(0.23)); - #else - modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); - #endif + modifier = uq4_12_multiply(modifier, (B_TERRAIN_TYPE_BOOST >= GEN_8 ? UQ_4_12(1.3) : UQ_4_12(1.5))); + if (moveType == TYPE_ELECTRIC && ((gFieldStatuses & STATUS_FIELD_MUDSPORT) + || AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_MUD_SPORT, 0))) + modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.23 : 0.5)); + if (moveType == TYPE_FIRE && ((gFieldStatuses & STATUS_FIELD_WATERSPORT) + || AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0))) + modifier = uq4_12_multiply(modifier, UQ_4_12(B_SPORT_DMG_REDUCTION >= GEN_5 ? 0.23 : 0.5)); // attacker's abilities switch (atkAbility) @@ -8984,9 +8948,9 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_RIVALRY: - if (AreBattlersOfOppositeGender(battlerAtk, battlerDef)) + if (AreBattlersOfSameGender(battlerAtk, battlerDef)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.25)); - else + else if (AreBattlersOfOppositeGender(battlerAtk, battlerDef)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.75)); break; case ABILITY_ANALYTIC: @@ -9043,7 +9007,11 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 break; case ABILITY_TRANSISTOR: if (moveType == TYPE_ELECTRIC) + #if B_TRANSISTOR_BOOST >= GEN_9 + modifier = uq4_12_multiply(modifier, UQ_4_12(5325 / 4096)); + #else modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); + #endif break; case ABILITY_DRAGONS_MAW: if (moveType == TYPE_DRAGON) @@ -9195,11 +9163,9 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_SOUL_DEW: - #if B_SOUL_DEW_BOOST >= GEN_7 - if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON)) - #else - if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && IS_MOVE_SPECIAL(move)) - #endif + if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) + && ((B_SOUL_DEW_BOOST >= GEN_7 && (moveType == TYPE_PSYCHIC || moveType == TYPE_DRAGON)) + || (B_SOUL_DEW_BOOST < GEN_7 && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && IS_MOVE_SPECIAL(move)))) modifier = uq4_12_multiply(modifier, holdEffectModifier); break; case HOLD_EFFECT_BUG_POWER: @@ -9241,7 +9207,6 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32 } return uq4_12_multiply_by_int_half_down(modifier, basePower); } -#undef TERRAIN_TYPE_BOOST static inline u32 CalcAttackStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 moveType, bool32 isCrit, bool32 updateFlags, u32 atkAbility, u32 defAbility, u32 holdEffectAtk) { @@ -9337,26 +9302,24 @@ static inline u32 CalcAttackStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 m if (moveType == TYPE_GRASS && gBattleMons[battlerAtk].hp <= (gBattleMons[battlerAtk].maxHP / 3)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; - #if B_PLUS_MINUS_INTERACTION >= GEN_5 case ABILITY_PLUS: + if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) + { + u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); + if (partnerAbility == ABILITY_MINUS + || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_PLUS)) + modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); + } + break; case ABILITY_MINUS: if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { u32 partnerAbility = GetBattlerAbility(BATTLE_PARTNER(battlerAtk)); - if (partnerAbility == ABILITY_PLUS || partnerAbility == ABILITY_MINUS) + if (partnerAbility == ABILITY_PLUS + || (B_PLUS_MINUS_INTERACTION >= GEN_5 && partnerAbility == ABILITY_MINUS)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); } break; - #else - case ABILITY_PLUS: - if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_MINUS) - modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); - break; - case ABILITY_MINUS: - if (IS_MOVE_SPECIAL(move) && IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_PLUS) - modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); - break; - #endif case ABILITY_FLOWER_GIFT: if (gBattleMons[battlerAtk].species == SPECIES_CHERRIM_SUNSHINE && IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN) && IS_MOVE_PHYSICAL(move)) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); @@ -9478,11 +9441,9 @@ static inline u32 CalcDefenseStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 usesDefStat = FALSE; } - #if B_EXPLOSION_DEFENSE <= GEN_4 // Self-destruct / Explosion cut defense in half - if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) + if (B_EXPLOSION_DEFENSE < GEN_5 && gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) defStat /= 2; - #endif // critical hits ignore positive stat changes if (isCrit && defStage > DEFAULT_STAT_STAGE) @@ -9568,14 +9529,13 @@ static inline u32 CalcDefenseStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 if (!usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; -#if B_SOUL_DEW_BOOST <= GEN_6 case HOLD_EFFECT_SOUL_DEW: - if ((gBattleMons[battlerDef].species == SPECIES_LATIAS || gBattleMons[battlerDef].species == SPECIES_LATIOS) + if (B_SOUL_DEW_BOOST < GEN_7 + && (gBattleMons[battlerDef].species == SPECIES_LATIAS || gBattleMons[battlerDef].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; -#endif } // sandstorm sp.def boost for rock types @@ -9601,34 +9561,10 @@ static inline s32 CalculateBaseDamage(u32 power, u32 userFinalAttack, u32 level, return power * userFinalAttack * (2 * level / 5 + 2) / targetFinalDefense / 50 + 2; } -#if B_MULTIPLE_TARGETS_DMG >= GEN_4 - #define V_MULTIPLE_TARGETS_DMG UQ_4_12(0.75) -#else - #define V_MULTIPLE_TARGETS_DMG UQ_4_12(0.5) -#endif - -#if B_CRIT_MULTIPLIER >= GEN_6 - #define V_CRIT_MULTIPLIER UQ_4_12(1.5) -#else - #define V_CRIT_MULTIPLIER UQ_4_12(2.0) -#endif - -#if B_BURN_FACADE_DMG >= GEN_6 - #define FACADE_PREVENTS_BURN_MALUS(move) (gBattleMoves[move].effect == EFFECT_FACADE) -#else - #define FACADE_PREVENTS_BURN_MALUS(move) (FALSE) -#endif - -#if B_PARENTAL_BOND_DMG < GEN_7 - #define V_PARENTAL_BOND_DMG UQ_4_12(0.5) -#else - #define V_PARENTAL_BOND_DMG UQ_4_12(0.25) -#endif - static inline uq4_12_t GetTargetDamageModifier(u32 move, u32 battlerAtk, u32 battlerDef) { if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2) - return V_MULTIPLE_TARGETS_DMG; + return B_MULTIPLE_TARGETS_DMG >= GEN_4 ? UQ_4_12(0.75) : UQ_4_12(0.5); return UQ_4_12(1.0); } @@ -9636,7 +9572,7 @@ static inline uq4_12_t GetParentalBondModifier(u32 battlerAtk) { if (gSpecialStatuses[battlerAtk].parentalBondState != PARENTAL_BOND_2ND_HIT) return UQ_4_12(1.0); - return V_PARENTAL_BOND_DMG; + return B_PARENTAL_BOND_DMG >= GEN_7 ? UQ_4_12(0.25) : UQ_4_12(0.5); } static inline uq4_12_t GetSameTypeAttackBonusModifier(u32 battlerAtk, u32 moveType, u32 move, u32 abilityAtk) @@ -9675,12 +9611,12 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(u32 battlerAtk, u32 move, u32 { if (gBattleMons[battlerAtk].status1 & STATUS1_BURN && IS_MOVE_PHYSICAL(move) - && !FACADE_PREVENTS_BURN_MALUS(move) + && (B_BURN_FACADE_DMG < GEN_6 || gBattleMoves[move].effect != EFFECT_FACADE) && abilityAtk != ABILITY_GUTS) return UQ_4_12(0.5); if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && IS_MOVE_SPECIAL(move) - && !FACADE_PREVENTS_BURN_MALUS(move) + && (B_BURN_FACADE_DMG < GEN_6 || gBattleMoves[move].effect != EFFECT_FACADE) && abilityAtk != ABILITY_GUTS) return UQ_4_12(0.5); return UQ_4_12(1.0); @@ -9688,7 +9624,9 @@ static inline uq4_12_t GetBurnOrFrostBiteModifier(u32 battlerAtk, u32 move, u32 static inline uq4_12_t GetCriticalModifier(bool32 isCrit) { - return isCrit ? V_CRIT_MULTIPLIER : UQ_4_12(1.0); + if (isCrit) + return B_CRIT_MULTIPLIER >= GEN_6 ? UQ_4_12(1.5) : UQ_4_12(2.0); + return UQ_4_12(1.0); } static inline uq4_12_t GetZMaxMoveAgainstProtectionModifier(u32 battlerDef, u32 move) @@ -10078,12 +10016,8 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov if (gBattleMoves[move].split == SPLIT_STATUS && move != MOVE_THUNDER_WAVE) { modifier = UQ_4_12(1.0); - #if B_GLARE_GHOST <= GEN_3 - if (move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST)) - { + if (B_GLARE_GHOST < GEN_4 && move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST)) modifier = UQ_4_12(0.0); - } - #endif } else if (moveType == TYPE_GROUND && !IsBattlerGrounded2(battlerDef, TRUE) && !(gBattleMoves[move].ignoreTypeIfFlyingAndUngrounded)) { @@ -10097,12 +10031,10 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov RecordAbilityBattle(battlerDef, ABILITY_LEVITATE); } } -#if B_SHEER_COLD_IMMUNITY >= GEN_7 - else if (move == MOVE_SHEER_COLD && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) + else if (B_SHEER_COLD_IMMUNITY >= GEN_7 && move == MOVE_SHEER_COLD && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) { modifier = UQ_4_12(0.0); } -#endif // Thousand Arrows ignores type modifiers for flying mons if (!IsBattlerGrounded(battlerDef) && (gBattleMoves[move].ignoreTypeIfFlyingAndUngrounded) @@ -10187,10 +10119,8 @@ static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier) uq4_12_t GetTypeModifier(u32 atkType, u32 defType) { -#if B_FLAG_INVERSE_BATTLE != 0 - if (FlagGet(B_FLAG_INVERSE_BATTLE)) + if (B_FLAG_INVERSE_BATTLE != 0 && FlagGet(B_FLAG_INVERSE_BATTLE)) return GetInverseTypeMultiplier(sTypeEffectivenessTable[atkType][defType]); -#endif return sTypeEffectivenessTable[atkType][defType]; } @@ -10285,7 +10215,7 @@ bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) bool32 CanMegaEvolve(u32 battler) { - u32 itemId, holdEffect, species; + u32 itemId, holdEffect; struct Pokemon *mon; u32 battlerPosition = GetBattlerPosition(battler); u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battler)); @@ -10319,7 +10249,6 @@ bool32 CanMegaEvolve(u32 battler) else mon = &gPlayerParty[gBattlerPartyIndexes[battler]]; - species = GetMonData(mon, MON_DATA_SPECIES); itemId = GetMonData(mon, MON_DATA_HELD_ITEM); if (itemId == ITEM_ENIGMA_BERRY_E_READER) @@ -10349,7 +10278,7 @@ bool32 CanMegaEvolve(u32 battler) bool32 CanUltraBurst(u32 battler) { - u32 itemId, holdEffect, species; + u32 itemId, holdEffect; struct Pokemon *mon; u32 battlerPosition = GetBattlerPosition(battler); u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battler)); @@ -10382,7 +10311,6 @@ bool32 CanUltraBurst(u32 battler) else mon = &gPlayerParty[gBattlerPartyIndexes[battler]]; - species = GetMonData(mon, MON_DATA_SPECIES); itemId = GetMonData(mon, MON_DATA_HELD_ITEM); // Check if there is an entry in the evolution table for Ultra Burst. @@ -10429,17 +10357,15 @@ bool32 IsBattlerUltraBursted(u32 battler) // Returns SPECIES_NONE if no form change is possible u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) { - u32 i, j; + u32 i; u16 targetSpecies = SPECIES_NONE; u16 species = gBattleMons[battler].species; const struct FormChange *formChanges = gFormChangeTablePointers[species]; u16 heldItem; - u32 ability; if (formChanges != NULL) { heldItem = gBattleMons[battler].item; - ability = GetBattlerAbility(battler); for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { @@ -10701,16 +10627,17 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler) bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler) { -#if B_BADGE_BOOST == GEN_3 - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER)) - return FALSE; - else if (GetBattlerSide(battler) != B_SIDE_PLAYER) - return FALSE; - else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) - return FALSE; - else if (FlagGet(badgeFlag)) - return TRUE; -#endif + if (B_BADGE_BOOST == GEN_3) + { + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER)) + return FALSE; + else if (GetBattlerSide(battler) != B_SIDE_PLAYER) + return FALSE; + else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) + return FALSE; + else if (FlagGet(badgeFlag)) + return TRUE; + } return FALSE; } @@ -10722,17 +10649,15 @@ u8 GetBattleMoveSplit(u32 moveId) return gBattleStruct->dynamax.activeSplit; if (gBattleStruct != NULL && gBattleStruct->swapDamageCategory) // Photon Geyser, Shell Side Arm, Light That Burns the Sky return SPLIT_PHYSICAL; + if (B_PHYSICAL_SPECIAL_SPLIT >= GEN_4) + return gBattleMoves[moveId].split; -#if B_PHYSICAL_SPECIAL_SPLIT >= GEN_4 - return gBattleMoves[moveId].split; -#else if (IS_MOVE_STATUS(moveId)) return SPLIT_STATUS; else if (gBattleMoves[moveId].type < TYPE_MYSTERY) return SPLIT_PHYSICAL; else return SPLIT_SPECIAL; -#endif } static bool32 TryRemoveScreens(u32 battler) @@ -10809,9 +10734,7 @@ bool32 CanFling(u32 battler) u16 item = gBattleMons[battler].item; if (item == ITEM_NONE - #if B_KLUTZ_FLING_INTERACTION >= GEN_5 - || GetBattlerAbility(battler) == ABILITY_KLUTZ - #endif + || (B_KLUTZ_FLING_INTERACTION >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ) || gFieldStatuses & STATUS_FIELD_MAGIC_ROOM || gDisableStructs[battler].embargoTimer != 0 || GetFlingPowerFromItemId(item) == 0 @@ -10946,9 +10869,7 @@ void TryRestoreHeldItems(void) for (i = 0; i < PARTY_SIZE; i++) { - #if B_RESTORE_HELD_BATTLE_ITEMS == FALSE - if (gBattleStruct->itemLost[i].stolen) - #endif + if (B_RESTORE_HELD_BATTLE_ITEMS == TRUE || gBattleStruct->itemLost[i].stolen) { lostItem = gBattleStruct->itemLost[i].originalItem; if (lostItem != ITEM_NONE && ItemId_GetPocket(lostItem) != POCKET_BERRIES) @@ -10972,9 +10893,7 @@ bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item) | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_SECRET_BASE - #if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE - | BATTLE_TYPE_TRAINER - #endif + | (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE ? BATTLE_TYPE_TRAINER : 0) ))) { return FALSE; @@ -11001,14 +10920,14 @@ void TrySaveExchangedItem(u32 battler, u16 stolenItem) { // Because BtlController_EmitSetMonData does SetMonData, we need to save the stolen item only if it matches the battler's original // So, if the player steals an item during battle and has it stolen from it, it will not end the battle with it (naturally) -#if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE + if (B_TRAINERS_KNOCK_OFF_ITEMS == FALSE) + return; // If regular trainer battle and mon's original item matches what is being stolen, save it to be restored at end of battle if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && GetBattlerSide(battler) == B_SIDE_PLAYER && stolenItem == gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].originalItem) gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].stolen = TRUE; -#endif } bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes) @@ -11133,7 +11052,8 @@ bool32 TryRoomService(u32 battler) bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget) { - #if B_PRANKSTER_DARK_TYPES >= GEN_7 + if (B_PRANKSTER_DARK_TYPES < GEN_7) + return FALSE; if (!gProtectStructs[battlerPrankster].pranksterElevated) return FALSE; if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef)) @@ -11146,8 +11066,6 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return FALSE; return TRUE; - #endif - return FALSE; } u16 GetUsedHeldItem(u32 battler) @@ -11172,8 +11090,6 @@ bool32 IsBattlerWeatherAffected(u32 battler, u32 weatherFlags) // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED u32 GetBattlerMoveTargetType(u32 battler, u32 move) { - u32 target; - if (gBattleMoves[move].effect == EFFECT_EXPANDING_FORCE && IsBattlerTerrainAffected(battler, STATUS_FIELD_PSYCHIC_TERRAIN)) return MOVE_TARGET_BOTH; @@ -11196,19 +11112,11 @@ bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move) static void SetRandomMultiHitCounter() { if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) - { gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5); - } + else if (B_MULTI_HIT_CHANCE >= GEN_5) + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. else - { -#if B_MULTI_HIT_CHANCE >= GEN_5 - // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. - gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); -#else - // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. - gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); -#endif - } + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. } void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon) @@ -11271,6 +11179,14 @@ bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2) return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 != gender2); } +bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2) +{ + u8 gender1 = GetBattlerGender(battler1); + u8 gender2 = GetBattlerGender(battler2); + + return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2); +} + u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance) { if (GetBattlerAbility(battler) == ABILITY_SERENE_GRACE) @@ -11286,7 +11202,7 @@ bool32 IsAlly(u32 battlerAtk, u32 battlerDef) bool32 IsGen6ExpShareEnabled(void) { -#if I_EXP_SHARE_ITEM < GEN_6 +#if I_EXP_SHARE_FLAG <= TEMP_FLAGS_END return FALSE; #else return FlagGet(I_EXP_SHARE_FLAG); @@ -11295,7 +11211,7 @@ bool32 IsGen6ExpShareEnabled(void) u8 GetBattlerType(u32 battler, u8 typeIndex) -{ +{ u16 types[3] = {0}; types[0] = gBattleMons[battler].type1; types[1] = gBattleMons[battler].type2; @@ -11307,11 +11223,7 @@ u8 GetBattlerType(u32 battler, u8 typeIndex) if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST) { if (types[0] == TYPE_FLYING && types[1] == TYPE_FLYING) -#if B_ROOST_PURE_FLYING >= GEN_5 - return TYPE_NORMAL; -#else - return TYPE_MYSTERY; -#endif + return B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY; else return types[typeIndex] == TYPE_FLYING ? TYPE_MYSTERY : types[typeIndex]; } diff --git a/src/battle_z_move.c b/src/battle_z_move.c index d760148b51..6c89420403 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -52,7 +52,6 @@ static void ZMoveSelectionDisplayPpNumber(u32 battler); static void ZMoveSelectionDisplayPower(u16 move, u16 zMove); static void ShowZMoveTriggerSprite(u8 battleId); static bool32 AreStatsMaxed(u8 battler, u8 n); -static u8 GetZMoveScore(u8 battlerAtk, u8 battlerDef, u16 baseMove, u16 zMove); static void ZMoveSelectionDisplayMoveType(u16 zMove, u32 battler); // Const Data @@ -158,15 +157,10 @@ void QueueZMove(u8 battler, u16 baseMove) bool32 IsViableZMove(u8 battler, u16 move) { - struct Pokemon *mon; - u8 battlerPosition = GetBattlerPosition(battler); - u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battler)); u32 item; u16 holdEffect; - u16 species; int moveSlotIndex; - species = gBattleMons[battler].species; item = gBattleMons[battler].item; for (moveSlotIndex = 0; moveSlotIndex < MAX_MON_MOVES; moveSlotIndex++) @@ -236,6 +230,8 @@ bool32 TryChangeZIndicator(u8 battler, u8 moveIndex) HideZMoveTriggerSprite(); // Was a viable z move, now is not -> slide out else if (!gBattleStruct->zmove.viable && viableZMove) ShowZMoveTriggerSprite(battler); // Was not a viable z move, now is -> slide back in + + return viableZMove; } #define SINGLES_Z_TRIGGER_POS_X_OPTIMAL (29) @@ -267,7 +263,7 @@ void CreateZMoveTriggerSprite(u8 battler, bool8 viable) else { x = gSprites[gHealthboxSpriteIds[battler]].x - SINGLES_Z_TRIGGER_POS_X_SLIDE; - y = gSprites[gHealthboxSpriteIds[battler]].y - SINGLES_Z_TRIGGER_POS_Y_DIFF, 0; + y = gSprites[gHealthboxSpriteIds[battler]].y - SINGLES_Z_TRIGGER_POS_Y_DIFF; } if (gBattleStruct->zmove.triggerSpriteId == 0xFF) @@ -350,7 +346,6 @@ void HideZMoveTriggerSprite(void) static void ShowZMoveTriggerSprite(u8 battler) { - struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId]; gBattleStruct->zmove.viable = TRUE; CreateZMoveTriggerSprite(battler, TRUE); } @@ -535,13 +530,11 @@ static void ZMoveSelectionDisplayPower(u16 move, u16 zMove) static void ZMoveSelectionDisplayPpNumber(u32 battler) { u8 *txtPtr; - struct ChooseMoveStruct *moveInfo; if (gBattleResources->bufferA[battler][2] == TRUE) // Check if we didn't want to display pp number return; SetPpNumbersPaletteInMoveSelection(battler); - moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); txtPtr = ConvertIntToDecimalStringN(gDisplayedStringBattle, 1, STR_CONV_MODE_RIGHT_ALIGN, 2); *(txtPtr)++ = CHAR_SLASH; ConvertIntToDecimalStringN(txtPtr, 1, STR_CONV_MODE_RIGHT_ALIGN, 2); @@ -551,7 +544,6 @@ static void ZMoveSelectionDisplayPpNumber(u32 battler) static void ZMoveSelectionDisplayMoveType(u16 zMove, u32 battler) { u8 *txtPtr; - struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); u8 zMoveType; GET_MOVE_TYPE(zMove, zMoveType); diff --git a/src/berry.c b/src/berry.c index e6ee039f40..88a5d0f9f3 100644 --- a/src/berry.c +++ b/src/berry.c @@ -1825,8 +1825,8 @@ bool8 PlayerHasBerries(void) // For all berry trees on screen, allow normal growth void SetBerryTreesSeen(void) { - s16 cam_left; - s16 cam_top; + u16 cam_left; + u16 cam_top; s16 left; s16 top; s16 right; @@ -1842,9 +1842,9 @@ void SetBerryTreesSeen(void) { if (gObjectEvents[i].active && gObjectEvents[i].movementType == MOVEMENT_TYPE_BERRY_TREE_GROWTH) { - cam_left = gObjectEvents[i].currentCoords.x; - cam_top = gObjectEvents[i].currentCoords.y; - if (left <= cam_left && cam_left <= right && top <= cam_top && cam_top <= bottom) + s16 x = gObjectEvents[i].currentCoords.x; + s16 y = gObjectEvents[i].currentCoords.y; + if (left <= x && x <= right && top <= y && y <= bottom) AllowBerryTreeGrowth(gObjectEvents[i].trainerRange_berryTreeId); } } diff --git a/src/berry_blender.c b/src/berry_blender.c index bdfb500d8b..6f827867f2 100644 --- a/src/berry_blender.c +++ b/src/berry_blender.c @@ -174,8 +174,8 @@ struct BerryBlender u16 progressBarValue; u16 maxProgressBarValue; u16 centerScale; - u16 bg_X; - u16 bg_Y; + s16 bg_X; + s16 bg_Y; u8 opponentTaskIds[BLENDER_MAX_PLAYERS - 1]; u8 perfectOpponents; // for debugging, NPCs will always hit Best u16 scores[BLENDER_MAX_PLAYERS][NUM_SCORE_TYPES]; diff --git a/src/contest.c b/src/contest.c index 3bfa964560..7b29b55908 100644 --- a/src/contest.c +++ b/src/contest.c @@ -5296,7 +5296,6 @@ static u16 SanitizeSpecies(u16 species) static void SetMoveSpecificAnimData(u8 contestant) { - s32 i; u16 move = SanitizeMove(eContestantStatus[contestant].currMove); u16 species = SanitizeSpecies(gContestMons[contestant].species); u8 targetContestant; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 2fea800b4a..896d4a530a 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -4078,11 +4078,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_HIDDEN_POWER] = { - #if B_HIDDEN_POWER_DMG >= GEN_6 - .power = 60, - #else - .power = 1, - #endif + .power = B_HIDDEN_POWER_DMG >= GEN_6 ? 60 : 1, .effect = EFFECT_HIDDEN_POWER, .type = TYPE_NORMAL, .accuracy = 100, @@ -13829,12 +13825,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_MATCHA_GOTCHA] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_MATCHA_GOTCHA + .effect = EFFECT_MATCHA_GOTCHA, .power = 80, .type = TYPE_GRASS, .accuracy = 90, .pp = 15, - .secondaryEffectChance = 20, //burn + .secondaryEffectChance = 20, .target = MOVE_TARGET_BOTH, .priority = 0, .split = SPLIT_SPECIAL, @@ -13845,7 +13841,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_SYRUP_BOMB] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_SYRUP_BOMB + .effect = EFFECT_SYRUP_BOMB, .power = 60, .type = TYPE_GRASS, .accuracy = 85, @@ -13861,7 +13857,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_IVY_CUDGEL] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_IVY_CUDGEL + .effect = EFFECT_IVY_CUDGEL, .power = 100, .type = TYPE_GRASS, .accuracy = 100, diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 4785c4717f..3574e02446 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -6221,6 +6221,7 @@ const u8 gMonIcon_PikachuUnovaCap[] = INCBIN_U8("graphics/pokemon/pikachu/unova_ const u8 gMonIcon_PikachuKalosCap[] = INCBIN_U8("graphics/pokemon/pikachu/kalos_cap/icon.4bpp"); const u8 gMonIcon_PikachuAlolaCap[] = INCBIN_U8("graphics/pokemon/pikachu/alola_cap/icon.4bpp"); const u8 gMonIcon_PikachuPartnerCap[] = INCBIN_U8("graphics/pokemon/pikachu/partner_cap/icon.4bpp"); +const u8 gMonIcon_PikachuWorldCap[] = INCBIN_U8("graphics/pokemon/pikachu/world_cap/icon.4bpp"); const u8 gMonIcon_PichuSpikyEared[] = INCBIN_U8("graphics/pokemon/pichu/spiky_eared/icon.4bpp"); const u8 gMonIcon_UnownB[] = INCBIN_U8("graphics/pokemon/unown/b/icon.4bpp"); const u8 gMonIcon_UnownC[] = INCBIN_U8("graphics/pokemon/unown/c/icon.4bpp"); diff --git a/src/data/items.h b/src/data/items.h index 131e08386a..a3bd7e3f39 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -4844,11 +4844,7 @@ const struct Item gItems[] = .name = _("Soul Dew"), .price = 0, .holdEffect = HOLD_EFFECT_SOUL_DEW, - #if B_SOUL_DEW_BOOST >= GEN_7 - .holdEffectParam = 20, - #else - .holdEffectParam = 50, - #endif + .holdEffectParam = B_SOUL_DEW_BOOST >= GEN_7 ? 20 : 50, .description = sSoulDewDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -9700,30 +9696,36 @@ const struct Item gItems[] = { .name = _("CornrstneMask"), .price = 0, + .holdEffect = HOLD_EFFECT_MASK, .description = sCornerstoneMaskDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .secondaryId = TYPE_ROCK, }, [ITEM_WELLSPRING_MASK] = { .name = _("WellsprngMask"), .price = 0, + .holdEffect = HOLD_EFFECT_MASK, .description = sWellspringMaskDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .secondaryId = TYPE_WATER, }, [ITEM_HEARTHFLAME_MASK] = { .name = _("HrthflameMask"), .price = 0, + .holdEffect = HOLD_EFFECT_MASK, .description = sHearthflameMaskDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .secondaryId = TYPE_FIRE, }, [ITEM_HEALTH_MOCHI] = diff --git a/src/data/pokemon/level_up_learnsets.h b/src/data/pokemon/level_up_learnsets.h index 17af6b8888..d7e866d933 100644 --- a/src/data/pokemon/level_up_learnsets.h +++ b/src/data/pokemon/level_up_learnsets.h @@ -1,4 +1,5 @@ #define LEVEL_UP_MOVE(lvl, moveLearned) {.move = moveLearned, .level = lvl} +#define LEVEL_UP_END {.move = LEVEL_UP_MOVE_END, .level = 0} static const struct LevelUpMove sBulbasaurLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), diff --git a/src/data/pokemon/species_info.h b/src/data/pokemon/species_info.h index 25f491cf28..d3acfd3fc5 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -12452,10 +12452,10 @@ const struct SpeciesInfo gSpeciesInfo[] = { .baseHP = 120, .baseAttack = 70, - .baseDefense = 120, + .baseDefense = P_UPDATED_STATS >= GEN_9 ? 110 : 120, .baseSpeed = 85, .baseSpAttack = 75, - .baseSpDefense = 130, + .baseSpDefense = P_UPDATED_STATS >= GEN_9 ? 120 : 130, .types = { TYPE_PSYCHIC, TYPE_PSYCHIC}, .catchRate = 3, .expYield = 270, @@ -17369,9 +17369,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, #if P_UPDATED_EGG_GROUPS >= GEN_8 - .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, - #else .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MINERAL}, + #else + .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, #endif .abilities = {ABILITY_OWN_TEMPO, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, @@ -17395,9 +17395,9 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, #if P_UPDATED_EGG_GROUPS >= GEN_8 - .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, - #else .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MINERAL}, + #else + .eggGroups = { EGG_GROUP_MONSTER, EGG_GROUP_MONSTER}, #endif .abilities = {ABILITY_OWN_TEMPO, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, @@ -20778,7 +20778,7 @@ const struct SpeciesInfo gSpeciesInfo[] = [SPECIES_ZACIAN] = { .baseHP = 92, - .baseAttack = 130, + .baseAttack = P_UPDATED_STATS >= GEN_9 ? 120 : 130, .baseDefense = 115, .baseSpeed = 138, .baseSpAttack = 80, @@ -20801,7 +20801,7 @@ const struct SpeciesInfo gSpeciesInfo[] = [SPECIES_ZAMAZENTA] = { .baseHP = 92, - .baseAttack = 130, + .baseAttack = P_UPDATED_STATS >= GEN_9 ? 120 : 130, .baseDefense = 115, .baseSpeed = 138, .baseSpAttack = 80, @@ -21025,7 +21025,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = STANDARD_FRIENDSHIP, .growthRate = GROWTH_MEDIUM_FAST, .eggGroups = { EGG_GROUP_BUG, EGG_GROUP_BUG}, - .abilities = {ABILITY_SWARM, ABILITY_SHEER_FORCE, ABILITY_STEADFAST}, + .abilities = {ABILITY_SWARM, ABILITY_SHEER_FORCE, ABILITY_SHARPNESS}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, }, @@ -21114,7 +21114,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = 35, .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, - .abilities = {ABILITY_PRESSURE, ABILITY_NONE, ABILITY_POISON_TOUCH}, + .abilities = {ABILITY_PRESSURE, ABILITY_UNBURDEN, ABILITY_POISON_TOUCH}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, }, @@ -23234,7 +23234,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_INTIMIDATE, ABILITY_FLASH_FIRE, ABILITY_ROCK_HEAD}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ARCANINE_HISUIAN] = @@ -23257,7 +23257,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_INTIMIDATE, ABILITY_FLASH_FIRE, ABILITY_ROCK_HEAD}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_VOLTORB_HISUIAN] = @@ -23280,7 +23280,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SOUNDPROOF, ABILITY_STATIC, ABILITY_AFTERMATH}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ELECTRODE_HISUIAN] = @@ -23303,7 +23303,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SOUNDPROOF, ABILITY_STATIC, ABILITY_AFTERMATH}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_TYPHLOSION_HISUIAN] = @@ -23326,7 +23326,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_BLAZE, ABILITY_NONE, ABILITY_FRISK}, .bodyColor = BODY_COLOR_YELLOW, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_QWILFISH_HISUIAN] = @@ -23341,7 +23341,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .catchRate = 45, .expYield = 88, .evYield_Attack = 1, - .itemRare = ITEM_POISON_BARB, + .itemRare = ITEM_POISON_BARB, .genderRatio = PERCENT_FEMALE(50), .eggCycles = 20, .friendship = STANDARD_FRIENDSHIP, @@ -23350,7 +23350,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_POISON_POINT, ABILITY_SWIFT_SWIM, ABILITY_INTIMIDATE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_SNEASEL_HISUIAN] = @@ -23371,10 +23371,10 @@ const struct SpeciesInfo gSpeciesInfo[] = .friendship = 35, .growthRate = GROWTH_MEDIUM_SLOW, .eggGroups = { EGG_GROUP_FIELD, EGG_GROUP_FIELD}, - .abilities = {ABILITY_INNER_FOCUS, ABILITY_KEEN_EYE, ABILITY_POISON_TOUCH}, + .abilities = {ABILITY_INNER_FOCUS, ABILITY_KEEN_EYE, ABILITY_PICKPOCKET}, .bodyColor = BODY_COLOR_BLACK, .noFlip = TRUE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #if P_GEN_5_POKEMON == TRUE @@ -23398,7 +23398,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_TORRENT, ABILITY_NONE, ABILITY_SHARPNESS}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_LILLIGANT_HISUIAN] = @@ -23422,7 +23422,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_CHLOROPHYLL, ABILITY_HUSTLE, ABILITY_LEAF_GUARD}, .bodyColor = BODY_COLOR_GREEN, .noFlip = TRUE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ZORUA_HISUIAN] = @@ -23445,7 +23445,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_ILLUSION, ABILITY_NONE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_ZOROARK_HISUIAN] = @@ -23468,7 +23468,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_ILLUSION, ABILITY_NONE}, .bodyColor = BODY_COLOR_GRAY, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_BRAVIARY_HISUIAN] = @@ -23491,7 +23491,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_KEEN_EYE, ABILITY_SHEER_FORCE, ABILITY_TINTED_LENS}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif @@ -23517,7 +23517,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SAP_SIPPER, ABILITY_SHELL_ARMOR, ABILITY_GOOEY}, .bodyColor = BODY_COLOR_PURPLE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_GOODRA_HISUIAN] = @@ -23540,7 +23540,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_SAP_SIPPER, ABILITY_SHELL_ARMOR, ABILITY_GOOEY}, .bodyColor = BODY_COLOR_PURPLE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, [SPECIES_AVALUGG_HISUIAN] = @@ -23563,7 +23563,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_STRONG_JAW, ABILITY_ICE_BODY, ABILITY_STURDY}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif @@ -23588,7 +23588,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_OVERGROW, ABILITY_NONE, ABILITY_SCRAPPY}, .bodyColor = BODY_COLOR_BROWN, .noFlip = FALSE, - .flags = SPECIES_FLAG_HISUIAN_FORM, + .flags = SPECIES_FLAG_HISUIAN_FORM, }, #endif @@ -24693,7 +24693,7 @@ const struct SpeciesInfo gSpeciesInfo[] = [SPECIES_ZACIAN_CROWNED_SWORD] = { .baseHP = 92, - .baseAttack = 170, + .baseAttack = P_UPDATED_STATS >= GEN_9 ? 150 : 170, .baseDefense = 115, .baseSpeed = 148, .baseSpAttack = 80, @@ -24716,11 +24716,11 @@ const struct SpeciesInfo gSpeciesInfo[] = [SPECIES_ZAMAZENTA_CROWNED_SHIELD] = { .baseHP = 92, - .baseAttack = 130, - .baseDefense = 145, + .baseAttack = P_UPDATED_STATS >= GEN_9 ? 120 : 130, + .baseDefense = P_UPDATED_STATS >= GEN_9 ? 140 : 145, .baseSpeed = 128, .baseSpAttack = 80, - .baseSpDefense = 145, + .baseSpDefense = P_UPDATED_STATS >= GEN_9 ? 140 : 145, .types = { TYPE_FIGHTING, TYPE_STEEL}, .catchRate = 10, .expYield = 360, diff --git a/src/daycare.c b/src/daycare.c index cc70840d14..3389903808 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -952,11 +952,12 @@ void RejectEggFromDayCare(void) RemoveEggFromDayCare(&gSaveBlock1Ptr->daycare); } + static const struct { u16 currSpecies; u16 item; u16 babySpecies; -} IncenseBabyTable[][3] = +} sIncenseBabyTable[] = { // Regular offspring, Item, Incense Offspring { SPECIES_WOBBUFFET, ITEM_LAX_INCENSE, SPECIES_WYNAUT }, @@ -970,6 +971,7 @@ static const struct { { SPECIES_MANTINE, ITEM_WAVE_INCENSE, SPECIES_MANTYKE }, }; +#if P_INCENSE_BREEDING < GEN_9 static void AlterEggSpeciesWithIncenseItem(u16 *species, struct DayCare *daycare) { u32 i; @@ -977,21 +979,22 @@ static void AlterEggSpeciesWithIncenseItem(u16 *species, struct DayCare *daycare motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM); fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM); - for (i = 0; i < ARRAY_COUNT(IncenseBabyTable); i++) + for (i = 0; i < ARRAY_COUNT(sIncenseBabyTable); i++) { - if (IncenseBabyTable[i]->babySpecies == *species && motherItem != IncenseBabyTable[i]->item && fatherItem != IncenseBabyTable[i]->item) + if (sIncenseBabyTable[i].babySpecies == *species && motherItem != sIncenseBabyTable[i].item && fatherItem != sIncenseBabyTable[i].item) { - *species = IncenseBabyTable[i]->currSpecies; + *species = sIncenseBabyTable[i].currSpecies; break; } } } +#endif static const struct { u16 offspring; u16 item; u16 move; -} BreedingSpecialMoveItemTable[][3] = +} sBreedingSpecialMoveItemTable[] = { // Offspring, Item, Move { SPECIES_PICHU, ITEM_LIGHT_BALL, MOVE_VOLT_TACKLE }, @@ -1003,14 +1006,14 @@ static void GiveMoveIfItem(struct Pokemon *mon, struct DayCare *daycare) u32 motherItem = GetBoxMonData(&daycare->mons[0].mon, MON_DATA_HELD_ITEM); u32 fatherItem = GetBoxMonData(&daycare->mons[1].mon, MON_DATA_HELD_ITEM); - for (i = 0; i < ARRAY_COUNT(BreedingSpecialMoveItemTable); i++) + for (i = 0; i < ARRAY_COUNT(sBreedingSpecialMoveItemTable); i++) { - if (BreedingSpecialMoveItemTable[i]->offspring == species - && (motherItem == BreedingSpecialMoveItemTable[i]->item || - fatherItem == BreedingSpecialMoveItemTable[i]->item)) + if (sBreedingSpecialMoveItemTable[i].offspring == species + && (motherItem == sBreedingSpecialMoveItemTable[i].item || + fatherItem == sBreedingSpecialMoveItemTable[i].item)) { - if (GiveMoveToMon(mon, BreedingSpecialMoveItemTable[i]->move) == MON_HAS_MAX_MOVES) - DeleteFirstMoveAndGiveMoveToMon(mon, BreedingSpecialMoveItemTable[i]->move); + if (GiveMoveToMon(mon, sBreedingSpecialMoveItemTable[i].move) == MON_HAS_MAX_MOVES) + DeleteFirstMoveAndGiveMoveToMon(mon, sBreedingSpecialMoveItemTable[i].move); } } } diff --git a/src/debug.c b/src/debug.c index f915235d8b..d1f3b2a48d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -260,12 +260,10 @@ EWRAM_DATA u32 gDebugAIFlags = 0; // Define functions static void Debug_ReShowMainMenu(void); static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate); -static void Debug_ShowMenuDynamic(u8 taskId); static void Debug_DestroyMenu(u8 taskId); static void Debug_DestroyMenu_Full(u8 taskId); static void DebugAction_Cancel(u8 taskId); static void DebugAction_DestroyExtraWindow(u8 taskId); -static void DebugTask_HandleMenuInput(u8 taskId, void (*HandleInput)(u8)); static void Debug_InitDebugBattleData(void); static void Debug_RefreshListMenu(u8 taskId); static void Debug_RedrawListMenu(u8 taskId); @@ -282,7 +280,6 @@ static void DebugAction_Util_Script_8(u8 taskId); static void DebugAction_OpenUtilitiesMenu(u8 taskId); static void DebugAction_OpenScriptsMenu(u8 taskId); static void DebugAction_OpenFlagsVarsMenu(u8 taskId); -static void DebugAction_OpenBattleMenu(u8 taskId); static void DebugAction_OpenGiveMenu(u8 taskId); static void DebugAction_OpenFillMenu(u8 taskId); static void DebugAction_OpenSoundMenu(u8 taskId); @@ -970,7 +967,6 @@ static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMte gTasks[inputTaskId].data[2] = 0; Debug_RefreshListMenu(inputTaskId); - //Debug_ShowMenuDynamic(inputTaskId); // draw everything CopyWindowToVram(windowId, 3); @@ -1122,10 +1118,8 @@ static void Debug_RefreshListMenu(u8 taskId) u16 i; const u8 sColor_Red[] = _("{COLOR RED}"); const u8 sColor_Green[] = _("{COLOR GREEN}"); - u8 listTaskId = gTasks[taskId].data[0]; - struct ListMenu *list = (void*) gTasks[listTaskId].data; - u8 totalItems, flagResult; - u8 const * name; + u8 totalItems = 0, flagResult = 0; + u8 const *name = NULL; if (sDebugMenuListData->listId == 0) { @@ -1179,7 +1173,7 @@ static void Debug_RefreshListMenu(u8 taskId) { flagResult = sDebugBattleData->aiFlags[i]; if (i == totalItems - 1) - flagResult == 0xFF; + flagResult = 0xFF; name = sDebugMenu_Items_Battle_1[i].name; } @@ -1347,10 +1341,9 @@ static void DebugTask_HandleBattleMenuReDraw(u8 taskId) } static void DebugTask_HandleMenuInput_Battle(u8 taskId) { - void (*func)(u8); - u8 listTaskId = gTasks[taskId].data[0]; - u32 input = ListMenu_ProcessInput(listTaskId); u16 idx; + u8 listTaskId = gTasks[taskId].data[0]; + ListMenu_ProcessInput(listTaskId); ListMenuGetCurrentItemArrayId(listTaskId, &idx); @@ -1549,12 +1542,6 @@ static void DebugAction_OpenFlagsVarsMenu(u8 taskId) Debug_ShowMenu(DebugTask_HandleMenuInput_FlagsVars, gMultiuseListMenuTemplate); } -static void DebugAction_OpenBattleMenu(u8 taskId) -{ - Debug_DestroyMenu(taskId); - sDebugMenuListData->listId = 1; - Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_0); -} static void DebugAction_OpenGiveMenu(u8 taskId) { @@ -1950,7 +1937,6 @@ static void DebugAction_Util_SetWallClock(u8 taskId) } static void DebugAction_Util_WatchCredits(u8 taskId) { - struct Task* task = &gTasks[taskId]; Debug_DestroyMenu_Full(taskId); SetMainCallback2(CB2_StartCreditsSequence); } @@ -3518,7 +3504,6 @@ static void DebugAction_Fill_PCBoxes_Fast(u8 taskId) //Credit: Sierraffinity static void DebugAction_Fill_PCBoxes_Slow(u8 taskId) { int boxId, boxPosition; - u32 personality; struct BoxPokemon boxMon; u32 species = SPECIES_BULBASAUR; bool8 spaceAvailable = FALSE; diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 7efc86fb19..cc96fd5105 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -360,7 +360,6 @@ static void AddHatchedMonToParty(u8 id) u8 isEgg = 0x46; // ? u16 species; u8 name[POKEMON_NAME_LENGTH + 1]; - u16 ball; u16 metLevel; u8 metLocation; struct Pokemon *mon = &gPlayerParty[id]; diff --git a/src/event_object_movement.c b/src/event_object_movement.c index ae643b661f..29969b1f6b 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -8883,7 +8883,7 @@ static void CreateLevitateMovementTask(struct ObjectEvent *objectEvent) u8 taskId = CreateTask(ApplyLevitateMovement, 0xFF); struct Task *task = &gTasks[taskId]; - StoreWordInTwoHalfwords(&task->data[0], (u32)objectEvent); + StoreWordInTwoHalfwords((u16*) &task->data[0], (u32)objectEvent); objectEvent->warpArrowSpriteId = taskId; task->data[3] = 0xFFFF; } @@ -8894,7 +8894,7 @@ static void ApplyLevitateMovement(u8 taskId) struct Sprite *sprite; struct Task *task = &gTasks[taskId]; - LoadWordFromTwoHalfwords(&task->data[0], (u32 *)&objectEvent); // load the map object pointer. + LoadWordFromTwoHalfwords((u16*) &task->data[0], (u32 *)&objectEvent); // load the map object pointer. sprite = &gSprites[objectEvent->spriteId]; if(!(task->data[2] & 3)) @@ -8911,7 +8911,7 @@ static void DestroyLevitateMovementTask(u8 taskId) struct ObjectEvent *objectEvent; struct Task *task = &gTasks[taskId]; - LoadWordFromTwoHalfwords(&task->data[0], (u32 *)&objectEvent); // unused objectEvent + LoadWordFromTwoHalfwords((u16*) &task->data[0], (u32 *)&objectEvent); // unused objectEvent DestroyTask(taskId); } diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 7af1912454..6a5422046e 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -68,7 +68,9 @@ static bool8 TryStartWarpEventScript(struct MapPosition *, u16); static bool8 TryStartMiscWalkingScripts(u16); static bool8 TryStartStepCountScript(u16); static void UpdateFriendshipStepCounter(void); +#if OW_POISON_DAMAGE < GEN_5 static bool8 UpdatePoisonStepCounter(void); +#endif // OW_POISON_DAMAGE void FieldClearPlayerInput(struct FieldInput *input) { @@ -655,6 +657,7 @@ void ClearPoisonStepCounter(void) VarSet(VAR_POISON_STEP_COUNTER, 0); } +#if OW_POISON_DAMAGE < GEN_5 static bool8 UpdatePoisonStepCounter(void) { u16 *ptr; @@ -679,6 +682,7 @@ static bool8 UpdatePoisonStepCounter(void) } return FALSE; } +#endif // OW_POISON_DAMAGE void RestartWildEncounterImmunitySteps(void) { diff --git a/src/field_door.c b/src/field_door.c index 255233ec23..b922c939b7 100644 --- a/src/field_door.c +++ b/src/field_door.c @@ -412,7 +412,7 @@ static void Task_AnimateDoor(u8 taskId) struct DoorAnimFrame *frames = (struct DoorAnimFrame *)(tFramesHi << 16 | tFramesLo); struct DoorGraphics *gfx = (struct DoorGraphics *)(tGfxHi << 16 | tGfxLo); - if (AnimateDoorFrame(gfx, frames, data) == FALSE) + if (AnimateDoorFrame(gfx, frames, gTasks[taskId].data) == FALSE) DestroyTask(taskId); } diff --git a/src/field_specials.c b/src/field_specials.c index c91f458ed1..2720e5f587 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -964,8 +964,8 @@ void FieldShowRegionMap(void) static bool8 IsPlayerInFrontOfPC(void) { - u16 x, y; - u16 tileInFront; + s16 x, y; + u32 tileInFront; GetXYCoordsOneStepInFrontOfPlayer(&x, &y); tileInFront = MapGridGetMetatileIdAt(x, y); diff --git a/src/field_weather_effect.c b/src/field_weather_effect.c index 55a4450f12..325979f86a 100644 --- a/src/field_weather_effect.c +++ b/src/field_weather_effect.c @@ -938,7 +938,7 @@ static void InitSnowflakeSpriteMovement(struct Sprite *sprite) sprite->tFallCounter = 0; } -static void WaitSnowflakeSprite(struct Sprite *sprite) +static void UNUSED WaitSnowflakeSprite(struct Sprite *sprite) { if (++gWeatherPtr->snowflakeTimer > 18) { @@ -953,7 +953,6 @@ static void WaitSnowflakeSprite(struct Sprite *sprite) static void UpdateSnowflakeSprite(struct Sprite *sprite) { s16 x; - s16 y; sprite->tPosY += sprite->tDeltaY; sprite->y = sprite->tPosY >> 7; diff --git a/src/fieldmap.c b/src/fieldmap.c index 4f94b0ad22..5e8ffec4aa 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -25,7 +25,7 @@ struct ConnectionFlags u8 east:1; }; -EWRAM_DATA static u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; +EWRAM_DATA u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; EWRAM_DATA struct MapHeader gMapHeader = {0}; EWRAM_DATA struct Camera gCamera = {0}; EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0}; @@ -48,16 +48,12 @@ static const struct MapConnection *GetIncomingConnection(u8 direction, int x, in static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, const struct MapConnection *connection); static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, int offset); -#define GetBorderBlockAt(x, y)({ \ - u16 block; \ - int i; \ - const u16 *border = gMapHeader.mapLayout->border; /* Unused, they read it again below */ \ - \ - i = (x + 1) & 1; \ - i += ((y + 1) & 1) * 2; \ - \ - block = gMapHeader.mapLayout->border[i] | MAPGRID_COLLISION_MASK; \ -}) +static inline u16 GetBorderBlockAt(int x, int y) +{ + int i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + return gMapHeader.mapLayout->border[i] | MAPGRID_COLLISION_MASK; +} #define AreCoordsWithinMapGridBounds(x, y) (x >= 0 && x < gBackupMapLayout.width && y >= 0 && y < gBackupMapLayout.height) @@ -681,7 +677,7 @@ bool8 CameraMove(int x, int y) { DebugPrintfLevel(MGBA_LOG_WARN, "GetIncomingConnection returned an invalid connection inside CameraMove!"); } - + } return gCamera.active; } diff --git a/src/hall_of_fame.c b/src/hall_of_fame.c index bfb4e4c9d8..caa497e395 100644 --- a/src/hall_of_fame.c +++ b/src/hall_of_fame.c @@ -1478,7 +1478,7 @@ static void UpdateDomeConfetti(struct ConfettiUtil *util) static void Task_DoDomeConfetti(u8 taskId) { u32 id = 0; - u16 *data = gTasks[taskId].data; + s16 *data = gTasks[taskId].data; switch (tState) { diff --git a/src/item_use.c b/src/item_use.c index 07dc2f5411..3c0f2b986c 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -1057,10 +1057,8 @@ static u32 GetBallThrowableState(void) return BALL_THROW_UNABLE_TWO_MONS; else if (IsPlayerPartyAndPokemonStorageFull() == TRUE) return BALL_THROW_UNABLE_NO_ROOM; -#if B_SEMI_INVULNERABLE_CATCH >= GEN_4 - else if (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE) + else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE)) return BALL_THROW_UNABLE_SEMI_INVULNERABLE; -#endif else if (FlagGet(B_FLAG_NO_CATCHING)) return BALL_THROW_UNABLE_DISABLED_FLAG; @@ -1099,14 +1097,12 @@ void ItemUseInBattle_PokeBall(u8 taskId) else DisplayItemMessageInBattlePyramid(taskId, gText_BoxFull, Task_CloseBattlePyramidBagMessage); break; -#if B_SEMI_INVULNERABLE_CATCH >= GEN_4 case BALL_THROW_UNABLE_SEMI_INVULNERABLE: if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, sText_CantThrowPokeBall_SemiInvulnerable, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, sText_CantThrowPokeBall_SemiInvulnerable, Task_CloseBattlePyramidBagMessage); break; -#endif case BALL_THROW_UNABLE_DISABLED_FLAG: if (!InBattlePyramid()) DisplayItemMessage(taskId, FONT_NORMAL, sText_CantThrowPokeBall_Disabled, CloseItemMessage); @@ -1116,30 +1112,6 @@ void ItemUseInBattle_PokeBall(u8 taskId) } } -static void Task_CloseStatIncreaseMessage(u8 taskId) -{ - if (JOY_NEW(A_BUTTON | B_BUTTON)) - { - if (!InBattlePyramid()) - Task_FadeAndCloseBagMenu(taskId); - else - CloseBattlePyramidBag(taskId); - } -} - -static void Task_UseStatIncreaseItem(u8 taskId) -{ - if(++gTasks[taskId].data[8] > 7) - { - PlaySE(SE_USE_ITEM); - RemoveBagItem(gSpecialVar_ItemId, 1); - if (!InBattlePyramid()) - DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); - else - DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); - } -} - static void ItemUseInBattle_ShowPartyMenu(u8 taskId) { if (!InBattlePyramid()) @@ -1216,12 +1188,10 @@ static bool32 CannotUseBagBattleItem(u16 itemId) failStr = gText_BoxFull; cannotUse++; break; - #if B_SEMI_INVULNERABLE_CATCH >= GEN_4 case BALL_THROW_UNABLE_SEMI_INVULNERABLE: failStr = sText_CantThrowPokeBall_SemiInvulnerable; cannotUse++; break; - #endif case BALL_THROW_UNABLE_DISABLED_FLAG: failStr = sText_CantThrowPokeBall_Disabled; cannotUse++; diff --git a/src/librfu_rfu.c b/src/librfu_rfu.c index 828d6450bc..2dbd404616 100644 --- a/src/librfu_rfu.c +++ b/src/librfu_rfu.c @@ -134,8 +134,6 @@ static const char str_checkMbootLL[] = "RFU-MBOOT"; u16 rfu_initializeAPI(u32 *APIBuffer, u16 buffByteSize, IntrFunc *sioIntrTable_p, bool8 copyInterruptToRam) { u16 i; - u16 *dst; - const u16 *src; u16 buffByteSizeMax; // is in EWRAM? @@ -182,11 +180,13 @@ u16 rfu_initializeAPI(u32 *APIBuffer, u16 buffByteSize, IntrFunc *sioIntrTable_p } // rfu_REQ_changeMasterSlave is the function next to rfu_STC_fastCopy #if LIBRFU_VERSION < 1026 - src = (const u16 *)((uintptr_t)&rfu_STC_fastCopy & ~1); - dst = gRfuFixed->fastCopyBuffer; +{ + const u16 *src = (const u16 *)((uintptr_t)&rfu_STC_fastCopy & ~1); + u16 *dst = gRfuFixed->fastCopyBuffer; buffByteSizeMax = ((void *)rfu_REQ_changeMasterSlave - (void *)rfu_STC_fastCopy) / sizeof(u16); while (buffByteSizeMax-- != 0) *dst++ = *src++; +} #else COPY( (uintptr_t)&rfu_STC_fastCopy & ~1, @@ -591,19 +591,17 @@ static void rfu_CB_pollAndEndSearchChild(u8 reqCommand, u16 reqResult) static void rfu_STC_readChildList(void) { - u32 stwiParam; u8 numSlots = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket8.data[1]; u8 *data_p; - u8 i; u8 bm_slot_id; -#if LIBRFU_VERSION < 1026 - u8 true_slots[RFU_CHILD_MAX]; -#endif #if LIBRFU_VERSION < 1026 + u8 true_slots[RFU_CHILD_MAX]; + if (numSlots != 0) { - stwiParam = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0]; + u8 i; + u32 stwiParam = gRfuFixed->STWIBuffer->rxPacketAlloc.rfuPacket32.data[0]; STWI_set_Callback_M(rfu_CB_defaultCallback); STWI_send_LinkStatusREQ(); if (STWI_poll_CommandEnd() == 0) diff --git a/src/m4a.c b/src/m4a.c index 7774d09cba..b80a357974 100644 --- a/src/m4a.c +++ b/src/m4a.c @@ -1,5 +1,6 @@ #include #include "gba/m4a_internal.h" +#include "global.h" extern const u8 gCgb3Vol[]; diff --git a/src/menu.c b/src/menu.c index 2d3a8a8b2f..b0c2ee4b76 100644 --- a/src/menu.c +++ b/src/menu.c @@ -67,7 +67,6 @@ static EWRAM_DATA u16 sTileNum = 0; static EWRAM_DATA u8 sPaletteNum = 0; static EWRAM_DATA u8 sYesNoWindowId = 0; static EWRAM_DATA u8 sHofPCTopBarWindowId = 0; -static EWRAM_DATA u16 sFiller = 0; // needed to align static EWRAM_DATA bool8 sScheduledBgCopiesToVram[4] = {FALSE}; static EWRAM_DATA u16 sTempTileDataBufferIdx = 0; static EWRAM_DATA void *sTempTileDataBuffer[0x20] = {NULL}; diff --git a/src/overworld.c b/src/overworld.c index bae1246153..bf2bcf5ace 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -131,7 +131,7 @@ static void UpdateAllLinkPlayers(u16 *, s32); static u8 FlipVerticalAndClearForced(u8, u8); static u8 LinkPlayerGetCollision(u8, u8, s16, s16); static void CreateLinkPlayerSprite(u8, u8); -static void GetLinkPlayerCoords(u8, u16 *, u16 *); +static void GetLinkPlayerCoords(u8, s16 *, s16 *); static u8 GetLinkPlayerFacingDirection(u8); static u8 GetLinkPlayerElevation(u8); static u8 GetLinkPlayerIdAt(s16, s16); @@ -358,9 +358,8 @@ static void (*const sMovementStatusHandler[])(struct LinkPlayerObjectEvent *, st void DoWhiteOut(void) { RunScriptImmediately(EventScript_WhiteOut); - #if B_WHITEOUT_MONEY == GEN_3 - SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2); - #endif + if (B_WHITEOUT_MONEY == GEN_3) + SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2); HealPlayerParty(); Overworld_ResetStateAfterWhiteOut(); SetWarpDestinationToLastHealLocation(); @@ -425,9 +424,8 @@ static void Overworld_ResetStateAfterWhiteOut(void) FlagClear(FLAG_SYS_SAFARI_MODE); FlagClear(FLAG_SYS_USE_STRENGTH); FlagClear(FLAG_SYS_USE_FLASH); -#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE - Overworld_ResetBattleFlagsAndVars(); -#endif + if (B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE) + Overworld_ResetBattleFlagsAndVars(); // If you were defeated by Kyogre/Groudon and the step counter has // maxed out, end the abnormal weather. if (VarGet(VAR_SHOULD_END_ABNORMAL_WEATHER) == 1) @@ -3016,7 +3014,7 @@ static u8 GetSpriteForLinkedPlayer(u8 linkPlayerId) return objEvent->spriteId; } -static void GetLinkPlayerCoords(u8 linkPlayerId, u16 *x, u16 *y) +static void GetLinkPlayerCoords(u8 linkPlayerId, s16 *x, s16 *y) { u8 objEventId = gLinkPlayerObjectEvents[linkPlayerId].objEventId; struct ObjectEvent *objEvent = &gObjectEvents[objEventId]; diff --git a/src/palette.c b/src/palette.c index f19ac07cf6..fccff062a8 100644 --- a/src/palette.c +++ b/src/palette.c @@ -62,7 +62,6 @@ ALIGNED(4) EWRAM_DATA u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE] = {0}; ALIGNED(4) EWRAM_DATA u16 gPlttBufferFaded[PLTT_BUFFER_SIZE] = {0}; static EWRAM_DATA struct PaletteStruct sPaletteStructs[NUM_PALETTE_STRUCTS] = {0}; EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0}; -static EWRAM_DATA u32 sFiller = 0; static EWRAM_DATA u32 sPlttBufferTransferPending = 0; EWRAM_DATA u8 ALIGNED(2) gPaletteDecompressionBuffer[PLTT_SIZE] = {0}; diff --git a/src/party_menu.c b/src/party_menu.c old mode 100755 new mode 100644 index e360c9a50e..8170ec7d25 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -228,7 +228,6 @@ static EWRAM_DATA u16 *sSlot1TilemapBuffer = 0; // for switching party slots static EWRAM_DATA u16 *sSlot2TilemapBuffer = 0; // EWRAM_DATA u8 gSelectedOrderFromParty[MAX_FRONTIER_PARTY_SIZE] = {0}; static EWRAM_DATA u16 sPartyMenuItemId = 0; -static EWRAM_DATA u16 sUnused = 0; EWRAM_DATA u8 gBattlePartyCurrentOrder[PARTY_SIZE / 2] = {0}; // bits 0-3 are the current pos of Slot 1, 4-7 are Slot 2, and so on static EWRAM_DATA u8 sInitialLevel = 0; static EWRAM_DATA u8 sFinalLevel = 0; @@ -5297,7 +5296,7 @@ static void Task_TryLearningNextMoveAfterText(u8 taskId) Task_TryLearningNextMove(taskId); } -static void DisplayExpPoints(u8 taskId, TaskFunc task, u8 holdEffectParam) +static void UNUSED DisplayExpPoints(u8 taskId, TaskFunc task, u8 holdEffectParam) { PlaySE(SE_USE_ITEM); ConvertIntToDecimalStringN(gStringVar2, sExpCandyExperienceTable[holdEffectParam], STR_CONV_MODE_LEFT_ALIGN, 3); @@ -5430,7 +5429,7 @@ static void Task_DisplayLevelUpStatsPg2(u8 taskId) static void DisplayLevelUpStatsPg1(u8 taskId) { - s16 *arrayPtr = sPartyMenuInternal->data; + u16 *arrayPtr = (u16*) sPartyMenuInternal->data; arrayPtr[12] = CreateLevelUpStatsWindow(); DrawLevelUpWindowPg1(arrayPtr[12], arrayPtr, &arrayPtr[6], TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY); @@ -5440,7 +5439,7 @@ static void DisplayLevelUpStatsPg1(u8 taskId) static void DisplayLevelUpStatsPg2(u8 taskId) { - s16 *arrayPtr = sPartyMenuInternal->data; + u16 *arrayPtr = (u16*) sPartyMenuInternal->data; DrawLevelUpWindowPg2(arrayPtr[12], &arrayPtr[6], TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY); CopyWindowToVram(arrayPtr[12], COPYWIN_GFX); diff --git a/src/player_pc.c b/src/player_pc.c index 7dc2616e71..07cc2dba7c 100644 --- a/src/player_pc.c +++ b/src/player_pc.c @@ -388,7 +388,7 @@ void PlayerPC(void) static void InitPlayerPCMenu(u8 taskId) { - u16 *data; + s16 *data; struct WindowTemplate windowTemplate; data = gTasks[taskId].data; @@ -408,7 +408,7 @@ static void InitPlayerPCMenu(u8 taskId) static void PlayerPCProcessMenuInput(u8 taskId) { - u16 *data; + s16 *data; s8 inputOptionId; data = gTasks[taskId].data; @@ -503,7 +503,7 @@ static void PlayerPC_TurnOff(u8 taskId) static void InitItemStorageMenu(u8 taskId, u8 var) { - u16 *data; + s16 *data; struct WindowTemplate windowTemplate; data = gTasks[taskId].data; @@ -621,7 +621,7 @@ static void ItemStorage_Toss(u8 taskId) static void ItemStorage_Enter(u8 taskId, bool8 toss) { - u16 *data = gTasks[taskId].data; + s16 *data = gTasks[taskId].data; tInTossMenu = toss; ItemStorage_EraseMainMenu(taskId); @@ -654,7 +654,7 @@ static void SetPlayerPCListCount(u8 taskId) static void ItemStorage_EraseMainMenu(u8 taskId) { - u16 *data = gTasks[taskId].data; + s16 *data = gTasks[taskId].data; ClearStdWindowAndFrameToTransparent(tWindowId, FALSE); ClearWindowTilemap(tWindowId); RemoveWindow(tWindowId); @@ -700,7 +700,7 @@ static void Mailbox_DrawMailboxMenu(u8 taskId) static void Mailbox_ProcessInput(u8 taskId) { - u16 *data = gTasks[taskId].data; + s16 *data = gTasks[taskId].data; if (!gPaletteFade.active) { @@ -1488,7 +1488,6 @@ static void ItemStorage_HandleRemoveItem(u8 taskId) static void ItemStorage_HandleErrorMessageInput(u8 taskId) { - s16 *data = gTasks[taskId].data; if (JOY_NEW(A_BUTTON | B_BUTTON)) { ItemStorage_PrintMessage(ItemStorage_GetMessage(gSaveBlock1Ptr->pcItems[gPlayerPCItemPageInfo.itemsAbove + gPlayerPCItemPageInfo.cursorPos].itemId)); diff --git a/src/pokedex.c b/src/pokedex.c index af1f965fe4..308c078c22 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -1591,7 +1591,7 @@ static void ResetPokedexView(struct PokedexView *pokedexView) void CB2_OpenPokedex(void) { -#if POKEDEX_PLUS_HGSS == TRUE +#if POKEDEX_PLUS_HGSS == TRUE CB2_OpenPokedexPlusHGSS(); return; #endif @@ -3943,11 +3943,12 @@ static void HighlightSubmenuScreenSelectBarItem(u8 a, u16 b) u8 DisplayCaughtMonDexPage(u16 dexNum, u32 otId, u32 personality) { -#if POKEDEX_PLUS_HGSS == TRUE - u8 taskId = CreateTask(Task_DisplayCaughtMonDexPageHGSS, 0); -#else - u8 taskId = CreateTask(Task_DisplayCaughtMonDexPage, 0); -#endif + u8 taskId = 0; + #if POKEDEX_PLUS_HGSS + taskId = CreateTask(Task_DisplayCaughtMonDexPageHGSS, 0); + #else + taskId = CreateTask(Task_DisplayCaughtMonDexPage, 0); + #endif // POKEDEX_PLUS_HGSS gTasks[taskId].tState = 0; gTasks[taskId].tDexNum = dexNum; @@ -5103,8 +5104,8 @@ static void Task_SearchCompleteWaitForInput(u8 taskId) static void Task_SelectSearchMenuItem(u8 taskId) { u8 menuItem; - u16 *cursorPos; - u16 *scrollOffset; + s16 *cursorPos; + s16 *scrollOffset; DrawOrEraseSearchParameterBox(FALSE); menuItem = gTasks[taskId].tMenuItem; @@ -5124,8 +5125,8 @@ static void Task_HandleSearchParameterInput(u8 taskId) { u8 menuItem; const struct SearchOptionText *texts; - u16 *cursorPos; - u16 *scrollOffset; + s16 *cursorPos; + s16 *scrollOffset; u16 maxOption; bool8 moved; @@ -5442,8 +5443,8 @@ static void DrawOrEraseSearchParameterBox(bool8 erase) static void PrintSearchParameterText(u8 taskId) { const struct SearchOptionText *texts = sSearchOptions[gTasks[taskId].tMenuItem].texts; - const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataCursorPos]; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataScrollOffset]; + const s16 *cursorPos = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataCursorPos]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataScrollOffset]; u16 i; u16 j; @@ -5457,8 +5458,8 @@ static void PrintSearchParameterText(u8 taskId) static u8 GetSearchModeSelection(u8 taskId, u8 option) { - const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[option].taskDataCursorPos]; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[option].taskDataScrollOffset]; + const s16 *cursorPos = &gTasks[taskId].data[sSearchOptions[option].taskDataCursorPos]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[option].taskDataScrollOffset]; u16 id = *cursorPos + *scrollOffset; switch (option) @@ -5529,7 +5530,7 @@ static void SetDefaultSearchModeAndOrder(u8 taskId) static bool8 SearchParamCantScrollUp(u8 taskId) { u8 menuItem = gTasks[taskId].tMenuItem; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; u16 lastOption = sSearchOptions[menuItem].numOptions - 1; if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset != 0) @@ -5541,7 +5542,7 @@ static bool8 SearchParamCantScrollUp(u8 taskId) static bool8 SearchParamCantScrollDown(u8 taskId) { u8 menuItem = gTasks[taskId].tMenuItem; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; u16 lastOption = sSearchOptions[menuItem].numOptions - 1; if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset < lastOption - MAX_SEARCH_PARAM_CURSOR_POS) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 0b2ce43cf1..be5633294e 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -2994,7 +2994,6 @@ static void CreateInterfaceSprites(u8 page) { u8 spriteId; u16 digitNum; - u8 color[3]; bool32 drawNextDigit; // Scroll arrows @@ -3906,7 +3905,7 @@ static void LoadScreenSelectBarSubmenu(u16 unused) CopyBgTilemapBufferToVram(1); } -static void HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused) +static void UNUSED HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused) { u8 i; u8 j; @@ -3933,7 +3932,7 @@ static void HighlightScreenSelectBarItem(u8 selectedScreen, u16 unused) CopyBgTilemapBufferToVram(1); } -static void HighlightSubmenuScreenSelectBarItem(u8 a, u16 b) +static void UNUSED HighlightSubmenuScreenSelectBarItem(u8 a, u16 b) { u8 i; u8 j; @@ -4178,7 +4177,7 @@ static void PrintInfoScreenTextSmall(const u8* str, u8 left, u8 top) AddTextPrinterParameterized4(0, 0, left, top, 0, 0, color, 0, str); } -static void PrintInfoScreenTextSmallWhite(const u8* str, u8 left, u8 top) +static void UNUSED PrintInfoScreenTextSmallWhite(const u8* str, u8 left, u8 top) { u8 color[3]; color[0] = TEXT_COLOR_TRANSPARENT; @@ -4256,14 +4255,11 @@ static void SetTypeIconPosAndPal(u8 typeId, u8 x, u8 y, u8 spriteArrayId) } static void PrintCurrentSpeciesTypeInfo(u8 newEntry, u16 species) { - u32 i; - u16 dexNum = SpeciesToNationalPokedexNum(species); u8 type1, type2; if (!newEntry) { species = NationalPokedexNumToSpeciesHGSS(sPokedexListItem->dexNum); - dexNum = SpeciesToNationalPokedexNum(species); } //type icon(s) #ifdef TX_RANDOMIZER_AND_CHALLENGES @@ -4454,7 +4450,7 @@ static void PrintMonWeight(u16 weight, u8 left, u8 top) } // Unused in the English version, used to print height/weight in versions which use metric system. -static void PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top) +static void UNUSED PrintDecimalNum(u8 windowId, u16 num, u8 left, u8 top) { u8 str[6]; bool8 outputted = FALSE; @@ -4646,7 +4642,7 @@ static u16 GetNextPosition(u8 direction, u16 position, u16 min, u16 max) // Unown and Spinda use the personality of the first seen individual of that species // All others use personality 0 -static u32 GetPokedexMonPersonality(u16 species) +static UNUSED u32 GetPokedexMonPersonality(u16 species) { if (species == SPECIES_UNOWN || species == SPECIES_SPINDA) { @@ -4670,15 +4666,13 @@ static u32 GetPokedexMonPersonality(u16 species) //************************************ u16 NationalPokedexNumToSpeciesHGSS(u16 nationalNum) { - u16 species; - if (!nationalNum) return 0; - if (sPokedexView->formSpecies != 0) - return sPokedexView->formSpecies; - else - return NationalPokedexNumToSpecies(nationalNum); + if (sPokedexView->formSpecies != 0) + return sPokedexView->formSpecies; + else + return NationalPokedexNumToSpecies(nationalNum); } static void LoadTilesetTilemapHGSS(u8 page) @@ -4785,8 +4779,8 @@ static void ResetStatsWindows(void) static void SaveMonDataInStruct(void) { u16 species = NationalPokedexNumToSpeciesHGSS(sPokedexListItem->dexNum); - u8 EVs[6] = {gSpeciesInfo[species].evYield_HP, gSpeciesInfo[species].evYield_Speed, gSpeciesInfo[species].evYield_Attack, gSpeciesInfo[species].evYield_SpAttack, gSpeciesInfo[species].evYield_Defense, gSpeciesInfo[species].evYield_SpDefense}; - u8 differentEVs; + u8 evs[6] = {gSpeciesInfo[species].evYield_HP, gSpeciesInfo[species].evYield_Speed, gSpeciesInfo[species].evYield_Attack, gSpeciesInfo[species].evYield_SpAttack, gSpeciesInfo[species].evYield_Defense, gSpeciesInfo[species].evYield_SpDefense}; + u8 differentEVs = 0; u8 i; //Count how many different EVs @@ -4948,7 +4942,7 @@ static void Task_LoadStatsScreen(u8 taskId) } } -static void FreeStatsScreenWindowAndBgBuffers(void) +static void UNUSED FreeStatsScreenWindowAndBgBuffers(void) { void *tilemapBuffer; @@ -5070,7 +5064,6 @@ static bool8 CalculateMoves(void) u16 statsMovesEgg[EGG_MOVES_ARRAY_COUNT] = {0}; u16 statsMovesLevelUp[MAX_LEVEL_UP_MOVES] = {0}; - u16 statsMovesTMHM[NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES] = {0}; u16 move; u8 numEggMoves = 0; @@ -5310,14 +5303,7 @@ static void PrintStatsScreen_Moves_Bottom(u8 taskId) static void PrintStatsScreen_NameGender(u8 taskId, u32 num, u32 value) { u8 str[16]; - u8 str2[32]; - u8 strEV[25]; u16 species = NationalPokedexNumToSpeciesHGSS(sPokedexListItem->dexNum); - u16 natNum; - u8 evVal; - const u8 *category; - const u8 *description; - const u8 *strEVtype; u8 base_x = 38; u8 base_y = 0; @@ -5403,7 +5389,6 @@ static void PrintStatsScreen_Left(u8 taskId) { u8 base_x = 8; u8 x_offset_column = 43; - u8 x_offset_value = 26; u8 column = 0; u8 base_x_offset = 70; u8 base_x_first_row = 23; @@ -5417,7 +5402,6 @@ static void PrintStatsScreen_Left(u8 taskId) u8 strBase[14]; u8 EVs[6] = {sPokedexView->sPokemonStats.evYield_HP, sPokedexView->sPokemonStats.evYield_Speed, sPokedexView->sPokemonStats.evYield_Attack, sPokedexView->sPokemonStats.evYield_SpAttack, sPokedexView->sPokemonStats.evYield_Defense, sPokedexView->sPokemonStats.evYield_SpDefense}; u8 differentEVs = 0; - u8 i; //Base stats if (gTasks[taskId].data[5] == 0) @@ -5816,7 +5800,6 @@ static void PrintStatsScreen_Left(u8 taskId) static void PrintStatsScreen_Abilities(u8 taskId) { - u16 species = NationalPokedexNumToSpeciesHGSS(sPokedexListItem->dexNum); u8 abilities_x = 5; u8 abilities_y = 3; u16 ability0; @@ -6096,7 +6079,6 @@ static void Task_HandleEvolutionScreenInput(u8 taskId) if (sPokedexView->sEvoScreenData.numAllEvolutions != 0 && sPokedexView->sEvoScreenData.numSeen != 0) { - u8 i; u8 base_y = 58; u8 base_y_offset = 9; u8 pos = sPokedexView->sEvoScreenData.menuPos; @@ -6263,8 +6245,6 @@ static u8 PrintPreEvolutions(u8 taskId, u16 species) u8 base_x = 13+8; u8 base_y = 51; u8 base_y_offset = 9; - u8 base_i = 0; - u8 depth_x = 16; u16 preEvolutionOne = 0; u16 preEvolutionTwo = 0; @@ -6355,8 +6335,7 @@ static u8 PrintPreEvolutions(u8 taskId, u16 species) static u8 PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 depth, u8 depth_i) { u16 i; - u16 j; - const struct MapHeader *mapHeader; + const struct MapHeader *mapHeader; u16 targetSpecies = 0; u16 previousTargetSpecies = 0; @@ -6469,119 +6448,119 @@ static u8 PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 depth, ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, 3); //beauty StringExpandPlaceholders(gStringVar4, gText_EVO_BEAUTY ); break; - case EVO_LEVEL_FEMALE: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_FEMALE ); - break; - case EVO_LEVEL_MALE: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_MALE ); - break; - case EVO_LEVEL_NIGHT: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NIGHT ); - break; - case EVO_LEVEL_DAY: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DAY ); - break; - case EVO_LEVEL_DUSK: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DUSK ); - break; - case EVO_ITEM_HOLD_DAY: - item = gEvolutionTable[species][i].param; //item - CopyItemName(item, gStringVar2); //item - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD_DAY ); - break; - case EVO_ITEM_HOLD_NIGHT: - item = gEvolutionTable[species][i].param; //item - CopyItemName(item, gStringVar2); //item - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD_NIGHT ); - break; - case EVO_MOVE: - StringCopy(gStringVar2, gMoveNames[gEvolutionTable[species][i].param]); - StringExpandPlaceholders(gStringVar4, gText_EVO_MOVE ); - break; - case EVO_FRIENDSHIP_MOVE_TYPE: - StringCopy(gStringVar2, gTypeNames[gEvolutionTable[species][i].param]); - StringExpandPlaceholders(gStringVar4, gText_EVO_FRIENDSHIP_MOVE_TYPE ); - break; - case EVO_MAPSEC: - StringCopy(gStringVar2, gRegionMapEntries[gEvolutionTable[species][i].param].name); - StringExpandPlaceholders(gStringVar4, gText_EVO_MAPSEC ); - break; - case EVO_ITEM_MALE: - item = gEvolutionTable[species][i].param; //item - CopyItemName(item, gStringVar2); //item - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_MALE ); - break; - case EVO_ITEM_FEMALE: - item = gEvolutionTable[species][i].param; //item - CopyItemName(item, gStringVar2); //item - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_FEMALE ); - break; - case EVO_LEVEL_RAIN: - //if (j == WEATHER_RAIN || j == WEATHER_RAIN_THUNDERSTORM || j == WEATHER_DOWNPOUR) - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_RAIN ); - break; - case EVO_SPECIFIC_MON_IN_PARTY: - StringCopy(gStringVar2, gSpeciesNames[gEvolutionTable[species][i].param]); //mon name - StringExpandPlaceholders(gStringVar4, gText_EVO_SPECIFIC_MON_IN_PARTY ); - break; - case EVO_LEVEL_DARK_TYPE_MON_IN_PARTY: - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DARK_TYPE_MON_IN_PARTY ); - break; - case EVO_TRADE_SPECIFIC_MON: - StringCopy(gStringVar2, gSpeciesNames[gEvolutionTable[species][i].param]); //mon name - StringExpandPlaceholders(gStringVar4, gText_EVO_TRADE_SPECIFIC_MON ); - break; - case EVO_SPECIFIC_MAP: - mapHeader = Overworld_GetMapHeaderByGroupAndId(gEvolutionTable[species][i].param >> 8, gEvolutionTable[species][i].param & 0xFF); - GetMapName(gStringVar2, mapHeader->regionMapSectionId, 0); - StringExpandPlaceholders(gStringVar4, gText_EVO_SPECIFIC_MAP ); - break; - case EVO_LEVEL_NATURE_AMPED: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NATURE_AMPED); - break; - case EVO_LEVEL_NATURE_LOW_KEY: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level - StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NATURE_LOW_KEY); - break; - case EVO_CRITICAL_HITS: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_CRITS_DIGITS); //crits - StringExpandPlaceholders(gStringVar4, gText_EVO_CRITICAL_HITS); - break; - case EVO_SCRIPT_TRIGGER_DMG: - ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_DMG_DIGITS); //damage - StringExpandPlaceholders(gStringVar4, gText_EVO_SCRIPT_TRIGGER_DMG); - break; - case EVO_DARK_SCROLL: - item = gEvolutionTable[species][i].param; - CopyItemName(item, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_EVO_DARK_SCROLL ); - break; - case EVO_WATER_SCROLL: - item = gEvolutionTable[species][i].param; - CopyItemName(item, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_EVO_WATER_SCROLL ); - break; - case EVO_ITEM_NIGHT: - item = gEvolutionTable[species][i].param; - CopyItemName(item, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_NIGHT ); - break; - case EVO_ITEM_DAY: - item = gEvolutionTable[species][i].param; - CopyItemName(item, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_DAY ); - break; - case EVO_ITEM_HOLD: - item = gEvolutionTable[species][i].param; - CopyItemName(item, gStringVar2); - StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD ); - break; + case EVO_LEVEL_FEMALE: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_FEMALE ); + break; + case EVO_LEVEL_MALE: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_MALE ); + break; + case EVO_LEVEL_NIGHT: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NIGHT ); + break; + case EVO_LEVEL_DAY: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DAY ); + break; + case EVO_LEVEL_DUSK: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DUSK ); + break; + case EVO_ITEM_HOLD_DAY: + item = gEvolutionTable[species][i].param; //item + CopyItemName(item, gStringVar2); //item + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD_DAY ); + break; + case EVO_ITEM_HOLD_NIGHT: + item = gEvolutionTable[species][i].param; //item + CopyItemName(item, gStringVar2); //item + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD_NIGHT ); + break; + case EVO_MOVE: + StringCopy(gStringVar2, gMoveNames[gEvolutionTable[species][i].param]); + StringExpandPlaceholders(gStringVar4, gText_EVO_MOVE ); + break; + case EVO_FRIENDSHIP_MOVE_TYPE: + StringCopy(gStringVar2, gTypeNames[gEvolutionTable[species][i].param]); + StringExpandPlaceholders(gStringVar4, gText_EVO_FRIENDSHIP_MOVE_TYPE ); + break; + case EVO_MAPSEC: + StringCopy(gStringVar2, gRegionMapEntries[gEvolutionTable[species][i].param].name); + StringExpandPlaceholders(gStringVar4, gText_EVO_MAPSEC ); + break; + case EVO_ITEM_MALE: + item = gEvolutionTable[species][i].param; //item + CopyItemName(item, gStringVar2); //item + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_MALE ); + break; + case EVO_ITEM_FEMALE: + item = gEvolutionTable[species][i].param; //item + CopyItemName(item, gStringVar2); //item + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_FEMALE ); + break; + case EVO_LEVEL_RAIN: + //if (j == WEATHER_RAIN || j == WEATHER_RAIN_THUNDERSTORM || j == WEATHER_DOWNPOUR) + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_RAIN ); + break; + case EVO_SPECIFIC_MON_IN_PARTY: + StringCopy(gStringVar2, gSpeciesNames[gEvolutionTable[species][i].param]); //mon name + StringExpandPlaceholders(gStringVar4, gText_EVO_SPECIFIC_MON_IN_PARTY ); + break; + case EVO_LEVEL_DARK_TYPE_MON_IN_PARTY: + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_DARK_TYPE_MON_IN_PARTY ); + break; + case EVO_TRADE_SPECIFIC_MON: + StringCopy(gStringVar2, gSpeciesNames[gEvolutionTable[species][i].param]); //mon name + StringExpandPlaceholders(gStringVar4, gText_EVO_TRADE_SPECIFIC_MON ); + break; + case EVO_SPECIFIC_MAP: + mapHeader = Overworld_GetMapHeaderByGroupAndId(gEvolutionTable[species][i].param >> 8, gEvolutionTable[species][i].param & 0xFF); + GetMapName(gStringVar2, mapHeader->regionMapSectionId, 0); + StringExpandPlaceholders(gStringVar4, gText_EVO_SPECIFIC_MAP ); + break; + case EVO_LEVEL_NATURE_AMPED: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NATURE_AMPED); + break; + case EVO_LEVEL_NATURE_LOW_KEY: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_LVL_DIGITS); //level + StringExpandPlaceholders(gStringVar4, gText_EVO_LEVEL_NATURE_LOW_KEY); + break; + case EVO_CRITICAL_HITS: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_CRITS_DIGITS); //crits + StringExpandPlaceholders(gStringVar4, gText_EVO_CRITICAL_HITS); + break; + case EVO_SCRIPT_TRIGGER_DMG: + ConvertIntToDecimalStringN(gStringVar2, gEvolutionTable[species][i].param, STR_CONV_MODE_LEADING_ZEROS, EVO_SCREEN_DMG_DIGITS); //damage + StringExpandPlaceholders(gStringVar4, gText_EVO_SCRIPT_TRIGGER_DMG); + break; + case EVO_DARK_SCROLL: + item = gEvolutionTable[species][i].param; + CopyItemName(item, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_EVO_DARK_SCROLL ); + break; + case EVO_WATER_SCROLL: + item = gEvolutionTable[species][i].param; + CopyItemName(item, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_EVO_WATER_SCROLL ); + break; + case EVO_ITEM_NIGHT: + item = gEvolutionTable[species][i].param; + CopyItemName(item, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_NIGHT ); + break; + case EVO_ITEM_DAY: + item = gEvolutionTable[species][i].param; + CopyItemName(item, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_DAY ); + break; + case EVO_ITEM_HOLD: + item = gEvolutionTable[species][i].param; + CopyItemName(item, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_EVO_ITEM_HOLD ); + break; default: StringExpandPlaceholders(gStringVar4, gText_EVO_UNKNOWN ); break; @@ -6852,13 +6831,9 @@ static void PrintForms(u8 taskId, u16 species) u8 j = 1; u16 speciesForm; - - bool8 left = TRUE; u8 base_x = 5; - u8 base_x_offset = 54; u8 base_y = 52; u8 base_y_offset = 9; - u8 base_i = 0; u8 times = 0; u8 y_offset_icons = 0; //For unown only @@ -6886,10 +6861,13 @@ static void PrintForms(u8 taskId, u16 species) gTasks[taskId].data[4+times] = CreateMonIcon(speciesForm, SpriteCB_MonIcon, 52 + 34*(times-1), 31, 4, 0); //Create pokemon sprite else if (times < 14) gTasks[taskId].data[4+times] = CreateMonIcon(speciesForm, SpriteCB_MonIcon, 18 + 34*(times-7), 70 - y_offset_icons, 4, 0); //Create pokemon sprite + // Can't print any more forms, because we're going out of bounds for task data. + /* else if (times < 21) gTasks[taskId].data[4+times] = CreateMonIcon(speciesForm, SpriteCB_MonIcon, 18 + 34*(times-14), 104 - y_offset_icons, 4, 0); //Create pokemon sprite else gTasks[taskId].data[4+times] = CreateMonIcon(speciesForm, SpriteCB_MonIcon, 18 + 34*(times-21), 138 - y_offset_icons, 4, 0); //Create pokemon sprite + */ gSprites[gTasks[taskId].data[4+times]].oam.priority = 0; } } @@ -7550,7 +7528,7 @@ static void Task_ClosePokedexFromSearchResultsStartMenu(u8 taskId) static int DoPokedexSearch(u8 dexMode, u8 order, u8 abcGroup, u8 bodyColor, u8 type1, u8 type2) { u16 species; - u16 i,j; + u16 i; u16 resultsCount; u8 types[2]; @@ -7738,7 +7716,7 @@ static void Task_LoadSearchMenu(u8 taskId) case 1: LoadCompressedSpriteSheet(&sInterfaceSpriteSheet[HGSS_DECAPPED]); LoadSpritePalettes(sInterfaceSpritePalette); - LoadSpritePalettes(sStatBarSpritePal); + LoadSpritePalettes(sStatBarSpritePal); CreateSearchParameterScrollArrows(taskId); for (i = 0; i < NUM_TASK_DATA; i++) gTasks[taskId].data[i] = 0; @@ -8014,8 +7992,8 @@ static void Task_SearchCompleteWaitForInput(u8 taskId) static void Task_SelectSearchMenuItem(u8 taskId) { u8 menuItem; - u16 *cursorPos; - u16 *scrollOffset; + s16 *cursorPos; + s16 *scrollOffset; DrawOrEraseSearchParameterBox(FALSE); menuItem = gTasks[taskId].tMenuItem; @@ -8035,8 +8013,8 @@ static void Task_HandleSearchParameterInput(u8 taskId) { u8 menuItem; const struct SearchOptionText *texts; - u16 *cursorPos; - u16 *scrollOffset; + s16 *cursorPos; + s16 *scrollOffset; u16 maxOption; bool8 moved; @@ -8354,8 +8332,8 @@ static void DrawOrEraseSearchParameterBox(bool8 erase) static void PrintSearchParameterText(u8 taskId) { const struct SearchOptionText *texts = sSearchOptions[gTasks[taskId].tMenuItem].texts; - const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataCursorPos]; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataScrollOffset]; + const s16 *cursorPos = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataCursorPos]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[gTasks[taskId].tMenuItem].taskDataScrollOffset]; u16 i; u16 j; @@ -8369,8 +8347,8 @@ static void PrintSearchParameterText(u8 taskId) static u8 GetSearchModeSelection(u8 taskId, u8 option) { - const u16 *cursorPos = &gTasks[taskId].data[sSearchOptions[option].taskDataCursorPos]; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[option].taskDataScrollOffset]; + const s16 *cursorPos = &gTasks[taskId].data[sSearchOptions[option].taskDataCursorPos]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[option].taskDataScrollOffset]; u16 id = *cursorPos + *scrollOffset; switch (option) @@ -8441,7 +8419,7 @@ static void SetDefaultSearchModeAndOrder(u8 taskId) static bool8 SearchParamCantScrollUp(u8 taskId) { u8 menuItem = gTasks[taskId].tMenuItem; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; u16 lastOption = sSearchOptions[menuItem].numOptions - 1; if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset != 0) @@ -8453,7 +8431,7 @@ static bool8 SearchParamCantScrollUp(u8 taskId) static bool8 SearchParamCantScrollDown(u8 taskId) { u8 menuItem = gTasks[taskId].tMenuItem; - const u16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; + const s16 *scrollOffset = &gTasks[taskId].data[sSearchOptions[menuItem].taskDataScrollOffset]; u16 lastOption = sSearchOptions[menuItem].numOptions - 1; if (lastOption > MAX_SEARCH_PARAM_CURSOR_POS && *scrollOffset < lastOption - MAX_SEARCH_PARAM_CURSOR_POS) diff --git a/src/pokemon.c b/src/pokemon.c index b71549257f..36ad137b2c 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4125,19 +4125,14 @@ static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) return checksum; } -#if B_FRIENDSHIP_BOOST == TRUE -#define CALC_FRIENDSHIP_BOOST() n = n + ((n * 10 * friendship) / (MAX_FRIENDSHIP * 100)); -#else -#define CALC_FRIENDSHIP_BOOST() -#endif - #define CALC_STAT(base, iv, ev, statIndex, field) \ { \ u8 baseStat = gSpeciesInfo[species].base; \ s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \ u8 nature = GetNature(mon); \ n = ModifyStatByNature(nature, n, statIndex); \ - CALC_FRIENDSHIP_BOOST() \ + if (B_FRIENDSHIP_BOOST == TRUE) \ + n = n + ((n * 10 * friendship) / (MAX_FRIENDSHIP * 100));\ SetMonData(mon, field, &n); \ } @@ -4323,7 +4318,7 @@ void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) s32 level = GetLevelFromBoxMonExp(boxMon); s32 i; - for (i = 0; gLevelUpLearnsets[species][i].move != LEVEL_UP_END; i++) + for (i = 0; gLevelUpLearnsets[species][i].move != LEVEL_UP_MOVE_END; i++) { if (gLevelUpLearnsets[species][i].level > level) break; @@ -4343,12 +4338,12 @@ void GiveBoxMonInitialMoveset_Fast(struct BoxPokemon *boxMon) //Credit: Asparagu { u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); s32 level = GetLevelFromBoxMonExp(boxMon); - s32 i, j; + s32 i; u16 levelMoveCount = 0; u16 moves[MAX_MON_MOVES] = {0}; u8 addedMoves = 0; - for (i = 0; gLevelUpLearnsets[species][i].move != LEVEL_UP_END; i++) + for (i = 0; gLevelUpLearnsets[species][i].move != LEVEL_UP_MOVE_END; i++) levelMoveCount++; for (i = levelMoveCount; (i >= 0 && addedMoves < MAX_MON_MOVES); i--) @@ -4385,7 +4380,7 @@ u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove) while (gLevelUpLearnsets[species][sLearningMoveTableID].level != level) { sLearningMoveTableID++; - if (gLevelUpLearnsets[species][sLearningMoveTableID].move == LEVEL_UP_END) + if (gLevelUpLearnsets[species][sLearningMoveTableID].move == LEVEL_UP_MOVE_END) return MOVE_NONE; } } @@ -4642,44 +4637,20 @@ static void DecryptBoxMon(struct BoxPokemon *boxMon) #define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \ case n: \ { \ - union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \ \ switch (substructType) \ { \ case 0: \ - substruct = &substructs ## n [v1]; \ + substruct = &boxMon->secure.substructs[v1]; \ break; \ case 1: \ - substruct = &substructs ## n [v2]; \ + substruct = &boxMon->secure.substructs[v2]; \ break; \ case 2: \ - substruct = &substructs ## n [v3]; \ + substruct = &boxMon->secure.substructs[v3]; \ break; \ case 3: \ - substruct = &substructs ## n [v4]; \ + substruct = &boxMon->secure.substructs[v4]; \ break; \ } \ break; \ @@ -4783,7 +4754,10 @@ u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data) return ret; } -u32 GetMonData2(struct Pokemon *mon, s32 field) __attribute__((alias("GetMonData3"))); +u32 GetMonData2(struct Pokemon *mon, s32 field) +{ + return GetMonData3(mon, field, NULL); +} /* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type * safety we have a GetBoxMonData macro (in include/pokemon.h) which @@ -5153,7 +5127,10 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) return retVal; } -u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) __attribute__((alias("GetBoxMonData3"))); +u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) +{ + return GetBoxMonData3(boxMon, field, NULL); +} #define SET8(lhs) (lhs) = *data #define SET16(lhs) (lhs) = data[0] + (data[1] << 8) @@ -5816,12 +5793,6 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, } \ } -#if B_X_ITEMS_BUFF >= GEN_7 - #define X_ITEM_STAGES 2 -#else - #define X_ITEM_STAGES 1 -#endif - // EXP candies store an index for this table in their holdEffectParam. const u32 sExpCandyExperienceTable[] = { [EXP_100 - 1] = 100, @@ -6394,18 +6365,20 @@ static void BufferStatRoseMessage(s32 statIdx) { gBattlerTarget = gBattlerInMenuId; StringCopy(gBattleTextBuff1, gStatNamesTable[sStatsToRaise[statIdx]]); -#if B_X_ITEMS_BUFF >= GEN_7 - StringCopy(gBattleTextBuff2, gText_StatSharply); - StringAppend(gBattleTextBuff2, gText_StatRose); -#else - StringCopy(gBattleTextBuff2, gText_StatRose); -#endif + if (B_X_ITEMS_BUFF >= GEN_7) + { + StringCopy(gBattleTextBuff2, gText_StatSharply); + StringAppend(gBattleTextBuff2, gText_StatRose); + } + else + { + StringCopy(gBattleTextBuff2, gText_StatRose); + } BattleStringExpandPlaceholdersToDisplayedString(gText_DefendersStatRose); } u8 *UseStatIncreaseItem(u16 itemId) { - int i; const u8 *itemEffect; if (itemId == ITEM_ENIGMA_BERRY_E_READER) @@ -7540,7 +7513,7 @@ u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves) { u16 moveLevel; - if (gLevelUpLearnsets[species][i].move == LEVEL_UP_END) + if (gLevelUpLearnsets[species][i].move == LEVEL_UP_MOVE_END) break; moveLevel = gLevelUpLearnsets[species][i].level; @@ -7569,7 +7542,7 @@ u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) u8 numMoves = 0; int i; - for (i = 0; i < MAX_LEVEL_UP_MOVES && gLevelUpLearnsets[species][i].move != LEVEL_UP_END; i++) + for (i = 0; i < MAX_LEVEL_UP_MOVES && gLevelUpLearnsets[species][i].move != LEVEL_UP_MOVE_END; i++) moves[numMoves++] = gLevelUpLearnsets[species][i].move; return numMoves; @@ -7594,7 +7567,7 @@ u8 GetNumberOfRelearnableMoves(struct Pokemon *mon) { u16 moveLevel; - if (gLevelUpLearnsets[species][i].move == LEVEL_UP_END) + if (gLevelUpLearnsets[species][i].move == LEVEL_UP_MOVE_END) break; moveLevel = gLevelUpLearnsets[species][i].level; @@ -8479,7 +8452,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg) // Returns SPECIES_NONE if no form change is possible u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg) { - u32 i, j; + u32 i; u16 targetSpecies = SPECIES_NONE; u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; @@ -8550,7 +8523,7 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) { - u32 i, j; + u32 i; const struct FormChange *formChanges = gFormChangeTablePointers[species]; if (formChanges != NULL) @@ -8578,7 +8551,7 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) { sLearningMoveTableID = 0; } - while(gLevelUpLearnsets[species][sLearningMoveTableID].move != LEVEL_UP_END) + while(gLevelUpLearnsets[species][sLearningMoveTableID].move != LEVEL_UP_MOVE_END) { while (gLevelUpLearnsets[species][sLearningMoveTableID].level == 0 || gLevelUpLearnsets[species][sLearningMoveTableID].level == level) { diff --git a/src/pokemon_debug.c b/src/pokemon_debug.c index 3c9a562776..8090a96f7c 100644 --- a/src/pokemon_debug.c +++ b/src/pokemon_debug.c @@ -378,7 +378,7 @@ static void ReloadPokemonSprites(struct PokemonDebugMenu *data); static void Exit_Debug_Pokemon(u8); //Text handling functions -static void PadString(const u8 *src, u8 *dst) +static void UNUSED PadString(const u8 *src, u8 *dst) { u32 i; @@ -542,7 +542,6 @@ static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits) static void SetArrowInvisibility(struct PokemonDebugMenu *data) { - bool8 invisible = data->currentSubmenu; switch (data->currentSubmenu) { case 0: @@ -672,7 +671,6 @@ static bool32 TryMoveDigit(struct PokemonDebugModifyArrows *modArrows, bool32 mo static void UpdateBattlerValue(struct PokemonDebugMenu *data) { - u32 i; switch (data->modifyArrows.typeOfVal) { case VAL_U16: @@ -706,13 +704,8 @@ static const struct CompressedSpritePalette *GetMonSpritePalStructCustom(u16 spe static void BattleLoadOpponentMonSpriteGfxCustom(u16 species, bool8 isFemale, bool8 isShiny, u8 battlerId) { - u16 paletteOffset; const void *lzPaletteData; - const struct CompressedSpritePalette *palette; - - paletteOffset = 0x100 + battlerId * 16; - - palette = GetMonSpritePalStructCustom(species, isFemale, isShiny); + u16 paletteOffset = 0x100 + battlerId * 16;; if (isShiny) { @@ -1109,9 +1102,7 @@ void CB2_Debug_Pokemon(void) FillBgTilemapBufferRect(0, 0, 0, 0, 32, 20, 15); InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); - data->battleBgType = 0; - data->battleTerrain = 0; - LoadBattleBg(data->battleBgType , data->battleTerrain); + LoadBattleBg(0, BATTLE_TERRAIN_GRASS); gMain.state++; break; @@ -1262,7 +1253,7 @@ static void ApplyOffsetSpriteValues(struct PokemonDebugMenu *data) gSprites[data->backspriteId].y = DEBUG_MON_BACK_Y + gMonBackPicCoords[species].y_offset + data->offsetsSpriteValues.offset_back_picCoords; //Front gSprites[data->frontspriteId].y = GetBattlerSpriteFinal_YCustom(species, data->offsetsSpriteValues.offset_front_picCoords, data->offsetsSpriteValues.offset_front_elevation); - + if (data->currentSubmenu == 2) UpdateShadowSpriteInvisible(data); } diff --git a/src/pokemon_icon.c b/src/pokemon_icon.c index 07c288d0bb..529ea61543 100644 --- a/src/pokemon_icon.c +++ b/src/pokemon_icon.c @@ -1072,7 +1072,7 @@ const u8 *const gMonIconTable[NUM_SPECIES + 1] = [SPECIES_PIKACHU_KALOS_CAP] = gMonIcon_PikachuKalosCap, [SPECIES_PIKACHU_ALOLA_CAP] = gMonIcon_PikachuAlolaCap, [SPECIES_PIKACHU_PARTNER_CAP] = gMonIcon_PikachuPartnerCap, - [SPECIES_PIKACHU_WORLD_CAP] = gMonIcon_QuestionMark, + [SPECIES_PIKACHU_WORLD_CAP] = gMonIcon_PikachuWorldCap, [SPECIES_PICHU_SPIKY_EARED] = gMonIcon_PichuSpikyEared, [SPECIES_UNOWN_B] = gMonIcon_UnownB, [SPECIES_UNOWN_C] = gMonIcon_UnownC, diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 982ce489e2..73032935d4 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -3750,9 +3750,8 @@ static void PrintMoveDetails(u16 move) if (sMonSummaryScreen->currPageIndex == PSS_PAGE_BATTLE_MOVES) { moveEffect = gBattleMoves[move].effect; - #if B_SHOW_SPLIT_ICON == TRUE - ShowSplitIcon(GetBattleMoveSplit(move)); - #endif + if (B_SHOW_SPLIT_ICON == TRUE) + ShowSplitIcon(GetBattleMoveSplit(move)); PrintMovePowerAndAccuracy(move); if (moveEffect != EFFECT_PLACEHOLDER) diff --git a/src/record_mixing.c b/src/record_mixing.c index c5d915a9db..7554316f7d 100644 --- a/src/record_mixing.c +++ b/src/record_mixing.c @@ -460,20 +460,20 @@ static void Task_MixingRecordsRecv(u8 taskId) task->func = Task_SendPacket; if (Link_AnyPartnersPlayingRubyOrSapphire()) { - StorePtrInTaskData(sSentRecord, &task->tSentRecord); + StorePtrInTaskData(sSentRecord, (u16*) &task->tSentRecord); subTaskId = CreateTask(Task_CopyReceiveBuffer, 80); task->tCopyTaskId = subTaskId; gTasks[subTaskId].tParentTaskId = taskId; - StorePtrInTaskData(sReceivedRecords, &gTasks[subTaskId].tRecvRecords); + StorePtrInTaskData(sReceivedRecords, (u16*) &gTasks[subTaskId].tRecvRecords); sRecordStructSize = sizeof(struct PlayerRecordRS); } else { - StorePtrInTaskData(sSentRecord, &task->tSentRecord); + StorePtrInTaskData(sSentRecord, (u16*) &task->tSentRecord); subTaskId = CreateTask(Task_CopyReceiveBuffer, 80); task->tCopyTaskId = subTaskId; gTasks[subTaskId].tParentTaskId = taskId; - StorePtrInTaskData(sReceivedRecords, &gTasks[subTaskId].tRecvRecords); + StorePtrInTaskData(sReceivedRecords,(u16*) &gTasks[subTaskId].tRecvRecords); sRecordStructSize = sizeof(struct PlayerRecordEmerald); } } @@ -495,7 +495,7 @@ static void Task_SendPacket(u8 taskId) { case 0: // Copy record data chunk to send buffer { - void *recordData = LoadPtrFromTaskData(&task->tSentRecord) + task->tNumChunksSent * BUFFER_CHUNK_SIZE; + void *recordData = LoadPtrFromTaskData((u16*)&task->tSentRecord) + task->tNumChunksSent * BUFFER_CHUNK_SIZE; memcpy(gBlockSendBuffer, recordData, BUFFER_CHUNK_SIZE); task->tState++; @@ -537,7 +537,7 @@ static void Task_CopyReceiveBuffer(u8 taskId) { if ((status >> i) & 1) { - void *dest = LoadPtrFromTaskData(&task->tRecvRecords) + task->tNumChunksRecv(i) * BUFFER_CHUNK_SIZE + sRecordStructSize * i; + void *dest = LoadPtrFromTaskData((u16*) &task->tRecvRecords) + task->tNumChunksRecv(i) * BUFFER_CHUNK_SIZE + sRecordStructSize * i; void *src = GetPlayerRecvBuffer(i); if ((task->tNumChunksRecv(i) + 1) * BUFFER_CHUNK_SIZE > sRecordStructSize) memcpy(dest, src, sRecordStructSize - task->tNumChunksRecv(i) * BUFFER_CHUNK_SIZE); @@ -765,9 +765,6 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size struct RecordMixingDaycareMail *mixMail; u8 playerSlot1, playerSlot2; void *ptr; - u8 unusedArr1[MAX_LINK_PLAYERS]; - u8 unusedArr2[MAX_LINK_PLAYERS]; - struct RecordMixingDaycareMail *unusedMixMail[MAX_LINK_PLAYERS]; bool8 canHoldItem[MAX_LINK_PLAYERS][DAYCARE_MON_COUNT]; u8 idxs[MAX_LINK_PLAYERS][2]; u8 numDaycareCanHold; @@ -782,8 +779,6 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size linkPlayerCount = GetLinkPlayerCount(); for (i = 0; i < MAX_LINK_PLAYERS; i++) { - unusedArr1[i] = 0xFF; - unusedArr2[i] = 0; canHoldItem[i][0] = FALSE; canHoldItem[i][1] = FALSE; } @@ -924,7 +919,6 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size for (i = 0; i < MAX_LINK_PLAYERS; i++) { mixMail = &records[multiplayerId * recordSize]; - unusedMixMail[i] = mixMail; } // Choose a random table id to determine who will diff --git a/src/region_map.c b/src/region_map.c index 21c6314d30..8936e668ac 100644 --- a/src/region_map.c +++ b/src/region_map.c @@ -1124,8 +1124,8 @@ static void RegionMap_InitializeStateBasedOnSSTidalLocation(void) { u16 y; u16 x; - u8 mapGroup; - u8 mapNum; + s8 mapGroup; + s8 mapNum; u16 dimensionScale; s16 xOnMap; s16 yOnMap; diff --git a/src/save.c b/src/save.c index 765fb045c3..3f8b25a3a3 100644 --- a/src/save.c +++ b/src/save.c @@ -94,7 +94,6 @@ u16 gSaveUnusedVar2; u16 gSaveAttemptStatus; EWRAM_DATA struct SaveSector gSaveDataBuffer = {0}; // Buffer used for reading/writing sectors -EWRAM_DATA static u8 sUnusedVar = 0; void ClearSaveData(void) { diff --git a/src/save_failed_screen.c b/src/save_failed_screen.c index f7f0162ff4..e9257debf2 100644 --- a/src/save_failed_screen.c +++ b/src/save_failed_screen.c @@ -41,9 +41,7 @@ enum static EWRAM_DATA u16 sSaveFailedType = {0}; static EWRAM_DATA u16 sClockInfo[2] = {0}; -static EWRAM_DATA u8 sUnused1[12] = {0}; static EWRAM_DATA u8 sWindowIds[2] = {0}; -static EWRAM_DATA u8 sUnused2[4] = {0}; static const struct OamData sClockOamData = { diff --git a/src/scrcmd.c b/src/scrcmd.c index 4b3835422e..288f70d994 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -783,8 +783,8 @@ bool8 ScrCmd_warphole(struct ScriptContext *ctx) { u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); - u16 x; - u16 y; + s16 x; + s16 y; PlayerGetDestCoords(&x, &y); if (mapGroup == MAP_GROUP(UNDEFINED) && mapNum == MAP_NUM(UNDEFINED)) @@ -1420,10 +1420,10 @@ bool8 ScrCmd_multichoicegrid(struct ScriptContext *ctx) bool8 ScrCmd_erasebox(struct ScriptContext *ctx) { - u8 left = ScriptReadByte(ctx); - u8 top = ScriptReadByte(ctx); - u8 right = ScriptReadByte(ctx); - u8 bottom = ScriptReadByte(ctx); + u8 UNUSED left = ScriptReadByte(ctx); + u8 UNUSED top = ScriptReadByte(ctx); + u8 UNUSED right = ScriptReadByte(ctx); + u8 UNUSED bottom = ScriptReadByte(ctx); // Menu_EraseWindowRect(left, top, right, bottom); return FALSE; @@ -1431,10 +1431,10 @@ bool8 ScrCmd_erasebox(struct ScriptContext *ctx) bool8 ScrCmd_drawboxtext(struct ScriptContext *ctx) { - u8 left = ScriptReadByte(ctx); - u8 top = ScriptReadByte(ctx); - u8 multichoiceId = ScriptReadByte(ctx); - bool8 ignoreBPress = ScriptReadByte(ctx); + u8 UNUSED left = ScriptReadByte(ctx); + u8 UNUSED top = ScriptReadByte(ctx); + u8 UNUSED multichoiceId = ScriptReadByte(ctx); + bool8 UNUSED ignoreBPress = ScriptReadByte(ctx); /*if (Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE) { @@ -1783,8 +1783,8 @@ bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx) bool8 ScrCmd_updatemoneybox(struct ScriptContext *ctx) { - u8 x = ScriptReadByte(ctx); - u8 y = ScriptReadByte(ctx); + u8 UNUSED x = ScriptReadByte(ctx); + u8 UNUSED y = ScriptReadByte(ctx); u8 ignore = ScriptReadByte(ctx); if (!ignore) @@ -1803,8 +1803,8 @@ bool8 ScrCmd_showcoinsbox(struct ScriptContext *ctx) bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx) { - u8 x = ScriptReadByte(ctx); - u8 y = ScriptReadByte(ctx); + u8 UNUSED x = ScriptReadByte(ctx); + u8 UNUSED y = ScriptReadByte(ctx); HideCoinsWindow(); return FALSE; @@ -1812,8 +1812,8 @@ bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx) bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) { - u8 x = ScriptReadByte(ctx); - u8 y = ScriptReadByte(ctx); + u8 UNUSED x = ScriptReadByte(ctx); + u8 UNUSED y = ScriptReadByte(ctx); PrintCoinsString(GetCoins()); return FALSE; @@ -2128,10 +2128,10 @@ bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx) // Below two are functions for elevators in RS, do nothing in Emerald bool8 ScrCmd_addelevmenuitem(struct ScriptContext *ctx) { - u8 v3 = ScriptReadByte(ctx); - u16 v5 = VarGet(ScriptReadHalfword(ctx)); - u16 v7 = VarGet(ScriptReadHalfword(ctx)); - u16 v9 = VarGet(ScriptReadHalfword(ctx)); + u8 UNUSED v3 = ScriptReadByte(ctx); + u16 UNUSED v5 = VarGet(ScriptReadHalfword(ctx)); + u16 UNUSED v7 = VarGet(ScriptReadHalfword(ctx)); + u16 UNUSED v9 = VarGet(ScriptReadHalfword(ctx)); //ScriptAddElevatorMenuItem(v3, v5, v7, v9); return FALSE; diff --git a/src/script_menu.c b/src/script_menu.c index d47d459e5e..01b7f6a588 100644 --- a/src/script_menu.c +++ b/src/script_menu.c @@ -273,8 +273,6 @@ static void Task_HandleMultichoiceInput(u8 taskId) bool8 ScriptMenu_YesNo(u8 left, u8 top) { - u8 taskId; - if (FuncIsActiveTask(Task_HandleYesNoInput) == TRUE) { return FALSE; @@ -283,7 +281,7 @@ bool8 ScriptMenu_YesNo(u8 left, u8 top) { gSpecialVar_Result = 0xFF; DisplayYesNoMenuDefaultYes(); - taskId = CreateTask(Task_HandleYesNoInput, 0x50); + CreateTask(Task_HandleYesNoInput, 0x50); return TRUE; } } diff --git a/src/secret_base.c b/src/secret_base.c index 9509cd0fc5..c5f21e252d 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -519,7 +519,7 @@ bool8 CurMapIsSecretBase(void) void InitSecretBaseAppearance(bool8 hidePC) { u16 secretBaseIdx; - u16 x, y; + s16 x, y; u8 *decorations; u8 *decorPos; @@ -915,7 +915,7 @@ void ShowSecretBaseRegistryMenu(void) static void Task_ShowSecretBaseRegistryMenu(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; LockPlayerFieldControls(); tNumBases = GetNumRegisteredSecretBases(); if (tNumBases != 0) @@ -977,7 +977,7 @@ static void RegistryMenu_OnCursorMove(s32 unused, bool8 flag, struct ListMenu *m static void FinalizeRegistryMenu(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; SetStandardWindowBorderStyle(tMainWindowId, FALSE); tListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, tScrollOffset, tSelectedRow); AddRegistryMenuScrollArrows(taskId); @@ -986,13 +986,13 @@ static void FinalizeRegistryMenu(u8 taskId) static void AddRegistryMenuScrollArrows(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; tArrowTaskId = AddScrollIndicatorArrowPairParameterized(SCROLL_ARROW_UP, 188, 12, 148, tNumBases - tMaxShownItems, TAG_SCROLL_ARROW, TAG_SCROLL_ARROW, &tScrollOffset); } static void HandleRegistryMenuInput(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; s32 input = ListMenu_ProcessInput(tListTaskId); ListMenuGetScrollAndRow(tListTaskId, &tScrollOffset, &tSelectedRow); @@ -1022,7 +1022,7 @@ static void HandleRegistryMenuInput(u8 taskId) static void ShowRegistryMenuActions(u8 taskId) { struct WindowTemplate template; - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; RemoveScrollIndicatorArrowPair(tArrowTaskId); template = sRegistryWindowTemplates[1]; template.width = GetMaxWidthInMenuTable(sRegistryMenuActions, 2); @@ -1054,7 +1054,7 @@ static void HandleRegistryMenuActionsInput(u8 taskId) static void ShowRegistryMenuDeleteConfirmation(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; ClearStdWindowAndFrame(tMainWindowId, FALSE); ClearStdWindowAndFrame(tActionWindowId, FALSE); ClearWindowTilemap(tMainWindowId); @@ -1074,7 +1074,7 @@ static void ShowRegistryMenuDeleteYesNo(u8 taskId) void DeleteRegistry_Yes_Callback(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; ClearDialogWindowAndFrame(0, FALSE); DestroyListMenuTask(tListTaskId, &tScrollOffset, &tSelectedRow); gSaveBlock1Ptr->secretBases[tSelectedBaseId].registryStatus = UNREGISTERED; @@ -1091,7 +1091,7 @@ static void DeleteRegistry_Yes(u8 taskId) static void DeleteRegistry_No(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; ClearDialogWindowAndFrame(0, FALSE); DestroyListMenuTask(tListTaskId, &tScrollOffset, &tSelectedRow); FinalizeRegistryMenu(taskId); @@ -1100,7 +1100,7 @@ static void DeleteRegistry_No(u8 taskId) static void ReturnToMainRegistryMenu(u8 taskId) { - s16 *data = gTasks[taskId].data; + u16 *data = (u16*) gTasks[taskId].data; AddRegistryMenuScrollArrows(taskId); ClearStdWindowAndFrame(tActionWindowId, FALSE); ClearWindowTilemap(tActionWindowId); diff --git a/src/siirtc.c b/src/siirtc.c index 0e598f7172..1536aecb42 100644 --- a/src/siirtc.c +++ b/src/siirtc.c @@ -66,7 +66,6 @@ extern vu16 GPIOPortDirection; -static u16 sDummy; // unused variable static bool8 sLocked; static int WriteCommand(u8 value); diff --git a/src/slot_machine.c b/src/slot_machine.c index 5ae0f9f1d5..d61a5bcb92 100644 --- a/src/slot_machine.c +++ b/src/slot_machine.c @@ -1116,7 +1116,7 @@ static void PlaySlotMachine_Internal(u8 machineId, MainCallback exitCallback) { struct Task *task = &gTasks[CreateTask(SlotMachineDummyTask, 0xFF)]; task->tMachineId = machineId; - StoreWordInTwoHalfwords(&task->tExitCallback, (intptr_t)exitCallback); + StoreWordInTwoHalfwords((u16*) &task->tExitCallback, (intptr_t)exitCallback); } // Extracts and assigns machineId and exit callback from task. diff --git a/src/start_menu.c b/src/start_menu.c index 7924520fa6..f90fe46d9c 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -311,11 +311,10 @@ static void BuildStartMenuActions(void) } else { - #if DEBUG_OVERWORLD_MENU == TRUE && DEBUG_OVERWORLD_IN_MENU == TRUE - BuildDebugStartMenu(); - #else - BuildNormalStartMenu(); - #endif + if (DEBUG_OVERWORLD_MENU == TRUE && DEBUG_OVERWORLD_IN_MENU == TRUE) + BuildDebugStartMenu(); + else + BuildNormalStartMenu(); } } diff --git a/src/tv.c b/src/tv.c index a3e56e165d..d39464bcc0 100644 --- a/src/tv.c +++ b/src/tv.c @@ -128,7 +128,6 @@ static void TVShowDone(void); static void InterviewAfter_FanClubLetter(void); static void InterviewAfter_RecentHappenings(void); static void InterviewAfter_PkmnFanClubOpinions(void); -static void InterviewAfter_Dummy(void); static void InterviewAfter_BravoTrainerPokemonProfile(void); static void InterviewAfter_BravoTrainerBattleTowerProfile(void); static void InterviewAfter_ContestLiveUpdates(void); @@ -1078,7 +1077,6 @@ void InterviewAfter(void) InterviewAfter_PkmnFanClubOpinions(); break; case TVSHOW_DUMMY: - InterviewAfter_Dummy(); break; case TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE: InterviewAfter_BravoTrainerPokemonProfile(); @@ -1620,11 +1618,6 @@ static void InterviewAfter_PkmnFanClubOpinions(void) show->fanclubOpinions.pokemonNameLanguage = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_LANGUAGE); } -static void InterviewAfter_Dummy(void) -{ - TVShow *show = &gSaveBlock1Ptr->tvShows[sCurTVShowSlot]; -} - static void TryStartRandomMassOutbreak(void) { u8 i; diff --git a/src/union_room.c b/src/union_room.c index a9a671a9ef..51f96c8adc 100644 --- a/src/union_room.c +++ b/src/union_room.c @@ -203,7 +203,6 @@ static EWRAM_DATA union struct WirelessLink_Group *group; struct WirelessLink_URoom *uRoom; } sWirelessLinkMain = {}; -static EWRAM_DATA u32 sUnused = 0; EWRAM_DATA struct RfuGameCompatibilityData gRfuPartnerCompatibilityData = {}; EWRAM_DATA u16 gUnionRoomOfferedSpecies = 0; EWRAM_DATA u8 gUnionRoomRequestedMonType = 0; @@ -4066,7 +4065,7 @@ static s32 UnionRoomGetPlayerInteractionResponse(struct RfuPlayerList *list, boo CopyAndTranslatePlayerName(gStringVar1, player); if (overrideGender) { - playerGender = (player->rfu.data.compatibility.playerTrainerId[overrideGender + 1] >> 3) & 1; + playerGender = (player->rfu.data.compatibility.playerTrainerId[overrideGender - 1] >> 3) & 1; } switch (player->rfu.data.activity & 0x3F) { diff --git a/src/union_room_chat.c b/src/union_room_chat.c index a109624508..c54d49db94 100644 --- a/src/union_room_chat.c +++ b/src/union_room_chat.c @@ -1953,7 +1953,7 @@ static u8 *GetLimitedMessageStartPtr(void) for (i = 0; i < numChars; i++) { if (*str == CHAR_EXTRA_SYMBOL) - *str++; + str++; str++; } @@ -3115,9 +3115,6 @@ static void DrawKeyboardWindow(void) static void LoadTextEntryWindow(void) { int i; - u8 unused[2]; - unused[0] = 0; - unused[1] = 0xFF; // Pointless, cleared below. The tiles are nonsense anyway, see LoadChatWindowGfx. for (i = 0; i < MAX_MESSAGE_LENGTH; i++) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 6016e08e69..3162c5ed23 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -418,10 +418,7 @@ static u8 PickWildMonNature(void) // check synchronize for a pokemon with the same ability if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG) && GetMonAbility(&gPlayerParty[0]) == ABILITY_SYNCHRONIZE - #if B_SYNCHRONIZE_NATURE <= GEN_7 - && (Random() % 2 == 0) - #endif - ) + && (B_SYNCHRONIZE_NATURE >= GEN_8 || Random() % 2 == 0)) { return GetMonData(&gPlayerParty[0], MON_DATA_PERSONALITY) % NUM_NATURES; } @@ -1114,20 +1111,13 @@ static void ApplyCleanseTagEncounterRateMod(u32 *encRate) bool8 TryDoDoubleWildBattle(void) { -#if B_DOUBLE_WILD_REQUIRE_2_MONS == TRUE - if (GetSafariZoneFlag() || GetMonsStateToDoubles() != PLAYER_HAS_TWO_USABLE_MONS) -#else - if (GetSafariZoneFlag()) -#endif + if (GetSafariZoneFlag() + || (B_DOUBLE_WILD_REQUIRE_2_MONS == TRUE && GetMonsStateToDoubles() != PLAYER_HAS_TWO_USABLE_MONS)) return FALSE; -#if B_FLAG_FORCE_DOUBLE_WILD != 0 - else if (FlagGet(B_FLAG_FORCE_DOUBLE_WILD)) + else if (B_FLAG_FORCE_DOUBLE_WILD != 0 && FlagGet(B_FLAG_FORCE_DOUBLE_WILD)) return TRUE; -#endif -#if B_DOUBLE_WILD_CHANCE != 0 - else if ((Random() % 100) + 1 <= B_DOUBLE_WILD_CHANCE) + else if (B_DOUBLE_WILD_CHANCE != 0 && ((Random() % 100) + 1 <= B_DOUBLE_WILD_CHANCE)) return TRUE; -#endif return FALSE; } diff --git a/test/battle/ability/beast_boost.c b/test/battle/ability/beast_boost.c new file mode 100644 index 0000000000..da63bf9c4d --- /dev/null +++ b/test/battle/ability/beast_boost.c @@ -0,0 +1,43 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(P_GEN_7_POKEMON == TRUE); // Because only Ultra Beasts have this ability +} + +SINGLE_BATTLE_TEST("Beast Boost boosts the most proficient stat when knocking out a target") +{ + u8 stats[] = {1, 1, 1, 1, 1}; + PARAMETRIZE { stats[0] = 255; } + PARAMETRIZE { stats[1] = 255; } + PARAMETRIZE { stats[2] = 255; } + PARAMETRIZE { stats[3] = 255; } + PARAMETRIZE { stats[4] = 255; } + GIVEN { + PLAYER(SPECIES_NIHILEGO) { Ability(ABILITY_BEAST_BOOST); Attack(stats[0]); Defense(stats[1]); SpAttack(stats[2]); SpDefense(stats[3]); Speed(stats[4]); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); SEND_OUT(opponent, 1); } + } SCENE { + ABILITY_POPUP(player, ABILITY_BEAST_BOOST); + switch(i) { + case 0: + MESSAGE("Nihilego's Beast Boost raised its Attack!"); + break; + case 1: + MESSAGE("Nihilego's Beast Boost raised its Defense!"); + break; + case 2: + MESSAGE("Nihilego's Beast Boost raised its Sp. Atk!"); + break; + case 3: + MESSAGE("Nihilego's Beast Boost raised its Sp. Def!"); + break; + case 4: + MESSAGE("Nihilego's Beast Boost raised its Speed!"); + break; + } + } +} diff --git a/test/battle/ability/defeatist.c b/test/battle/ability/defeatist.c new file mode 100644 index 0000000000..820c7da355 --- /dev/null +++ b/test/battle/ability/defeatist.c @@ -0,0 +1,46 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_ECHOED_VOICE].split == SPLIT_SPECIAL); +} + +SINGLE_BATTLE_TEST("Defeatist halves Attack when HP <= 50%", s16 damage) +{ + u32 hp; + PARAMETRIZE { hp = 400; } + PARAMETRIZE { hp = 200; } + GIVEN { + PLAYER(SPECIES_ARCHEN) { Ability(ABILITY_DEFEATIST); HP(hp), MaxHP(400);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Defeatist halves Special Attack when HP <= 50%", s16 damage) +{ + u32 hp; + PARAMETRIZE { hp = 400; } + PARAMETRIZE { hp = 200; } + GIVEN { + PLAYER(SPECIES_ARCHEN) { Ability(ABILITY_DEFEATIST); HP(hp), MaxHP(400);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ECHOED_VOICE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ECHOED_VOICE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} diff --git a/test/battle/ability/dragons_maw.c b/test/battle/ability/dragons_maw.c new file mode 100644 index 0000000000..af633d81d0 --- /dev/null +++ b/test/battle/ability/dragons_maw.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Dragon's Maw increases Dragon-type move damage", s16 damage) +{ + u32 move; + u16 ability; + + PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_KLUTZ; } + PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_DRAGONS_MAW; } + PARAMETRIZE { move = MOVE_DRAGON_CLAW; ability = ABILITY_KLUTZ; } + PARAMETRIZE { move = MOVE_DRAGON_CLAW; ability = ABILITY_DRAGONS_MAW; } + PARAMETRIZE { move = MOVE_DRAGON_BREATH; ability = ABILITY_KLUTZ; } + PARAMETRIZE { move = MOVE_DRAGON_BREATH; ability = ABILITY_DRAGONS_MAW; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].type != TYPE_DRAGON); + ASSUME(gBattleMoves[MOVE_DRAGON_CLAW].type == TYPE_DRAGON); + ASSUME(gBattleMoves[MOVE_DRAGON_BREATH].type == TYPE_DRAGON); + ASSUME(gBattleMoves[MOVE_DRAGON_CLAW].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_DRAGON_BREATH].split == SPLIT_SPECIAL); + PLAYER(SPECIES_REGIDRAGO) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Dragon Claw should be affected + EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Dragon Breath should be affected + } +} diff --git a/test/battle/ability/earth_eater.c b/test/battle/ability/earth_eater.c new file mode 100644 index 0000000000..a0ba2b54dd --- /dev/null +++ b/test/battle/ability/earth_eater.c @@ -0,0 +1,46 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Earth Eater heals 25% when hit by ground type moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_MUD_SLAP].type == TYPE_GROUND); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MUD_SLAP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_EARTH_EATER); + HP_BAR(player, damage: -25); + MESSAGE("Wobbuffet restored HP using its Earth Eater!"); + } +} + +SINGLE_BATTLE_TEST("Earth Eater does not activate if protected") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_MUD_SLAP].type == TYPE_GROUND); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); } + } SCENE { + NONE_OF { ABILITY_POPUP(player, ABILITY_EARTH_EATER); HP_BAR(player); MESSAGE("Wobbuffet restored HP using its Earth Eater!"); } + } +} + +SINGLE_BATTLE_TEST("Earth Eater activates on status moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SAND_ATTACK].type == TYPE_GROUND); + ASSUME(gBattleMoves[MOVE_SAND_ATTACK].split == SPLIT_STATUS); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_EARTH_EATER); HP(1); MaxHP(100); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SAND_ATTACK); } + } SCENE { + ABILITY_POPUP(player, ABILITY_EARTH_EATER); + HP_BAR(player, damage: -25); + MESSAGE("Wobbuffet restored HP using its Earth Eater!"); + } +} diff --git a/test/battle/ability/gale_wings.c b/test/battle/ability/gale_wings.c new file mode 100644 index 0000000000..d44bfb4d4e --- /dev/null +++ b/test/battle/ability/gale_wings.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP") +{ + u16 hp; + PARAMETRIZE { hp = 100; } + PARAMETRIZE { hp = 99; } + GIVEN { + ASSUME(B_GALE_WINGS >= GEN_7); + ASSUME(gBattleMoves[MOVE_AERIAL_ACE].type == TYPE_FLYING); + PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(hp); MaxHP(100); Speed(1);} + OPPONENT(SPECIES_WOBBUFFET) { Speed(100);}; + } WHEN { + TURN { MOVE(player, MOVE_AERIAL_ACE); } + } SCENE { + if (hp == 100) { + MESSAGE("Talonflame used Aerial Ace!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } + else { + MESSAGE("Foe Wobbuffet used Celebrate!"); + MESSAGE("Talonflame used Aerial Ace!"); + } + } +} + +SINGLE_BATTLE_TEST("Gale Wings only grants priority to Flying-type moves") +{ + u32 move; + PARAMETRIZE { move = MOVE_AERIAL_ACE; } + PARAMETRIZE { move = MOVE_FLARE_BLITZ; } + GIVEN { + ASSUME(B_GALE_WINGS >= GEN_7); + ASSUME(gBattleMoves[MOVE_AERIAL_ACE].type == TYPE_FLYING); + ASSUME(gBattleMoves[MOVE_FLARE_BLITZ].type == TYPE_FIRE); + PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(100); MaxHP(100); Speed(1);} + OPPONENT(SPECIES_WOBBUFFET) { Speed(100);}; + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + if (move == MOVE_AERIAL_ACE) { + MESSAGE("Talonflame used Aerial Ace!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } + else { + MESSAGE("Foe Wobbuffet used Celebrate!"); + MESSAGE("Talonflame used Flare Blitz!"); + } + } +} + +TO_DO_BATTLE_TEST("Gale Wings doesn't increase priority of Flying-type Hidden Power, Natural Gift, Judgment or Tera Blast"); diff --git a/test/battle/ability/ice_scales.c b/test/battle/ability/ice_scales.c new file mode 100644 index 0000000000..2bbe7dab05 --- /dev/null +++ b/test/battle/ability/ice_scales.c @@ -0,0 +1,35 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(P_GEN_8_POKEMON == TRUE); // Because only Frosmoth can have this ability. +} + +SINGLE_BATTLE_TEST("Ice Scales halves the damage from special moves", s16 damage) +{ + u32 move; + u16 ability; + PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYCHIC; } + PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_PSYCHIC; } + PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_PSYSHOCK; } + PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_PSYSHOCK; } + PARAMETRIZE { ability = ABILITY_SHIELD_DUST; move = MOVE_TACKLE; } + PARAMETRIZE { ability = ABILITY_ICE_SCALES; move = MOVE_TACKLE; } + GIVEN { + ASSUME(gBattleMoves[MOVE_PSYCHIC].split == SPLIT_SPECIAL); + ASSUME(gBattleMoves[MOVE_PSYSHOCK].split == SPLIT_SPECIAL); + ASSUME(gBattleMoves[MOVE_PSYSHOCK].effect == EFFECT_PSYSHOCK); + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_FROSMOTH) { Ability(ability); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); // Ice Scales halves the damage of Psychic + EXPECT_MUL_EQ(results[2].damage, UQ_4_12(0.5), results[3].damage); // Ice Scales halves the damage of Psyshock, even if it targets Defense + EXPECT_EQ(results[4].damage, results[5].damage); // Ice Scales doesn't affect the damage of physical moves + } +} diff --git a/test/battle/ability/leaf_guard.c b/test/battle/ability/leaf_guard.c index 2c052b5a67..66eb6fc186 100644 --- a/test/battle/ability/leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -4,11 +4,12 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") { u32 move; - PARAMETRIZE { move = MOVE_WILL_O_WISP; } - PARAMETRIZE { move = MOVE_HYPNOSIS; } - PARAMETRIZE { move = MOVE_THUNDER_WAVE; } - PARAMETRIZE { move = MOVE_TOXIC; } - PARAMETRIZE { move = MOVE_POWDER_SNOW; } + u16 status; + PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; } + PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; } + PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; } + PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; } + PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; } GIVEN { ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP); @@ -20,39 +21,14 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") } WHEN { TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); } } SCENE { - switch (move) - { - case MOVE_WILL_O_WISP: - MESSAGE("Foe Wobbuffet used Will-o-Wisp!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, opponent); - ABILITY_POPUP(player, ABILITY_LEAF_GUARD); - MESSAGE("It doesn't affect Leafeon…"); - break; - case MOVE_HYPNOSIS: - MESSAGE("Foe Wobbuffet used Hypnosis!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, opponent); - ABILITY_POPUP(player, ABILITY_LEAF_GUARD); - MESSAGE("It doesn't affect Leafeon…"); - break; - case MOVE_THUNDER_WAVE: - MESSAGE("Foe Wobbuffet used Thunder Wave!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_WAVE, opponent); - ABILITY_POPUP(player, ABILITY_LEAF_GUARD); - MESSAGE("It doesn't affect Leafeon…"); - break; - case MOVE_TOXIC: - MESSAGE("Foe Wobbuffet used Toxic!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent); - ABILITY_POPUP(player, ABILITY_LEAF_GUARD); - MESSAGE("It doesn't affect Leafeon…"); - break; - case MOVE_POWDER_SNOW: - MESSAGE("Foe Wobbuffet used Powder Snow!"); - ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER_SNOW, opponent); - MESSAGE("It's super effective!"); - break; + if (move != MOVE_POWDER_SNOW) { + NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ABILITY_POPUP(player, ABILITY_LEAF_GUARD); + MESSAGE("It doesn't affect Leafeon…"); + } else { + NOT ABILITY_POPUP(player, ABILITY_LEAF_GUARD); } - NONE_OF { STATUS_ICON(player, status1: TRUE); } + NOT STATUS_ICON(player, status); } } diff --git a/test/battle/ability/neuroforce.c b/test/battle/ability/neuroforce.c new file mode 100644 index 0000000000..df15bd4511 --- /dev/null +++ b/test/battle/ability/neuroforce.c @@ -0,0 +1,30 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(P_GEN_7_POKEMON == TRUE); // Because only Necrozma can have this ability. +} + +SINGLE_BATTLE_TEST("Neuroforce increases the strength of super-effective moves by 25%", s16 damage) +{ + u32 move; + u16 ability; + PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_SHADOW_BALL; } + PARAMETRIZE { ability = ABILITY_KLUTZ; move = MOVE_SHADOW_BALL; } + PARAMETRIZE { ability = ABILITY_NEUROFORCE; move = MOVE_TACKLE; } + PARAMETRIZE { ability = ABILITY_KLUTZ; move = MOVE_TACKLE; } + GIVEN { + ASSUME(gBattleMoves[MOVE_SHADOW_BALL].type == TYPE_GHOST); + ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL); + PLAYER(SPECIES_NECROZMA_ULTRA) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[1].damage, UQ_4_12(1.25), results[0].damage); // Neuroforce boosts the power of super-effective moves + EXPECT_EQ(results[2].damage, results[3].damage); // Neuroforce doesn't boost the power of other moves + } +} diff --git a/test/battle/ability/opportunist.c b/test/battle/ability/opportunist.c new file mode 100644 index 0000000000..f344bd026f --- /dev/null +++ b/test/battle/ability/opportunist.c @@ -0,0 +1,106 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Opportunist only copies foe's positive stat changes in a turn", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_NONE; } + PARAMETRIZE { ability = ABILITY_OPPORTUNIST; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SHELL_SMASH); } + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + if (ability == ABILITY_NONE) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_SMASH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + } else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + } + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + // stat boosts should be the same + EXPECT_EQ(player->statStages[STAT_ATK], opponent->statStages[STAT_ATK]); + EXPECT_EQ(player->statStages[STAT_SPATK], opponent->statStages[STAT_SPATK]); + EXPECT_EQ(player->statStages[STAT_SPEED], opponent->statStages[STAT_SPEED]); + // opportunist should not copy stat drops from shell smash + EXPECT_LT(player->statStages[STAT_DEF], opponent->statStages[STAT_DEF]); + EXPECT_LT(player->statStages[STAT_SPDEF], opponent->statStages[STAT_SPDEF]); + } +} + + +DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimidate against Contrary foe in a double battle", s16 damageLeft, s16 damageRight) +{ + u32 abilityLeft, abilityRight; + + PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_CONTRARY; } + PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_TANGLED_FEET; } + PARAMETRIZE { abilityLeft = ABILITY_CONTRARY; abilityRight = ABILITY_TANGLED_FEET; } + PARAMETRIZE { abilityLeft = ABILITY_TANGLED_FEET; abilityRight = ABILITY_CONTRARY; } + + GIVEN { + PLAYER(SPECIES_MIGHTYENA) { Ability(ABILITY_INTIMIDATE); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_OPPORTUNIST); } + OPPONENT(SPECIES_SPINDA) { Ability(abilityLeft); } + OPPONENT(SPECIES_SPINDA) { Ability(abilityRight); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft); MOVE(opponentRight, MOVE_TACKLE, target: playerRight); } + } SCENE { + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + if (abilityLeft == ABILITY_CONTRARY) { + ABILITY_POPUP(opponentLeft, ABILITY_CONTRARY); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Foe Spinda's Attack rose!"); + } else { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Mightyena's Intimidate cuts Foe Spinda's attack!"); + } + if (abilityRight == ABILITY_CONTRARY) { + ABILITY_POPUP(opponentRight, ABILITY_CONTRARY); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Foe Spinda's Attack rose!"); + } else { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Mightyena's Intimidate cuts Foe Spinda's attack!"); + } + + if ((abilityLeft == ABILITY_CONTRARY && abilityRight != ABILITY_CONTRARY) + || (abilityLeft != ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY)) { + ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST); + MESSAGE("Wobbuffet copied its opponent's stat changes!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Wobbuffet's Attack rose!"); + } else if (abilityLeft == ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY) { + ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST); + MESSAGE("Wobbuffet copied its opponent's stat changes!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Wobbuffet's Attack sharply rose!"); + } + + HP_BAR(playerLeft, captureDamage: &results[i].damageLeft); + HP_BAR(playerRight, captureDamage: &results[i].damageRight); + } THEN { + EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + (abilityLeft == ABILITY_CONTRARY ? 1 : - 1)); + EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + (abilityRight == ABILITY_CONTRARY ? 1 : - 1)); + if ((abilityLeft == ABILITY_CONTRARY && abilityRight != ABILITY_CONTRARY) + || (abilityLeft != ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY)) { + EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } else if (abilityLeft == ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY) { + EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + } + } + FINALLY { + EXPECT_MUL_EQ(results[1].damageLeft, Q_4_12(2.25), results[0].damageLeft); + EXPECT_MUL_EQ(results[1].damageRight, Q_4_12(2.25), results[0].damageRight); + } +} + +TO_DO_BATTLE_TEST("Opportunist doesn't copy ally stat increases"); +TO_DO_BATTLE_TEST("Opportunist doesn't copy foe stat increases gained via Opportunist"); +TO_DO_BATTLE_TEST("Opportunist copies foe stat increased gained via Swagger and Flatter"); diff --git a/test/battle/ability/poison_heal.c b/test/battle/ability/poison_heal.c new file mode 100644 index 0000000000..2ee7620c62 --- /dev/null +++ b/test/battle/ability/poison_heal.c @@ -0,0 +1,77 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Poison Heal heals from (Toxic) Poison damage") +{ + u8 status; + PARAMETRIZE { status = STATUS1_POISON; } + PARAMETRIZE { status = STATUS1_TOXIC_POISON; } + + GIVEN { + PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(status); HP(1), MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_POISON_HEAL); + MESSAGE("The poisoning healed Shroomish a little bit!"); + HP_BAR(player, damage: -50); + } +} + +SINGLE_BATTLE_TEST("Poison Heal heals from Toxic Poison damage are constant") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(STATUS1_TOXIC_POISON); HP(1), MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { } + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_POISON_HEAL); + MESSAGE("The poisoning healed Shroomish a little bit!"); + HP_BAR(player, captureDamage: &turnOneHit); + + ABILITY_POPUP(player, ABILITY_POISON_HEAL); + MESSAGE("The poisoning healed Shroomish a little bit!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Poison Heal does not heal or cause damage when under Heal Block") +{ + GIVEN { + PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(STATUS1_POISON); HP(1), MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_HEAL_BLOCK); } + } SCENE { + NONE_OF { + ABILITY_POPUP(player, ABILITY_POISON_HEAL); + MESSAGE("The poisoning healed Shroomish a little bit!"); + HP_BAR(player, damage: -50); + } + } +} + +SINGLE_BATTLE_TEST("Poison Heal activates before Toxic Orb") +{ + GIVEN { + PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Item(ITEM_TOXIC_ORB); HP(1), MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + NONE_OF { + ABILITY_POPUP(player, ABILITY_POISON_HEAL); + MESSAGE("The poisoning healed Shroomish a little bit!"); + HP_BAR(player, damage: -50); + HP_BAR(player, damage: 50); + } + } +} diff --git a/test/battle/ability/protosynthesis.c b/test/battle/ability/protosynthesis.c index 0ed74d4f65..0d53141c34 100644 --- a/test/battle/ability/protosynthesis.c +++ b/test/battle/ability/protosynthesis.c @@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Protosynthesis boosts either Attack or Special Attack, not b { u16 species; u32 move; - u16 damage[2]; + s16 damage[2]; PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; } PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; } @@ -58,7 +58,7 @@ SINGLE_BATTLE_TEST("Protosynthesis either boosts Defense or Special Defense, not { u16 species; u32 move; - u16 damage[2]; + s16 damage[2]; PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; } PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; } diff --git a/test/battle/ability/purifying_salt.c b/test/battle/ability/purifying_salt.c new file mode 100644 index 0000000000..0a53dbc61b --- /dev/null +++ b/test/battle/ability/purifying_salt.c @@ -0,0 +1,65 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Purifying Salt halves damage from Ghost-type moves", s16 damage) +{ + u16 ability; + PARAMETRIZE { ability = ABILITY_STURDY; } + PARAMETRIZE { ability = ABILITY_PURIFYING_SALT; } + GIVEN { + ASSUME(gBattleMoves[MOVE_SHADOW_BALL].type == TYPE_GHOST); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SHADOW_BALL); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Purifying Salt makes Rest fail") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_PURIFYING_SALT); HP(1); MaxHP(100);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REST); } + } SCENE { + NONE_OF { + MESSAGE("Wobbuffet went to sleep!"); + } + } +} + +SINGLE_BATTLE_TEST("Purifying Salt grants immunity to status effects") +{ + u32 move; + u16 status; + PARAMETRIZE { move = MOVE_WILL_O_WISP; status = STATUS1_BURN; } + PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; } + PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; } + PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; } + PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; } + GIVEN { + ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); + ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP); + ASSUME(gBattleMoves[MOVE_THUNDER_WAVE].effect == EFFECT_PARALYZE); + ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC); + ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_PURIFYING_SALT); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + if (move != MOVE_POWDER_SNOW) { + NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ABILITY_POPUP(player, ABILITY_PURIFYING_SALT); + MESSAGE("It doesn't affect Wobbuffet…"); + } else { + NOT ABILITY_POPUP(player, ABILITY_PURIFYING_SALT); + } + NOT STATUS_ICON(player, status); + } +} diff --git a/test/battle/ability/quark_drive.c b/test/battle/ability/quark_drive.c index bce6795cae..d9c7cf7307 100644 --- a/test/battle/ability/quark_drive.c +++ b/test/battle/ability/quark_drive.c @@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Quark Drive boosts either Attack or Special Attack, not both { u16 species; u32 move; - u16 damage[2]; + s16 damage[2]; PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; } PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; } @@ -58,7 +58,7 @@ SINGLE_BATTLE_TEST("Quark Drive either boosts Defense or Special Defense, not bo { u16 species; u32 move; - u16 damage[2]; + s16 damage[2]; PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; } PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; } diff --git a/test/battle/ability/quick_draw.c b/test/battle/ability/quick_draw.c new file mode 100644 index 0000000000..7dd918e5d3 --- /dev/null +++ b/test/battle/ability/quick_draw.c @@ -0,0 +1,17 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Quick Draw has a 30% chance of going first") +{ + PASSES_RANDOMLY(3, 10, RNG_QUICK_DRAW); + GIVEN { + PLAYER(SPECIES_SLOWBRO_GALARIAN) { Ability(ABILITY_QUICK_DRAW); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_QUICK_DRAW); + MESSAGE("Slowbro used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } +} diff --git a/test/battle/ability/rivalry.c b/test/battle/ability/rivalry.c new file mode 100644 index 0000000000..a7f4216ce0 --- /dev/null +++ b/test/battle/ability/rivalry.c @@ -0,0 +1,99 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE); + ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE); + ASSUME(gSpeciesInfo[SPECIES_PORYGON].genderRatio == MON_GENDERLESS); +} + +SINGLE_BATTLE_TEST("Rivalry increases power by x1.25 towards Pokémon of the same gender", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species) { Ability(ability); } + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.25), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Rivalry decreases power by x0.75 towards Pokémon of different gender", s16 damage) +{ + u16 species1, species2, ability; + PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species1 = SPECIES_NIDOKING; species2 = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species1 = SPECIES_NIDOQUEEN; species2 = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species1 = SPECIES_NIDOQUEEN; species2 = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species1) { Ability(ability); } + OPPONENT(species2); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.75), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the attacker is genderless", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_PORYGON].abilities[0] == ABILITY_TRACE); + PLAYER(SPECIES_PORYGON) { Ability(ABILITY_TRACE); } // No genderless mon naturally gets Rivalry + OPPONENT(species) { Ability(ability); }; + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT(results[0].damage == results[1].damage); + EXPECT(results[2].damage == results[3].damage); + } +} + + +SINGLE_BATTLE_TEST("Rivalry doesn't modify power if the target is genderless", s16 damage) +{ + u16 species, ability; + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOKING; ability = ABILITY_RIVALRY; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_POISON_POINT; } + PARAMETRIZE { species = SPECIES_NIDOQUEEN; ability = ABILITY_RIVALRY; } + + GIVEN { + PLAYER(species) { Ability(ability); }; + OPPONENT(SPECIES_PORYGON); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT(results[0].damage == results[1].damage); + EXPECT(results[2].damage == results[3].damage); + } +} diff --git a/test/battle/ability/rocky_payload.c b/test/battle/ability/rocky_payload.c new file mode 100644 index 0000000000..498b09c9d9 --- /dev/null +++ b/test/battle/ability/rocky_payload.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Rocky Payload increases Rock-type move damage", s16 damage) +{ + u32 move; + u16 ability; + + PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_BIG_PECKS; } + PARAMETRIZE { move = MOVE_TACKLE; ability = ABILITY_ROCKY_PAYLOAD; } + PARAMETRIZE { move = MOVE_ROCK_THROW; ability = ABILITY_BIG_PECKS; } + PARAMETRIZE { move = MOVE_ROCK_THROW; ability = ABILITY_ROCKY_PAYLOAD; } + PARAMETRIZE { move = MOVE_POWER_GEM; ability = ABILITY_BIG_PECKS; } + PARAMETRIZE { move = MOVE_POWER_GEM; ability = ABILITY_ROCKY_PAYLOAD; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].type != TYPE_ROCK); + ASSUME(gBattleMoves[MOVE_ROCK_THROW].type == TYPE_ROCK); + ASSUME(gBattleMoves[MOVE_POWER_GEM].type == TYPE_ROCK); + ASSUME(gBattleMoves[MOVE_ROCK_THROW].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_POWER_GEM].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Rock Throw should be affected + EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Power Gem should be affected + } +} diff --git a/test/battle/ability/sap_sipper.c b/test/battle/ability/sap_sipper.c new file mode 100644 index 0000000000..89ec422491 --- /dev/null +++ b/test/battle/ability/sap_sipper.c @@ -0,0 +1,55 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Sap Sipper negates damage from Grass-type moves") +{ + GIVEN { + PLAYER(SPECIES_MARILL) { Ability(ABILITY_SAP_SIPPER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_VINE_WHIP); } + } SCENE { + NONE_OF { HP_BAR(player); } + } +} + +SINGLE_BATTLE_TEST("Sap Sipper negates effects from Grass-type moves") +{ + GIVEN { + PLAYER(SPECIES_MARILL) { Ability(ABILITY_SAP_SIPPER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SPORE); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); } + NONE_OF { STATUS_ICON(player, sleep: TRUE); } + } +} + +SINGLE_BATTLE_TEST("Sap Sipper increases Attack by one stage when hit by a Grass-type move") +{ + GIVEN { + PLAYER(SPECIES_MARILL) { Ability(ABILITY_SAP_SIPPER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_VINE_WHIP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_SAP_SIPPER); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Marill's Attack rose!"); + } +} + +SINGLE_BATTLE_TEST("Sap Sipper does not increase Attack if already maxed") +{ + GIVEN { + PLAYER(SPECIES_MARILL) { Ability(ABILITY_SAP_SIPPER); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + } WHEN { + TURN { MOVE(player, MOVE_BELLY_DRUM); MOVE(opponent, MOVE_VINE_WHIP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_SAP_SIPPER); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + NONE_OF { MESSAGE("Marill's Attack rose!"); } + } +} diff --git a/test/battle/ability/seed_sower.c b/test/battle/ability/seed_sower.c index 706e43ede5..609077cca2 100644 --- a/test/battle/ability/seed_sower.c +++ b/test/battle/ability/seed_sower.c @@ -29,10 +29,10 @@ SINGLE_BATTLE_TEST("Seed Sower sets up Grassy Terrain when hit by an attack") DOUBLE_BATTLE_TEST("Multi-target moves hit correct battlers after Seed Sower is triggered") // #2796 { u32 j, k, l; - u16 usedMove; + u16 usedMove = MOVE_NONE; static const u16 moves[] = {MOVE_HYPER_VOICE, MOVE_SURF}; - u16 abilities[MAX_BATTLERS_COUNT]; - u8 attacker; + u16 abilities[MAX_BATTLERS_COUNT] = {0}; + u8 attacker = 0; for (j = 0; j < ARRAY_COUNT(moves); j++) { diff --git a/test/battle/ability/sharpness.c b/test/battle/ability/sharpness.c new file mode 100644 index 0000000000..6360c4f8b3 --- /dev/null +++ b/test/battle/ability/sharpness.c @@ -0,0 +1,29 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(P_GEN_4_POKEMON == TRUE); // Because no = GEN_9 + EXPECT_MUL_EQ(results[2].damage, Q_4_12(5325 / 4096), results[3].damage); // Wild Charge should be affected + EXPECT_MUL_EQ(results[4].damage, Q_4_12(5325 / 4096), results[5].damage); // Thunder Shock should be affected + #else + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Wild Charge should be affected + EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Thunder Shock should be affected + #endif + } +} diff --git a/test/battle/ability/wind_power.c b/test/battle/ability/wind_power.c index 4616a69fb7..ad7d63a0e7 100644 --- a/test/battle/ability/wind_power.c +++ b/test/battle/ability/wind_power.c @@ -107,7 +107,7 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind mo DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 2/3 target move") { - u16 move, abilityLeft, abilityRight; + u16 abilityLeft, abilityRight; PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER;} PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } diff --git a/test/battle/ai.c b/test/battle/ai.c index 47308df4de..fd91634db9 100644 --- a/test/battle/ai.c +++ b/test/battle/ai.c @@ -142,10 +142,9 @@ AI_SINGLE_BATTLE_TEST("AI prefers moves which deal more damage instead of moves { u8 turns = 0; u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; - u16 expectedMove, abilityAtk, abilityDef, expectedMove2; + u16 expectedMove, abilityAtk, abilityDef; abilityAtk = ABILITY_NONE; - expectedMove2 = MOVE_NONE; // Scald and Poison Jab take 3 hits, Waterfall takes 2. PARAMETRIZE { move1 = MOVE_WATERFALL; move2 = MOVE_SCALD; move3 = MOVE_POISON_JAB; move4 = MOVE_WATER_GUN; expectedMove = MOVE_WATERFALL; turns = 2; } @@ -195,7 +194,7 @@ AI_SINGLE_BATTLE_TEST("AI prefers Earthquake over Drill Run if both require the AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking into account accuracy and move effect") { u16 move1 = MOVE_NONE, move2 = MOVE_NONE, move3 = MOVE_NONE, move4 = MOVE_NONE; - u16 expectedMove, abilityAtk = ABILITY_NONE, abilityDef; + u16 expectedMove, abilityAtk = ABILITY_NONE; u16 expectedMove2 = MOVE_NONE; // Psychic is not very effective, but always hits. Solarbeam requires a charging turn, Double Edge has recoil and Focus Blast can miss; @@ -288,7 +287,7 @@ AI_DOUBLE_BATTLE_TEST("AI won't use a Weather changing move if partner already c { u32 j, k; static const u16 weatherMoves[] = {MOVE_SUNNY_DAY, MOVE_HAIL, MOVE_RAIN_DANCE, MOVE_SANDSTORM, MOVE_SNOWSCAPE}; - u16 weatherMoveLeft, weatherMoveRight; + u16 weatherMoveLeft = MOVE_NONE, weatherMoveRight = MOVE_NONE; for (j = 0; j < ARRAY_COUNT(weatherMoves); j++) { @@ -341,7 +340,7 @@ AI_DOUBLE_BATTLE_TEST("AI will not use Helping Hand if partner does not have any AI_DOUBLE_BATTLE_TEST("AI will not use a status move if partner already chose Helping Hand") { s32 j; - u32 statusMove; + u32 statusMove = MOVE_NONE; for (j = MOVE_NONE + 1; j < MOVES_COUNT; j++) { diff --git a/test/battle/exp.c b/test/battle/exp.c index e01055a9be..a7879b692c 100644 --- a/test/battle/exp.c +++ b/test/battle/exp.c @@ -26,7 +26,7 @@ WILD_BATTLE_TEST("Pokemon gain exp after catching a Pokemon") #endif // B_EXP_CATCH -WILD_BATTLE_TEST("Higher leveled Pokemon give more exp", u32 exp) +WILD_BATTLE_TEST("Higher leveled Pokemon give more exp", s32 exp) { u8 level = 0; @@ -47,7 +47,7 @@ WILD_BATTLE_TEST("Higher leveled Pokemon give more exp", u32 exp) } } -WILD_BATTLE_TEST("Lucky Egg boosts gained exp points by 50%", u32 exp) +WILD_BATTLE_TEST("Lucky Egg boosts gained exp points by 50%", s32 exp) { u32 item = 0; @@ -70,7 +70,7 @@ WILD_BATTLE_TEST("Lucky Egg boosts gained exp points by 50%", u32 exp) #if (B_SCALED_EXP == GEN_5 || B_SCALED_EXP >= GEN_7) -WILD_BATTLE_TEST("Exp is scaled to player and opponent's levels", u32 exp) +WILD_BATTLE_TEST("Exp is scaled to player and opponent's levels", s32 exp) { u8 level = 0; @@ -93,7 +93,7 @@ WILD_BATTLE_TEST("Exp is scaled to player and opponent's levels", u32 exp) #endif -WILD_BATTLE_TEST("Large exp gains are supported", u32 exp) // #1455 +WILD_BATTLE_TEST("Large exp gains are supported", s32 exp) // #1455 { u8 level = 0; diff --git a/test/battle/form_change/mega_evolution.c b/test/battle/form_change/mega_evolution.c index 3b47c7c86b..51037e77c7 100644 --- a/test/battle/form_change/mega_evolution.c +++ b/test/battle/form_change/mega_evolution.c @@ -74,7 +74,7 @@ SINGLE_BATTLE_TEST("Rayquaza can Mega Evolve knowing Dragon Ascent") SINGLE_BATTLE_TEST("Mega Evolution affects turn order") { GIVEN { - ASSUME(B_MEGA_EVO_TURN_ORDER); + ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); } OPPONENT(SPECIES_WOBBUFFET) { Speed(106); } } WHEN { @@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Mega Evolution affects turn order") SINGLE_BATTLE_TEST("Abilities replaced by Mega Evolution do not affect turn order") { GIVEN { - ASSUME(B_MEGA_EVO_TURN_ORDER); + ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); ASSUME(gSpeciesInfo[SPECIES_SABLEYE_MEGA].abilities[0] != ABILITY_STALL && gSpeciesInfo[SPECIES_SABLEYE_MEGA].abilities[1] != ABILITY_STALL); PLAYER(SPECIES_SABLEYE) { Item(ITEM_SABLENITE); Ability(ABILITY_STALL); Speed(105); } diff --git a/test/battle/form_change/ultra_burst.c b/test/battle/form_change/ultra_burst.c index e58d42c3da..0b4b07d891 100644 --- a/test/battle/form_change/ultra_burst.c +++ b/test/battle/form_change/ultra_burst.c @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("Ultra Burst affects turn order") { GIVEN { ASSUME(P_GEN_7_POKEMON == TRUE); - ASSUME(B_MEGA_EVO_TURN_ORDER); + ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z); Speed(105); } OPPONENT(SPECIES_WOBBUFFET) { Speed(106); } } WHEN { diff --git a/test/battle/hold_effect/attack_up.c b/test/battle/hold_effect/attack_up.c new file mode 100644 index 0000000000..2a6dd7c2df --- /dev/null +++ b/test/battle/hold_effect/attack_up.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_LIECHI_BERRY].holdEffect == HOLD_EFFECT_ATTACK_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Liechi Berry raises the holder's Attack by one stage when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LIECHI_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Using Liechi Berry, the Attack of Wobbuffet rose!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Liechi Berry, the Attack of Wobbuffet rose!"); + } + } THEN { + if (move == MOVE_DRAGON_RAGE) + EXPECT_EQ(player->statStages[STAT_ATK], 7); + } +} + +SINGLE_BATTLE_TEST("Liechi Berry raises Attack by one stage when HP drops to 1/2 or below if holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_LIECHI_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Liechi Berry, the Attack of Bellsprout rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Liechi Berry raises Attack by one stage when HP drops to 1/4 or below if holder has Ripen") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_APPLIN) { MaxHP(160); HP(80); Ability(ABILITY_RIPEN); Item(ITEM_LIECHI_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Liechi Berry, the Attack of Applin sharply rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/hold_effect/clear_amulet.c b/test/battle/hold_effect/clear_amulet.c index 39e6c22a69..552dbd91e8 100644 --- a/test/battle/hold_effect/clear_amulet.c +++ b/test/battle/hold_effect/clear_amulet.c @@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats") PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); }; } WHEN { - TURN { MOVE(player, MOVE_ROCK_SMASH); } + TURN { MOVE(player, move); } } SCENE { NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } } diff --git a/test/battle/hold_effect/critical_hit_up.c b/test/battle/hold_effect/critical_hit_up.c new file mode 100644 index 0000000000..799a1e423f --- /dev/null +++ b/test/battle/hold_effect/critical_hit_up.c @@ -0,0 +1,67 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_LANSAT_BERRY].holdEffect == HOLD_EFFECT_CRITICAL_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); + } + } +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/2 or below") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Bellsprout used Lansat Berry to get pumped!"); + } +} + +SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below") +{ + PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT); + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].highCritRatio == FALSE); + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_LANSAT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet used Lansat Berry to get pumped!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + MESSAGE("A critical hit!"); + } +} diff --git a/test/battle/hold_effect/custap_berry.c b/test/battle/hold_effect/custap_berry.c new file mode 100644 index 0000000000..8b6c7832d4 --- /dev/null +++ b/test/battle/hold_effect/custap_berry.c @@ -0,0 +1,37 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_CUSTAP_BERRY].holdEffect == HOLD_EFFECT_CUSTAP_BERRY); +} + +SINGLE_BATTLE_TEST("Custap Berry allows the holder to move first in its priority bracket when HP is below 1/4") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(1); MaxHP(160); HP(40); Item(ITEM_CUSTAP_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet can act faster, thanks to Custap Berry!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} + +SINGLE_BATTLE_TEST("Custap Berry allows the holder to move first in its priority bracket when HP is below 1/2. If the holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { Speed(1); MaxHP(160); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_CUSTAP_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Bellsprout can act faster, thanks to Custap Berry!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} diff --git a/test/battle/hold_effect/defense_up.c b/test/battle/hold_effect/defense_up.c new file mode 100644 index 0000000000..4326f156dc --- /dev/null +++ b/test/battle/hold_effect/defense_up.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_GANLON_BERRY].holdEffect == HOLD_EFFECT_DEFENSE_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Ganlon Berry raises the holder's Defense by one stage when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_GANLON_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Using Ganlon Berry, the Defense of Wobbuffet rose!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Ganlon Berry, the Defense of Wobbuffet rose!"); + } + } THEN { + if (move == MOVE_DRAGON_RAGE) + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Ganlon Berry raises Defense by one stage when HP drops to 1/2 or below if holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_GANLON_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Ganlon Berry, the Defense of Bellsprout rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Ganlon Berry raises Defense by one stage when HP drops to 1/4 or below if holder has Ripen") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_APPLIN) { MaxHP(160); HP(80); Ability(ABILITY_RIPEN); Item(ITEM_GANLON_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Ganlon Berry, the Defense of Applin sharply rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/hold_effect/enigma_berry.c b/test/battle/hold_effect/enigma_berry.c index 6758ac4026..79db0678dc 100644 --- a/test/battle/hold_effect/enigma_berry.c +++ b/test/battle/hold_effect/enigma_berry.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - gItems[ITEM_ENIGMA_BERRY].holdEffect == HOLD_EFFECT_ENIGMA_BERRY; + ASSUME(gItems[ITEM_ENIGMA_BERRY].holdEffect == HOLD_EFFECT_ENIGMA_BERRY); } SINGLE_BATTLE_TEST("Enigma Berry recovers 25% of HP if hit by super effective move") diff --git a/test/battle/hold_effect/jaboca_berry.c b/test/battle/hold_effect/jaboca_berry.c new file mode 100644 index 0000000000..ce102ff83a --- /dev/null +++ b/test/battle/hold_effect/jaboca_berry.c @@ -0,0 +1,44 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_JABOCA_BERRY].holdEffect == HOLD_EFFECT_JABOCA_BERRY); +} + +SINGLE_BATTLE_TEST("Jaboca Berry causes the attacker to lose 1/8 of its max HP if a physical move was used") +{ + s16 damage; + + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_JABOCA_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + HP_BAR(player, captureDamage: &damage); + MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Jaboca Berry!"); + } THEN { + EXPECT_EQ(player->maxHP / 8, damage); + } +} + +SINGLE_BATTLE_TEST("Jaboca Berry is not triggered by a special move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWIFT].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_JABOCA_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NOT MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Jaboca Berry!"); + } +} diff --git a/test/battle/hold_effect/kee_berry.c b/test/battle/hold_effect/kee_berry.c new file mode 100644 index 0000000000..a809381226 --- /dev/null +++ b/test/battle/hold_effect/kee_berry.c @@ -0,0 +1,60 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_KEE_BERRY].holdEffect == HOLD_EFFECT_KEE_BERRY); +} + +SINGLE_BATTLE_TEST("Kee Berry raises the holder's Defense by one stage when hit by a physical move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_KEE_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Using Kee Berry, the Defense of Foe Wobbuffet rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Kee Berry raises the holder's Defense by two stages with Ripen when hit by a physical move") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_APPLIN) { Item(ITEM_KEE_BERRY); Ability(ABILITY_RIPEN); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Using Kee Berry, the Defense of Foe Applin sharply rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 2); + } +} + +SINGLE_BATTLE_TEST("Kee Berry is not triggered by a special move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWIFT].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_KEE_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NOT MESSAGE("Using Kee Berry, the Defense of Foe Wobbuffet rose!"); + } +} diff --git a/test/battle/hold_effect/leftovers.c b/test/battle/hold_effect/leftovers.c index 7e51a3bd75..341f9c3779 100644 --- a/test/battle/hold_effect/leftovers.c +++ b/test/battle/hold_effect/leftovers.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - gItems[ITEM_LEFTOVERS].holdEffect == HOLD_EFFECT_LEFTOVERS; + ASSUME(gItems[ITEM_LEFTOVERS].holdEffect == HOLD_EFFECT_LEFTOVERS); } SINGLE_BATTLE_TEST("Leftovers recovers 1/16th HP at end of turn") diff --git a/test/battle/hold_effect/maranga_berry.c b/test/battle/hold_effect/maranga_berry.c new file mode 100644 index 0000000000..08f827c30c --- /dev/null +++ b/test/battle/hold_effect/maranga_berry.c @@ -0,0 +1,60 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_MARANGA_BERRY].holdEffect == HOLD_EFFECT_MARANGA_BERRY); +} + +SINGLE_BATTLE_TEST("Maranga Berry raises the holder's Sp. Def by one stage when hit by a special move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWIFT].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_MARANGA_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Using Maranga Berry, the Sp. Def of Foe Wobbuffet rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Maranga Berry raises the holder's Sp. Def by two stages with Ripen when hit by a special move") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gBattleMoves[MOVE_SWIFT].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_APPLIN) { Item(ITEM_MARANGA_BERRY); Ability(ABILITY_RIPEN); } + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("Using Maranga Berry, the Sp. Def of Foe Applin sharply rose!"); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 2); + } +} + +SINGLE_BATTLE_TEST("Maranga Berry raises the holder's Sp. Def by one stage when hit by a special move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_MARANGA_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NOT MESSAGE("Using Maranga Berry, the Sp. Def of Foe Wobbuffet rose!"); + } +} diff --git a/test/battle/hold_effect/metronome.c b/test/battle/hold_effect/metronome.c index 76cd27c6f1..63a0bb3eae 100644 --- a/test/battle/hold_effect/metronome.c +++ b/test/battle/hold_effect/metronome.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - gItems[ITEM_METRONOME].holdEffect == HOLD_EFFECT_METRONOME; + ASSUME(gItems[ITEM_METRONOME].holdEffect == HOLD_EFFECT_METRONOME); } const uq4_12_t MetronomeMultipliers[] = { diff --git a/test/battle/hold_effect/micle_berry.c b/test/battle/hold_effect/micle_berry.c new file mode 100644 index 0000000000..224c2fecf6 --- /dev/null +++ b/test/battle/hold_effect/micle_berry.c @@ -0,0 +1,68 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_MICLE_BERRY].holdEffect == HOLD_EFFECT_MICLE_BERRY); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2 when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_MICLE_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); + } + } +} + +SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2 when HP drops to 1/2 or below") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_MICLE_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Bellsprout boosted the accuracy of its next move using Micle Berry!"); + } +} + +SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2") +{ + PASSES_RANDOMLY(24, 25, RNG_ACCURACY); + GIVEN { + ASSUME(gBattleMoves[MOVE_SUBMISSION].accuracy == 80); + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_MICLE_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); MOVE(player, MOVE_SUBMISSION); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet boosted the accuracy of its next move using Micle Berry!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBMISSION, player); + } +} + + diff --git a/test/battle/hold_effect/mirror_herb.c b/test/battle/hold_effect/mirror_herb.c index 1e9058b08e..9191f3fee1 100644 --- a/test/battle/hold_effect/mirror_herb.c +++ b/test/battle/hold_effect/mirror_herb.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(gItems[ITEM_MIRROR_HERB].holdEffect == HOLD_EFFECT_MIRROR_HERB); } -SINGLE_BATTLE_TEST("Mirror Herb copies all of foe's stat changes in a turn", s16 damage) +SINGLE_BATTLE_TEST("Mirror Herb copies all of foe's positive stat changes in a turn", s16 damage) { u32 item; PARAMETRIZE { item = ITEM_NONE; } @@ -34,7 +34,7 @@ SINGLE_BATTLE_TEST("Mirror Herb copies all of foe's stat changes in a turn", s16 } } -SINGLE_BATTLE_TEST("Mirror Herb copies all of of Stuff Cheeks") +SINGLE_BATTLE_TEST("Mirror Herb copies all of Stuff Cheeks' stat boosts") { GIVEN { ASSUME(gItems[ITEM_LIECHI_BERRY].holdEffect == HOLD_EFFECT_ATTACK_UP); diff --git a/test/battle/hold_effect/random_stat_up.c b/test/battle/hold_effect/random_stat_up.c new file mode 100644 index 0000000000..9033c6b0af --- /dev/null +++ b/test/battle/hold_effect/random_stat_up.c @@ -0,0 +1,11 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_STARF_BERRY].holdEffect == HOLD_EFFECT_RANDOM_STAT_UP); +} + +TO_DO_BATTLE_TEST("Starf Berry randomly raises the holder's Attack, Defense, Sp. Atk, Sp. Def, or Speed by two stages when the holder's HP drop to 1/4 or below") +TO_DO_BATTLE_TEST("Starf Berry randomly raises the holder's Attack, Defense, Sp. Atk, Sp. Def, or Speed by two stages when the holder's HP drop to 1/2 or below if it has Gluttony") +TO_DO_BATTLE_TEST("Starf Berry randomly raises the holder's Attack, Defense, Sp. Atk, Sp. Def, or Speed by four stages when the holder's HP drop to 1/4 or below if it has Riped") diff --git a/test/battle/hold_effect/rowap_berry.c b/test/battle/hold_effect/rowap_berry.c new file mode 100644 index 0000000000..4145948791 --- /dev/null +++ b/test/battle/hold_effect/rowap_berry.c @@ -0,0 +1,44 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_ROWAP_BERRY].holdEffect == HOLD_EFFECT_ROWAP_BERRY); +} + +SINGLE_BATTLE_TEST("Rowap Berry causes the attacker to lose 1/8 of its max HP if a special move was used") +{ + s16 damage; + + GIVEN { + ASSUME(gBattleMoves[MOVE_SWIFT].split == SPLIT_SPECIAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROWAP_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + HP_BAR(player, captureDamage: &damage); + MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Rowap Berry!"); + } THEN { + EXPECT_EQ(player->maxHP / 8, damage); + } +} + +SINGLE_BATTLE_TEST("Rowap Berry is not triggered by a physical move") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ROWAP_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + NOT MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Rowap Berry!"); + } +} diff --git a/test/battle/hold_effect/safety_goggles.c b/test/battle/hold_effect/safety_goggles.c index 3deeeb810f..f00cdb3325 100644 --- a/test/battle/hold_effect/safety_goggles.c +++ b/test/battle/hold_effect/safety_goggles.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES; + ASSUME(gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES); }; SINGLE_BATTLE_TEST("Safety Goggles block powder and spore moves") diff --git a/test/battle/hold_effect/special_attack_up.c b/test/battle/hold_effect/special_attack_up.c new file mode 100644 index 0000000000..1059960abc --- /dev/null +++ b/test/battle/hold_effect/special_attack_up.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_PETAYA_BERRY].holdEffect == HOLD_EFFECT_SP_ATTACK_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Petaya Berry raises the holder's Sp. Atk by one stage when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_PETAYA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Using Petaya Berry, the Sp. Atk of Wobbuffet rose!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Petaya Berry, the Sp. Atk of Wobbuffet rose!"); + } + } THEN { + if (move == MOVE_DRAGON_RAGE) + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Petaya Berry raises Sp. Atk by one stage when HP drops to 1/2 or below if holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_PETAYA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Petaya Berry, the Sp. Atk of Bellsprout rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Petaya Berry raises Sp. Atk by one stage when HP drops to 1/4 or below if holder has Ripen") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_APPLIN) { MaxHP(160); HP(80); Ability(ABILITY_RIPEN); Item(ITEM_PETAYA_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Petaya Berry, the Sp. Atk of Applin sharply rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/hold_effect/special_defense_up.c b/test/battle/hold_effect/special_defense_up.c new file mode 100644 index 0000000000..9a6c8c44be --- /dev/null +++ b/test/battle/hold_effect/special_defense_up.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_APICOT_BERRY].holdEffect == HOLD_EFFECT_SP_DEFENSE_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Apicot Berry raises the holder's Sp. Def by one stage when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_APICOT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Using Apicot Berry, the Sp. Def of Wobbuffet rose!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Apicot Berry, the Sp. Def of Wobbuffet rose!"); + } + } THEN { + if (move == MOVE_DRAGON_RAGE) + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Apicot Berry raises Sp. Def by one stage when HP drops to 1/2 or below if holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_APICOT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Apicot Berry, the Sp. Def of Bellsprout rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Apicot Berry raises Sp. Def by one stage when HP drops to 1/4 or below if holder has Ripen") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_APPLIN) { MaxHP(160); HP(80); Ability(ABILITY_RIPEN); Item(ITEM_APICOT_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Apicot Berry, the Sp. Def of Applin sharply rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/hold_effect/speed_up.c b/test/battle/hold_effect/speed_up.c new file mode 100644 index 0000000000..62ca65dbc2 --- /dev/null +++ b/test/battle/hold_effect/speed_up.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_SALAC_BERRY].holdEffect == HOLD_EFFECT_SPEED_UP); + ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE); +} + +SINGLE_BATTLE_TEST("Salac Berry raises the holder's Speed by one stage when HP drops to 1/4 or below") +{ + u32 move; + + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_DRAGON_RAGE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(160); HP(80); Item(ITEM_SALAC_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (move == MOVE_TACKLE) + { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("Using Salac Berry, the Speed of Wobbuffet rose!"); + } + else + { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Salac Berry, the Speed of Wobbuffet rose!"); + } + } THEN { + if (move == MOVE_DRAGON_RAGE) + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Salac Berry raises Speed by one stage when HP drops to 1/2 or below if holder has Gluttony") +{ + GIVEN { + PLAYER(SPECIES_BELLSPROUT) { MaxHP(80); HP(80); Ability(ABILITY_GLUTTONY); Item(ITEM_SALAC_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Salac Berry, the Speed of Bellsprout rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Salac Berry raises Speed by one stage when HP drops to 1/4 or below if holder has Ripen") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_APPLIN) { MaxHP(160); HP(80); Ability(ABILITY_RIPEN); Item(ITEM_SALAC_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Using Salac Berry, the Speed of Applin sharply rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + } +} diff --git a/test/battle/move_effect/hit_set_remove_terrain.c b/test/battle/move_effect/hit_set_remove_terrain.c index 5c21d08538..4a54eb436d 100644 --- a/test/battle/move_effect/hit_set_remove_terrain.c +++ b/test/battle/move_effect/hit_set_remove_terrain.c @@ -22,8 +22,8 @@ SINGLE_BATTLE_TEST("Steel Roller and Ice Spinner can remove a terrain from the f MOVE_MISTY_TERRAIN, }; - u16 terrainMove; - u16 removeTerrainMove; + u16 terrainMove = MOVE_NONE; + u16 removeTerrainMove = MOVE_NONE; for (j = 0; j < ARRAY_COUNT(terrainMoves); j++) { diff --git a/test/battle/move_effect/ivy_cudgel.c b/test/battle/move_effect/ivy_cudgel.c new file mode 100644 index 0000000000..ef0611c84f --- /dev/null +++ b/test/battle/move_effect/ivy_cudgel.c @@ -0,0 +1,24 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Ivy Gudgel changes the move type depending on the mask the user holds") +{ + u16 species; + u16 item; + + PARAMETRIZE { species = SPECIES_BLASTOISE; item = ITEM_NONE; } + PARAMETRIZE { species = SPECIES_CHARIZARD; item = ITEM_CORNERSTONE_MASK; } + PARAMETRIZE { species = SPECIES_CHARIZARD; item = ITEM_WELLSPRING_MASK; } + PARAMETRIZE { species = SPECIES_VENUSAUR; item = ITEM_HEARTHFLAME_MASK; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(item); } + OPPONENT(species); + } WHEN { + TURN { MOVE(player, MOVE_IVY_CUDGEL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_IVY_CUDGEL, player); + HP_BAR(opponent); + MESSAGE("It's super effective!"); + } +} diff --git a/test/battle/move_effect/matcha_gotcha.c b/test/battle/move_effect/matcha_gotcha.c new file mode 100644 index 0000000000..f1b76b5fcc --- /dev/null +++ b/test/battle/move_effect/matcha_gotcha.c @@ -0,0 +1,66 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_MATCHA_GOTCHA].effect == EFFECT_MATCHA_GOTCHA); +} + +SINGLE_BATTLE_TEST("Matcha Gotcha inflicts burn 20% of the time") +{ + PASSES_RANDOMLY(20, 100, RNG_SECONDARY_EFFECT); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MATCHA_GOTCHA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent); + STATUS_ICON(opponent, burn: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Matcha Gatcha can burn both targets") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft); + HP_BAR(opponentLeft); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentLeft); + STATUS_ICON(opponentLeft, burn: TRUE); + HP_BAR(opponentRight); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentRight); + STATUS_ICON(opponentRight, burn: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Matcha Gatcha recovers 50% of the damage dealt from both targets") +{ + s16 damageLeft; + s16 damageRight; + s16 healedLeft; + s16 healedRight; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damageLeft); + HP_BAR(playerLeft, captureDamage: &healedLeft); + HP_BAR(opponentRight, captureDamage: &damageRight); + HP_BAR(playerLeft, captureDamage: &healedRight); + } +} diff --git a/test/battle/move_effect/reflect.c b/test/battle/move_effect/reflect.c index dd8738f72b..68d0af1a45 100644 --- a/test/battle/move_effect/reflect.c +++ b/test/battle/move_effect/reflect.c @@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Reflect reduces physical damage", s16 damage) SINGLE_BATTLE_TEST("Reflect applies for 5 turns") { - u16 damage[6]; + s16 damage[6]; GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/roost.c b/test/battle/move_effect/roost.c index 4a3f90602d..c213c951e8 100644 --- a/test/battle/move_effect/roost.c +++ b/test/battle/move_effect/roost.c @@ -58,8 +58,8 @@ SINGLE_BATTLE_TEST("Roost fails if the user is under the effects of Heal Block") } SINGLE_BATTLE_TEST("Roost recovers 50% of the user's Max HP") -{ - s16 hp; +{ + u16 hp; KNOWN_FAILING; // All healing is currently rounded down GIVEN { @@ -218,7 +218,7 @@ SINGLE_BATTLE_TEST("Roost, if used by a Mystery/Flying type, treats the user as MESSAGE("It's not very effective…"); MESSAGE("It doesn't affect Moltres…"); } - } + } } // Tested in ORAS @@ -230,9 +230,9 @@ DOUBLE_BATTLE_TEST("Roost suppresses the user's not-yet-aquired Flying-type this PLAYER(SPECIES_KECLEON) { Speed(40); HP(150); Ability(ABILITY_COLOR_CHANGE); } PLAYER(SPECIES_WOBBUFFET) { Speed(10); } OPPONENT(SPECIES_PIDGEY) { Speed(30); } - OPPONENT(SPECIES_SANDSHREW) { Speed(20); } + OPPONENT(SPECIES_SANDSHREW) { Speed(20); } } WHEN { - TURN { MOVE(playerLeft, MOVE_ROOST); + TURN { MOVE(playerLeft, MOVE_ROOST); MOVE(opponentLeft, MOVE_GUST, target: playerLeft); MOVE(opponentRight, MOVE_EARTHQUAKE, target: playerLeft); } } SCENE { @@ -427,6 +427,6 @@ SINGLE_BATTLE_TEST("Roost does not suppress the ungrounded effect of Telekinesis } // Tested in ORAS -// Transform does not copy the Roost "status" either. +// Transform does not copy the Roost "status" either. // Probably better as a Transform test. TO_DO_BATTLE_TEST("Roost's suppression does not prevent others who are Transforming into the user from copying its Flying-type"); diff --git a/test/battle/move_effect/salt_cure.c b/test/battle/move_effect/salt_cure.c index fcf240631a..b0b58c997c 100644 --- a/test/battle/move_effect/salt_cure.c +++ b/test/battle/move_effect/salt_cure.c @@ -8,18 +8,19 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Salt Cure inflicts 1/8 of the target's maximum HP as damage per turn") { + u32 j; GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_SALT_CURE); } - for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) TURN {} } SCENE { s32 maxHP = GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP); ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); MESSAGE("Foe Wobbuffet is being salt cured!"); - for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SALT_CURE_DAMAGE, opponent); HP_BAR(opponent, damage: maxHP / 8); MESSAGE("Foe Wobbuffet is hurt by Salt Cure!"); @@ -70,3 +71,17 @@ SINGLE_BATTLE_TEST("Salt Cure is removed when the afflicted Pokémon is switched } } } + +SINGLE_BATTLE_TEST("If Salt Cure faints the target no status will be applied") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_SALT_CURE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SALT_CURE, player); + NOT MESSAGE("Foe Wobbuffet is being salt cured!"); + MESSAGE("Foe Wobbuffet fainted!"); + } +} diff --git a/test/battle/move_effect/syrup_bomb.c b/test/battle/move_effect/syrup_bomb.c new file mode 100644 index 0000000000..ae689b3629 --- /dev/null +++ b/test/battle/move_effect/syrup_bomb.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Syrup Bomb covers the foe in sticky syrup for 3 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + TURN {} + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wobbuffet's Speed fell!"); + MESSAGE("Foe Wobbuffet was freed from Syrup Bomb!"); + } +} + +SINGLE_BATTLE_TEST("Syrup Bomb is prevented by Bulletproof") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CHESPIN) { Ability(ABILITY_BULLETPROOF); } + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_BULLETPROOF); + MESSAGE("Foe Chespin's Bulletproof blocks Syrup Bomb!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + NOT HP_BAR(opponent); + } +} + +SINGLE_BATTLE_TEST("Clear Body, White Smoke and Full Metal Body prevent Sticky Syrup speed reduction") +{ + u32 species; + u32 ability; + + PARAMETRIZE { species = SPECIES_BELDUM; ability = ABILITY_CLEAR_BODY; } + PARAMETRIZE { species = SPECIES_TORKOAL; ability = ABILITY_WHITE_SMOKE; } + PARAMETRIZE { species = SPECIES_SOLGALEO; ability = ABILITY_FULL_METAL_BODY; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + if (species == SPECIES_BELDUM) + { + MESSAGE("Foe Beldum got covered in sticky syrup!"); + ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); + MESSAGE("Foe Beldum's Clear Body prevents stat loss!"); + } + else if (species == SPECIES_TORKOAL) + { + MESSAGE("Foe Torkoal got covered in sticky syrup!"); + ABILITY_POPUP(opponent, ABILITY_WHITE_SMOKE); + MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); + } + else if (species == SPECIES_SOLGALEO) + { + MESSAGE("Foe Solgaleo got covered in sticky syrup!"); + ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); + MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); + } + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Beldum's Speed fell!"); + } +} + +SINGLE_BATTLE_TEST("Clear Amulet prevents Sticky Syrup speed reduction") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); } + } WHEN { + TURN { MOVE(player, MOVE_SYRUP_BOMB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SYRUP_BOMB, player); + HP_BAR(opponent); + MESSAGE("Foe Wobbuffet got covered in sticky syrup!"); + MESSAGE("Foe Wobbuffet's Speed was not lowered!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT MESSAGE("Foe Wobbuffet's Speed fell!"); + } +} diff --git a/test/battle/move_effect/teatime.c b/test/battle/move_effect/teatime.c index 7995937fa5..c34b742920 100644 --- a/test/battle/move_effect/teatime.c +++ b/test/battle/move_effect/teatime.c @@ -96,7 +96,7 @@ SINGLE_BATTLE_TEST("Teatime causes other Pokemon to consume their Berry even if DOUBLE_BATTLE_TEST("Teatime causes all Pokémon to consume their berry") { - struct BattlePokemon *user; + struct BattlePokemon *user = NULL; PARAMETRIZE { user = playerLeft; } PARAMETRIZE { user = playerRight; } PARAMETRIZE { user = opponentLeft; } @@ -143,7 +143,7 @@ SINGLE_BATTLE_TEST("Teatime does not affect Pokémon in the semi-invulnerable tu PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NONE); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); } } WHEN { - TURN { + TURN { MOVE(opponent, MOVE_FLY); MOVE(player, MOVE_TEATIME); } @@ -170,7 +170,7 @@ SINGLE_BATTLE_TEST("Teatime triggers Volt Absorb if it has been affected by Elec PLAYER(SPECIES_JOLTEON) { Ability(ABILITY_VOLT_ABSORB); Item(item); HP(55); MaxHP(100); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); } } WHEN { - TURN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TEATIME); } @@ -206,7 +206,7 @@ SINGLE_BATTLE_TEST("Teatime triggers Lightning Rod if it has been affected by El PLAYER(SPECIES_PIKACHU) { Ability(ABILITY_LIGHTNING_ROD); Item(item); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); } } WHEN { - TURN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TEATIME); } @@ -246,7 +246,7 @@ SINGLE_BATTLE_TEST("Teatime triggers Motor Drive if it has been affected by Elec PLAYER(SPECIES_ELECTIVIRE) { Ability(ABILITY_MOTOR_DRIVE); Item(item); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIECHI_BERRY); } } WHEN { - TURN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_TEATIME); } diff --git a/test/battle/status1/bad_poison.c b/test/battle/status1/bad_poison.c index 7a430086bd..2ee3f05278 100644 --- a/test/battle/status1/bad_poison.c +++ b/test/battle/status1/bad_poison.c @@ -3,21 +3,23 @@ SINGLE_BATTLE_TEST("Bad poison deals 1/16th cumulative damage per turn") { + u32 j; GIVEN { PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) TURN {} } SCENE { s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); + for (j = 0; j < 4; j++) + HP_BAR(player, damage: maxHP / 16 * (j + 1)); } } SINGLE_BATTLE_TEST("Bad poison cumulative damage resets on switch") { + u32 j; GIVEN { PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } PLAYER(SPECIES_WYNAUT); @@ -31,9 +33,9 @@ SINGLE_BATTLE_TEST("Bad poison cumulative damage resets on switch") TURN {} } SCENE { s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 2; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); - for (i = 0; i < 2; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); + for (j = 0; j < 2; j++) + HP_BAR(player, damage: maxHP / 16 * (j + 1)); + for (j = 0; j < 2; j++) + HP_BAR(player, damage: maxHP / 16 * (j + 1)); } } diff --git a/test/battle/status1/burn.c b/test/battle/status1/burn.c index 84439ec9ef..77d58e5cc3 100644 --- a/test/battle/status1/burn.c +++ b/test/battle/status1/burn.c @@ -3,16 +3,17 @@ SINGLE_BATTLE_TEST("Burn deals 1/16th damage per turn") { + u32 j; GIVEN { ASSUME(B_BURN_DAMAGE >= GEN_LATEST); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) TURN {} } SCENE { s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) HP_BAR(player, damage: maxHP / 16); } } diff --git a/test/battle/status1/poison.c b/test/battle/status1/poison.c index 771d0d2eca..12f6ffa95f 100644 --- a/test/battle/status1/poison.c +++ b/test/battle/status1/poison.c @@ -3,15 +3,16 @@ SINGLE_BATTLE_TEST("Poison deals 1/8th damage per turn") { + u32 j; GIVEN { PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) TURN {} } SCENE { s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) HP_BAR(player, damage: maxHP / 8); } } diff --git a/test/battle/status1/sleep.c b/test/battle/status1/sleep.c index 8ef6137d35..b3dd403eb1 100644 --- a/test/battle/status1/sleep.c +++ b/test/battle/status1/sleep.c @@ -3,7 +3,7 @@ SINGLE_BATTLE_TEST("Sleep prevents the battler from using a move") { - u32 turns; + u32 turns, j; PARAMETRIZE { turns = 1; } PARAMETRIZE { turns = 2; } PARAMETRIZE { turns = 3; } @@ -11,10 +11,10 @@ SINGLE_BATTLE_TEST("Sleep prevents the battler from using a move") PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(turns)); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - for (i = 0; i < turns; i++) + for (j = 0; j < turns; j++) TURN { MOVE(player, MOVE_CELEBRATE); } } SCENE { - for (i = 0; i < turns - 1; i++) + for (j = 0; j < turns - 1; j++) MESSAGE("Wobbuffet is fast asleep."); MESSAGE("Wobbuffet woke up!"); STATUS_ICON(player, none: TRUE); diff --git a/test/random.c b/test/random.c index 5ca4b814df..b99a5921e1 100644 --- a/test/random.c +++ b/test/random.c @@ -196,7 +196,6 @@ TEST("RandomElement generates a uniform distribution") TEST("RandomUniform mul-based faster than mod-based (compile-time)") { - u32 i; struct Benchmark mulBenchmark, modBenchmark; u32 mulSum = 0, modSum = 0; diff --git a/test/test_runner.c b/test/test_runner.c index 637ff0ed83..15ed889aac 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -88,7 +88,7 @@ static u32 AssignCostToRunner(void) u32 minCostProcess; if (gTestRunnerState.test->runner == &gAssumptionsRunner) - return TRUE; + return gTestRunnerI; minCostProcess = MinCostProcess(); @@ -188,13 +188,6 @@ void CB2_TestRunner(void) REG_TM2CNT_L = UINT16_MAX - (274 * 60); // Approx. 1 second. REG_TM2CNT_H = TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_1024CLK; - // NOTE: Assumes that the compiler interns __FILE__. - if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename) - { - gTestRunnerState.result = TEST_RESULT_ASSUMPTION_FAIL; - return; - } - sCurrentTest.address = (uintptr_t)gTestRunnerState.test; sCurrentTest.state = CURRENT_TEST_STATE_ESTIMATE; @@ -210,9 +203,17 @@ void CB2_TestRunner(void) sCurrentTest.state = CURRENT_TEST_STATE_RUN; if (gTestRunnerState.test->runner->setUp) gTestRunnerState.test->runner->setUp(gTestRunnerState.test->data); - gTestRunnerState.test->runner->run(gTestRunnerState.test->data); + // NOTE: Assumes that the compiler interns __FILE__. + if (gTestRunnerState.skipFilename == gTestRunnerState.test->filename) // Assumption fails for tests in this file. + { + gTestRunnerState.result = TEST_RESULT_ASSUMPTION_FAIL; + return; + } + else + { + gTestRunnerState.test->runner->run(gTestRunnerState.test->data); + } break; - case STATE_REPORT_RESULT: REG_TM2CNT_H = 0; @@ -254,7 +255,9 @@ void CB2_TestRunner(void) if (gTestRunnerState.test->runner == &gAssumptionsRunner) { if (gTestRunnerState.result != TEST_RESULT_PASS) + { gTestRunnerState.skipFilename = gTestRunnerState.test->filename; + } } else { @@ -511,6 +514,7 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va) s32 c, d; u32 p; const char *s; + const u8 *pokeS; while (*fmt) { switch ((c = *fmt++)) @@ -605,8 +609,8 @@ static s32 MgbaVPrintf_(const char *fmt, va_list va) i = MgbaPutchar_(i, c); break; case 'S': - s = va_arg(va, const u8 *); - while ((c = *s++) != EOS) + pokeS = va_arg(va, const u8 *); + while ((c = *pokeS++) != EOS) { if ((c = gWireless_RSEtoASCIITable[c]) != '\0') i = MgbaPutchar_(i, c); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 2da8f606b3..fc100ff8a1 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -4,6 +4,7 @@ #include "battle_anim.h" #include "battle_controllers.h" #include "characters.h" +#include "fieldmap.h" #include "item_menu.h" #include "main.h" #include "malloc.h" @@ -34,7 +35,9 @@ #undef Q_4_12 #define Q_4_12(n) (s32)((n) * 4096) -EWRAM_DATA struct BattleTestRunnerState *gBattleTestRunnerState = NULL; +// Alias sBackupMapData to avoid using heap. +struct BattleTestRunnerState *const gBattleTestRunnerState = (void *)sBackupMapData; +STATIC_ASSERT(sizeof(struct BattleTestRunnerState) <= sizeof(sBackupMapData), sBackupMapDataSpace); static void CB2_BattleTest_NextParameter(void); static void CB2_BattleTest_NextTrial(void); @@ -146,9 +149,6 @@ static u32 BattleTest_EstimateCost(void *data) { u32 cost; const struct BattleTest *test = data; - STATE = AllocZeroed(sizeof(*STATE)); - if (!STATE) - return 0; STATE->runRandomly = TRUE; InvokeTestFunction(test); cost = 1; @@ -158,23 +158,21 @@ static u32 BattleTest_EstimateCost(void *data) cost *= 3; else if (STATE->trials > 1) cost *= STATE->trials; - FREE_AND_SET_NULL(STATE); return cost; } static void BattleTest_SetUp(void *data) { const struct BattleTest *test = data; - STATE = AllocZeroed(sizeof(*STATE)); - if (!STATE) - Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE = AllocZerod(%d)", sizeof(*STATE)); + memset(STATE, 0, sizeof(*STATE)); InvokeTestFunction(test); STATE->parameters = STATE->parametersCount; if (STATE->parametersCount == 0 && test->resultsSize > 0) Test_ExitWithResult(TEST_RESULT_INVALID, "results without PARAMETRIZE"); - STATE->results = AllocZeroed(test->resultsSize * STATE->parameters); - if (!STATE->results) - Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE->results = AllocZerod(%d)", sizeof(test->resultsSize * STATE->parameters)); + if (sizeof(*STATE) + test->resultsSize * STATE->parameters > sizeof(sBackupMapData)) + Test_ExitWithResult(TEST_RESULT_ERROR, "OOM: STATE (%d) + STATE->results (%d) too big for sBackupMapData (%d)", sizeof(*STATE), test->resultsSize * STATE->parameters, sizeof(sBackupMapData)); + STATE->results = (void *)((char *)sBackupMapData + sizeof(struct BattleTestRunnerState)); + memset(STATE->results, 0, test->resultsSize * STATE->parameters); switch (test->type) { case BATTLE_TEST_SINGLES: @@ -215,7 +213,7 @@ static void PrintTestName(void) // modifiers. static void SetImplicitSpeeds(void) { - s32 i, j; + s32 i; u32 speed = 12; u32 hasSpeeds = 0; u32 allSpeeds = ((1 << DATA.playerPartySize) - 1) | (((1 << DATA.opponentPartySize) - 1) << 6); @@ -538,6 +536,7 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz STATE->trialRatio = Q_4_12(1) / count; return (const u8 *)array + size * STATE->runTrial; } + return (const u8 *)array + size * index; } static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) @@ -698,10 +697,10 @@ static s32 TryHP(s32 i, s32 n, u32 battlerId, u32 oldHP, u32 newHP) switch (event->type) { case HP_EVENT_NEW_HP: - *(u16 *)event->address = newHP; + *(u16 *)(u32)(event->address) = newHP; break; case HP_EVENT_DELTA_HP: - *(s16 *)event->address = oldHP - newHP; + *(s16 *)(u32)(event->address) = oldHP - newHP; break; } return i; @@ -787,7 +786,7 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) if (!expectedAction->pass) { - u32 i, expectedMoveId, countExpected; + u32 i, expectedMoveId = 0, countExpected; bool32 movePasses = FALSE; if (expectedAction->type != B_ACTION_USE_MOVE) @@ -1074,10 +1073,10 @@ static s32 TryExp(s32 i, s32 n, u32 battlerId, u32 oldExp, u32 newExp) switch (event->type) { case EXP_EVENT_NEW_EXP: - *(u32 *)event->address = newExp; + *(u32 *)(u32)(event->address) = newExp; break; case EXP_EVENT_DELTA_EXP: - *(s32 *)event->address = oldExp - newExp; + *(s32 *)(u32)(event->address) = oldExp - newExp; break; } return i; @@ -1386,15 +1385,10 @@ static void CB2_BattleTest_NextTrial(void) static void BattleTest_TearDown(void *data) { - if (STATE) - { - // Free resources that aren't cleaned up when the battle was - // aborted unexpectedly. - if (STATE->tearDownBattle) - TearDownBattle(); - FREE_AND_SET_NULL(STATE->results); - FREE_AND_SET_NULL(STATE); - } + // Free resources that aren't cleaned up when the battle was + // aborted unexpectedly. + if (STATE->tearDownBattle) + TearDownBattle(); } static bool32 BattleTest_CheckProgress(void *data) @@ -1525,7 +1519,6 @@ static const u16 sNaturePersonalities[NUM_NATURES] = static u32 GenerateNature(u32 nature, u32 offset) { - int i; if (offset <= nature) nature -= offset; else @@ -1993,7 +1986,6 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx) { - s32 i; s32 battlerId = battler - gBattleMons; u32 moveId, moveSlot; s32 target; @@ -2095,7 +2087,6 @@ void ExpectSendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex } if (!(DATA.actionBattlers & (1 << battlerId))) { - const struct BattleTest *test = GetBattleTest(); if (IsAITest() && (battlerId & BIT_SIDE) == B_SIDE_OPPONENT) // If Move was not specified, allow any move used. SetAiActionToPass(sourceLine, battlerId); else @@ -2536,8 +2527,6 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve void ValidateFinally(u32 sourceLine) { // Defer this error until after estimating the cost. - if (STATE->results == NULL) - return; INVALID_IF(STATE->parametersCount == 0, "FINALLY without PARAMETRIZE"); } @@ -2550,7 +2539,7 @@ u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex) // to improve performance. struct AILogLine *GetLogLine(u32 battlerId, u32 moveIndex) { - s32 i, j; + s32 i; for (i = 0; i < MAX_AI_LOG_LINES; i++) { @@ -2562,11 +2551,11 @@ struct AILogLine *GetLogLine(u32 battlerId, u32 moveIndex) } Test_ExitWithResult(TEST_RESULT_ERROR, "Too many AI log lines"); + return NULL; } void TestRunner_Battle_AILogScore(const char *file, u32 line, u32 battlerId, u32 moveIndex, s32 score, bool32 setScore) { - s32 i; struct AILogLine *log; if (!DATA.logAI) return;