conflicts

This commit is contained in:
AlexOn1ine 2025-04-06 14:59:12 +02:00
commit e8cc3c81f8
28 changed files with 965 additions and 865 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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[];

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -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
};

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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}!"),

View File

@ -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)

View File

@ -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;
}

View File

@ -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,
},

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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]);

View File

@ -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]);

View File

@ -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); }
}
}

View File

@ -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!");
}
}

View File

@ -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")

View File

@ -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: