diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 8e433916f9..8f23b0665d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1948,14 +1948,6 @@ various \battler, VARIOUS_RESTORE_PP .endm - .macro tryactivatemoxie battler:req - various \battler, VARIOUS_TRY_ACTIVATE_MOXIE - .endm - - .macro tryactivatebeastboost battler:req - various \battler, VARIOUS_TRY_ACTIVATE_BEAST_BOOST - .endm - .macro tryactivatereceiver battler:req various \battler, VARIOUS_TRY_ACTIVATE_RECEIVER .endm @@ -2239,10 +2231,6 @@ .4byte \jumpInstr .endm - .macro tryactivategrimneigh, battler:req - various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH - .endm - .macro consumeberry battler:req, fromBattler:req various \battler, VARIOUS_CONSUME_BERRY .byte \fromBattler @@ -2303,10 +2291,6 @@ .4byte \jumpInstr .endm - .macro tryactivatebattlebond battler:req - various \battler, VARIOUS_TRY_ACTIVATE_BATTLE_BOND - .endm - .macro jumpifcantreverttoprimal jumpInstr:req various BS_ATTACKER, VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL .4byte \jumpInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c058922e4e..bd6e742312 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3836,7 +3836,7 @@ BattleScript_EffectHoldHands:: attackcanceler attackstring ppreduce - jumpifsideaffecting BS_TARGET, SIDE_STATUS_CRAFTY_SHIELD, BattleScript_ButItFailed + accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_ButItFailed attackanimation waitanimation @@ -5414,10 +5414,6 @@ BattleScript_FaintTarget:: tryactivatefellstinger BS_ATTACKER tryactivatesoulheart tryactivatereceiver BS_TARGET - tryactivatemoxie BS_ATTACKER @ and chilling neigh, as one ice rider - tryactivatebeastboost BS_ATTACKER - tryactivategrimneigh BS_ATTACKER @ and as one shadow rider - tryactivatebattlebond BS_ATTACKER trytrainerslidefirstdownmsg BS_TARGET return @@ -8470,10 +8466,9 @@ BattleScript_RaiseStatOnFaintingTarget:: statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_RaiseStatOnFaintingTarget_End copybyte gBattlerAbility, gBattlerAttacker call BattleScript_AbilityPopUp - setgraphicalstatchangevalues playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 waitanimation - printstring STRINGID_LASTABILITYRAISEDSTAT + printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG BattleScript_RaiseStatOnFaintingTarget_End: return @@ -8640,6 +8635,29 @@ BattleScript_BattleBondActivatesOnMoveEndAttacker:: printstring STRINGID_ATTACKERBECAMEASHSPECIES return +BattleScript_EffectBattleBondStatIncrease:: + call BattleScript_AbilityPopUp + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + setstatchanger STAT_ATK, 1, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpAtk + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_EffectBattleBondStatIncreaseTrySpAtk: + setstatchanger STAT_SPATK, 1, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseTrySpeed + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseTrySpeed + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_EffectBattleBondStatIncreaseTrySpeed: + setstatchanger STAT_SPEED, 1, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_EffectBattleBondStatIncreaseRet + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_EffectBattleBondStatIncreaseRet + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_EffectBattleBondStatIncreaseRet: + return + BattleScript_DancerActivates:: call BattleScript_AbilityPopUp waitmessage B_WAIT_TIME_SHORT diff --git a/include/battle.h b/include/battle.h index 0213c60fc7..4fe2947375 100644 --- a/include/battle.h +++ b/include/battle.h @@ -138,11 +138,7 @@ struct DisableStruct // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects struct ProtectStruct { - u32 protected:1; - u32 spikyShielded:1; - u32 kingsShielded:1; - u32 banefulBunkered:1; - u32 obstructed:1; + u32 protected:7; // 126 protect options u32 endured:1; u32 noValidMoves:1; u32 helpingHand:1; @@ -167,9 +163,8 @@ struct ProtectStruct u32 usedThroatChopPreventedMove:1; u32 statRaised:1; u32 usedCustapBerry:1; // also quick claw - u32 touchedProtectLike:1; - u32 unused:1; // End of 32-bit bitfield + u16 touchedProtectLike:1; u16 disableEjectPack:1; u16 statFell:1; u16 pranksterElevated:1; @@ -177,16 +172,13 @@ struct ProtectStruct u16 beakBlastCharge:1; u16 quash:1; u16 shellTrap:1; - u16 maxGuarded:1; - u16 silkTrapped:1; - u16 burningBulwarked:1; u16 eatMirrorHerb:1; u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u16 usedAllySwitch:1; - u16 padding:2; + u16 padding:4; // End of 16-bit bitfield - u32 physicalDmg; - u32 specialDmg; + u16 physicalDmg; + u16 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; }; @@ -201,17 +193,17 @@ struct SpecialStatus u8 lightningRodRedirected:1; u8 restoredBattlerSprite: 1; u8 faintedHasReplacement:1; - u8 focusBanded:1; - u8 focusSashed:1; u8 emergencyExited:1; u8 afterYou:1; - // End of byte - u8 sturdied:1; + u8 enduredDamage:1; u8 stormDrainRedirected:1; + // End of byte u8 switchInAbilityDone:1; u8 switchInItemDone:1; u8 instructedChosenTarget:3; u8 berryReduced:1; + u8 announceNeutralizingGas:1; // See Cmd_switchineffects + u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS // End of byte u8 gemParam; // End of byte @@ -219,19 +211,15 @@ struct SpecialStatus u8 rototillerAffected:1; // to be affected by rototiller u8 parentalBondState:2; u8 multiHitOn:1; - u8 announceNeutralizingGas:1; // See Cmd_switchineffects - u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS - u8 affectionEndured:1; - // End of byte - u8 dancerUsedMove:1; - u8 dancerOriginalTarget:3; - u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects. u8 distortedTypeMatchups:1; u8 teraShellAbilityDone:1; u8 criticalHit:1; // End of byte - u8 enduredDamage:1; - u8 padding:7; + u8 dancerUsedMove:1; + u8 dancerOriginalTarget:3; + u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects. + u8 unused:3; + // End of byte }; struct SideTimer @@ -723,7 +711,7 @@ struct BattleStruct u8 startingStatusDone:1; u8 terrainDone:1; u8 overworldWeatherDone:1; - u8 obedienceResult:3; + u8 unused:3; u8 isAtkCancelerForCalledMove:1; // Certain cases in atk canceler should only be checked once, when the original move is called, however others need to be checked the twice. u8 friskedAbility:1; // If identifies two mons, show the ability pop-up only once. u8 fickleBeamBoosted:1; @@ -784,7 +772,7 @@ struct BattleStruct u8 hitSwitchTargetFailed:1; u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects. u8 spriteIgnore0Hp:1; - u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. + u8 battleBondBoost[NUM_BATTLE_SIDES]; // Bitfield for each party. u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies. u8 itemPartyIndex[MAX_BATTLERS_COUNT]; u8 itemMoveIndex[MAX_BATTLERS_COUNT]; @@ -908,18 +896,6 @@ static inline bool32 IsBattleMoveRecoil(u32 move) gBattleMons[battlerId].types[2] = TYPE_MYSTERY; \ } -#define IS_BATTLER_PROTECTED(battlerId)(gProtectStructs[battlerId].protected \ - || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD \ - || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_QUICK_GUARD \ - || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_CRAFTY_SHIELD \ - || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_MAT_BLOCK \ - || gProtectStructs[battlerId].spikyShielded \ - || gProtectStructs[battlerId].kingsShielded \ - || gProtectStructs[battlerId].banefulBunkered \ - || gProtectStructs[battlerId].burningBulwarked \ - || gProtectStructs[battlerId].obstructed \ - || gProtectStructs[battlerId].silkTrapped) - #define GET_STAT_BUFF_ID(n) ((n & 7)) // first three bits 0x1, 0x2, 0x4 #define GET_STAT_BUFF_VALUE_WITH_SIGN(n) ((n & 0xF8)) #define GET_STAT_BUFF_VALUE(n) (((n >> 3) & 0xF)) // 0x8, 0x10, 0x20, 0x40 @@ -936,11 +912,11 @@ static inline bool32 IsBattleMoveRecoil(u32 move) // in include/constants/battle_script_commands.h struct BattleScripting { - s32 painSplitHp; + s32 unused1; s32 bideDmg; u8 multihitString[6]; bool8 expOnCatch; - u8 unused; + u8 unused2; u8 animArg1; u8 animArg2; u16 savedStringId; diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 6715cee619..d9e8edd018 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -236,5 +236,6 @@ u32 IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move); bool32 IsBattlerItemEnabled(u32 battler); bool32 IsBattlerPredictedToSwitch(u32 battler); bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef); +bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData); #endif //GUARD_BATTLE_AI_UTIL_H diff --git a/include/battle_scripts.h b/include/battle_scripts.h index d2b4ab5806..752e15c6c3 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -427,6 +427,7 @@ extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; extern const u8 BattleScript_GulpMissileFormChange[]; extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[]; +extern const u8 BattleScript_EffectBattleBondStatIncrease[]; extern const u8 BattleScript_DesolateLandActivates[]; extern const u8 BattleScript_PrimordialSeaActivates[]; extern const u8 BattleScript_PrimalWeatherBlocksMove[]; diff --git a/include/battle_util.h b/include/battle_util.h index 9fb2cfb1a1..49448adffc 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -232,6 +232,7 @@ u32 IsAbilityOnField(u32 ability); u32 IsAbilityOnFieldExcept(u32 battler, u32 ability); u32 IsAbilityPreventingEscape(u32 battler); bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move); +u32 GetProtectType(enum ProtectMethod method); bool32 CanBattlerEscape(u32 battler); // no ability check void BattleScriptExecute(const u8 *BS_ptr); void BattleScriptPushCursorAndCallback(const u8 *BS_ptr); @@ -351,13 +352,11 @@ bool32 IsSleepClauseEnabled(); void ClearDamageCalcResults(void); u32 DoesDestinyBondFail(u32 battler); bool32 IsMoveEffectBlockedByTarget(u32 ability); -u32 NumAffectedSpreadMoveTargets(void); bool32 IsPursuitTargetSet(void); void ClearPursuitValuesIfSet(u32 battler); void ClearPursuitValues(void); bool32 HasWeatherEffect(void); -bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move); -bool32 EmergencyExitCanBeTriggered(u32 battler); u32 RestoreWhiteHerbStats(u32 battler); +bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index c142fcabe8..0aa37db354 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -157,6 +157,7 @@ // In Gen4, it's 30%. In Gen5+ it has 11% to sleep, 9% chance to poison and 10% chance to paralyze. #define B_PICKUP_WILD GEN_LATEST // In Gen9+, Pickup allows its user to pickup its own used item at the end of the turn in wild battles. #define B_MAGIC_GUARD GEN_LATEST // In Gen4 only, Magic Guard ignores immobilization caused by paralysis +#define B_BATTLE_BOND GEN_LATEST // In Gen9+, Battle Bond increases Atk, SpAtk and Speed by one stage, once per battle // 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. diff --git a/include/constants/battle.h b/include/constants/battle.h index ce1cf0e948..fc1127b8c8 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -239,15 +239,11 @@ #define SIDE_STATUS_TOXIC_SPIKES (1 << 13) #define SIDE_STATUS_STEALTH_ROCK (1 << 14) // Missing flags previously were SIDE_STATUS_TOXIC_SPIKES_DAMAGED, SIDE_STATUS_STEALTH_ROCK_DAMAGED, SIDE_STATUS_STICKY_WEB_DAMAGED -#define SIDE_STATUS_QUICK_GUARD (1 << 18) -#define SIDE_STATUS_WIDE_GUARD (1 << 19) -#define SIDE_STATUS_CRAFTY_SHIELD (1 << 20) -#define SIDE_STATUS_MAT_BLOCK (1 << 21) -#define SIDE_STATUS_STEELSURGE (1 << 22) -#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 23) -#define SIDE_STATUS_RAINBOW (1 << 24) -#define SIDE_STATUS_SEA_OF_FIRE (1 << 25) -#define SIDE_STATUS_SWAMP (1 << 26) +#define SIDE_STATUS_STEELSURGE (1 << 18) +#define SIDE_STATUS_DAMAGE_NON_TYPES (1 << 19) +#define SIDE_STATUS_RAINBOW (1 << 20) +#define SIDE_STATUS_SEA_OF_FIRE (1 << 21) +#define SIDE_STATUS_SWAMP (1 << 22) #define SIDE_STATUS_HAZARDS_ANY (SIDE_STATUS_SPIKES | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE) #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 6b6b4b9348..b0cccc2626 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -121,7 +121,6 @@ enum CmdVarious VARIOUS_INSTANT_HP_DROP, VARIOUS_CLEAR_STATUS, VARIOUS_RESTORE_PP, - VARIOUS_TRY_ACTIVATE_MOXIE, VARIOUS_TRY_ACTIVATE_FELL_STINGER, VARIOUS_PLAY_MOVE_ANIMATION, VARIOUS_SET_LUCKY_CHANT, @@ -168,7 +167,6 @@ enum CmdVarious VARIOUS_LOSE_TYPE, VARIOUS_TRY_ACTIVATE_SOULHEART, VARIOUS_TRY_ACTIVATE_RECEIVER, - VARIOUS_TRY_ACTIVATE_BEAST_BOOST, VARIOUS_TRY_FRISK, VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, VARIOUS_TRY_FAIRY_LOCK, @@ -181,7 +179,6 @@ enum CmdVarious VARIOUS_JUMP_IF_ABSENT, VARIOUS_DESTROY_ABILITY_POPUP, VARIOUS_TOTEM_BOOST, - VARIOUS_TRY_ACTIVATE_GRIM_NEIGH, VARIOUS_MOVEEND_ITEM_EFFECTS, VARIOUS_TERRAIN_SEED, VARIOUS_MAKE_INVISIBLE, @@ -192,7 +189,6 @@ enum CmdVarious VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, VARIOUS_GET_ROTOTILLER_TARGETS, VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, - VARIOUS_TRY_ACTIVATE_BATTLE_BOND, VARIOUS_CONSUME_BERRY, VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, VARIOUS_JUMP_IF_SPECIES, @@ -284,7 +280,7 @@ enum MoveEndEffects MOVEEND_RECOIL, MOVEEND_RAPID_SPIN, MOVEEND_ITEM_EFFECTS_ATTACKER, - MOVEEND_MAGICIAN, // Occurs after final multi-hit strike, and after other items/abilities would activate + MOVEEND_ABILITY_BLOCK, MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Eject Pack MOVEEND_RED_CARD, // Red Card triggers before Eject Pack MOVEEND_EJECT_BUTTON, diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 16d41f3977..db5ee7b16e 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -467,274 +467,273 @@ #define STRINGID_FRISKACTIVATES 465 #define STRINGID_UNNERVEENTERS 466 #define STRINGID_HARVESTBERRY 467 -#define STRINGID_LASTABILITYRAISEDSTAT 468 -#define STRINGID_MAGICBOUNCEACTIVATES 469 -#define STRINGID_PROTEANTYPECHANGE 470 -#define STRINGID_SYMBIOSISITEMPASS 471 -#define STRINGID_STEALTHROCKDMG 472 -#define STRINGID_TOXICSPIKESABSORBED 473 -#define STRINGID_TOXICSPIKESPOISONED 474 -#define STRINGID_STICKYWEBSWITCHIN 475 -#define STRINGID_HEALINGWISHCAMETRUE 476 -#define STRINGID_HEALINGWISHHEALED 477 -#define STRINGID_LUNARDANCECAMETRUE 478 -#define STRINGID_CUSEDBODYDISABLED 479 -#define STRINGID_ATTACKERACQUIREDABILITY 480 -#define STRINGID_TARGETABILITYSTATLOWER 481 -#define STRINGID_TARGETSTATWONTGOHIGHER 482 -#define STRINGID_PKMNMOVEBOUNCEDABILITY 483 -#define STRINGID_IMPOSTERTRANSFORM 484 -#define STRINGID_ASSAULTVESTDOESNTALLOW 485 -#define STRINGID_GRAVITYPREVENTSUSAGE 486 -#define STRINGID_HEALBLOCKPREVENTSUSAGE 487 -#define STRINGID_NOTDONEYET 488 -#define STRINGID_STICKYWEBUSED 489 -#define STRINGID_QUASHSUCCESS 490 -#define STRINGID_PKMNBLEWAWAYTOXICSPIKES 491 -#define STRINGID_PKMNBLEWAWAYSTICKYWEB 492 -#define STRINGID_PKMNBLEWAWAYSTEALTHROCK 493 -#define STRINGID_IONDELUGEON 494 -#define STRINGID_TOPSYTURVYSWITCHEDSTATS 495 -#define STRINGID_TERRAINBECOMESMISTY 496 -#define STRINGID_TERRAINBECOMESGRASSY 497 -#define STRINGID_TERRAINBECOMESELECTRIC 498 -#define STRINGID_TERRAINBECOMESPSYCHIC 499 -#define STRINGID_TARGETELECTRIFIED 500 -#define STRINGID_MEGAEVOREACTING 501 -#define STRINGID_MEGAEVOEVOLVED 502 -#define STRINGID_DRASTICALLY 503 -#define STRINGID_SEVERELY 504 -#define STRINGID_INFESTATION 505 -#define STRINGID_NOEFFECTONTARGET 506 -#define STRINGID_BURSTINGFLAMESHIT 507 -#define STRINGID_BESTOWITEMGIVING 508 -#define STRINGID_THIRDTYPEADDED 509 -#define STRINGID_FELLFORFEINT 510 -#define STRINGID_POKEMONCANNOTUSEMOVE 511 -#define STRINGID_COVEREDINPOWDER 512 -#define STRINGID_POWDEREXPLODES 513 -#define STRINGID_BELCHCANTSELECT 514 -#define STRINGID_SPECTRALTHIEFSTEAL 515 -#define STRINGID_GRAVITYGROUNDING 516 -#define STRINGID_MISTYTERRAINPREVENTS 517 -#define STRINGID_GRASSYTERRAINHEALS 518 -#define STRINGID_ELECTRICTERRAINPREVENTS 519 -#define STRINGID_PSYCHICTERRAINPREVENTS 520 -#define STRINGID_SAFETYGOGGLESPROTECTED 521 -#define STRINGID_FLOWERVEILPROTECTED 522 -#define STRINGID_SWEETVEILPROTECTED 523 -#define STRINGID_AROMAVEILPROTECTED 524 -#define STRINGID_CELEBRATEMESSAGE 525 -#define STRINGID_USEDINSTRUCTEDMOVE 526 -#define STRINGID_THROATCHOPENDS 527 -#define STRINGID_PKMNCANTUSEMOVETHROATCHOP 528 -#define STRINGID_LASERFOCUS 529 -#define STRINGID_GEMACTIVATES 530 -#define STRINGID_BERRYDMGREDUCES 531 -#define STRINGID_AIRBALLOONFLOAT 532 -#define STRINGID_AIRBALLOONPOP 533 -#define STRINGID_INCINERATEBURN 534 -#define STRINGID_BUGBITE 535 -#define STRINGID_ILLUSIONWOREOFF 536 -#define STRINGID_ATTACKERCUREDTARGETSTATUS 537 -#define STRINGID_ATTACKERLOSTFIRETYPE 538 -#define STRINGID_HEALERCURE 539 -#define STRINGID_SCRIPTINGABILITYSTATRAISE 540 -#define STRINGID_RECEIVERABILITYTAKEOVER 541 -#define STRINGID_PKNMABSORBINGPOWER 542 -#define STRINGID_NOONEWILLBEABLETORUNAWAY 543 -#define STRINGID_DESTINYKNOTACTIVATES 544 -#define STRINGID_CLOAKEDINAFREEZINGLIGHT 545 -#define STRINGID_CLEARAMULETWONTLOWERSTATS 546 -#define STRINGID_FERVENTWISHREACHED 547 -#define STRINGID_AIRLOCKACTIVATES 548 -#define STRINGID_PRESSUREENTERS 549 -#define STRINGID_DARKAURAENTERS 550 -#define STRINGID_FAIRYAURAENTERS 551 -#define STRINGID_AURABREAKENTERS 552 -#define STRINGID_COMATOSEENTERS 553 -#define STRINGID_SCREENCLEANERENTERS 554 -#define STRINGID_FETCHEDPOKEBALL 555 -#define STRINGID_BATTLERABILITYRAISEDSTAT 556 -#define STRINGID_ASANDSTORMKICKEDUP 557 -#define STRINGID_PKMNSWILLPERISHIN3TURNS 558 -#define STRINGID_ABILITYRAISEDSTATDRASTICALLY 559 -#define STRINGID_AURAFLAREDTOLIFE 560 -#define STRINGID_ASONEENTERS 561 -#define STRINGID_CURIOUSMEDICINEENTERS 562 -#define STRINGID_CANACTFASTERTHANKSTO 563 -#define STRINGID_MICLEBERRYACTIVATES 564 -#define STRINGID_PKMNSHOOKOFFTHETAUNT 565 -#define STRINGID_PKMNGOTOVERITSINFATUATION 566 -#define STRINGID_ITEMCANNOTBEREMOVED 567 -#define STRINGID_STICKYBARBTRANSFER 568 -#define STRINGID_PKMNBURNHEALED 569 -#define STRINGID_REDCARDACTIVATE 570 -#define STRINGID_EJECTBUTTONACTIVATE 571 -#define STRINGID_ATKGOTOVERINFATUATION 572 -#define STRINGID_TORMENTEDNOMORE 573 -#define STRINGID_HEALBLOCKEDNOMORE 574 -#define STRINGID_ATTACKERBECAMEFULLYCHARGED 575 -#define STRINGID_ATTACKERBECAMEASHSPECIES 576 -#define STRINGID_EXTREMELYHARSHSUNLIGHT 577 -#define STRINGID_EXTREMESUNLIGHTFADED 578 -#define STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT 579 -#define STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED 580 -#define STRINGID_HEAVYRAIN 581 -#define STRINGID_HEAVYRAINLIFTED 582 -#define STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN 583 -#define STRINGID_NORELIEFROMHEAVYRAIN 584 -#define STRINGID_MYSTERIOUSAIRCURRENT 585 -#define STRINGID_STRONGWINDSDISSIPATED 586 -#define STRINGID_MYSTERIOUSAIRCURRENTBLOWSON 587 -#define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 588 -#define STRINGID_STUFFCHEEKSCANTSELECT 589 -#define STRINGID_PKMNREVERTEDTOPRIMAL 590 -#define STRINGID_BUTPOKEMONCANTUSETHEMOVE 591 -#define STRINGID_BUTHOOPACANTUSEIT 592 -#define STRINGID_BROKETHROUGHPROTECTION 593 -#define STRINGID_ABILITYALLOWSONLYMOVE 594 -#define STRINGID_SWAPPEDABILITIES 595 -#define STRINGID_PASTELVEILPROTECTED 596 -#define STRINGID_PASTELVEILENTERS 597 -#define STRINGID_BATTLERTYPECHANGEDTO 598 -#define STRINGID_BOTHCANNOLONGERESCAPE 599 -#define STRINGID_CANTESCAPEDUETOUSEDMOVE 600 -#define STRINGID_PKMNBECAMEWEAKERTOFIRE 601 -#define STRINGID_ABOUTTOUSEPOLTERGEIST 602 -#define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 603 -#define STRINGID_NEUTRALIZINGGASENTERS 604 -#define STRINGID_NEUTRALIZINGGASOVER 605 -#define STRINGID_TARGETTOOHEAVY 606 -#define STRINGID_PKMNTOOKTARGETHIGH 607 -#define STRINGID_PKMNINSNAPTRAP 608 -#define STRINGID_METEORBEAMCHARGING 609 -#define STRINGID_HEATUPBEAK 610 -#define STRINGID_COURTCHANGE 611 -#define STRINGID_PLAYERLOSTTOENEMYTRAINER 612 -#define STRINGID_PLAYERPAIDPRIZEMONEY 613 -#define STRINGID_ZPOWERSURROUNDS 614 -#define STRINGID_ZMOVEUNLEASHED 615 -#define STRINGID_ZMOVERESETSSTATS 616 -#define STRINGID_ZMOVEALLSTATSUP 617 -#define STRINGID_ZMOVEZBOOSTCRIT 618 -#define STRINGID_ZMOVERESTOREHP 619 -#define STRINGID_ZMOVESTATUP 620 -#define STRINGID_ZMOVEHPTRAP 621 -#define STRINGID_ATTACKEREXPELLEDTHEPOISON 622 -#define STRINGID_ATTACKERSHOOKITSELFAWAKE 623 -#define STRINGID_ATTACKERBROKETHROUGHPARALYSIS 624 -#define STRINGID_ATTACKERHEALEDITSBURN 625 -#define STRINGID_ATTACKERMELTEDTHEICE 626 -#define STRINGID_TARGETTOUGHEDITOUT 627 -#define STRINGID_ATTACKERLOSTELECTRICTYPE 628 -#define STRINGID_ATTACKERSWITCHEDSTATWITHTARGET 629 -#define STRINGID_BEINGHITCHARGEDPKMNWITHPOWER 630 -#define STRINGID_SUNLIGHTACTIVATEDABILITY 631 -#define STRINGID_STATWASHEIGHTENED 632 -#define STRINGID_ELECTRICTERRAINACTIVATEDABILITY 633 -#define STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT 634 -#define STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN 635 -#define STRINGID_PKMNSABILITYPREVENTSABILITY 636 -#define STRINGID_PREPARESHELLTRAP 637 -#define STRINGID_SHELLTRAPDIDNTWORK 638 -#define STRINGID_SPIKESDISAPPEAREDFROMTEAM 639 -#define STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM 640 -#define STRINGID_STICKYWEBDISAPPEAREDFROMTEAM 641 -#define STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM 642 -#define STRINGID_COULDNTFULLYPROTECT 643 -#define STRINGID_STOCKPILEDEFFECTWOREOFF 644 -#define STRINGID_PKMNREVIVEDREADYTOFIGHT 645 -#define STRINGID_ITEMRESTOREDSPECIESHEALTH 646 -#define STRINGID_ITEMCUREDSPECIESSTATUS 647 -#define STRINGID_ITEMRESTOREDSPECIESPP 648 -#define STRINGID_THUNDERCAGETRAPPED 649 -#define STRINGID_PKMNHURTBYFROSTBITE 650 -#define STRINGID_PKMNGOTFROSTBITE 651 -#define STRINGID_PKMNSITEMHEALEDFROSTBITE 652 -#define STRINGID_ATTACKERHEALEDITSFROSTBITE 653 -#define STRINGID_PKMNFROSTBITEHEALED 654 -#define STRINGID_PKMNFROSTBITEHEALED2 655 -#define STRINGID_PKMNFROSTBITEHEALEDBY 656 -#define STRINGID_MIRRORHERBCOPIED 657 -#define STRINGID_STARTEDSNOW 658 -#define STRINGID_SNOWCONTINUES 659 -#define STRINGID_SNOWSTOPPED 660 -#define STRINGID_SNOWWARNINGSNOW 661 -#define STRINGID_PKMNITEMMELTED 662 -#define STRINGID_ULTRABURSTREACTING 663 -#define STRINGID_ULTRABURSTCOMPLETED 664 -#define STRINGID_TEAMGAINEDEXP 665 -#define STRINGID_CURRENTMOVECANTSELECT 666 -#define STRINGID_TARGETISBEINGSALTCURED 667 -#define STRINGID_TARGETISHURTBYSALTCURE 668 -#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 669 -#define STRINGID_SHARPSTEELFLOATS 670 -#define STRINGID_SHARPSTEELDMG 671 -#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 672 -#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 673 -#define STRINGID_TEAMTRAPPEDWITHVINES 674 -#define STRINGID_PKMNHURTBYVINES 675 -#define STRINGID_TEAMCAUGHTINVORTEX 676 -#define STRINGID_PKMNHURTBYVORTEX 677 -#define STRINGID_TEAMSURROUNDEDBYFIRE 678 -#define STRINGID_PKMNBURNINGUP 679 -#define STRINGID_TEAMSURROUNDEDBYROCKS 680 -#define STRINGID_PKMNHURTBYROCKSTHROWN 681 -#define STRINGID_MOVEBLOCKEDBYDYNAMAX 682 -#define STRINGID_ZEROTOHEROTRANSFORMATION 683 -#define STRINGID_THETWOMOVESBECOMEONE 684 -#define STRINGID_ARAINBOWAPPEAREDONSIDE 685 -#define STRINGID_THERAINBOWDISAPPEARED 686 -#define STRINGID_WAITINGFORPARTNERSMOVE 687 -#define STRINGID_SEAOFFIREENVELOPEDSIDE 688 -#define STRINGID_HURTBYTHESEAOFFIRE 689 -#define STRINGID_THESEAOFFIREDISAPPEARED 690 -#define STRINGID_SWAMPENVELOPEDSIDE 691 -#define STRINGID_THESWAMPDISAPPEARED 692 -#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 693 -#define STRINGID_HOSPITALITYRESTORATION 694 -#define STRINGID_ELECTROSHOTCHARGING 695 -#define STRINGID_ITEMWASUSEDUP 696 -#define STRINGID_ATTACKERLOSTITSTYPE 697 -#define STRINGID_SHEDITSTAIL 698 -#define STRINGID_CLOAKEDINAHARSHLIGHT 699 -#define STRINGID_SUPERSWEETAROMAWAFTS 700 -#define STRINGID_DIMENSIONSWERETWISTED 701 -#define STRINGID_BIZARREARENACREATED 702 -#define STRINGID_BIZARREAREACREATED 703 -#define STRINGID_TIDYINGUPCOMPLETE 704 -#define STRINGID_PKMNTERASTALLIZEDINTO 705 -#define STRINGID_BOOSTERENERGYACTIVATES 706 -#define STRINGID_FOGCREPTUP 707 -#define STRINGID_FOGISDEEP 708 -#define STRINGID_FOGLIFTED 709 -#define STRINGID_PKMNMADESHELLGLEAM 710 -#define STRINGID_FICKLEBEAMDOUBLED 711 -#define STRINGID_COMMANDERACTIVATES 712 -#define STRINGID_POKEFLUTECATCHY 713 -#define STRINGID_POKEFLUTE 714 -#define STRINGID_MONHEARINGFLUTEAWOKE 715 -#define STRINGID_SUNLIGHTISHARSH 716 -#define STRINGID_ITISHAILING 717 -#define STRINGID_ITISSNOWING 718 -#define STRINGID_ISCOVEREDWITHGRASS 719 -#define STRINGID_MISTSWIRLSAROUND 720 -#define STRINGID_ELECTRICCURRENTISRUNNING 721 -#define STRINGID_SEEMSWEIRD 722 -#define STRINGID_WAGGLINGAFINGER 723 -#define STRINGID_BLOCKEDBYSLEEPCLAUSE 724 -#define STRINGID_SUPEREFFECTIVETWOFOES 725 -#define STRINGID_NOTVERYEFFECTIVETWOFOES 726 -#define STRINGID_ITDOESNTAFFECTTWOFOES 727 -#define STRINGID_SENDCAUGHTMONPARTYORBOX 728 -#define STRINGID_PKMNSENTTOPCAFTERCATCH 729 -#define STRINGID_PKMNDYNAMAXED 730 -#define STRINGID_PKMNGIGANTAMAXED 731 -#define STRINGID_TIMETODYNAMAX 732 -#define STRINGID_TIMETOGIGANTAMAX 733 +#define STRINGID_MAGICBOUNCEACTIVATES 468 +#define STRINGID_PROTEANTYPECHANGE 469 +#define STRINGID_SYMBIOSISITEMPASS 470 +#define STRINGID_STEALTHROCKDMG 471 +#define STRINGID_TOXICSPIKESABSORBED 472 +#define STRINGID_TOXICSPIKESPOISONED 473 +#define STRINGID_STICKYWEBSWITCHIN 474 +#define STRINGID_HEALINGWISHCAMETRUE 475 +#define STRINGID_HEALINGWISHHEALED 476 +#define STRINGID_LUNARDANCECAMETRUE 477 +#define STRINGID_CUSEDBODYDISABLED 478 +#define STRINGID_ATTACKERACQUIREDABILITY 479 +#define STRINGID_TARGETABILITYSTATLOWER 480 +#define STRINGID_TARGETSTATWONTGOHIGHER 481 +#define STRINGID_PKMNMOVEBOUNCEDABILITY 482 +#define STRINGID_IMPOSTERTRANSFORM 483 +#define STRINGID_ASSAULTVESTDOESNTALLOW 484 +#define STRINGID_GRAVITYPREVENTSUSAGE 485 +#define STRINGID_HEALBLOCKPREVENTSUSAGE 486 +#define STRINGID_NOTDONEYET 487 +#define STRINGID_STICKYWEBUSED 488 +#define STRINGID_QUASHSUCCESS 489 +#define STRINGID_PKMNBLEWAWAYTOXICSPIKES 490 +#define STRINGID_PKMNBLEWAWAYSTICKYWEB 491 +#define STRINGID_PKMNBLEWAWAYSTEALTHROCK 492 +#define STRINGID_IONDELUGEON 493 +#define STRINGID_TOPSYTURVYSWITCHEDSTATS 494 +#define STRINGID_TERRAINBECOMESMISTY 495 +#define STRINGID_TERRAINBECOMESGRASSY 496 +#define STRINGID_TERRAINBECOMESELECTRIC 497 +#define STRINGID_TERRAINBECOMESPSYCHIC 498 +#define STRINGID_TARGETELECTRIFIED 499 +#define STRINGID_MEGAEVOREACTING 500 +#define STRINGID_MEGAEVOEVOLVED 501 +#define STRINGID_DRASTICALLY 502 +#define STRINGID_SEVERELY 503 +#define STRINGID_INFESTATION 504 +#define STRINGID_NOEFFECTONTARGET 505 +#define STRINGID_BURSTINGFLAMESHIT 506 +#define STRINGID_BESTOWITEMGIVING 507 +#define STRINGID_THIRDTYPEADDED 508 +#define STRINGID_FELLFORFEINT 509 +#define STRINGID_POKEMONCANNOTUSEMOVE 510 +#define STRINGID_COVEREDINPOWDER 511 +#define STRINGID_POWDEREXPLODES 512 +#define STRINGID_BELCHCANTSELECT 513 +#define STRINGID_SPECTRALTHIEFSTEAL 514 +#define STRINGID_GRAVITYGROUNDING 515 +#define STRINGID_MISTYTERRAINPREVENTS 516 +#define STRINGID_GRASSYTERRAINHEALS 517 +#define STRINGID_ELECTRICTERRAINPREVENTS 518 +#define STRINGID_PSYCHICTERRAINPREVENTS 519 +#define STRINGID_SAFETYGOGGLESPROTECTED 520 +#define STRINGID_FLOWERVEILPROTECTED 521 +#define STRINGID_SWEETVEILPROTECTED 522 +#define STRINGID_AROMAVEILPROTECTED 523 +#define STRINGID_CELEBRATEMESSAGE 524 +#define STRINGID_USEDINSTRUCTEDMOVE 525 +#define STRINGID_THROATCHOPENDS 526 +#define STRINGID_PKMNCANTUSEMOVETHROATCHOP 527 +#define STRINGID_LASERFOCUS 528 +#define STRINGID_GEMACTIVATES 529 +#define STRINGID_BERRYDMGREDUCES 530 +#define STRINGID_AIRBALLOONFLOAT 531 +#define STRINGID_AIRBALLOONPOP 532 +#define STRINGID_INCINERATEBURN 533 +#define STRINGID_BUGBITE 534 +#define STRINGID_ILLUSIONWOREOFF 535 +#define STRINGID_ATTACKERCUREDTARGETSTATUS 536 +#define STRINGID_ATTACKERLOSTFIRETYPE 537 +#define STRINGID_HEALERCURE 538 +#define STRINGID_SCRIPTINGABILITYSTATRAISE 539 +#define STRINGID_RECEIVERABILITYTAKEOVER 540 +#define STRINGID_PKNMABSORBINGPOWER 541 +#define STRINGID_NOONEWILLBEABLETORUNAWAY 542 +#define STRINGID_DESTINYKNOTACTIVATES 543 +#define STRINGID_CLOAKEDINAFREEZINGLIGHT 544 +#define STRINGID_CLEARAMULETWONTLOWERSTATS 545 +#define STRINGID_FERVENTWISHREACHED 546 +#define STRINGID_AIRLOCKACTIVATES 547 +#define STRINGID_PRESSUREENTERS 548 +#define STRINGID_DARKAURAENTERS 549 +#define STRINGID_FAIRYAURAENTERS 550 +#define STRINGID_AURABREAKENTERS 551 +#define STRINGID_COMATOSEENTERS 552 +#define STRINGID_SCREENCLEANERENTERS 553 +#define STRINGID_FETCHEDPOKEBALL 554 +#define STRINGID_BATTLERABILITYRAISEDSTAT 555 +#define STRINGID_ASANDSTORMKICKEDUP 556 +#define STRINGID_PKMNSWILLPERISHIN3TURNS 557 +#define STRINGID_ABILITYRAISEDSTATDRASTICALLY 558 +#define STRINGID_AURAFLAREDTOLIFE 559 +#define STRINGID_ASONEENTERS 560 +#define STRINGID_CURIOUSMEDICINEENTERS 561 +#define STRINGID_CANACTFASTERTHANKSTO 562 +#define STRINGID_MICLEBERRYACTIVATES 563 +#define STRINGID_PKMNSHOOKOFFTHETAUNT 564 +#define STRINGID_PKMNGOTOVERITSINFATUATION 565 +#define STRINGID_ITEMCANNOTBEREMOVED 566 +#define STRINGID_STICKYBARBTRANSFER 567 +#define STRINGID_PKMNBURNHEALED 568 +#define STRINGID_REDCARDACTIVATE 569 +#define STRINGID_EJECTBUTTONACTIVATE 570 +#define STRINGID_ATKGOTOVERINFATUATION 571 +#define STRINGID_TORMENTEDNOMORE 572 +#define STRINGID_HEALBLOCKEDNOMORE 573 +#define STRINGID_ATTACKERBECAMEFULLYCHARGED 574 +#define STRINGID_ATTACKERBECAMEASHSPECIES 575 +#define STRINGID_EXTREMELYHARSHSUNLIGHT 576 +#define STRINGID_EXTREMESUNLIGHTFADED 577 +#define STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT 578 +#define STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED 579 +#define STRINGID_HEAVYRAIN 580 +#define STRINGID_HEAVYRAINLIFTED 581 +#define STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN 582 +#define STRINGID_NORELIEFROMHEAVYRAIN 583 +#define STRINGID_MYSTERIOUSAIRCURRENT 584 +#define STRINGID_STRONGWINDSDISSIPATED 585 +#define STRINGID_MYSTERIOUSAIRCURRENTBLOWSON 586 +#define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 587 +#define STRINGID_STUFFCHEEKSCANTSELECT 588 +#define STRINGID_PKMNREVERTEDTOPRIMAL 589 +#define STRINGID_BUTPOKEMONCANTUSETHEMOVE 590 +#define STRINGID_BUTHOOPACANTUSEIT 591 +#define STRINGID_BROKETHROUGHPROTECTION 592 +#define STRINGID_ABILITYALLOWSONLYMOVE 593 +#define STRINGID_SWAPPEDABILITIES 594 +#define STRINGID_PASTELVEILPROTECTED 595 +#define STRINGID_PASTELVEILENTERS 596 +#define STRINGID_BATTLERTYPECHANGEDTO 597 +#define STRINGID_BOTHCANNOLONGERESCAPE 598 +#define STRINGID_CANTESCAPEDUETOUSEDMOVE 599 +#define STRINGID_PKMNBECAMEWEAKERTOFIRE 600 +#define STRINGID_ABOUTTOUSEPOLTERGEIST 601 +#define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 602 +#define STRINGID_NEUTRALIZINGGASENTERS 603 +#define STRINGID_NEUTRALIZINGGASOVER 604 +#define STRINGID_TARGETTOOHEAVY 605 +#define STRINGID_PKMNTOOKTARGETHIGH 606 +#define STRINGID_PKMNINSNAPTRAP 607 +#define STRINGID_METEORBEAMCHARGING 608 +#define STRINGID_HEATUPBEAK 609 +#define STRINGID_COURTCHANGE 610 +#define STRINGID_PLAYERLOSTTOENEMYTRAINER 611 +#define STRINGID_PLAYERPAIDPRIZEMONEY 612 +#define STRINGID_ZPOWERSURROUNDS 613 +#define STRINGID_ZMOVEUNLEASHED 614 +#define STRINGID_ZMOVERESETSSTATS 615 +#define STRINGID_ZMOVEALLSTATSUP 616 +#define STRINGID_ZMOVEZBOOSTCRIT 617 +#define STRINGID_ZMOVERESTOREHP 618 +#define STRINGID_ZMOVESTATUP 619 +#define STRINGID_ZMOVEHPTRAP 620 +#define STRINGID_ATTACKEREXPELLEDTHEPOISON 621 +#define STRINGID_ATTACKERSHOOKITSELFAWAKE 622 +#define STRINGID_ATTACKERBROKETHROUGHPARALYSIS 623 +#define STRINGID_ATTACKERHEALEDITSBURN 624 +#define STRINGID_ATTACKERMELTEDTHEICE 625 +#define STRINGID_TARGETTOUGHEDITOUT 626 +#define STRINGID_ATTACKERLOSTELECTRICTYPE 627 +#define STRINGID_ATTACKERSWITCHEDSTATWITHTARGET 628 +#define STRINGID_BEINGHITCHARGEDPKMNWITHPOWER 629 +#define STRINGID_SUNLIGHTACTIVATEDABILITY 630 +#define STRINGID_STATWASHEIGHTENED 631 +#define STRINGID_ELECTRICTERRAINACTIVATEDABILITY 632 +#define STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT 633 +#define STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN 634 +#define STRINGID_PKMNSABILITYPREVENTSABILITY 635 +#define STRINGID_PREPARESHELLTRAP 636 +#define STRINGID_SHELLTRAPDIDNTWORK 637 +#define STRINGID_SPIKESDISAPPEAREDFROMTEAM 638 +#define STRINGID_TOXICSPIKESDISAPPEAREDFROMTEAM 639 +#define STRINGID_STICKYWEBDISAPPEAREDFROMTEAM 640 +#define STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM 641 +#define STRINGID_COULDNTFULLYPROTECT 642 +#define STRINGID_STOCKPILEDEFFECTWOREOFF 643 +#define STRINGID_PKMNREVIVEDREADYTOFIGHT 644 +#define STRINGID_ITEMRESTOREDSPECIESHEALTH 645 +#define STRINGID_ITEMCUREDSPECIESSTATUS 646 +#define STRINGID_ITEMRESTOREDSPECIESPP 647 +#define STRINGID_THUNDERCAGETRAPPED 648 +#define STRINGID_PKMNHURTBYFROSTBITE 649 +#define STRINGID_PKMNGOTFROSTBITE 650 +#define STRINGID_PKMNSITEMHEALEDFROSTBITE 651 +#define STRINGID_ATTACKERHEALEDITSFROSTBITE 652 +#define STRINGID_PKMNFROSTBITEHEALED 653 +#define STRINGID_PKMNFROSTBITEHEALED2 654 +#define STRINGID_PKMNFROSTBITEHEALEDBY 655 +#define STRINGID_MIRRORHERBCOPIED 656 +#define STRINGID_STARTEDSNOW 657 +#define STRINGID_SNOWCONTINUES 658 +#define STRINGID_SNOWSTOPPED 659 +#define STRINGID_SNOWWARNINGSNOW 660 +#define STRINGID_PKMNITEMMELTED 661 +#define STRINGID_ULTRABURSTREACTING 662 +#define STRINGID_ULTRABURSTCOMPLETED 663 +#define STRINGID_TEAMGAINEDEXP 664 +#define STRINGID_CURRENTMOVECANTSELECT 665 +#define STRINGID_TARGETISBEINGSALTCURED 666 +#define STRINGID_TARGETISHURTBYSALTCURE 667 +#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 668 +#define STRINGID_SHARPSTEELFLOATS 669 +#define STRINGID_SHARPSTEELDMG 670 +#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 671 +#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 672 +#define STRINGID_TEAMTRAPPEDWITHVINES 673 +#define STRINGID_PKMNHURTBYVINES 674 +#define STRINGID_TEAMCAUGHTINVORTEX 675 +#define STRINGID_PKMNHURTBYVORTEX 676 +#define STRINGID_TEAMSURROUNDEDBYFIRE 677 +#define STRINGID_PKMNBURNINGUP 678 +#define STRINGID_TEAMSURROUNDEDBYROCKS 679 +#define STRINGID_PKMNHURTBYROCKSTHROWN 680 +#define STRINGID_MOVEBLOCKEDBYDYNAMAX 681 +#define STRINGID_ZEROTOHEROTRANSFORMATION 682 +#define STRINGID_THETWOMOVESBECOMEONE 683 +#define STRINGID_ARAINBOWAPPEAREDONSIDE 684 +#define STRINGID_THERAINBOWDISAPPEARED 685 +#define STRINGID_WAITINGFORPARTNERSMOVE 686 +#define STRINGID_SEAOFFIREENVELOPEDSIDE 687 +#define STRINGID_HURTBYTHESEAOFFIRE 688 +#define STRINGID_THESEAOFFIREDISAPPEARED 689 +#define STRINGID_SWAMPENVELOPEDSIDE 690 +#define STRINGID_THESWAMPDISAPPEARED 691 +#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 692 +#define STRINGID_HOSPITALITYRESTORATION 693 +#define STRINGID_ELECTROSHOTCHARGING 694 +#define STRINGID_ITEMWASUSEDUP 695 +#define STRINGID_ATTACKERLOSTITSTYPE 696 +#define STRINGID_SHEDITSTAIL 697 +#define STRINGID_CLOAKEDINAHARSHLIGHT 698 +#define STRINGID_SUPERSWEETAROMAWAFTS 699 +#define STRINGID_DIMENSIONSWERETWISTED 700 +#define STRINGID_BIZARREARENACREATED 701 +#define STRINGID_BIZARREAREACREATED 702 +#define STRINGID_TIDYINGUPCOMPLETE 703 +#define STRINGID_PKMNTERASTALLIZEDINTO 704 +#define STRINGID_BOOSTERENERGYACTIVATES 705 +#define STRINGID_FOGCREPTUP 706 +#define STRINGID_FOGISDEEP 707 +#define STRINGID_FOGLIFTED 708 +#define STRINGID_PKMNMADESHELLGLEAM 709 +#define STRINGID_FICKLEBEAMDOUBLED 710 +#define STRINGID_COMMANDERACTIVATES 711 +#define STRINGID_POKEFLUTECATCHY 712 +#define STRINGID_POKEFLUTE 713 +#define STRINGID_MONHEARINGFLUTEAWOKE 714 +#define STRINGID_SUNLIGHTISHARSH 715 +#define STRINGID_ITISHAILING 716 +#define STRINGID_ITISSNOWING 717 +#define STRINGID_ISCOVEREDWITHGRASS 718 +#define STRINGID_MISTSWIRLSAROUND 719 +#define STRINGID_ELECTRICCURRENTISRUNNING 720 +#define STRINGID_SEEMSWEIRD 721 +#define STRINGID_WAGGLINGAFINGER 722 +#define STRINGID_BLOCKEDBYSLEEPCLAUSE 723 +#define STRINGID_SUPEREFFECTIVETWOFOES 724 +#define STRINGID_NOTVERYEFFECTIVETWOFOES 725 +#define STRINGID_ITDOESNTAFFECTTWOFOES 726 +#define STRINGID_SENDCAUGHTMONPARTYORBOX 727 +#define STRINGID_PKMNSENTTOPCAFTERCATCH 728 +#define STRINGID_PKMNDYNAMAXED 729 +#define STRINGID_PKMNGIGANTAMAXED 730 +#define STRINGID_TIMETODYNAMAX 731 +#define STRINGID_TIMETOGIGANTAMAX 732 -#define BATTLESTRINGS_COUNT 734 +#define BATTLESTRINGS_COUNT 733 // 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/generational_changes.h b/include/constants/generational_changes.h index e9653d26d5..dea3b3bf9c 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -12,6 +12,7 @@ enum GenConfigTag GEN_CONFIG_GALE_WINGS, GEN_CONFIG_HEAL_BELL_SOUNDPROOF, GEN_CONFIG_TELEPORT_BEHAVIOR, + GEN_CONFIG_BATTLE_BOND, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index 1aad93f915..41198c394d 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -15,6 +15,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS, [GEN_CONFIG_HEAL_BELL_SOUNDPROOF] = B_HEAL_BELL_SOUNDPROOF, [GEN_CONFIG_TELEPORT_BEHAVIOR] = B_TELEPORT_BEHAVIOR, + [GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND, }; #if TESTING diff --git a/include/move.h b/include/move.h index d00751642a..ce1c40f5cc 100644 --- a/include/move.h +++ b/include/move.h @@ -38,6 +38,30 @@ struct AdditionalEffect u8 chance; // 0% = effect certain, primary effect }; +enum ProtectType +{ + PROTECT_TYPE_NONE, + PROTECT_TYPE_SIDE, + PROTECT_TYPE_SINGLE, +}; + +enum ProtectMethod +{ + PROTECT_NONE, + PROTECT_NORMAL, + PROTECT_SPIKY_SHIELD, + PROTECT_KINGS_SHIELD, + PROTECT_BANEFUL_BUNKER, + PROTECT_BURNING_BULWARK, + PROTECT_OBSTRUCT, + PROTECT_SILK_TRAP, + PROTECT_MAX_GUARD, + PROTECT_WIDE_GUARD, + PROTECT_QUICK_GUARD, + PROTECT_CRAFTY_SHIELD, + PROTECT_MAT_BLOCK, +}; + struct MoveInfo { const u8 *name; @@ -113,10 +137,7 @@ struct MoveInfo u16 stringId; u16 status; } twoTurnAttack; - struct { - u16 side; - u16 property; // can be used to remove the hardcoded values - } protect; + u32 protectMethod; u32 status; u32 moveProperty; u32 holdEffect; @@ -447,9 +468,9 @@ static inline u32 GetMoveTwoTurnAttackWeather(u32 moveId) return gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status; } -static inline u32 GetMoveProtectSide(u32 moveId) +static inline u32 GetMoveProtectMethod(u32 moveId) { - return gMovesInfo[SanitizeMoveId(moveId)].argument.protect.side; + return gMovesInfo[SanitizeMoveId(moveId)].argument.protectMethod; } static inline u32 GetMoveEffectArg_Status(u32 moveId) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 867c0dc89f..e243ac176c 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1200,6 +1200,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_QUIVER_DANCE: case EFFECT_GEOMANCY: + if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, aiData)) + ADJUST_SCORE(-10); if (gBattleMons[battlerAtk].statStages[STAT_SPATK] >= MAX_STAT_STAGE || !HasMoveWithCategory(battlerAtk, DAMAGE_CATEGORY_SPECIAL)) ADJUST_SCORE(-10); else if (!BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPEED)) @@ -1735,6 +1737,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_BELLY_DRUM: case EFFECT_FILLET_AWAY: + if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, aiData)) + ADJUST_SCORE(-10); if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] <= 60) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index e8e6a51ba9..fee630cedb 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -3937,6 +3937,10 @@ static u32 IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 statI if (considerContrary && AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY) return NO_INCREASE; + // Don't increase stats if opposing battler has Unaware + if (HasBattlerSideAbility(battlerDef, ABILITY_UNAWARE, AI_DATA)) + return NO_INCREASE; + // Don't increase stat if AI is at +4 if (gBattleMons[battlerAtk].statStages[statId] >= MAX_STAT_STAGE - 2) return NO_INCREASE; @@ -4423,3 +4427,12 @@ bool32 IsBattlerItemEnabled(u32 battler) return FALSE; return TRUE; } + +bool32 HasBattlerSideAbility(u32 battler, u32 ability, struct AiLogicData *aiData) +{ + if (aiData->abilities[battler] == ability) + return TRUE; + if (IsDoubleBattle() && AI_DATA->abilities[BATTLE_PARTNER(battler)] == ability) + return TRUE; + return FALSE; +} diff --git a/src/battle_main.c b/src/battle_main.c index 85cdb7b997..6e4eb0899f 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3276,14 +3276,10 @@ const u8* FaintClearSetData(u32 battler) memset(&gDisableStructs[battler], 0, sizeof(struct DisableStruct)); - gProtectStructs[battler].protected = FALSE; - gProtectStructs[battler].spikyShielded = FALSE; - gProtectStructs[battler].kingsShielded = FALSE; - gProtectStructs[battler].banefulBunkered = FALSE; + if (GetProtectType(gProtectStructs[battler].protected) == PROTECT_TYPE_SINGLE) // Side type protects expire at the end of the turn + gProtectStructs[battler].protected = PROTECT_NONE; + gProtectStructs[battler].quash = FALSE; - gProtectStructs[battler].obstructed = FALSE; - gProtectStructs[battler].silkTrapped = FALSE; - gProtectStructs[battler].burningBulwarked = FALSE; gProtectStructs[battler].endured = FALSE; gProtectStructs[battler].noValidMoves = FALSE; gProtectStructs[battler].helpingHand = FALSE; @@ -5104,10 +5100,7 @@ static void TurnValuesCleanUp(bool8 var0) { if (var0) { - gProtectStructs[i].protected = FALSE; - gProtectStructs[i].spikyShielded = FALSE; - gProtectStructs[i].kingsShielded = FALSE; - gProtectStructs[i].banefulBunkered = FALSE; + gProtectStructs[i].protected = PROTECT_NONE; gProtectStructs[i].quash = FALSE; gProtectStructs[i].usedCustapBerry = FALSE; gProtectStructs[i].quickDraw = FALSE; @@ -5139,8 +5132,6 @@ static void TurnValuesCleanUp(bool8 var0) gBattleStruct->battlerState[i].usedEjectItem = FALSE; } - gSideStatuses[B_SIDE_PLAYER] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK); - gSideStatuses[B_SIDE_OPPONENT] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK); gSideTimers[B_SIDE_PLAYER].followmeTimer = 0; gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0; diff --git a/src/battle_message.c b/src/battle_message.c index a8bd1244cf..61a304e782 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -631,7 +631,6 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} frisked {B_DEF_NAME_WITH_PREFIX2} and found its {B_LAST_ITEM}!"), [STRINGID_UNNERVEENTERS] = COMPOUND_STRING("{B_DEF_TEAM1} team is too nervous to eat Berries!"), [STRINGID_HARVESTBERRY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} harvested its {B_LAST_ITEM}!"), - [STRINGID_LASTABILITYRAISEDSTAT] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_LAST_ABILITY} raised its {B_BUFF1}!"), [STRINGID_MAGICBOUNCEACTIVATES] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} bounced the {B_ATK_NAME_WITH_PREFIX2} back!"), [STRINGID_PROTEANTYPECHANGE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} transformed it into the {B_BUFF1} type!"), [STRINGID_SYMBIOSISITEMPASS] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} passed its {B_LAST_ITEM} to {B_EFF_NAME_WITH_PREFIX2} through {B_LAST_ABILITY}!"), diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a54cff0804..183419f05b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1153,6 +1153,85 @@ bool32 IsMoveNotAllowedInSkyBattles(u32 move) return (gBattleStruct->isSkyBattle && IsMoveSkyBattleBanned(gCurrentMove)); } +u32 NumAffectedSpreadMoveTargets(void) +{ + u32 targetCount = 1; + + if (!IsDoubleSpreadMove()) + return targetCount; + + targetCount = 0; + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT)) + targetCount++; + } + + return targetCount; +} + +u32 NumFaintedBattlersByAttacker(u32 battlerAtk) +{ + u32 numMonsFainted = 0; + + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (battler == battlerAtk) + continue; + + if (IsBattlerTurnDamaged(battler) && !IsBattlerAlive(battler)) + numMonsFainted++; + } + + return numMonsFainted; +} + +bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +{ + bool32 effect = FALSE; + + if (IsPowderMove(move) && (battlerAtk != battlerDef)) + { + if (B_POWDER_GRASS >= GEN_6 + && (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || GetBattlerAbility(battlerDef) == ABILITY_OVERCOAT)) + { + gBattlerAbility = battlerDef; + RecordAbilityBattle(gBattlerTarget, ABILITY_OVERCOAT); + effect = TRUE; + } + else if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) + { + RecordItemEffectBattle(battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); + gLastUsedItem = gBattleMons[battlerDef].item; + effect = TRUE; + } + + if (effect) + gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; + } + + return effect; +} + +bool32 EmergencyExitCanBeTriggered(u32 battler) +{ + u32 ability = GetBattlerAbility(battler); + + if (ability != ABILITY_EMERGENCY_EXIT && ability != ABILITY_WIMP_OUT) + return FALSE; + + if (IsBattlerTurnDamaged(battler) + && IsBattlerAlive(battler) + && HadMoreThanHalfHpNowDoesnt(battler) + && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) + && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) + && CountUsablePartyMons(battler) > 0 + && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) + return TRUE; + + return FALSE; +} + static void Cmd_attackcanceler(void) { CMD_ARGS(); @@ -1283,7 +1362,9 @@ static void Cmd_attackcanceler(void) } // Z-moves and Max Moves bypass protection, but deal reduced damage (factored in AccumulateOtherModifiers) - if ((IsZMove(gCurrentMove) || IsMaxMove(gCurrentMove)) && IS_BATTLER_PROTECTED(gBattlerTarget)) + if ((IsZMove(gCurrentMove) || IsMaxMove(gCurrentMove)) + && gProtectStructs[gBattlerTarget].protected != PROTECT_NONE + && gProtectStructs[gBattlerTarget].protected != PROTECT_MAX_GUARD) { BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_CouldntFullyProtect; @@ -1626,7 +1707,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u gBattlescriptCurrInstr = nextInstr; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) { - if (gProtectStructs[gBattlerTarget].maxGuarded) + if (gProtectStructs[gBattlerTarget].protected == PROTECT_MAX_GUARD) gBattlescriptCurrInstr = nextInstr; else AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, gCurrentMove); @@ -2080,6 +2161,7 @@ static void Cmd_adjustdamage(void) u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); u32 moveEffect = GetMoveEffect(gCurrentMove); bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); + bool32 enduredHit = FALSE; for (battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) { @@ -2121,65 +2203,58 @@ static void Cmd_adjustdamage(void) gPotentialItemEffectBattler = battlerDef; - if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param) + if (moveEffect == EFFECT_FALSE_SWIPE) { + enduredHit = TRUE; + } + else if (gProtectStructs[battlerDef].endured) + { + enduredHit = TRUE; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED; + } + else if (holdEffect == HOLD_EFFECT_FOCUS_BAND && rand < param) + { + enduredHit = TRUE; RecordItemEffectBattle(battlerDef, holdEffect); - gSpecialStatuses[battlerDef].focusBanded = TRUE; + gLastUsedItem = gBattleMons[battlerDef].item; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; } else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef)) { + enduredHit = TRUE; RecordAbilityBattle(battlerDef, ABILITY_STURDY); - gSpecialStatuses[battlerDef].sturdied = TRUE; + gLastUsedAbility = ABILITY_STURDY; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED; } else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef)) { + enduredHit = TRUE; RecordItemEffectBattle(battlerDef, holdEffect); - gSpecialStatuses[battlerDef].focusSashed = TRUE; + gLastUsedItem = gBattleMons[battlerDef].item; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; } else if (B_AFFECTION_MECHANICS == TRUE && GetBattlerSide(battlerDef) == B_SIDE_PLAYER && affectionScore >= AFFECTION_THREE_HEARTS) { if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20) || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) - gSpecialStatuses[battlerDef].affectionEndured = TRUE; + { + enduredHit = TRUE; + gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; + } } - if (moveEffect != EFFECT_FALSE_SWIPE - && !gProtectStructs[battlerDef].endured - && !gSpecialStatuses[battlerDef].focusBanded - && !gSpecialStatuses[battlerDef].focusSashed - && (B_AFFECTION_MECHANICS == FALSE || !gSpecialStatuses[battlerDef].affectionEndured) - && !gSpecialStatuses[battlerDef].sturdied) - continue; - // Handle reducing the dmg to 1 hp. - gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; - gSpecialStatuses[battlerDef].enduredDamage = TRUE; - - if (gProtectStructs[battlerDef].endured) + if (enduredHit) { - gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED; - } - else if (gSpecialStatuses[battlerDef].focusBanded || gSpecialStatuses[battlerDef].focusSashed) - { - gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_HUNG_ON; - gLastUsedItem = gBattleMons[battlerDef].item; - gSpecialStatuses[battlerDef].focusBanded = FALSE; - gSpecialStatuses[battlerDef].focusSashed = FALSE; - } - else if (gSpecialStatuses[battlerDef].sturdied) - { - gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_STURDIED; - gLastUsedAbility = ABILITY_STURDY; - } - else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[battlerDef].affectionEndured) - { - gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; + gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; + gSpecialStatuses[battlerDef].enduredDamage = TRUE; } } if (calcSpreadMoveDamage) gBattleStruct->calculatedDamageDone = TRUE; + gBattlescriptCurrInstr = cmd->nextInstr; if (gSpecialStatuses[gBattlerAttacker].gemBoost @@ -2208,7 +2283,6 @@ static void Cmd_multihitresultmessage(void) if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_STURDIED) { gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_HUNG_ON); - gSpecialStatuses[gBattlerTarget].sturdied = FALSE; // Delete this line to make Sturdy last for the duration of the whole move turn. BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_SturdiedMsg; return; @@ -2218,8 +2292,6 @@ static void Cmd_multihitresultmessage(void) gLastUsedItem = gBattleMons[gBattlerTarget].item; gPotentialItemEffectBattler = gBattlerTarget; gBattleStruct->moveResultFlags[gBattlerTarget] &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_HUNG_ON); - gSpecialStatuses[gBattlerTarget].focusBanded = FALSE; // Delete this line to make Focus Band last for the duration of the whole move turn. - gSpecialStatuses[gBattlerTarget].focusSashed = FALSE; // Delete this line to make Focus Sash last for the duration of the whole move turn. BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_HangedOnMsg; return; @@ -2886,7 +2958,6 @@ static void Cmd_resultmessage(void) else if (*moveResultFlags & MOVE_RESULT_STURDIED) { *moveResultFlags &= ~(MOVE_RESULT_STURDIED | MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON); - gSpecialStatuses[gBattlerTarget].sturdied = FALSE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_SturdiedMsg; return; @@ -2913,7 +2984,6 @@ static void Cmd_resultmessage(void) } else if (B_AFFECTION_MECHANICS == TRUE && (*moveResultFlags & MOVE_RESULT_FOE_ENDURED_AFFECTION)) { - gSpecialStatuses[gBattlerTarget].affectionEndured = FALSE; *moveResultFlags &= ~MOVE_RESULT_FOE_ENDURED_AFFECTION; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AffectionBasedEndurance; @@ -3871,19 +3941,20 @@ void SetMoveEffect(bool32 primary, bool32 certain) } break; case MOVE_EFFECT_FEINT: - if (IS_BATTLER_PROTECTED(gBattlerTarget)) + i = FALSE; // Remove Protect if any + if (gProtectStructs[gBattlerTarget].protected != PROTECT_NONE + && gProtectStructs[gBattlerTarget].protected != PROTECT_MAX_GUARD) + { + gProtectStructs[gBattlerTarget].protected = PROTECT_NONE; + i = TRUE; + } + if (GetProtectType(gProtectStructs[BATTLE_PARTNER(gBattlerTarget)].protected) == PROTECT_TYPE_SIDE) + { + gProtectStructs[BATTLE_PARTNER(gBattlerTarget)].protected = PROTECT_NONE; + i = TRUE; + } + if (i) { - gProtectStructs[gBattlerTarget].protected = FALSE; - gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_WIDE_GUARD; - gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_QUICK_GUARD; - gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_CRAFTY_SHIELD; - gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~SIDE_STATUS_MAT_BLOCK; - gProtectStructs[gBattlerTarget].spikyShielded = FALSE; - gProtectStructs[gBattlerTarget].kingsShielded = FALSE; - gProtectStructs[gBattlerTarget].banefulBunkered = FALSE; - gProtectStructs[gBattlerTarget].obstructed = FALSE; - gProtectStructs[gBattlerTarget].silkTrapped = FALSE; - gProtectStructs[gBattlerTarget].burningBulwarked = FALSE; BattleScriptPush(gBattlescriptCurrInstr + 1); if (gCurrentMove == MOVE_HYPERSPACE_FURY) gBattlescriptCurrInstr = BattleScript_HyperspaceFuryRemoveProtect; @@ -6221,6 +6292,133 @@ static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, u32 mov return FALSE; } +static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move) +{ + u32 effect = FALSE; + u32 abilityAtk = GetBattlerAbility(battlerAtk); + + switch (abilityAtk) + { + case ABILITY_MAGICIAN: + if (move != MOVE_FLING && move != MOVE_NATURAL_GIFT + && gBattleMons[battlerAtk].item == ITEM_NONE + && gBattleMons[battlerDef].item != ITEM_NONE + && IsBattlerAlive(battlerAtk) + && IsBattlerTurnDamaged(battlerDef) + && CanStealItem(battlerAtk, battlerDef, gBattleMons[battlerDef].item) + && !gSpecialStatuses[battlerAtk].gemBoost // In base game, gems are consumed after magician would activate. + && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(battlerDef)] & (1u << gBattlerPartyIndexes[battlerDef])) + && !DoesSubstituteBlockMove(battlerAtk, battlerDef, move) + && (GetBattlerAbility(battlerDef) != ABILITY_STICKY_HOLD || !IsBattlerAlive(battlerDef))) + { + StealTargetItem(battlerAtk, battlerDef); + gBattleScripting.battler = gBattlerAbility = battlerAtk; + gEffectBattler = battlerDef; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MagicianActivates; + gSpecialStatuses[battlerAtk].preventLifeOrbDamage = TRUE; + effect = TRUE; + } + break; + case ABILITY_MOXIE: + case ABILITY_CHILLING_NEIGH: + case ABILITY_AS_ONE_ICE_RIDER: + case ABILITY_GRIM_NEIGH: + case ABILITY_AS_ONE_SHADOW_RIDER: + case ABILITY_BEAST_BOOST: + { + if (!IsBattlerAlive(battlerAtk) || NoAliveMonsForEitherParty()) + break; + + u32 stat = STAT_ATK; + u32 numMonsFainted = NumFaintedBattlersByAttacker(battlerAtk); + + if (abilityAtk == ABILITY_BEAST_BOOST) + stat = GetHighestStatId(battlerAtk); + else if (abilityAtk == ABILITY_GRIM_NEIGH || abilityAtk == ABILITY_AS_ONE_SHADOW_RIDER) + stat = STAT_SPATK; + + if (numMonsFainted && CompareStat(battlerAtk, stat, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gLastUsedAbility = abilityAtk; + if (abilityAtk == ABILITY_AS_ONE_ICE_RIDER) + gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_CHILLING_NEIGH; + else if (abilityAtk == ABILITY_AS_ONE_SHADOW_RIDER) + gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_GRIM_NEIGH; + + SET_STATCHANGER(stat, numMonsFainted, FALSE); + PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); + gBattleScripting.animArg1 = GET_STAT_BUFF_ID(stat) + (numMonsFainted > 1 ? STAT_ANIM_PLUS2 : STAT_ANIM_PLUS1); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RaiseStatOnFaintingTarget; + effect = TRUE; + } + } + break; + case ABILITY_BATTLE_BOND: + { + if (!IsBattlerAlive(battlerAtk) + || NoAliveMonsForEitherParty() + || NumFaintedBattlersByAttacker(battlerAtk) == 0) + break; + + u32 side = GetBattlerSide(battlerAtk); + + if (gBattleStruct->battleBondBoost[side] & (1u << gBattlerPartyIndexes[battlerAtk])) + break; + + + if (GetGenConfig(GEN_CONFIG_BATTLE_BOND) < GEN_9 && gBattleMons[battlerAtk].species == SPECIES_GRENINJA_BATTLE_BOND) + { + // TODO: Convert this to a proper FORM_CHANGE type. + gLastUsedAbility = abilityAtk; + gBattleStruct->battleBondBoost[side] |= 1u << gBattlerPartyIndexes[battlerAtk]; + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerAtk].species); + gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[battlerAtk]] = gBattleMons[battlerAtk].species; + gBattleMons[battlerAtk].species = SPECIES_GRENINJA_ASH; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; + effect = TRUE; + } + else + { + u32 numStatBuffs = 0; + if (CompareStat(battlerAtk, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_ATK) + STAT_ANIM_PLUS1; + numStatBuffs++; + } + if (CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPATK) + STAT_ANIM_PLUS1; + numStatBuffs++; + } + if (CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPEED) + STAT_ANIM_PLUS1; + numStatBuffs++; + } + + if (numStatBuffs > 0) + { + if (numStatBuffs > 1) + gBattleScripting.animArg1 = STAT_ANIM_MULTIPLE_PLUS1; + + gLastUsedAbility = abilityAtk; + gBattlerAbility = battlerAtk; + gBattleStruct->battleBondBoost[side] |= 1u << gBattlerPartyIndexes[battlerAtk]; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EffectBattleBondStatIncrease; + effect = TRUE; + } + } + } + break; + } + + return effect; +} + static void Cmd_moveend(void) { CMD_ARGS(u8 endMode, u8 endState); @@ -6256,84 +6454,104 @@ static void Cmd_moveend(void) case MOVEEND_PROTECT_LIKE_EFFECT: if (gProtectStructs[gBattlerAttacker].touchedProtectLike) { - if (gProtectStructs[gBattlerTarget].spikyShielded - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) - && !IsMagicGuardProtected(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) + enum ProtectMethod method = gProtectStructs[gBattlerTarget].protected; + switch (method) { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; - if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) - gBattleStruct->moveDamage[gBattlerAttacker] = 1; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SPIKY_SHIELD); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_SpikyShieldEffect; - effect = 1; - } - else if (gProtectStructs[gBattlerTarget].kingsShielded - && !IsProtectEffectAffected(gBattlerAttacker, gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - 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; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; - effect = 1; - } - else if (gProtectStructs[gBattlerTarget].banefulBunkered - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) - { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - gBattleScripting.moveEffect = MOVE_EFFECT_POISON | MOVE_EFFECT_AFFECTS_USER; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BANEFUL_BUNKER); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; - effect = 1; - } - else if (gProtectStructs[gBattlerTarget].obstructed - && moveEffect != EFFECT_SUCKER_PUNCH - && moveEffect != EFFECT_UPPER_HAND - && !IsProtectEffectAffected(gBattlerAttacker, gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - i = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable - gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_2; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; - effect = 1; - } - else if (gProtectStructs[gBattlerTarget].silkTrapped - && !IsProtectEffectAffected(gBattlerAttacker, gCurrentMove)) - { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - i = gBattlerAttacker; - gBattlerAttacker = gBattlerTarget; - gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable - gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; - effect = 1; - } - else if (gProtectStructs[gBattlerTarget].burningBulwarked - && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) - { - gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; - gBattleScripting.moveEffect = MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BURNING_BULWARK); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; - effect = 1; + case PROTECT_SPIKY_SHIELD: + if (moveEffect != EFFECT_COUNTER + && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && !IsMagicGuardProtected(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; + if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) + gBattleStruct->moveDamage[gBattlerAttacker] = 1; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SPIKY_SHIELD); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SpikyShieldEffect; + effect = 1; + } + break; + case PROTECT_KINGS_SHIELD: + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + 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; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; + effect = 1; + } + break; + case PROTECT_BANEFUL_BUNKER: + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + gBattleScripting.moveEffect = MOVE_EFFECT_POISON | MOVE_EFFECT_AFFECTS_USER; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BANEFUL_BUNKER); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; + effect = 1; + } + break; + case PROTECT_BURNING_BULWARK: + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + gBattleScripting.moveEffect = MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_BURNING_BULWARK); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; + effect = 1; + } + break; + case PROTECT_OBSTRUCT: + if (moveEffect != EFFECT_SUCKER_PUNCH // Why??? + && moveEffect != EFFECT_UPPER_HAND // Why??? + && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + i = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_2; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; + effect = 1; + } + break; + case PROTECT_SILK_TRAP: + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + { + gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; + i = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; + effect = 1; + } + break; + case PROTECT_NONE: + case PROTECT_NORMAL: + case PROTECT_MAX_GUARD: + case PROTECT_WIDE_GUARD: + case PROTECT_QUICK_GUARD: + case PROTECT_CRAFTY_SHIELD: + case PROTECT_MAT_BLOCK: + break; } + // Not strictly a protect effect, but works the same way - else if (gProtectStructs[gBattlerTarget].beakBlastCharge - && CanBeBurned(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + if (gProtectStructs[gBattlerTarget].beakBlastCharge + && CanBeBurned(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleMons[gBattlerAttacker].status1 = STATUS1_BURN; @@ -6980,9 +7198,6 @@ static void Cmd_moveend(void) gHitMarker |= (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING); gBattleScripting.animTargetsHit = 0; gBattleScripting.moveendState = 0; - gSpecialStatuses[gBattlerTarget].sturdied = 0; - gSpecialStatuses[gBattlerTarget].focusBanded = 0; // Delete this line to make Focus Band last for the duration of the whole move turn. - gSpecialStatuses[gBattlerTarget].focusSashed = 0; // Delete this line to make Focus Sash last for the duration of the whole move turn. gSpecialStatuses[gBattlerAttacker].multiHitOn = TRUE; MoveValuesCleanUp(); BattleScriptPush(GetMoveBattleScript(gCurrentMove)); @@ -7003,27 +7218,8 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - case MOVEEND_MAGICIAN: - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_MAGICIAN - && gCurrentMove != MOVE_FLING && gCurrentMove != MOVE_NATURAL_GIFT - && gBattleMons[gBattlerAttacker].item == ITEM_NONE - && gBattleMons[gBattlerTarget].item != ITEM_NONE - && IsBattlerAlive(gBattlerAttacker) - && IsBattlerTurnDamaged(gBattlerTarget) - && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) - && !gSpecialStatuses[gBattlerAttacker].gemBoost // In base game, gems are consumed after magician would activate. - && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) - && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove) - && (GetBattlerAbility(gBattlerTarget) != ABILITY_STICKY_HOLD || !IsBattlerAlive(gBattlerTarget))) - { - StealTargetItem(gBattlerAttacker, gBattlerTarget); - gBattleScripting.battler = gBattlerAbility = gBattlerAttacker; - gEffectBattler = gBattlerTarget; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MagicianActivates; - gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = TRUE; - effect = TRUE; - } + case MOVEEND_ABILITY_BLOCK: + effect = HandleMoveEndAbilityBlock(gBattlerAttacker, gBattlerTarget, gCurrentMove); gBattleScripting.moveendState++; break; case MOVEEND_SHEER_FORCE: @@ -9960,16 +10156,6 @@ static bool32 ChangeOrderTargetAfterAttacker(void) return TRUE; } -static u32 CalculateBattlerPartyCount(u32 battler) -{ - u32 count; - if (GetBattlerSide(battler) == B_SIDE_PLAYER) - count = CalculatePlayerPartyCount(); - else - count = CalculateEnemyPartyCount(); - return count; -} - static void Cmd_various(void) { CMD_ARGS(u8 battler, u8 id); @@ -10559,53 +10745,6 @@ static void Cmd_various(void) MarkBattlerForControllerExec(battler); break; } - case VARIOUS_TRY_ACTIVATE_MOXIE: // and chilling neigh + as one ice rider - { - VARIOUS_ARGS(); - - u16 battlerAbility = GetBattlerAbility(battler); - - if ((battlerAbility == ABILITY_MOXIE - || battlerAbility == ABILITY_CHILLING_NEIGH - || battlerAbility == ABILITY_AS_ONE_ICE_RIDER) - && HasAttackerFaintedTarget() - && !NoAliveMonsForEitherParty() - && CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(STAT_ATK, 1, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK); - BattleScriptPush(cmd->nextInstr); - gLastUsedAbility = battlerAbility; - if (battlerAbility == ABILITY_AS_ONE_ICE_RIDER) - gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_CHILLING_NEIGH; - gBattlescriptCurrInstr = BattleScript_RaiseStatOnFaintingTarget; - return; - } - break; - } - case VARIOUS_TRY_ACTIVATE_GRIM_NEIGH: // and as one shadow rider - { - VARIOUS_ARGS(); - - u16 battlerAbility = GetBattlerAbility(battler); - - if ((battlerAbility == ABILITY_GRIM_NEIGH - || battlerAbility == ABILITY_AS_ONE_SHADOW_RIDER) - && HasAttackerFaintedTarget() - && !NoAliveMonsForEitherParty() - && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK); - BattleScriptPush(cmd->nextInstr); - gLastUsedAbility = battlerAbility; - if (battlerAbility == ABILITY_AS_ONE_SHADOW_RIDER) - gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_GRIM_NEIGH; - gBattlescriptCurrInstr = BattleScript_RaiseStatOnFaintingTarget; - return; - } - break; - } case VARIOUS_TRY_ACTIVATE_RECEIVER: // Partner gets fainted's ally ability { VARIOUS_ARGS(); @@ -10624,24 +10763,6 @@ static void Cmd_various(void) } break; } - case VARIOUS_TRY_ACTIVATE_BEAST_BOOST: - { - VARIOUS_ARGS(); - - i = GetHighestStatId(battler); - if (GetBattlerAbility(battler) == ABILITY_BEAST_BOOST - && HasAttackerFaintedTarget() - && !NoAliveMonsForEitherParty() - && CompareStat(gBattlerAttacker, i, MAX_STAT_STAGE, CMP_LESS_THAN)) - { - SET_STATCHANGER(i, 1, FALSE); - PREPARE_STAT_BUFFER(gBattleTextBuff1, i); - BattleScriptPush(cmd->nextInstr); - gBattlescriptCurrInstr = BattleScript_AttackerAbilityStatRaise; - return; - } - break; - } case VARIOUS_TRY_ACTIVATE_SOULHEART: { VARIOUS_ARGS(); @@ -10706,7 +10827,7 @@ static void Cmd_various(void) case VARIOUS_SUCKER_PUNCH_CHECK: { VARIOUS_ARGS(const u8 *failInstr); - if (gProtectStructs[gBattlerTarget].obstructed) + if (gProtectStructs[gBattlerTarget].protected == PROTECT_OBSTRUCT) gBattlescriptCurrInstr = cmd->failInstr; else if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget)) gBattlescriptCurrInstr = cmd->failInstr; @@ -11487,25 +11608,6 @@ static void Cmd_various(void) } return; } - // TODO: Convert this to a proper FORM_CHANGE type. - case VARIOUS_TRY_ACTIVATE_BATTLE_BOND: - { - VARIOUS_ARGS(); - if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND - && HasAttackerFaintedTarget() - && CalculateBattlerPartyCount(gBattlerTarget) > 1 - && !(gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker]))) - { - gBattleStruct->battleBondTransformed[GetBattlerSide(gBattlerAttacker)] |= 1u << gBattlerPartyIndexes[gBattlerAttacker]; - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); - gBattleStruct->changedSpecies[GetBattlerSide(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; - gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; - return; - } - break; - } case VARIOUS_CONSUME_BERRY: { VARIOUS_ARGS(bool8 fromBattler); @@ -11748,102 +11850,40 @@ static void Cmd_setprotectlike(void) { CMD_ARGS(); - bool32 fail = TRUE; + bool32 protectFails = TRUE; bool32 notLastTurn = TRUE; + u32 protectMethod = GetMoveProtectMethod(gCurrentMove); TryResetProtectUseCounter(gBattlerAttacker); + if (gCurrentTurnActionNumber == (gBattlersCount - 1)) notLastTurn = FALSE; if ((sProtectSuccessRates[gDisableStructs[gBattlerAttacker].protectUses] >= Random() && notLastTurn) - || (gCurrentMove == MOVE_WIDE_GUARD && B_WIDE_GUARD != GEN_5) - || (gCurrentMove == MOVE_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) + || (protectMethod == PROTECT_WIDE_GUARD && B_WIDE_GUARD != GEN_5) + || (protectMethod == PROTECT_QUICK_GUARD && B_QUICK_GUARD != GEN_5)) { - if (!GetMoveProtectSide(gCurrentMove)) // Protects one mon only. + if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) { - if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) - { - gProtectStructs[gBattlerAttacker].endured = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; - } - else if (gCurrentMove == MOVE_DETECT || gCurrentMove == MOVE_PROTECT) - { - gProtectStructs[gBattlerAttacker].protected = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_SPIKY_SHIELD) - { - gProtectStructs[gBattlerAttacker].spikyShielded = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_KINGS_SHIELD) - { - gProtectStructs[gBattlerAttacker].kingsShielded = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_BANEFUL_BUNKER) - { - gProtectStructs[gBattlerAttacker].banefulBunkered = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_OBSTRUCT) - { - gProtectStructs[gBattlerAttacker].obstructed = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_MAX_GUARD) - { - gProtectStructs[gBattlerAttacker].maxGuarded = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_SILK_TRAP) - { - gProtectStructs[gBattlerAttacker].silkTrapped = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } - else if (gCurrentMove == MOVE_BURNING_BULWARK) - { - gProtectStructs[gBattlerAttacker].burningBulwarked = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; - } + gProtectStructs[gBattlerAttacker].endured = TRUE; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; + } + else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE) + { + gProtectStructs[gBattlerAttacker].protected = protectMethod; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; + } + else + { + gProtectStructs[gBattlerAttacker].protected = protectMethod; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_ITSELF; + } - gDisableStructs[gBattlerAttacker].protectUses++; - fail = FALSE; - } - else // Protects the whole side. - { - u8 side = GetBattlerSide(gBattlerAttacker); - if (gCurrentMove == MOVE_WIDE_GUARD && !(gSideStatuses[side] & SIDE_STATUS_WIDE_GUARD)) - { - gSideStatuses[side] |= SIDE_STATUS_WIDE_GUARD; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; - gDisableStructs[gBattlerAttacker].protectUses++; - fail = FALSE; - } - else if (gCurrentMove == MOVE_QUICK_GUARD && !(gSideStatuses[side] & SIDE_STATUS_QUICK_GUARD)) - { - gSideStatuses[side] |= SIDE_STATUS_QUICK_GUARD; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; - gDisableStructs[gBattlerAttacker].protectUses++; - fail = FALSE; - } - else if (gCurrentMove == MOVE_CRAFTY_SHIELD && !(gSideStatuses[side] & SIDE_STATUS_CRAFTY_SHIELD)) - { - gSideStatuses[side] |= SIDE_STATUS_CRAFTY_SHIELD; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; - gDisableStructs[gBattlerAttacker].protectUses++; - fail = FALSE; - } - else if (gCurrentMove == MOVE_MAT_BLOCK && !(gSideStatuses[side] & SIDE_STATUS_MAT_BLOCK)) - { - gSideStatuses[side] |= SIDE_STATUS_MAT_BLOCK; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECTED_TEAM; - fail = FALSE; - } - } + gDisableStructs[gBattlerAttacker].protectUses++; + protectFails = FALSE; } - if (fail) + if (protectFails) { gDisableStructs[gBattlerAttacker].protectUses = 0; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PROTECT_FAILED; @@ -13036,6 +13076,10 @@ static void Cmd_setlightscreen(void) gBattlescriptCurrInstr = cmd->nextInstr; } +#define NOT_ENDURED 0 +#define FOCUS_SASHED 1 +#define FOCUS_BANDED 2 +#define AFFECTION_ENDURED 3 static void Cmd_tryKO(void) { CMD_ARGS(const u8 *failInstr); @@ -13043,6 +13087,9 @@ static void Cmd_tryKO(void) bool32 lands = FALSE; u32 holdEffect = GetBattlerHoldEffect(gBattlerTarget, TRUE); u16 targetAbility = GetBattlerAbility(gBattlerTarget); + u32 rand = Random() % 100; + u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); + u32 endured = NOT_ENDURED; // Dynamaxed Pokemon cannot be hit by OHKO moves. if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX)) @@ -13057,14 +13104,21 @@ static void Cmd_tryKO(void) if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < GetBattlerHoldEffectParam(gBattlerTarget)) { - gSpecialStatuses[gBattlerTarget].focusBanded = TRUE; + endured = FOCUS_BANDED; RecordItemEffectBattle(gBattlerTarget, holdEffect); } else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget)) { - gSpecialStatuses[gBattlerTarget].focusSashed = TRUE; + endured = FOCUS_SASHED; RecordItemEffectBattle(gBattlerTarget, holdEffect); } + else if (B_AFFECTION_MECHANICS == TRUE && GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER && affectionScore >= AFFECTION_THREE_HEARTS) + { + if ((affectionScore == AFFECTION_FIVE_HEARTS && rand < 20) + || (affectionScore == AFFECTION_FOUR_HEARTS && rand < 15) + || (affectionScore == AFFECTION_THREE_HEARTS && rand < 10)) + endured = AFFECTION_ENDURED; + } if (targetAbility == ABILITY_STURDY) { @@ -13099,13 +13153,13 @@ static void Cmd_tryKO(void) gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED; } - else if (gSpecialStatuses[gBattlerTarget].focusBanded || gSpecialStatuses[gBattlerTarget].focusSashed) + else if (endured == FOCUS_BANDED || endured == FOCUS_SASHED) { gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_HUNG_ON; gLastUsedItem = gBattleMons[gBattlerTarget].item; } - else if (B_AFFECTION_MECHANICS == TRUE && gSpecialStatuses[gBattlerTarget].affectionEndured) + else if (endured == AFFECTION_ENDURED) { gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; @@ -13128,6 +13182,10 @@ static void Cmd_tryKO(void) } } } +#undef NOT_ENDURED +#undef FOCUS_SASHED +#undef FOCUS_BANDED +#undef AFFECTION_ENDURED // Super Fang static void Cmd_damagetohalftargethp(void) diff --git a/src/battle_util.c b/src/battle_util.c index 9917b833f2..c054043206 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2850,12 +2850,12 @@ static inline uq4_12_t GetSupremeOverlordModifier(u32 battler) return UQ_4_12(1.0) + (PercentToUQ4_12(gBattleStruct->supremeOverlordCounter[battler] * 10)); } -static inline bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) +bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) { u32 cutoff = gBattleMons[battler].maxHP / 2; // Had more than half of hp before, now has less - return (gBattleStruct->hpBefore[battler] > cutoff - && gBattleMons[battler].hp <= cutoff); + return gBattleStruct->hpBefore[battler] > cutoff + && gBattleMons[battler].hp <= cutoff; } #define ANIM_STAT_HP 0 @@ -5021,7 +5021,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_OPPORTUNIST: if (gProtectStructs[battler].activateOpportunist == 2) { - gBattleScripting.animArg1 = 0; gBattleScripting.battler = battler; gProtectStructs[battler].activateOpportunist--; ChooseStatBoostAnimation(battler); @@ -7470,45 +7469,55 @@ bool32 IsMoveMakingContact(u32 move, u32 battlerAtk) } } +static inline bool32 IsSideProtected(u32 battler, enum ProtectMethod method) +{ + return gProtectStructs[battler].protected == method + || gProtectStructs[BATTLE_PARTNER(battler)].protected == method; +} + bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) { + if (gProtectStructs[battlerDef].protected == PROTECT_NONE + && gProtectStructs[BATTLE_PARTNER(battlerDef)].protected == PROTECT_NONE) + return FALSE; + + if (gProtectStructs[battlerDef].protected != PROTECT_MAX_GUARD && !MoveIgnoresProtect(move)) + { + if (IsZMove(move) || IsMaxMove(move)) + return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). + if (IsMoveMakingContact(move, battlerAtk) && GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST) + return FALSE; + } + bool32 isProtected = FALSE; - if ((IsZMove(move) || IsMaxMove(move)) - && (!gProtectStructs[battlerDef].maxGuarded || MoveIgnoresProtect(move))) - isProtected = FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). - else if (gProtectStructs[battlerDef].maxGuarded && IsMoveBlockedByMaxGuard(move)) - isProtected = TRUE; - else if (!gProtectStructs[battlerDef].maxGuarded // Max Guard cannot be bypassed by Unseen Fist - && IsMoveMakingContact(move, battlerAtk) - && GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST) - isProtected = FALSE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD && IsBattleMoveStatus(move) && GetMoveEffect(move) != EFFECT_COACHING) + if (IsSideProtected(battlerDef, PROTECT_CRAFTY_SHIELD) + && IsBattleMoveStatus(move) + && GetMoveEffect(move) != EFFECT_COACHING) isProtected = TRUE; else if (MoveIgnoresProtect(move)) isProtected = FALSE; - else if (gProtectStructs[battlerDef].protected) + else if (IsSideProtected(battlerDef, PROTECT_WIDE_GUARD) && IsSpreadMove(GetBattlerMoveTargetType(battlerAtk, move))) isProtected = TRUE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_WIDE_GUARD - && GetBattlerMoveTargetType(battlerAtk, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + else if (gProtectStructs[battlerDef].protected == PROTECT_NORMAL) isProtected = TRUE; - else if (gProtectStructs[battlerDef].banefulBunkered) + else if (gProtectStructs[battlerDef].protected == PROTECT_SPIKY_SHIELD) isProtected = TRUE; - else if (gProtectStructs[battlerDef].burningBulwarked) + else if (gProtectStructs[battlerDef].protected == PROTECT_MAX_GUARD) isProtected = TRUE; - else if ((gProtectStructs[battlerDef].obstructed || gProtectStructs[battlerDef].silkTrapped) && !IsBattleMoveStatus(move)) + else if (gProtectStructs[battlerDef].protected == PROTECT_BANEFUL_BUNKER) isProtected = TRUE; - else if (gProtectStructs[battlerDef].spikyShielded) + else if (gProtectStructs[battlerDef].protected == PROTECT_BURNING_BULWARK) isProtected = TRUE; - else if (gProtectStructs[battlerDef].kingsShielded && !IsBattleMoveStatus(move)) + else if (gProtectStructs[battlerDef].protected == PROTECT_OBSTRUCT && !IsBattleMoveStatus(move)) isProtected = TRUE; - else if (gProtectStructs[battlerDef].maxGuarded) + else if (gProtectStructs[battlerDef].protected == PROTECT_SILK_TRAP && !IsBattleMoveStatus(move)) isProtected = TRUE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_QUICK_GUARD - && GetChosenMovePriority(battlerAtk) > 0) + else if (gProtectStructs[battlerDef].protected == PROTECT_KINGS_SHIELD && !IsBattleMoveStatus(move)) isProtected = TRUE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MAT_BLOCK - && !IsBattleMoveStatus(move)) + else if (IsSideProtected(battlerDef, PROTECT_QUICK_GUARD) && GetChosenMovePriority(battlerAtk) > 0) + isProtected = TRUE; + else if (IsSideProtected(battlerDef, PROTECT_MAT_BLOCK) && !IsBattleMoveStatus(move)) isProtected = TRUE; else isProtected = FALSE; @@ -7519,6 +7528,31 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) return isProtected; } +u32 GetProtectType(enum ProtectMethod method) +{ + switch (method) + { + case PROTECT_NONE: + return PROTECT_TYPE_NONE; + case PROTECT_NORMAL: + case PROTECT_SPIKY_SHIELD: + case PROTECT_KINGS_SHIELD: + case PROTECT_BANEFUL_BUNKER: + case PROTECT_BURNING_BULWARK: + case PROTECT_OBSTRUCT: + case PROTECT_SILK_TRAP: + case PROTECT_MAX_GUARD: + return PROTECT_TYPE_SINGLE; + case PROTECT_WIDE_GUARD: + case PROTECT_QUICK_GUARD: + case PROTECT_CRAFTY_SHIELD: + case PROTECT_MAT_BLOCK: + return PROTECT_TYPE_SIDE; + } + + return FALSE; +} + // Only called directly when calculating damage type effectiveness static bool32 IsBattlerGroundedInverseCheck(u32 battler, bool32 considerInverse) { @@ -8891,7 +8925,9 @@ static inline uq4_12_t GetGlaiveRushModifier(u32 battlerDef) static inline uq4_12_t GetZMaxMoveAgainstProtectionModifier(struct DamageCalculationData *damageCalcData) { - if ((IsZMove(damageCalcData->move) || IsMaxMove(damageCalcData->move)) && IS_BATTLER_PROTECTED(damageCalcData->battlerDef)) + if ((IsZMove(damageCalcData->move) || IsMaxMove(damageCalcData->move)) + && gProtectStructs[damageCalcData->battlerDef].protected != PROTECT_NONE + && gProtectStructs[damageCalcData->battlerDef].protected != PROTECT_MAX_GUARD) return UQ_4_12(0.25); return UQ_4_12(1.0); } @@ -10994,23 +11030,6 @@ bool32 IsMoveEffectBlockedByTarget(u32 ability) return FALSE; } -u32 NumAffectedSpreadMoveTargets(void) -{ - u32 targetCount = 1; - - if (!IsDoubleSpreadMove()) - return targetCount; - - targetCount = 0; - for (u32 battler = 0; battler < gBattlersCount; battler++) - { - if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT)) - targetCount++; - } - - return targetCount; -} - bool32 IsPursuitTargetSet(void) { for (u32 battler = 0; battler < gBattlersCount; battler++) @@ -11052,49 +11071,3 @@ bool32 HasWeatherEffect(void) return TRUE; } - -bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) -{ - bool32 effect = FALSE; - - if (IsPowderMove(move) && (battlerAtk != battlerDef)) - { - if (B_POWDER_GRASS >= GEN_6 - && (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || GetBattlerAbility(battlerDef) == ABILITY_OVERCOAT)) - { - gBattlerAbility = battlerDef; - RecordAbilityBattle(gBattlerTarget, ABILITY_OVERCOAT); - effect = TRUE; - } - else if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) - { - RecordItemEffectBattle(battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); - gLastUsedItem = gBattleMons[battlerDef].item; - effect = TRUE; - } - - if (effect) - gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; - } - - return effect; -} - -bool32 EmergencyExitCanBeTriggered(u32 battler) -{ - u32 ability = GetBattlerAbility(battler); - - if (ability != ABILITY_EMERGENCY_EXIT && ability != ABILITY_WIMP_OUT) - return FALSE; - - if (IsBattlerTurnDamaged(battler) - && IsBattlerAlive(battler) - && HadMoreThanHalfHpNowDoesnt(battler) - && (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)) - && !(gBattleTypeFlags & BATTLE_TYPE_ARENA) - && CountUsablePartyMons(battler) > 0 - && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) - return TRUE; - - return FALSE; -} diff --git a/src/data/moves_info.h b/src/data/moves_info.h index b34aad70d4..fee2dcccc4 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -4789,6 +4789,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 4 : 3, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_NORMAL }, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .metronomeBanned = TRUE, .copycatBanned = TRUE, @@ -5179,6 +5180,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = B_UPDATED_MOVE_DATA >= GEN_5 ? 4 : 3, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_NORMAL }, .zMove = { .effect = Z_EFFECT_EVSN_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -12049,7 +12051,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = { .protect.side = TRUE, }, + .argument = { .protectMethod = PROTECT_WIDE_GUARD }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -12810,7 +12812,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = { .protect.side = TRUE, }, + .argument = { .protectMethod = PROTECT_QUICK_GUARD, }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -14268,7 +14270,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 0, .category = DAMAGE_CATEGORY_STATUS, - .argument = { .protect.side = TRUE }, + .argument = { .protectMethod = PROTECT_MAT_BLOCK, }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .snatchAffected = TRUE, .ignoresProtect = TRUE, @@ -14694,7 +14696,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 3, .category = DAMAGE_CATEGORY_STATUS, - .argument = { .protect.side = TRUE, }, + .argument = { .protectMethod = PROTECT_CRAFTY_SHIELD }, .zMove = { .effect = Z_EFFECT_SPDEF_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -14936,6 +14938,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_KINGS_SHIELD }, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -15140,6 +15143,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_SPIKY_SHIELD }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -15829,6 +15833,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_BANEFUL_BUNKER }, .zMove = { .effect = Z_EFFECT_DEF_UP_1 }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -18211,6 +18216,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_OBSTRUCT }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, @@ -19598,6 +19604,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_SILK_TRAP }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, @@ -20814,6 +20821,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_BURNING_BULWARK }, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, @@ -21559,6 +21567,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_USER, .priority = 4, .category = DAMAGE_CATEGORY_STATUS, + .argument = { .protectMethod = PROTECT_MAX_GUARD }, .battleAnimScript = gBattleAnimMove_MaxGuard, }, diff --git a/test/battle/ability/battle_bond.c b/test/battle/ability/battle_bond.c index f480367798..401df267b6 100644 --- a/test/battle/ability/battle_bond.c +++ b/test/battle/ability/battle_bond.c @@ -6,26 +6,6 @@ ASSUMPTIONS ASSUME(!IsBattleMoveStatus(MOVE_WATER_GUN)); } -SINGLE_BATTLE_TEST("Battle Bond does not transform species other than Greninja") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_BATTLE_BOND); } - OPPONENT(SPECIES_WOBBUFFET) { HP(1); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_WATER_GUN); SEND_OUT(opponent, 1); } - } SCENE { - HP_BAR(opponent); - MESSAGE("The opposing Wobbuffet fainted!"); - NONE_OF { - ABILITY_POPUP(player, ABILITY_BATTLE_BOND); - MESSAGE("Wobbuffet became fully charged due to its bond with its trainer!"); - } - } THEN { - EXPECT(player->species == SPECIES_WOBBUFFET); - } -} - // Battle Bond transforms the pokemon when fainting any battler(opposing or partner), unless it's the last pokemon and the battle ends. SINGLE_BATTLE_TEST("Battle Bond transforms player's Greninja - Singles") { @@ -37,6 +17,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms player's Greninja - Singles") PARAMETRIZE {monsCountPlayer = 2; monsCountOpponent = 2; } GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND); if (monsCountPlayer == 2) { PLAYER(SPECIES_WOBBUFFET); @@ -84,6 +65,7 @@ SINGLE_BATTLE_TEST("Battle Bond transforms opponent's Greninja - Singles") PARAMETRIZE {monsCountPlayer = 2; monsCountOpponent = 2; } GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); OPPONENT(SPECIES_GRENINJA_BATTLE_BOND); if (monsCountOpponent == 2) { OPPONENT(SPECIES_WOBBUFFET); @@ -131,6 +113,7 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A PARAMETRIZE {monsCountPlayer = 3; monsCountOpponent = 3; } GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND); PLAYER(SPECIES_WOBBUFFET) { HP(1); } if (monsCountPlayer == 3) { @@ -158,3 +141,51 @@ DOUBLE_BATTLE_TEST("Battle Bond transforms player's Greninja when fainting its A EXPECT(playerLeft->species == SPECIES_GRENINJA_ASH); } } + +SINGLE_BATTLE_TEST("Battle Bond increases Atk, SpAtk and Speed by 1 stage (Gen9+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_9); + PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_GUN); SEND_OUT(opponent, 1); } + } SCENE { + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet fainted!"); + ABILITY_POPUP(player, ABILITY_BATTLE_BOND); + } THEN { + EXPECT(player->species != SPECIES_GRENINJA_ASH); + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Battle Bond increases a Stat even if only one can be increased (Gen9+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_9); + PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_DRAGON_DANCE); } + TURN { MOVE(player, MOVE_WATER_GUN); SEND_OUT(opponent, 1); } + } SCENE { + HP_BAR(opponent); + MESSAGE("The opposing Wobbuffet fainted!"); + ABILITY_POPUP(player, ABILITY_BATTLE_BOND); + } THEN { + EXPECT(player->species != SPECIES_GRENINJA_ASH); + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 6); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 6); + } +} diff --git a/test/battle/ability/beast_boost.c b/test/battle/ability/beast_boost.c index fde1683104..432fded4c9 100644 --- a/test/battle/ability/beast_boost.c +++ b/test/battle/ability/beast_boost.c @@ -19,19 +19,19 @@ SINGLE_BATTLE_TEST("Beast Boost boosts the most proficient stat when knocking ou ABILITY_POPUP(player, ABILITY_BEAST_BOOST); switch(i) { case 0: - MESSAGE("Nihilego's Beast Boost raised its Attack!"); + MESSAGE("Nihilego's Attack rose!"); break; case 1: - MESSAGE("Nihilego's Beast Boost raised its Defense!"); + MESSAGE("Nihilego's Defense rose!"); break; case 2: - MESSAGE("Nihilego's Beast Boost raised its Sp. Atk!"); + MESSAGE("Nihilego's Sp. Atk rose!"); break; case 3: - MESSAGE("Nihilego's Beast Boost raised its Sp. Def!"); + MESSAGE("Nihilego's Sp. Def rose!"); break; case 4: - MESSAGE("Nihilego's Beast Boost raised its Speed!"); + MESSAGE("Nihilego's Speed rose!"); break; } } diff --git a/test/battle/ability/grim_neigh.c b/test/battle/ability/grim_neigh.c index c58487722b..69d60db93e 100644 --- a/test/battle/ability/grim_neigh.c +++ b/test/battle/ability/grim_neigh.c @@ -16,22 +16,16 @@ DOUBLE_BATTLE_TEST("Grim Neigh raises Sp. Attack by one stage after directly cau } WHEN { TURN { MOVE(playerLeft, MOVE_DISCHARGE); SEND_OUT(opponentLeft, 2); } } SCENE { - int i; - ANIMATION(ANIM_TYPE_MOVE, MOVE_DISCHARGE, playerLeft); - for (i = 0; i < 3; i++) { - ONE_OF { - MESSAGE("Snorunt fainted!"); - MESSAGE("The opposing Glalie fainted!"); - MESSAGE("The opposing Abra fainted!"); - } - ABILITY_POPUP(playerLeft, abilityPopUp); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - if (species == SPECIES_SPECTRIER) - MESSAGE("Spectrier's Grim Neigh raised its Sp. Atk!"); - else - MESSAGE("Calyrex's Grim Neigh raised its Sp. Atk!"); - } + MESSAGE("The opposing Glalie fainted!"); + MESSAGE("Snorunt fainted!"); + MESSAGE("The opposing Abra fainted!"); + ABILITY_POPUP(playerLeft, abilityPopUp); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + if (species == SPECIES_SPECTRIER) + MESSAGE("Spectrier's Sp. Atk drastically rose!"); + else + MESSAGE("Calyrex's Sp. Atk drastically rose!"); } THEN { EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 3); } @@ -98,9 +92,9 @@ DOUBLE_BATTLE_TEST("Grim Neigh does not increase damage done by the same move th ABILITY_POPUP(playerLeft, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); if (species == SPECIES_SPECTRIER) - MESSAGE("Spectrier's Grim Neigh raised its Sp. Atk!"); + MESSAGE("Spectrier's Sp. Atk rose!"); else - MESSAGE("Calyrex's Grim Neigh raised its Sp. Atk!"); + MESSAGE("Calyrex's Sp. Atk rose!"); } THEN { EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); EXPECT_EQ(damage[0], damage[1]); diff --git a/test/battle/ability/moxie.c b/test/battle/ability/moxie.c index 35ae64d164..a39fb91df8 100644 --- a/test/battle/ability/moxie.c +++ b/test/battle/ability/moxie.c @@ -17,24 +17,18 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh raises Attack by one stage after direct } WHEN { TURN { MOVE(playerLeft, MOVE_EARTHQUAKE); SEND_OUT(opponentLeft, 2); } } SCENE { - int i; - ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft); - for (i = 0; i < 3; i++) { - ONE_OF { - MESSAGE("Snorunt fainted!"); - MESSAGE("The opposing Glalie fainted!"); - MESSAGE("The opposing Abra fainted!"); - } - ABILITY_POPUP(playerLeft, abilityPopUp); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); - if (species == SPECIES_SALAMENCE) - MESSAGE("Salamence's Moxie raised its Attack!"); - else if (species == SPECIES_GLASTRIER) - MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); - else - MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); - } + MESSAGE("The opposing Glalie fainted!"); + MESSAGE("Snorunt fainted!"); + MESSAGE("The opposing Abra fainted!"); + ABILITY_POPUP(playerLeft, abilityPopUp); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + if (species == SPECIES_SALAMENCE) + MESSAGE("Salamence's Attack drastically rose!"); + else if (species == SPECIES_GLASTRIER) + MESSAGE("Glastrier's Attack drastically rose!"); + else + MESSAGE("Calyrex's Attack drastically rose!"); } THEN { EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 3); } @@ -140,11 +134,11 @@ DOUBLE_BATTLE_TEST("Moxie/Chilling Neigh does not increase damage done by the sa ABILITY_POPUP(playerLeft, abilityPopUp); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); if (species == SPECIES_SALAMENCE) - MESSAGE("Salamence's Moxie raised its Attack!"); + MESSAGE("Salamence's Attack rose!"); else if (species == SPECIES_GLASTRIER) - MESSAGE("Glastrier's Chilling Neigh raised its Attack!"); + MESSAGE("Glastrier's Attack rose!"); else - MESSAGE("Calyrex's Chilling Neigh raised its Attack!"); + MESSAGE("Calyrex's Attack rose!"); } THEN { EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); EXPECT_EQ(damage[0], damage[1]); diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 783c951d1c..4eb3071b76 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -899,3 +899,15 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers Focus Sash when det TURN { MOVE(player, MOVE_AIR_SLASH); EXPECT_MOVE(opponent, MOVE_FLAMETHROWER); } } } + +AI_SINGLE_BATTLE_TEST("AI won't boost stats against opponent with Unaware") +{ + GIVEN { + MoveHasAdditionalEffectSelf(MOVE_SWORDS_DANCE, MOVE_EFFECT_ATK_PLUS_2); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY); + PLAYER(SPECIES_QUAGSIRE) { Ability(ABILITY_UNAWARE); Moves(MOVE_TACKLE); } + OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_BODY_SLAM, MOVE_SWORDS_DANCE); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); EXPECT_MOVE(opponent, MOVE_BODY_SLAM); } + } +} diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index ea8957e474..b58f3122b0 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -401,6 +401,7 @@ SINGLE_BATTLE_TEST("Dynamax: Dynamaxed Pokemon that changes forms does not gain { u16 capturedHP, finalHP; GIVEN { + WITH_CONFIG(GEN_CONFIG_BATTLE_BOND, GEN_8); PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); HP(100); Speed(100); } OPPONENT(SPECIES_CATERPIE) { HP(1); Speed(1000); } OPPONENT(SPECIES_WOBBUFFET) { Speed(10); } @@ -1556,7 +1557,7 @@ SINGLE_BATTLE_TEST("Dynamax: Moxie clones can be triggered by Max Moves fainting } SCENE { MESSAGE("The opposing Wobbuffet fainted!"); ABILITY_POPUP(player, ABILITY_MOXIE); - MESSAGE("Gyarados's Moxie raised its Attack!"); + MESSAGE("Gyarados's Attack rose!"); } } diff --git a/test/battle/move_effect/ohko.c b/test/battle/move_effect/ohko.c index 11dbb78f1f..6ca65a3ab3 100644 --- a/test/battle/move_effect/ohko.c +++ b/test/battle/move_effect/ohko.c @@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon") SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has No-Guard") { GIVEN { - ASSUME(GetMoveEffect(MOVE_SHEER_COLD) == EFFECT_OHKO); + ASSUME(ItemId_GetHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH); PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -36,6 +36,34 @@ SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has } } +SINGLE_BATTLE_TEST("OHKO moves can can be endured by Focus Sash") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(player, MOVE_SHEER_COLD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player); + HP_BAR(opponent, hp: 1); + MESSAGE("The opposing Wobbuffet hung on using its Focus Sash!"); + } +} + +SINGLE_BATTLE_TEST("OHKO moves can can be endured by Sturdy") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GEODUDE) { Ability(ABILITY_STURDY); } + } WHEN { + TURN { MOVE(player, MOVE_SHEER_COLD); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player); + ABILITY_POPUP(opponent, ABILITY_STURDY); + MESSAGE("The opposing Geodude was protected by Sturdy!"); + } +} + TO_DO_BATTLE_TEST("Fissure faints the target, skipping regular damage calculations") TO_DO_BATTLE_TEST("Fissure always fails if the target has a higher level than the user") TO_DO_BATTLE_TEST("Fissure's accuracy increases by 1% for every level the user has over the target") diff --git a/test/text.c b/test/text.c index 7650c2dd59..e29ec68b76 100644 --- a/test/text.c +++ b/test/text.c @@ -67,7 +67,7 @@ TEST("Move names fit on Contest Screen") TEST("Move names fit on TMs & HMs Bag Screen") { u32 i; - const u32 fontId = FONT_NARROWER, widthPx = 61; + const u32 fontId = FONT_NARROWER, widthPx = 61; u32 move = MOVE_NONE; for (i = 1; i < MOVES_COUNT; i++) { @@ -713,7 +713,6 @@ TEST("Battle strings fit on the battle message window") case STRINGID_TARGETABILITYSTATRAISE: case STRINGID_TARGETSSTATWASMAXEDOUT: case STRINGID_ATTACKERABILITYSTATRAISE: - case STRINGID_LASTABILITYRAISEDSTAT: case STRINGID_TARGETABILITYSTATLOWER: case STRINGID_SCRIPTINGABILITYSTATRAISE: case STRINGID_BATTLERABILITYRAISEDSTAT: