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 0b72e1cf98..e533173e11 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -856,6 +856,10 @@ gBattleAnims_Moves:: .4byte Move_MAGICAL_TORQUE .4byte Move_PSYBLADE .4byte Move_HYDRO_STEAM + .4byte Move_BLOOD_MOON + .4byte Move_MATCHA_GOTCHA + .4byte Move_SYRUP_BOMB + .4byte Move_IVY_CUDGEL @@@@ Z MOVES .4byte Move_BREAKNECK_BLITZ .4byte Move_ALL_OUT_PUMMELING @@ -16505,6 +16509,10 @@ Move_COMBAT_TORQUE:: Move_MAGICAL_TORQUE:: Move_PSYBLADE:: Move_HYDRO_STEAM:: +Move_BLOOD_MOON:: +Move_MATCHA_GOTCHA:: +Move_SYRUP_BOMB:: +Move_IVY_CUDGEL:: end @to do @@@@@@@@@@@@@@@@@@@@@@@ GEN 1-3 @@@@@@@@@@@@@@@@@@@@@@@ @@ -19418,8 +19426,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 a1ccf6f2b1..cc82035705 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -438,8 +438,51 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHit @ EFFECT_GIGATON_HAMMER .4byte BattleScript_EffectSaltCure @ EFFECT_SALT_CURE + .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 @@ -3332,6 +3375,7 @@ BattleScript_EffectPoisonHit: BattleScript_EffectAbsorb:: call BattleScript_EffectHit_Ret + seteffectwithchance jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_AbsorbHealBlock setdrainedhp manipulatedamage DMG_BIG_ROOT @@ -3852,6 +3896,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 @@ -7959,9 +8004,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 @@ -8711,28 +8757,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 @@ -9901,6 +9925,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 9bb3fb7597..96112a63d5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -103,6 +103,7 @@ struct DisableStruct u8 toxicSpikesDone:1; u8 stickyWebDone:1; u8 stealthRockDone:1; + u8 syrupBombTimer; }; struct ProtectStruct @@ -149,6 +150,7 @@ struct ProtectStruct u16 shellTrap: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; @@ -901,7 +903,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 @@ -920,7 +922,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 @@ -1014,7 +1016,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_ai_util.h b/include/battle_ai_util.h index 6a51963ae3..37e9c509da 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -112,8 +112,6 @@ bool32 IsStatLoweringMoveEffect(u32 moveEffect); bool32 IsMoveRedirectionPrevented(u32 move, u32 atkAbility); bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsHazardMoveEffect(u32 moveEffect); -bool32 MoveCallsOtherMove(u32 move); -bool32 MoveRequiresRecharging(u32 move); bool32 IsEncoreEncouragedEffect(u32 moveEffect); void ProtectChecks(u32 battlerAtk, u32 battlerDef, u32 move, u32 predictedMove, s32 *score); bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect); diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 335aafb589..c2a73d01fd 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[]; @@ -478,6 +479,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 aee79daee5..a6756d1dd0 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -8,6 +8,8 @@ #define B_CONFUSION_SELF_DMG_CHANCE GEN_LATEST // In Gen7+, confusion has a 33.3% of self-damage, instead of 50%. #define B_MULTI_HIT_CHANCE GEN_LATEST // In Gen5+, multi-hit moves have different %. See Cmd_setmultihitcounter for values. #define B_WHITEOUT_MONEY GEN_LATEST // In Gen4+, the amount of money lost by losing a battle is determined by the amount of badges earned. Previously, it would cut the current money by half. (While this change was also in FRLG, for the sake of simplicity, setting this to GEN_3 will result in RSE behavior.) +#define B_LIGHT_BALL_ATTACK_BOOST GEN_LATEST // In Gen4+, Light Ball doubles the power of physical moves in addition to special moves. +#define B_SANDSTORM_SPDEF_BOOST GEN_LATEST // In Gen4+, Sandstorm weather multiplies the Sp. Defense of Rock-type Pokémon by x1.5. // Experience settings #define B_EXP_CATCH GEN_LATEST // In Gen6+, Pokémon get experience from catching. @@ -23,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. @@ -126,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/abilities.h b/include/constants/abilities.h index 94e5986f77..d844a94e11 100644 --- a/include/constants/abilities.h +++ b/include/constants/abilities.h @@ -324,8 +324,16 @@ #define ABILITY_ARMOR_TAIL 296 #define ABILITY_EARTH_EATER 297 #define ABILITY_MYCELIUM_MIGHT 298 +#define ABILITY_HOSPITALITY 299 +#define ABILITY_MINDS_EYE 300 +#define ABILITY_EMBODY_ASPECT_TEAL 301 +#define ABILITY_EMBODY_ASPECT_HEARTHFLAME 302 +#define ABILITY_EMBODY_ASPECT_WELLSPRING 303 +#define ABILITY_EMBODY_ASPECT_CORNERSTONE 304 +#define ABILITY_TOXIC_CHAIN 305 +#define ABILITY_SUPERSWEET_SYRUP 306 -#define ABILITIES_COUNT_GEN9 299 +#define ABILITIES_COUNT_GEN9 307 #define ABILITIES_COUNT ABILITIES_COUNT_GEN9 diff --git a/include/constants/battle.h b/include/constants/battle.h index 68fade0ff9..a96f13164a 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -189,6 +189,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) @@ -385,8 +386,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 90d14d58fb..d5b8db6183 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -414,7 +414,10 @@ #define EFFECT_MORTAL_SPIN 408 #define EFFECT_GIGATON_HAMMER 409 #define EFFECT_SALT_CURE 410 +#define EFFECT_MATCHA_GOTCHA 411 +#define EFFECT_SYRUP_BOMB 412 +#define EFFECT_IVY_CUDGEL 413 -#define NUM_BATTLE_MOVE_EFFECTS 411 +#define NUM_BATTLE_MOVE_EFFECTS 414 #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 86a80c33cb..54b7a4437c 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -670,8 +670,10 @@ #define STRINGID_CURRENTMOVECANTSELECT 668 #define STRINGID_TARGETISBEINGSALTCURED 669 #define STRINGID_TARGETISHURTBYSALTCURE 670 +#define STRINGID_OPPORTUNISTCOPIED 671 +#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 672 -#define BATTLESTRINGS_COUNT 671 +#define BATTLESTRINGS_COUNT 673 // 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/item_effects.h b/include/constants/item_effects.h index fca7924514..ac1c7d5c5b 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -66,6 +66,7 @@ #define ITEM6_ADD_EV 10 #define ITEM6_SUBTRACT_EV -10 #define ITEM6_ADD_ONE_EV 1 +#define ITEM6_RESET_EV 0 // Used for GetItemEffectType. #define ITEM_EFFECT_X_ITEM 0 diff --git a/include/constants/items.h b/include/constants/items.h index 20cbc6379b..1cf69b9da4 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -914,7 +914,23 @@ #define ITEM_PEAT_BLOCK 797 #define ITEM_BERSERK_GENE 798 -#define ITEMS_COUNT 799 +#define ITEM_FAIRY_FEATHER 799 +#define ITEM_SYRUPY_APPLE 800 +#define ITEM_UNREMARKABLE_TEACUP 801 +#define ITEM_MASTERPIECE_TEACUP 802 +#define ITEM_CORNERSTONE_MASK 803 +#define ITEM_WELLSPRING_MASK 804 +#define ITEM_HEARTHFLAME_MASK 805 +#define ITEM_HEALTH_MOCHI 806 +#define ITEM_MUSCLE_MOCHI 807 +#define ITEM_RESIST_MOCHI 808 +#define ITEM_GENIUS_MOCHI 809 +#define ITEM_CLEVER_MOCHI 810 +#define ITEM_SWIFT_MOCHI 811 +#define ITEM_FRESH_START_MOCHI 812 +#define ITEM_GLIMMERING_CHARM 813 + +#define ITEMS_COUNT 814 #define ITEM_FIELD_ARROW ITEMS_COUNT // A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations diff --git a/include/constants/moves.h b/include/constants/moves.h index dd00aacb45..b3a881b77f 100644 --- a/include/constants/moves.h +++ b/include/constants/moves.h @@ -860,8 +860,12 @@ #define MOVE_MAGICAL_TORQUE 826 #define MOVE_PSYBLADE 827 #define MOVE_HYDRO_STEAM 828 +#define MOVE_BLOOD_MOON 829 +#define MOVE_MATCHA_GOTCHA 830 +#define MOVE_SYRUP_BOMB 831 +#define MOVE_IVY_CUDGEL 832 -#define MOVES_COUNT_GEN9 829 +#define MOVES_COUNT_GEN9 833 #define MOVES_COUNT MOVES_COUNT_GEN9 diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index e3dd15000f..6ff50807af 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 09d24fc31a..0cf0f356dd 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -6158,6 +6158,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/item_use.h b/include/item_use.h index 6b3d0c590e..05ff09c0bc 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -13,6 +13,7 @@ void ItemUseOutOfBattle_WailmerPail(u8); void ItemUseOutOfBattle_Medicine(u8); void ItemUseOutOfBattle_AbilityCapsule(u8); void ItemUseOutOfBattle_AbilityPatch(u8); +void ItemUseOutOfBattle_ResetEVs(u8); void ItemUseOutOfBattle_ReduceEV(u8); void ItemUseOutOfBattle_SacredAsh(u8); void ItemUseOutOfBattle_PPRecovery(u8); diff --git a/include/party_menu.h b/include/party_menu.h index 38139cc962..1b618741cb 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -53,6 +53,7 @@ void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task); void ItemUseCB_Medicine(u8 taskId, TaskFunc task); void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task); void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task); +void ItemUseCB_ResetEVs(u8 taskId, TaskFunc task); void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task); void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task); void ItemUseCB_PPUp(u8 taskId, TaskFunc task); diff --git a/include/random.h b/include/random.h index db1dea3983..af3d7c75e5 100644 --- a/include/random.h +++ b/include/random.h @@ -92,6 +92,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/strings.h b/include/strings.h index a298a2f9ae..4fd5670a0d 100644 --- a/include/strings.h +++ b/include/strings.h @@ -3166,4 +3166,6 @@ extern const u8 gText_TellHimTheWords[]; extern const u8 gText_ExpShareOn[]; extern const u8 gText_ExpShareOff[]; +extern const u8 gText_BasePointsResetToZero[]; + #endif // GUARD_STRINGS_H diff --git a/include/test/battle.h b/include/test/battle.h index 2314e0961c..f0808c6d09 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/include/test_runner.h b/include/test_runner.h index 78c41ac31e..e0df88b0a6 100644 --- a/include/test_runner.h +++ b/include/test_runner.h @@ -24,8 +24,6 @@ void TestRunner_Battle_CheckBattleRecordActionType(u32 battlerId, u32 recordInde u32 TestRunner_Battle_GetForcedAbility(u32 side, u32 partyIndex); -s32 MgbaPrintf_(const char *fmt, ...); - #else #define TestRunner_Battle_RecordAbilityPopUp(...) (void)0 @@ -45,8 +43,6 @@ s32 MgbaPrintf_(const char *fmt, ...); #define TestRunner_Battle_GetForcedAbility(...) (u32)0 -#define MgbaPrintf_(...) (u32)0 - #endif #endif 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 9ff37fd45d..6ed887cb69 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)) @@ -2534,8 +2521,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (instructedMove == MOVE_NONE || gBattleMoves[instructedMove].instructBanned - || MoveRequiresRecharging(instructedMove) - || MoveCallsOtherMove(instructedMove) + || gBattleMoves[instructedMove].effect == EFFECT_RECHARGE || IsZMove(instructedMove) || (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF) || gBattleMons[battlerDef].status2 & STATUS2_MULTIPLETURNS @@ -3154,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]; @@ -3185,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); } @@ -3829,10 +3801,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 { @@ -3853,10 +3822,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); @@ -3905,9 +3871,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; @@ -4363,9 +4328,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 b6d3d4f363..64936e0b98 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -383,41 +383,6 @@ static const u16 sIgnoredPowerfulMoveEffects[] = IGNORED_MOVES_END }; -static const u16 sIgnoreMoldBreakerMoves[] = -{ - MOVE_MOONGEIST_BEAM, - MOVE_SUNSTEEL_STRIKE, - MOVE_PHOTON_GEYSER, - MOVE_LIGHT_THAT_BURNS_THE_SKY, - MOVE_MENACING_MOONRAZE_MAELSTROM, - MOVE_SEARING_SUNRAZE_SMASH, -}; - -static const u16 sRechargeMoves[] = -{ - MOVE_HYPER_BEAM, - MOVE_BLAST_BURN, - MOVE_HYDRO_CANNON, - MOVE_FRENZY_PLANT, - MOVE_GIGA_IMPACT, - MOVE_ROCK_WRECKER, - MOVE_ROAR_OF_TIME, - MOVE_PRISMATIC_LASER, - MOVE_METEOR_ASSAULT, - MOVE_ETERNABEAM, -}; - -static const u16 sOtherMoveCallingMoves[] = -{ - MOVE_ASSIST, - MOVE_COPYCAT, - MOVE_ME_FIRST, - MOVE_METRONOME, - MOVE_MIRROR_MOVE, - MOVE_NATURE_POWER, - MOVE_SLEEP_TALK, -}; - // Functions u32 GetAIChosenMove(u32 battlerId) { @@ -651,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) @@ -702,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; @@ -741,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) @@ -846,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; @@ -859,7 +820,6 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes gBattleStruct->beatUpSlot = 0; } break; - #endif } // Handle other multi-strike moves @@ -1265,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); @@ -1311,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); @@ -1500,18 +1459,10 @@ 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 - for (i = 0; i < ARRAY_COUNT(sIgnoreMoldBreakerMoves); i++) - { - if (move == sIgnoreMoldBreakerMoves[i]) - return TRUE; - } - - if (IsMoldBreakerTypeAbility(atkAbility)) + if (IsMoldBreakerTypeAbility(atkAbility) || gBattleMoves[move].ignoresTargetAbility) return TRUE; return FALSE; @@ -1536,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 @@ -1546,8 +1495,6 @@ u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move) bool32 IsAromaVeilProtectedMove(u32 move) { - u32 i; - switch (move) { case MOVE_DISABLE: @@ -1672,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); @@ -1687,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; @@ -1722,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; } @@ -1849,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 @@ -2340,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: @@ -2359,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; } @@ -2453,28 +2391,6 @@ bool32 IsEncoreEncouragedEffect(u32 moveEffect) return FALSE; } -bool32 MoveRequiresRecharging(u32 move) -{ - u32 i; - for (i = 0; i < ARRAY_COUNT(sRechargeMoves); i++) - { - if (move == sRechargeMoves[i]) - return TRUE; - } - return FALSE; -} - -bool32 MoveCallsOtherMove(u32 move) -{ - u32 i; - for (i = 0; i < ARRAY_COUNT(sOtherMoveCallingMoves); i++) - { - if (move == sOtherMoveCallingMoves[i]) - return TRUE; - } - return FALSE; -} - static u32 GetLeechSeedDamage(u32 battlerId) { u32 damage = 0; @@ -2520,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; } @@ -2768,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 @@ -2778,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 @@ -2921,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; @@ -3474,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; @@ -3557,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(); @@ -3645,7 +3550,6 @@ bool32 IsPartyFullyHealedExceptBattler(u32 battlerId) bool32 PartyHasMoveSplit(u32 battlerId, u32 split) { - u32 firstId, lastId; struct Pokemon *party = GetBattlerParty(battlerId); u32 i, j; @@ -3781,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: @@ -3821,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; } @@ -3853,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); } } @@ -3876,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); } } @@ -3904,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); } } @@ -3917,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) @@ -3942,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); } } @@ -3955,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 1f04e01697..49607a1565 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); @@ -8727,6 +8725,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 @@ -8754,6 +8753,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 c74ccc3c18..61cf11a0a5 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -856,11 +856,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 0ac5c38923..56f7a0c083 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -590,9 +590,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] = @@ -622,8 +621,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 516e299b43..07c8cbbf14 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) @@ -716,25 +717,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) @@ -1788,7 +1790,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 3a335be2c0..332d6fbc78 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -841,7 +841,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 064241c6e3..d71fa5e5bf 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); @@ -886,14 +889,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); @@ -907,15 +908,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 d1e5757fb9..6c2b8168dc 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 @@ -995,10 +989,8 @@ void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHPBoxes) MegaIndicator_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 } } @@ -1090,7 +1082,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; @@ -1692,7 +1684,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); @@ -1739,7 +1730,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); @@ -1754,7 +1744,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; @@ -2614,15 +2604,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 { @@ -3239,10 +3226,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); @@ -3312,7 +3301,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) @@ -3395,18 +3383,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, @@ -3457,9 +3437,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)) @@ -3468,12 +3447,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))) { @@ -3510,10 +3489,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) @@ -3571,7 +3548,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; @@ -3592,27 +3570,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) @@ -3672,13 +3648,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 c303baaa66..11e07bab73 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 6671513253..325d66eb23 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,8 +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 CheckMegaEvolutionBeforeTurn(void); static void CheckQuickClaw_CustapBerryActivation(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); static void ReturnFromBattleToOverworld(void); @@ -134,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 @@ -236,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; @@ -509,7 +500,6 @@ void CB2_InitBattle(void) static void CB2_InitBattleInternal(void) { s32 i; - u16 targetSpecies; SetHBlankCallback(NULL); SetVBlankCallback(NULL); @@ -606,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); } @@ -1941,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 @@ -2697,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) @@ -3244,6 +3207,7 @@ void SwitchInClearSetData(u32 battler) gSelectedMonPartyId = PARTY_SIZE; // Allow for illegal abilities within tests. + #if TESTING if (gTestRunnerEnabled) { u32 side = GetBattlerSide(battler); @@ -3251,6 +3215,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); } @@ -3516,11 +3481,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 @@ -3589,11 +3553,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; @@ -3631,11 +3594,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 @@ -3655,14 +3617,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); } @@ -3750,6 +3711,7 @@ static void TryDoEventsBeforeFirstTurn(void) } // Allow for illegal abilities within tests. + #if TESTING if (gTestRunnerEnabled && gBattleStruct->switchInAbilitiesCounter == 0) { for (i = 0; i < gBattlersCount; ++i) @@ -3760,6 +3722,7 @@ static void TryDoEventsBeforeFirstTurn(void) gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex); } } + #endif // TESTING if (gBattleStruct->switchInAbilitiesCounter == 0) { @@ -3790,14 +3753,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) @@ -3822,6 +3784,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; @@ -3855,6 +3820,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) @@ -3994,10 +3961,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) @@ -4661,11 +4626,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; } @@ -4697,9 +4658,7 @@ s8 GetMovePriority(u32 battler, u16 move) priority = gBattleMoves[move].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++; @@ -4749,7 +4708,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 @@ -4759,7 +4718,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 @@ -4968,6 +4927,7 @@ static void TurnValuesCleanUp(bool8 var0) gProtectStructs[i].kingsShielded = FALSE; gProtectStructs[i].banefulBunkered = FALSE; gProtectStructs[i].quash = FALSE; + gProtectStructs[i].usedCustapBerry = FALSE; } else { @@ -5013,8 +4973,6 @@ static bool32 TryDoMegaEvosBeforeMoves(void) if (!(gHitMarker & HITMARKER_RUN) && (gBattleStruct->mega.toEvolve || gBattleStruct->burst.toBurst)) { u32 i, battler; - struct Pokemon *party; - struct Pokemon *mon; u8 megaOrder[MAX_BATTLERS_COUNT]; PopulateArrayWithBattlers(megaOrder); @@ -5027,8 +4985,6 @@ static bool32 TryDoMegaEvosBeforeMoves(void) gBattlerAttacker = megaOrder[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 @@ -5042,17 +4998,14 @@ static bool32 TryDoMegaEvosBeforeMoves(void) battler = gBattlerAttacker = megaOrder[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; } @@ -5061,7 +5014,6 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) if (!(gHitMarker & HITMARKER_RUN)) { u32 i; - struct Pokemon *mon; u8 battlers[MAX_BATTLERS_COUNT]; PopulateArrayWithBattlers(battlers); @@ -5134,7 +5086,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) @@ -5404,9 +5355,8 @@ 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 for (i = 0; i < PARTY_SIZE; i++) { bool8 changedForm = FALSE; @@ -5422,11 +5372,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 @@ -5459,10 +5407,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; } @@ -5640,6 +5587,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) @@ -5737,9 +5688,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 9ca01f8cf9..6999932ef3 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!"); @@ -807,9 +807,12 @@ 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_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, @@ -1469,6 +1472,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[] = @@ -1850,11 +1854,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, @@ -2948,7 +2948,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) @@ -3016,7 +3016,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) { @@ -3068,7 +3068,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)) { @@ -3088,7 +3088,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)) { @@ -3164,7 +3164,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; @@ -3745,7 +3744,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; @@ -3785,7 +3784,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; @@ -4028,9 +4027,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 7952a75b4e..0c42bedbb9 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 @@ -1284,10 +1275,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; @@ -1345,10 +1334,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; @@ -1542,13 +1529,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)) { @@ -1588,14 +1573,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) @@ -1604,13 +1587,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) { @@ -1735,12 +1718,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; } @@ -1927,9 +1908,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); // Record ability only if move had at least +3 chance to get a crit @@ -2037,20 +2016,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) @@ -2058,15 +2034,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; @@ -2087,12 +2060,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; @@ -2285,18 +2256,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); @@ -2581,8 +2545,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; @@ -2590,7 +2553,6 @@ static void Cmd_resultmessage(void) gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance; return; } - #endif else { gBattleCommunication[MSG_DISPLAY] = 0; @@ -2752,7 +2714,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; @@ -3035,13 +2997,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]; @@ -3140,11 +3105,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]; @@ -3186,11 +3147,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); } @@ -3210,15 +3172,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; @@ -3510,6 +3466,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; @@ -3565,10 +3523,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; @@ -3681,6 +3636,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; } } @@ -4114,16 +4082,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); @@ -4141,12 +4110,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; @@ -4171,9 +4142,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 { @@ -4197,11 +4167,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; } @@ -4354,7 +4320,6 @@ static void Cmd_getexp(void) } } -#if B_MULTI_BATTLE_WHITEOUT >= GEN_4 static bool32 NoAliveMonsForPlayerAndPartner(void) { u32 i; @@ -4374,7 +4339,6 @@ static bool32 NoAliveMonsForPlayerAndPartner(void) return (HP_count == 0); } -#endif static bool32 NoAliveMonsForPlayer(void) { @@ -4439,8 +4403,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; @@ -4450,10 +4413,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; @@ -4947,14 +4906,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 @@ -5272,11 +5229,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; @@ -5350,10 +5306,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; @@ -5429,6 +5382,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 @@ -6033,19 +5992,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; } @@ -6056,10 +6013,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; @@ -6078,12 +6033,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; @@ -6963,6 +6917,8 @@ static void Cmd_switchineffects(void) { if (DoSwitchInAbilitiesItems(battler)) return; + else if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0)) + return; } gDisableStructs[battler].stickyWebDone = FALSE; @@ -7643,9 +7599,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))) @@ -8209,15 +8163,13 @@ static bool32 TryDefogClear(u32 battlerAtk, bool32 clear) DEFOG_CLEAR(SIDE_STATUS_STEALTH_ROCK, stealthRockAmount, BattleScript_StealthRockDefog, 0); DEFOG_CLEAR(SIDE_STATUS_TOXIC_SPIKES, toxicSpikesAmount, BattleScript_ToxicSpikesDefog, 0); DEFOG_CLEAR(SIDE_STATUS_STICKY_WEB, stickyWebAmount, BattleScript_StickyWebDefog, 0); - #if 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; @@ -8365,7 +8317,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]; @@ -8488,7 +8440,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; @@ -9062,6 +9014,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: @@ -9228,11 +9181,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; @@ -9479,8 +9428,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); } @@ -9771,7 +9722,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; @@ -9883,7 +9834,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 } @@ -9891,19 +9842,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 @@ -11053,14 +11004,19 @@ static void Cmd_manipulatedamage(void) gBattleMoveDamage *= -1; break; case DMG_RECOIL_FROM_MISS: - #if B_RECOIL_IF_MISS_DMG >= GEN_5 - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 2; - #elif B_RECOIL_IF_MISS_DMG == GEN_4 - if ((gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage) - gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 2; - #else - gBattleMoveDamage /= 2; - #endif + if (B_RECOIL_IF_MISS_DMG >= GEN_5) + { + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 2; + } + else if (B_RECOIL_IF_MISS_DMG == GEN_4) + { + if ((gBattleMons[gBattlerTarget].maxHP / 2) < gBattleMoveDamage) + gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP / 2; + } + else + { + gBattleMoveDamage /= 2; + } if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; break; @@ -11184,11 +11140,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; } @@ -11363,6 +11316,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; } } @@ -11617,12 +11572,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; } } } @@ -11680,7 +11642,7 @@ static void Cmd_normalisebuffs(void) { CMD_ARGS(); - s32 i, j; + s32 i; for (i = 0; i < gBattlersCount; i++) TryResetBattlerStatChanges(i); @@ -11727,13 +11689,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 } } @@ -11759,7 +11720,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; @@ -11815,7 +11775,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = 6; - monsCount = 6; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11833,7 +11792,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE / 2; } - monsCount = PARTY_SIZE / 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11850,7 +11808,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE / 2; } - monsCount = PARTY_SIZE / 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11860,7 +11817,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = PARTY_SIZE; - monsCount = PARTY_SIZE; } else { @@ -11874,7 +11830,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 +11838,6 @@ static void Cmd_forcerandomswitch(void) { firstMonId = 0; lastMonId = PARTY_SIZE; - monsCount = PARTY_SIZE; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -11891,7 +11845,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]; } @@ -11950,68 +11903,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) @@ -12021,15 +11950,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) @@ -12120,10 +12076,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; } @@ -12141,13 +12095,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; @@ -12530,12 +12482,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; } @@ -12612,13 +12559,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 @@ -12655,7 +12601,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 @@ -12823,26 +12768,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); @@ -12916,11 +12841,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 @@ -12944,17 +12865,9 @@ static void Cmd_tryspiteppreduce(void) break; } - #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; if (gBattleMons[gBattlerTarget].pp[i] < ppToDeduct) ppToDeduct = gBattleMons[gBattlerTarget].pp[i]; @@ -13740,16 +13653,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; @@ -13860,26 +13776,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; @@ -13923,9 +13842,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; @@ -14064,14 +13981,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, gBattleMons[gBattlerTarget].maxHP / 2); - #endif + { + gBattleMoveDamage = max(1, gBattleMons[gBattlerTarget].maxHP / 2); + } gBattleMoveDamage *= -1; if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) @@ -14492,31 +14412,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; @@ -14539,11 +14454,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; @@ -14650,7 +14561,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; @@ -14658,18 +14570,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; @@ -14677,14 +14592,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) @@ -14697,10 +14614,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) @@ -14847,18 +14762,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 @@ -14941,81 +14853,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) @@ -15027,11 +14918,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++) @@ -15057,44 +14944,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; @@ -15474,17 +15362,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; } @@ -15720,8 +15605,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; @@ -15744,9 +15633,6 @@ static bool32 CriticalCapture(u32 odds) return TRUE; return FALSE; -#else - return FALSE; -#endif } static const u16 sParentalBondBannedEffects[] = @@ -15775,7 +15661,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++) @@ -15880,7 +15766,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 2ef1fa0572..5429788d23 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); @@ -577,12 +576,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()) @@ -828,10 +825,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]; @@ -855,8 +850,7 @@ void HandleAction_ActionFinished(void) gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 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 @@ -886,7 +880,6 @@ void HandleAction_ActionFinished(void) } } } - #endif } static const u8 sAbilitiesAffectedByMoldBreaker[] = @@ -1342,7 +1335,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); @@ -1575,11 +1567,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: @@ -1591,6 +1578,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; } @@ -2417,25 +2408,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: @@ -2480,8 +2467,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)) { @@ -2489,7 +2476,6 @@ u8 DoFieldEndTurnEffects(void) BattleScriptExecute(BattleScript_AffectionBasedStatusHeal); break; } - #endif } gBattleStruct->turnCountersTracker++; break; @@ -2541,6 +2527,7 @@ enum ENDTURN_PLASMA_FISTS, ENDTURN_CUD_CHEW, ENDTURN_SALT_CURE, + ENDTURN_SYRUP_BOMB, ENDTURN_BATTLER_COUNT }; @@ -2709,11 +2696,7 @@ u8 DoBattlerEndTurnEffects(void) && gBattleMons[battler].hp != 0) { MAGIC_GUARD_CHECK; - #if B_BURN_DAMAGE >= GEN_7 - gBattleMoveDamage = gBattleMons[battler].maxHP / 16; - #else - gBattleMoveDamage = gBattleMons[battler].maxHP / 8; - #endif + gBattleMoveDamage = gBattleMons[battler].maxHP / (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. @@ -2732,11 +2715,7 @@ u8 DoBattlerEndTurnEffects(void) && gBattleMons[battler].hp != 0) { MAGIC_GUARD_CHECK; - #if B_BURN_DAMAGE >= GEN_7 - gBattleMoveDamage = gBattleMons[battler].maxHP / 16; - #else - gBattleMoveDamage = gBattleMons[battler].maxHP / 8; - #endif + gBattleMoveDamage = gBattleMons[battler].maxHP / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; BattleScriptExecute(BattleScript_FrostbiteTurnDmg); @@ -2791,15 +2770,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 = gBattleMons[battler].maxHP / 6; + gBattleMoveDamage = gBattleMons[battler].maxHP / (B_BINDING_DAMAGE >= GEN_6 ? 6 : 8); else - gBattleMoveDamage = gBattleMons[battler].maxHP / 8; - #else - gBattleMoveDamage = gBattleMons[battler].maxHP / 8; - else - gBattleMoveDamage = gBattleMons[battler].maxHP / 16; - #endif + gBattleMoveDamage = gBattleMons[battler].maxHP / (B_BINDING_DAMAGE >= GEN_6 ? 8 : 16); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; @@ -2990,11 +2963,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); @@ -3116,6 +3089,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_BATTLER_COUNT: // done gBattleStruct->turnEffectsTracker = 0; gBattleStruct->turnEffectsBattlerId++; @@ -3272,27 +3266,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 @@ -3546,11 +3538,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; @@ -3664,11 +3652,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; @@ -3773,8 +3758,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; @@ -3791,7 +3775,6 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gBattleStruct->beatUpSlot = 0; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } - #endif gBattleStruct->atkCancellerTracker++; break; case CANCELLER_END: @@ -4021,14 +4004,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]); @@ -4163,7 +4144,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; @@ -4173,9 +4153,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 @@ -4199,24 +4176,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); @@ -4224,16 +4202,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; @@ -4270,16 +4247,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; } @@ -4367,7 +4345,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; @@ -4564,19 +4541,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; @@ -4838,11 +4812,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++) { @@ -5037,10 +5007,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)) { @@ -5081,11 +5048,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; @@ -5122,9 +5085,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); } } } @@ -5387,11 +5349,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 = gBattleMons[gBattlerAttacker].maxHP / 8; - #else - gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16; - #endif + gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16); if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -5738,9 +5696,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(); @@ -5789,6 +5747,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++) { @@ -5847,6 +5826,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect = 4; break; } + if (effect != 0) { switch (effect) @@ -5888,10 +5868,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; @@ -6237,15 +6215,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; @@ -6259,10 +6232,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) @@ -6361,11 +6332,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 @@ -6438,19 +6406,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); @@ -6486,8 +6445,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)) @@ -6593,9 +6550,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; @@ -6627,6 +6582,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(); @@ -6710,9 +6666,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) @@ -6758,46 +6712,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; } @@ -6828,64 +6783,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)) { @@ -7048,8 +7017,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; @@ -7093,39 +7061,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; @@ -7134,10 +7113,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); @@ -7145,7 +7127,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); @@ -7153,7 +7137,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); @@ -7161,13 +7147,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); @@ -7175,7 +7165,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; @@ -7184,7 +7176,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) @@ -7229,12 +7223,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; @@ -7366,11 +7361,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 = gBattleMons[battler].maxHP / 16; if (gBattleMoveDamage == 0) @@ -7619,10 +7611,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 @@ -7645,7 +7635,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; @@ -7661,11 +7651,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; @@ -7703,7 +7690,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; @@ -7759,7 +7746,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: @@ -7770,7 +7757,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: @@ -7781,7 +7768,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: @@ -7792,7 +7779,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 @@ -7956,7 +7943,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; @@ -8061,10 +8048,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; @@ -8078,11 +8063,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) @@ -8293,10 +8277,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) @@ -8689,10 +8671,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: @@ -8730,18 +8709,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: @@ -8762,9 +8740,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)) @@ -8830,20 +8807,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)); @@ -8854,25 +8824,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) @@ -8907,9 +8871,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: @@ -8966,7 +8930,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) @@ -9118,11 +9086,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: @@ -9164,7 +9130,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) { @@ -9260,26 +9225,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)); @@ -9335,7 +9298,7 @@ static inline u32 CalcAttackStat(u32 move, u32 battlerAtk, u32 battlerDef, u32 m modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_LIGHT_BALL: - if (atkBaseSpeciesId == SPECIES_PIKACHU) + if (atkBaseSpeciesId == SPECIES_PIKACHU && (B_LIGHT_BALL_ATTACK_BOOST >= GEN_4 || IS_MOVE_SPECIAL(move))) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(2.0)); break; case HOLD_EFFECT_CHOICE_BAND: @@ -9401,11 +9364,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) @@ -9491,21 +9452,20 @@ 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 - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && weather & B_WEATHER_SANDSTORM && !usesDefStat) + if (B_SANDSTORM_SPDEF_BOOST >= GEN_4 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ROCK) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SANDSTORM) && !usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); // snow def boost for ice types - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && weather & B_WEATHER_SNOW && usesDefStat) + if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE) && IsBattlerWeatherAffected(battlerDef, B_WEATHER_SNOW) && usesDefStat) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); // The defensive stats of a Player's Pokémon are boosted by x1.1 (+10%) if they have the 5th badge and 7th badges. @@ -9524,34 +9484,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); } @@ -9559,7 +9495,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) @@ -9598,12 +9534,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); @@ -9611,7 +9547,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 GetZMoveAgainstProtectionModifier(u32 battlerDef) @@ -10001,12 +9939,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)) { @@ -10020,12 +9954,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) @@ -10110,10 +10042,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]; } @@ -10208,7 +10138,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)); @@ -10242,7 +10172,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) @@ -10272,7 +10201,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)); @@ -10305,7 +10234,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. @@ -10352,17 +10280,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++) { @@ -10613,16 +10539,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; } @@ -10632,17 +10559,15 @@ u8 GetBattleMoveSplit(u32 moveId) return gBattleStruct->zmove.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) @@ -10719,9 +10644,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 @@ -10856,9 +10779,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) @@ -10882,9 +10803,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; @@ -10911,14 +10830,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) @@ -11043,7 +10962,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)) @@ -11056,8 +10976,6 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch return FALSE; return TRUE; - #endif - return FALSE; } u16 GetUsedHeldItem(u32 battler) @@ -11082,8 +11000,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; @@ -11103,19 +11019,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) @@ -11176,6 +11084,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) @@ -11191,7 +11107,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); @@ -11200,7 +11116,7 @@ bool32 IsGen6ExpShareEnabled(void) u8 GetBattlerType(u32 battler, u8 typeIndex) -{ +{ u16 types[3] = {0}; types[0] = gBattleMons[battler].type1; types[1] = gBattleMons[battler].type2; @@ -11212,11 +11128,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 80ac9f9458..bdc46d2327 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -4078,11 +4078,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [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, @@ -13813,6 +13809,68 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .zMoveEffect = Z_EFFECT_NONE, }, + [MOVE_BLOOD_MOON] = + { + .effect = EFFECT_GIGATON_HAMMER, + .power = 140, + .type = TYPE_NORMAL, + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .split = SPLIT_SPECIAL, + .zMoveEffect = Z_EFFECT_NONE, + }, + + [MOVE_MATCHA_GOTCHA] = + { + .effect = EFFECT_MATCHA_GOTCHA, + .power = 80, + .type = TYPE_GRASS, + .accuracy = 90, + .pp = 15, + .secondaryEffectChance = 20, + .target = MOVE_TARGET_BOTH, + .priority = 0, + .split = SPLIT_SPECIAL, + .zMoveEffect = Z_EFFECT_NONE, + .thawsUser = TRUE, + .metronomeBanned = TRUE, + }, + + [MOVE_SYRUP_BOMB] = + { + .effect = EFFECT_SYRUP_BOMB, + .power = 60, + .type = TYPE_GRASS, + .accuracy = 85, + .pp = 10, + .secondaryEffectChance = 100, // syrup bomb volatile status + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .split = SPLIT_SPECIAL, + .zMoveEffect = Z_EFFECT_NONE, + .ballisticMove = TRUE, + .metronomeBanned = TRUE, + }, + + [MOVE_IVY_CUDGEL] = + { + .effect = EFFECT_IVY_CUDGEL, + .power = 100, + .type = TYPE_GRASS, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .split = SPLIT_PHYSICAL, + .zMoveEffect = Z_EFFECT_NONE, + .highCritRatio = TRUE, + .metronomeBanned = TRUE, + }, + // Z-Moves [MOVE_BREAKNECK_BLITZ] = { diff --git a/src/data/contest_moves.h b/src/data/contest_moves.h index 3d633a2562..6084091683 100644 --- a/src/data/contest_moves.h +++ b/src/data/contest_moves.h @@ -6066,6 +6066,14 @@ const struct ContestMove gContestMoves[MOVES_COUNT] = [MOVE_PSYBLADE] = {0}, // TODO [MOVE_HYDRO_STEAM] = {0}, // TODO + + [MOVE_BLOOD_MOON] = {0}, // TODO + + [MOVE_MATCHA_GOTCHA] = {0}, // TODO + + [MOVE_SYRUP_BOMB] = {0}, // TODO + + [MOVE_IVY_CUDGEL] = {0}, // TODO }; const struct ContestEffect gContestEffects[] = diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 7c8afc0066..9ff1c5656d 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -6089,6 +6089,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/item_icon_table.h b/src/data/item_icon_table.h index a0a207be2d..30ae4ba19f 100644 --- a/src/data/item_icon_table.h +++ b/src/data/item_icon_table.h @@ -844,6 +844,21 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] = [ITEM_LINKING_CORD] = {gItemIcon_LinkingCord, gItemIconPalette_LinkingCord}, [ITEM_PEAT_BLOCK] = {gItemIcon_PeatBlock, gItemIconPalette_PeatBlock}, [ITEM_BERSERK_GENE] = {gItemIcon_BerserkGene, gItemIconPalette_BerserkGene}, + [ITEM_FAIRY_FEATHER] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_FairyFeather, gItemIconPalette_FairyFeather}, + [ITEM_SYRUPY_APPLE] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_SyrupyApple, gItemIconPalette_SyrupyApple}, + [ITEM_UNREMARKABLE_TEACUP] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_UnremarkableTeacup, gItemIconPalette_UnremarkableTeacup}, + [ITEM_MASTERPIECE_TEACUP] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_MasterpieceTeacup, gItemIconPalette_MasterpieceTeacup}, + [ITEM_CORNERSTONE_MASK] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_CornerstoneMask, gItemIconPalette_CornerstoneMask}, + [ITEM_WELLSPRING_MASK] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_WellspringMask, gItemIconPalette_WellspringMask}, + [ITEM_HEARTHFLAME_MASK] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_HearthflameMask, gItemIconPalette_HearthflameMask}, + [ITEM_HEALTH_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_HealthMochi}, + [ITEM_MUSCLE_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_MuscleMochi}, + [ITEM_RESIST_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_ResistMochi}, + [ITEM_GENIUS_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_GeniusMochi}, + [ITEM_CLEVER_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_CleverMochi}, + [ITEM_SWIFT_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_SwiftMochi}, + [ITEM_FRESH_START_MOCHI] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_Mochi, gItemIconPalette_FreshStartMochi}, + [ITEM_GLIMMERING_CHARM] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, // {gItemIcon_GlimmeringCharm, gItemIconPalette_GlimmeringCharm}, // Return to field arrow [ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow}, }; diff --git a/src/data/items.h b/src/data/items.h index 1093d29122..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, @@ -9649,4 +9645,174 @@ const struct Item gItems[] = .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 10, }, + + [ITEM_FAIRY_FEATHER] = + { + .name = _("Fairy Feather"), + .price = 1000, + .holdEffect = HOLD_EFFECT_FAIRY_POWER, + .holdEffectParam = TYPE_BOOST_PARAM, + .description = sFairyFeatherDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 10, + }, + + [ITEM_SYRUPY_APPLE] = + { + .name = _("Syrupy Apple"), + .price = 2200, + .description = sSyrupyAppleDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 30, + }, + + [ITEM_UNREMARKABLE_TEACUP] = + { + .name = _("UnrmkblTeacup"), + .price = 1600, + .description = sUnremarkableTeacupDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 80, + }, + + [ITEM_MASTERPIECE_TEACUP] = + { + .name = _("MstrpceTeacup"), + .price = 38000, + .description = sMasterpieceTeacupDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 80, + }, + + [ITEM_CORNERSTONE_MASK] = + { + .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] = + { + .name = _("Health Mochi"), + .price = 500, + .description = sHealthMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_MUSCLE_MOCHI] = + { + .name = _("Muscle Mochi"), + .price = 500, + .description = sMuscleMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_RESIST_MOCHI] = + { + .name = _("Resist Mochi"), + .price = 500, + .description = sResistMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_GENIUS_MOCHI] = + { + .name = _("Genius Mochi"), + .price = 500, + .description = sGeniusMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_CLEVER_MOCHI] = + { + .name = _("Clever Mochi"), + .price = 500, + .description = sCleverMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_SWIFT_MOCHI] = + { + .name = _("Swift Mochi"), + .price = 500, + .description = sSwiftMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Medicine, + .flingPower = 30, + }, + + [ITEM_FRESH_START_MOCHI] = + { + .name = _("FrshStrtMochi"), + .price = 300, + .description = sFreshStartMochiDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_ResetEVs, + .flingPower = 30, + }, + + [ITEM_GLIMMERING_CHARM] = + { + .name = _("GlmmringCharm"), + .price = 0, + .importance = 1, + .description = sGlimmeringCharmDesc, + .pocket = POCKET_KEY_ITEMS, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + }, }; diff --git a/src/data/pokemon/item_effects.h b/src/data/pokemon/item_effects.h index d7482d5043..81be2ca115 100644 --- a/src/data/pokemon/item_effects.h +++ b/src/data/pokemon/item_effects.h @@ -282,6 +282,49 @@ const u8 gItemEffect_SpdefFeather[11] = { [10] = 0, }; +const u8 gItemEffect_HpMochi[11] = { + [4] = ITEM4_EV_HP, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_AtkMochi[11] = { + [4] = ITEM4_EV_ATK, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_DefMochi[11] = { + [5] = ITEM5_EV_DEF, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_SpeedMochi[11] = { + [5] = ITEM5_EV_SPEED, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_SpatkMochi[11] = { + [5] = ITEM5_EV_SPATK, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_SpdefMochi[11] = { + [5] = ITEM5_EV_SPDEF, + [6] = ITEM6_ADD_EV, + [10] = 0, +}; + +const u8 gItemEffect_ResetMochi[11] = { + [4] = ITEM4_EV_HP | ITEM4_EV_ATK, + [5] = ITEM5_EV_DEF | ITEM5_EV_SPEED | ITEM5_EV_SPATK | ITEM5_EV_SPDEF, + [6] = ITEM6_RESET_EV, + [10] = 0, +}; + const u8 gItemEffect_RareCandy[10] = { [3] = ITEM3_LEVEL_UP, [4] = ITEM4_REVIVE | ITEM4_HEAL_HP, @@ -508,6 +551,15 @@ const u8 *const gItemEffectTable[ITEMS_COUNT] = [ITEM_CLEVER_FEATHER] = gItemEffect_SpdefFeather, [ITEM_SWIFT_FEATHER] = gItemEffect_SpeedFeather, + //Mochi + [ITEM_HEALTH_MOCHI] = gItemEffect_HpMochi, + [ITEM_MUSCLE_MOCHI] = gItemEffect_AtkMochi, + [ITEM_RESIST_MOCHI] = gItemEffect_DefMochi, + [ITEM_GENIUS_MOCHI] = gItemEffect_SpatkMochi, + [ITEM_CLEVER_MOCHI] = gItemEffect_SpdefMochi, + [ITEM_SWIFT_MOCHI] = gItemEffect_SpeedMochi, + [ITEM_FRESH_START_MOCHI] = gItemEffect_ResetMochi, + // Candy [ITEM_RARE_CANDY] = gItemEffect_RareCandy, [ITEM_EXP_CANDY_XS] = gItemEffect_RareCandy, 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 76904ecff0..52b5fac92c 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -12036,10 +12036,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, @@ -16972,9 +16972,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, @@ -16998,9 +16998,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, @@ -20653,7 +20653,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, @@ -20676,7 +20676,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, @@ -20921,7 +20921,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, }, @@ -21010,7 +21010,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, }, @@ -23130,7 +23130,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] = @@ -23153,7 +23153,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] = @@ -23176,7 +23176,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] = @@ -23199,7 +23199,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] = @@ -23222,7 +23222,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] = @@ -23237,7 +23237,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, @@ -23246,7 +23246,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] = @@ -23267,10 +23267,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 @@ -23294,7 +23294,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] = @@ -23318,7 +23318,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] = @@ -23341,7 +23341,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] = @@ -23364,7 +23364,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] = @@ -23387,7 +23387,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 @@ -23413,7 +23413,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] = @@ -23436,7 +23436,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] = @@ -23459,7 +23459,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 @@ -23484,7 +23484,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 @@ -24586,7 +24586,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, @@ -24609,11 +24609,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/data/text/abilities.h b/src/data/text/abilities.h index a3bad09b1b..dce75dd912 100644 --- a/src/data/text/abilities.h +++ b/src/data/text/abilities.h @@ -289,6 +289,14 @@ static const u8 sToxicDebrisDescription[] = _("Throws poison spikes if hit."); static const u8 sArmorTailDescription[] = _("Protects from priority."); static const u8 sEarthEaterDescription[] = _("Eats ground to heal HP."); static const u8 sMyceliumMightDescription[] = _("Status moves never fail."); +static const u8 sHospitalityDescription[] = _("Restores ally's HP."); +static const u8 sMindsEyeDescription[] = _("Keen Eye and Scrappy."); +static const u8 sEmbodyAspectTealDescription[] = _("Raises Speed."); +static const u8 sEmbodyAspectHearthflameDescription[] = _("Raises Attack."); +static const u8 sEmbodyAspectWellspringDescription[] = _("Raises Sp. Def."); +static const u8 sEmbodyAspectCornerstoneDescription[] = _("Raises Defense."); +static const u8 sToxicChainDescription[] = _("Moves can poison."); +static const u8 sSupersweetSyrupDescription[] = _("Lowers the foe's Speed."); #if B_EXPANDED_ABILITY_NAMES == TRUE const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = @@ -592,6 +600,14 @@ const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = [ABILITY_ARMOR_TAIL] = _("Armor Tail"), [ABILITY_EARTH_EATER] = _("Earth Eater"), [ABILITY_MYCELIUM_MIGHT] = _("Mycelium Might"), + [ABILITY_HOSPITALITY] = _("Hospitality"), + [ABILITY_MINDS_EYE] = _("Mind's Eye"), + [ABILITY_EMBODY_ASPECT_TEAL] = _("Embody Aspect"), + [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = _("Embody Aspect"), + [ABILITY_EMBODY_ASPECT_WELLSPRING] = _("Embody Aspect"), + [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("Embody Aspect"), + [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), + [ABILITY_SUPERSWEET_SYRUP] = _("Supersweet Syrup"), }; #else // 12 characters const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = @@ -895,6 +911,14 @@ const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = [ABILITY_ARMOR_TAIL] = _("Armor Tail"), [ABILITY_EARTH_EATER] = _("Earth Eater"), [ABILITY_MYCELIUM_MIGHT] = _("MceliumMight"), + [ABILITY_HOSPITALITY] = _("Hospitality"), + [ABILITY_MINDS_EYE] = _("Mind's Eye"), + [ABILITY_EMBODY_ASPECT_TEAL] = _("EmbodyAspect"), + [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = _("EmbodyAspect"), + [ABILITY_EMBODY_ASPECT_WELLSPRING] = _("EmbodyAspect"), + [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("EmbodyAspect"), + [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), + [ABILITY_SUPERSWEET_SYRUP] = _("SuprswtSyrup"), }; #endif @@ -1199,4 +1223,12 @@ const u8 *const gAbilityDescriptionPointers[ABILITIES_COUNT] = [ABILITY_ARMOR_TAIL] = sArmorTailDescription, [ABILITY_EARTH_EATER] = sEarthEaterDescription, [ABILITY_MYCELIUM_MIGHT] = sMyceliumMightDescription, + [ABILITY_HOSPITALITY] = sHospitalityDescription, + [ABILITY_MINDS_EYE] = sMindsEyeDescription, + [ABILITY_EMBODY_ASPECT_TEAL] = sEmbodyAspectTealDescription, + [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = sEmbodyAspectHearthflameDescription, + [ABILITY_EMBODY_ASPECT_WELLSPRING] = sEmbodyAspectWellspringDescription, + [ABILITY_EMBODY_ASPECT_CORNERSTONE] = sEmbodyAspectCornerstoneDescription, + [ABILITY_TOXIC_CHAIN] = sToxicChainDescription, + [ABILITY_SUPERSWEET_SYRUP] = sSupersweetSyrupDescription, }; diff --git a/src/data/text/item_descriptions.h b/src/data/text/item_descriptions.h index 0948fbe187..6e74ec173c 100644 --- a/src/data/text/item_descriptions.h +++ b/src/data/text/item_descriptions.h @@ -3918,3 +3918,78 @@ static const u8 sBerserkGene[] = _( "Sharply boosts\n" "Attack, but causes\n" "lasting confusion."); + +static const u8 sFairyFeatherDesc[] = _( + "A hold item that\n" + "raises the power of\n" + "Fairy-type moves."); + +static const u8 sSyrupyAppleDesc[] = _( + "A very syrupy apple\n" + "that makes certain\n" + "Pokémon evolve."); + +static const u8 sUnremarkableTeacupDesc[] = _( + "A cracked teacup\n" + "that makes certain\n" + "Pokémon evolve."); + +static const u8 sMasterpieceTeacupDesc[] = _( + "A chipped teacup\n" + "that makes certain\n" + "Pokémon evolve."); + +static const u8 sCornerstoneMaskDesc[] = _( + "Allows Ogerpon to\n" + "wield the Rock-\n" + "type in battle."); + +static const u8 sWellspringMaskDesc[] = _( + "Allows Ogerpon to\n" + "wield the Water-\n" + "type in battle."); + +static const u8 sHearthflameMaskDesc[] = _( + "Allows Ogerpon to\n" + "wield the Fire-\n" + "type in battle."); + +static const u8 sHealthMochiDesc[] = _( + "An item that raises\n" + "the base HP of\n" + "a Pokémon."); + +static const u8 sMuscleMochiDesc[] = _( + "An item that raises\n" + "the base Attack of\n" + "a Pokémon."); + +static const u8 sResistMochiDesc[] = _( + "An item that raises\n" + "the base Defense\n" + "of a Pokémon."); + +static const u8 sGeniusMochiDesc[] = _( + "An item that raises\n" + "the base Sp. Atk.\n" + "of a Pokémon."); + +static const u8 sCleverMochiDesc[] = _( + "An item that raises\n" + "the base Sp. Def.\n" + "of a Pokémon."); + +static const u8 sSwiftMochiDesc[] = _( + "An item that raises\n" + "the base Speed of\n" + "a Pokémon."); + +static const u8 sFreshStartMochiDesc[] = _( + "An item that resets\n" + "all base points of\n" + "a Pokémon."); + +static const u8 sGlimmeringCharmDesc[] = _( + "A charm that will\n" + "raise the shards\n" + "from Tera Raids."); diff --git a/src/data/text/move_descriptions.h b/src/data/text/move_descriptions.h index f950c2a1aa..3c1189144a 100644 --- a/src/data/text/move_descriptions.h +++ b/src/data/text/move_descriptions.h @@ -3260,6 +3260,22 @@ static const u8 sHydroSteamDescription[] = _( "This move's power increases\n" "under harsh sunlight."); +static const u8 sBloodMoonDescription[] = _( + "Unleashes the blood moon.\n" + "Can't be used twice in a row."); + +static const u8 sMatchaGotchaDescription[] = _( + "Absorbs half the damage\n" + "inflicted. May cause a burn."); + +static const u8 sSyrupBombDescription[] = _( + "Lowers the foe's speed\n" + "each turn for 3 turns."); + +static const u8 sIvyCudgelDescription[] = _( + "Type changes with held mask.\n" + "High critical-hit ratio."); + const u8 gNotDoneYetDescription[] = _( "This move can't be used. Its\n" "effect is in development."); @@ -4099,4 +4115,8 @@ const u8 *const gMoveDescriptionPointers[MOVES_COUNT - 1] = [MOVE_MAGICAL_TORQUE - 1] = sMagicalTorqueDescription, [MOVE_PSYBLADE - 1] = sPsybladeDescription, [MOVE_HYDRO_STEAM - 1] = sHydroSteamDescription, + [MOVE_BLOOD_MOON - 1] = sBloodMoonDescription, + [MOVE_MATCHA_GOTCHA - 1] = sMatchaGotchaDescription, + [MOVE_SYRUP_BOMB - 1] = sSyrupBombDescription, + [MOVE_IVY_CUDGEL - 1] = sIvyCudgelDescription, }; diff --git a/src/data/text/move_names.h b/src/data/text/move_names.h index 85d406dcab..8ec4520e94 100644 --- a/src/data/text/move_names.h +++ b/src/data/text/move_names.h @@ -831,6 +831,10 @@ const u8 gMoveNames[MOVES_COUNT][MOVE_NAME_LENGTH + 1] = [MOVE_MAGICAL_TORQUE] = _("Magical Torque"), [MOVE_PSYBLADE] = _("Psyblade"), [MOVE_HYDRO_STEAM] = _("Hydro Steam"), + [MOVE_BLOOD_MOON] = _("Blood Moon"), + [MOVE_MATCHA_GOTCHA] = _("Matcha Gotcha"), + [MOVE_SYRUP_BOMB] = _("Syrup Bomb"), + [MOVE_IVY_CUDGEL] = _("Ivy Cudgel"), }; #else // 12 letters @@ -1665,6 +1669,10 @@ const u8 gMoveNames[MOVES_COUNT][MOVE_NAME_LENGTH + 1] = [MOVE_MAGICAL_TORQUE] = _("MagiclTorque"), [MOVE_PSYBLADE] = _("Psyblade"), [MOVE_HYDRO_STEAM] = _("Hydro Steam"), + [MOVE_BLOOD_MOON] = _("Blood Moon"), + [MOVE_MATCHA_GOTCHA] = _("MatchaGotcha"), + [MOVE_SYRUP_BOMB] = _("Syrup Bomb"), + [MOVE_IVY_CUDGEL] = _("Ivy Cudgel"), }; #endif 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 853556db0b..64963f72d3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -281,12 +281,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); @@ -303,7 +301,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); @@ -1025,7 +1022,6 @@ static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMte gTasks[inputTaskId].tSubWindowId = 0; Debug_RefreshListMenu(inputTaskId); - //Debug_ShowMenuDynamic(inputTaskId); // draw everything CopyWindowToVram(windowId, COPYWIN_FULL); @@ -1182,10 +1178,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].tMenuTaskId; - 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) { @@ -1239,7 +1233,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; } @@ -1412,10 +1406,9 @@ static void DebugTask_HandleBattleMenuReDraw(u8 taskId) static void DebugTask_HandleMenuInput_Battle(u8 taskId) { - void (*func)(u8); - u8 listTaskId = gTasks[taskId].tMenuTaskId; - u32 input = ListMenu_ProcessInput(listTaskId); u16 idx; + u8 listTaskId = gTasks[taskId].tMenuTaskId; + ListMenu_ProcessInput(listTaskId); ListMenuGetCurrentItemArrayId(listTaskId, &idx); @@ -1618,12 +1611,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) { @@ -3629,7 +3616,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 eb3565fec6..3c0f2b986c 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -795,6 +795,12 @@ void ItemUseOutOfBattle_AbilityPatch(u8 taskId) SetUpItemUseCallback(taskId); } +void ItemUseOutOfBattle_ResetEVs(u8 taskId) +{ + gItemUseCB = ItemUseCB_ResetEVs; + SetUpItemUseCallback(taskId); +} + void ItemUseOutOfBattle_ReduceEV(u8 taskId) { gItemUseCB = ItemUseCB_ReduceEV; @@ -1051,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; @@ -1093,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); @@ -1110,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()) @@ -1210,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 71f1f8b8cf..01fa439cdd 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 4ed4433e65..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; @@ -4777,6 +4776,33 @@ static void Task_ClosePartyMenuAfterText(u8 taskId) } } +void ItemUseCB_ResetEVs(u8 taskId, TaskFunc task) +{ + struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; + u16 item = gSpecialVar_ItemId; + bool8 cannotUseEffect = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0); + + if (cannotUseEffect) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = task; + } + else + { + gPartyMenuUseExitCallback = TRUE; + PlaySE(SE_USE_ITEM); + RemoveBagItem(item, 1); + GetMonNickname(mon, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_BasePointsResetToZero); + DisplayPartyMenuMessage(gStringVar4, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = task; + } +} + void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; @@ -5270,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); @@ -5403,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); @@ -5413,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 61e35a66f9..d79a690c55 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 03c7c34712..7bbf2702e4 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4090,19 +4090,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); \ } @@ -4288,7 +4283,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; @@ -4308,12 +4303,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--) @@ -4350,7 +4345,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; } } @@ -4607,44 +4602,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; \ @@ -4748,7 +4719,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 @@ -5118,7 +5092,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) @@ -5781,12 +5758,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, @@ -5953,7 +5924,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov dataSigned += temp2; } - else // Decreasing EV (HP or Atk) + else if (evChange < 0) // Decreasing EV (HP or Atk) { if (dataSigned == 0) { @@ -5970,6 +5941,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (dataSigned < 0) dataSigned = 0; } + else // Reset EV (HP or Atk) + { + if (dataSigned == 0) + break; + + dataSigned = 0; + } // Update EVs and stats SetMonData(mon, sGetMonDataEVConstants[temp1], &dataSigned); @@ -6133,7 +6111,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov dataSigned += temp2; } - else // Decreasing EV + else if (evChange < 0) // Decreasing EV { if (dataSigned == 0) { @@ -6150,6 +6128,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (dataSigned < 0) dataSigned = 0; } + else // Reset EV + { + if (dataSigned == 0) + break; + + dataSigned = 0; + } // Update EVs and stats SetMonData(mon, sGetMonDataEVConstants[temp1 + 2], &dataSigned); @@ -6345,18 +6330,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) @@ -7491,7 +7478,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; @@ -7520,7 +7507,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; @@ -7545,7 +7532,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; @@ -8414,7 +8401,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]; @@ -8485,7 +8472,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) @@ -8513,7 +8500,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 3e3cdf470d..29a65da0fe 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 28a9626245..a6e4101d38 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/strings.c b/src/strings.c index b9a089ba32..52b6fefc02 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1833,7 +1833,7 @@ const u8 gText_Berry[] = _("BERRY"); const u8 gText_Berries[] = _("BERRIES"); const u8 gText_ExpShareOn[] = _("The Exp. Share has been turned on.{PAUSE_UNTIL_PRESS}"); const u8 gText_ExpShareOff[] = _("The Exp. Share has been turned off.{PAUSE_UNTIL_PRESS}"); - +const u8 gText_BasePointsResetToZero[] = _("{STR_VAR_1}'s base points\nwere all reset to zero!{PAUSE_UNTIL_PRESS}"); //HGSS_Ui PokedexPlus #if POKEDEX_PLUS_HGSS == TRUE const u8 gText_Stats_Buttons[] = _("{A_BUTTON}TOGGLE {DPAD_UPDOWN}MOVES"); 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 51daa11174..8482ff243c 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 @@ -1990,7 +1983,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; @@ -2092,7 +2084,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 @@ -2533,8 +2524,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"); } @@ -2547,7 +2536,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++) { @@ -2559,11 +2548,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;