Secondary/primary effects overhaul (#3577)

This commit is contained in:
Eduardo Quezada D'Ottone 2024-01-11 19:37:29 -03:00 committed by GitHub
commit 22b9337e97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 3450 additions and 3601 deletions

View File

@ -92,19 +92,30 @@
.4byte \ptr
.endm
.macro seteffectwithchance
.macro setadditionaleffects
1:
.byte 0x15
jumpifhalfword CMP_EQUAL, sMOVE_EFFECT, MOVE_EFFECT_CONTINUE, 1b
.endm
.macro seteffectprimary
.macro seteffectprimary moveEffect=0
.if \moveEffect != 0
setmoveeffect \moveEffect
.endif
.byte 0x16
.endm
.macro seteffectsecondary
.macro seteffectsecondary moveEffect=0
.if \moveEffect != 0
setmoveeffect \moveEffect
.endif
.byte 0x17
.endm
.macro clearstatusfromeffect battler:req
.macro clearstatusfromeffect battler:req, moveEffect=0
.if \moveEffect != 0
setmoveeffect \moveEffect
.endif
.byte 0x18
.byte \battler
.endm
@ -764,7 +775,7 @@
.byte 0x8b
.endm
.macro confuseifrepeatingattackends
.macro unused0x8C
.byte 0x8c
.endm
@ -1175,8 +1186,10 @@
.4byte \jumpInstr
.endm
.macro getsecretpowereffect
.macro jumpifnotcurrentmoveargtype battler:req, failInstr:req
.byte 0xe4
.byte \battler
.4byte \failInstr
.endm
.macro pickup
@ -1810,8 +1823,8 @@
.4byte \jumpInstr
.endm
.macro argumentstatuseffect
various BS_ATTACKER, VARIOUS_ARGUMENT_STATUS_EFFECT
.macro setargtobattledamage
various BS_ATTACKER, VARIOUS_SET_ARG_TO_BATTLE_DAMAGE
.endm
.macro tryhitswitchtarget failInstr:req
@ -1855,10 +1868,6 @@
various \battler, VARIOUS_POWER_TRICK
.endm
.macro argumenttomoveeffect
various BS_ATTACKER, VARIOUS_ARGUMENT_TO_MOVE_EFFECT
.endm
.macro jumpifnotgrounded battler:req, jumpInstr:req
various \battler, VARIOUS_JUMP_IF_NOT_GROUNDED
.4byte \jumpInstr

File diff suppressed because it is too large Load Diff

View File

@ -600,6 +600,7 @@ struct BattleStruct
u32 expValue;
u8 expGettersOrder[PARTY_SIZE]; // First battlers which were sent out, then via exp-share
u8 expGetterMonId;
u8 additionalEffectsCounter:2;
u8 expOrderId:3;
u8 expGetterBattlerId:2;
u8 teamGotExpMsgPrinted:1; // The 'Rest of your team got msg' has been printed.
@ -780,9 +781,7 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER
#define IS_MOVE_SPECIAL(move)(GetBattleMoveCategory(move) == BATTLE_CATEGORY_SPECIAL)
#define IS_MOVE_STATUS(move)(gBattleMoves[move].category == BATTLE_CATEGORY_STATUS)
#define IS_EFFECT_RECOIL(effect)(effect == EFFECT_RECOIL || effect == EFFECT_RECOIL_IF_MISS)
#define IS_MOVE_RECOIL(move)(IS_EFFECT_RECOIL(gBattleMoves[move].effect))
#define IS_MOVE_RECOIL(move)(gBattleMoves[move].recoil > 0 || gBattleMoves[move].effect == EFFECT_RECOIL_IF_MISS)
#define BATTLER_MAX_HP(battlerId)(gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP)
#define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0) || (gBattleStruct->enduredDamage & gBitTable[gBattlerTarget]))

View File

@ -63,7 +63,6 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability);
bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u32 move);
u32 AI_GetBattlerMoveTargetType(u32 battlerId, u32 move);
bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove);
u32 AI_CalcSecondaryEffectChance(u32 battler, u32 secondaryEffectChance);
// stat stage checks
bool32 AnyStatIsRaised(u32 battlerId);
@ -101,6 +100,9 @@ bool32 HasOnlyMovesWithCategory(u32 battlerId, u32 category, bool32 onlyOffensiv
bool32 HasMoveWithCategory(u32 battler, u32 category);
bool32 HasMoveWithType(u32 battler, u32 type);
bool32 HasMoveEffect(u32 battlerId, u32 moveEffect);
bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument);
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect);
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception);
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
bool32 IsAromaVeilProtectedMove(u32 move);
bool32 IsNonVolatileStatusMoveEffect(u32 moveEffect);
@ -119,7 +121,7 @@ bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect);
bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef);
bool32 IsHealingMove(u32 move);
bool32 HasHealingEffect(u32 battler);
bool32 IsTrappingMoveEffect(u32 effect);
bool32 IsTrappingMove(u32 move);
bool32 HasTrappingMoveEffect(u32 battler);
bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 HasThawingMove(u32 battler);
@ -188,5 +190,9 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score
void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, bool8 isPartyMonAttacker);
s32 AI_CheckMoveEffects(u32 battlerAtk, u32 battlerDef, u32 move, s32 score, struct AiLogicData *aiData, u32 predictedMove, bool32 isDoubleBattle);
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData);
#endif //GUARD_BATTLE_AI_UTIL_H

View File

@ -29,7 +29,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
u8 GetBattlerTurnOrderNum(u8 battlerId);
bool32 NoAliveMonsForPlayer(void);
bool32 NoAliveMonsForEitherParty(void);
void SetMoveEffect(bool32 primary, u32 certain);
void SetMoveEffect(bool32 primary, bool32 certain);
bool32 CanBattlerSwitch(u32 battlerId);
void BattleDestroyYesNoCursorAt(u8 cursorPosition);
void BattleCreateYesNoCursorAt(u8 cursorPosition);
@ -48,7 +48,6 @@ u32 IsAbilityStatusProtected(u32 battler);
bool32 TryResetBattlerStatChanges(u8 battler);
bool32 CanCamouflage(u8 battlerId);
u16 GetNaturePowerMove(void);
u16 GetSecretPowerMoveEffect(void);
void StealTargetItem(u8 battlerStealer, u8 battlerItem);
u8 GetCatchingBattler(void);
u32 GetHighestStatId(u32 battlerId);

View File

@ -303,8 +303,6 @@ extern const u8 BattleScript_StickyWebDefog[];
extern const u8 BattleScript_StealthRockDefog[];
extern const u8 BattleScript_MegaEvolution[];
extern const u8 BattleScript_WishMegaEvolution[];
extern const u8 BattleScript_MoveEffectRecoilWithStatus[];
extern const u8 BattleScript_EffectWithChance[];
extern const u8 BattleScript_MoveEffectClearSmog[];
extern const u8 BattleScript_SideStatusWoreOffReturn[];
extern const u8 BattleScript_MoveEffectSmackDown[];
@ -444,9 +442,9 @@ extern const u8 BattleScript_AffectionBasedStatusHeal[];
extern const u8 BattleScript_AffectionBasedEndurance[];
extern const u8 BattleScript_SymbiosisActivates[];
extern const u8 BattleScript_MultiHitPrintStrings[];
extern const u8 BattleScript_BurnUpRemoveType[];
extern const u8 BattleScript_RemoveFireType[];
extern const u8 BattleScript_TargetAbilityStatRaiseRet[];
extern const u8 BattleScript_DoubleShockRemoveType[];
extern const u8 BattleScript_RemoveElectricType[];
extern const u8 BattleScript_SeedSowerActivates[];
extern const u8 BattleScript_AngerShellActivates[];
extern const u8 BattleScript_WellBakedBodyActivates[];
@ -525,6 +523,7 @@ extern const u8 BattleScript_EffectRaiseCritAlliesAnim[];
extern const u8 BattleScript_EffectHealOneSixthAllies[];
extern const u8 BattleScript_EffectCureStatusAllies[];
extern const u8 BattleScript_EffectRecycleBerriesAllies[];
extern const u8 BattleScript_RemoveGenericType[];
// dynamax and max raids
extern const u8 BattleScript_DynamaxBegins[];

View File

@ -221,6 +221,10 @@ void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon);
void RecalcBattlerStats(u32 battler, struct Pokemon *mon);
bool32 IsAlly(u32 battlerAtk, u32 battlerDef);
bool32 IsGen6ExpShareEnabled(void);
bool32 MoveHasMoveEffect(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectWithChance(u32 move, u32 moveEffect, u32 chance);
bool32 MoveHasMoveEffectSelf(u32 move, u32 moveEffect);
bool32 MoveHasMoveEffectSelfArg(u32 move, u32 moveEffect, u32 argument);
bool32 CanSleep(u32 battler);
bool32 CanBePoisoned(u32 battlerAttacker, u32 battlerTarget);
@ -238,9 +242,11 @@ void RemoveConfusionStatus(u32 battler);
u8 GetBattlerGender(u32 battler);
bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2);
bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2);
u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance, u16 moveEffect);
u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect);
bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect);
u8 GetBattlerType(u32 battler, u8 typeIndex);
bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon);
bool8 IsMonBannedFromSkyBattles(u16 species);
void RemoveBattlerType(u32 battler, u8 type);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -197,7 +197,7 @@
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
#define B_FOG_TERRAIN TRUE // If TRUE, overworld Fog generates Misty Terrain as in Gen 8.
#define B_TERRAIN_TYPE_BOOST GEN_LATEST // In Gen8, damage is boosted by 30% instead of 50%.
#define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See GetSecretPowerMoveEffect.
#define B_SECRET_POWER_EFFECT GEN_LATEST // Secret Power's effects change depending on terrain and generation. See MOVE_EFFECT_SECRET_POWER's case in `SetMoveEffect`.
#define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation.
#define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves.
#define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType.

View File

@ -324,6 +324,7 @@
#define MOVE_EFFECT_TOXIC 6
#define MOVE_EFFECT_FROSTBITE 7
#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_FROSTBITE // All above move effects apply primary status
#define MOVE_EFFECT_FREEZE_OR_FROSTBITE (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE)
#define MOVE_EFFECT_CONFUSION 8
#define MOVE_EFFECT_FLINCH 9
#define MOVE_EFFECT_TRI_ATTACK 10
@ -345,7 +346,7 @@
#define MOVE_EFFECT_SP_DEF_MINUS_1 26
#define MOVE_EFFECT_ACC_MINUS_1 27
#define MOVE_EFFECT_EVS_MINUS_1 28
#define MOVE_EFFECT_BURN_UP 29
#define MOVE_EFFECT_REMOVE_ARG_TYPE 29
#define MOVE_EFFECT_RECHARGE 30
#define MOVE_EFFECT_RAGE 31
#define MOVE_EFFECT_STEAL_ITEM 32
@ -387,20 +388,20 @@
#define MOVE_EFFECT_BUG_BITE 68
#define MOVE_EFFECT_RECOIL_HP_25 69
#define MOVE_EFFECT_TRAP_BOTH 70
#define MOVE_EFFECT_DOUBLE_SHOCK 71
#define MOVE_EFFECT_ROUND 72
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 73
#define MOVE_EFFECT_DIRE_CLAW 74
#define MOVE_EFFECT_STEALTH_ROCK 75
#define MOVE_EFFECT_SPIKES 76
#define MOVE_EFFECT_TRIPLE_ARROWS 77
#define MOVE_EFFECT_SYRUP_BOMB 78
#define MOVE_EFFECT_FLORAL_HEALING 79
#define MOVE_EFFECT_ROUND 71
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 72
#define MOVE_EFFECT_DIRE_CLAW 73
#define MOVE_EFFECT_STEALTH_ROCK 74
#define MOVE_EFFECT_SPIKES 75
#define MOVE_EFFECT_SYRUP_BOMB 76
#define MOVE_EFFECT_FLORAL_HEALING 77
#define MOVE_EFFECT_SECRET_POWER 78
#define NUM_MOVE_EFFECTS 80
#define NUM_MOVE_EFFECTS 79
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000
#define MOVE_EFFECT_AFFECTS_USER 0x2000
#define MOVE_EFFECT_CERTAIN 0x4000
#define MOVE_EFFECT_CONTINUE 0x8000
// Battle terrain defines for gBattleTerrain.
#define BATTLE_TERRAIN_GRASS 0

View File

@ -3,424 +3,352 @@
#define EFFECT_HIT 0
#define EFFECT_SLEEP 1
#define EFFECT_POISON_HIT 2
#define EFFECT_ABSORB 3
#define EFFECT_BURN_HIT 4
#define EFFECT_FREEZE_HIT 5
#define EFFECT_PARALYZE_HIT 6
#define EFFECT_EXPLOSION 7
#define EFFECT_DREAM_EATER 8
#define EFFECT_MIRROR_MOVE 9
#define EFFECT_ATTACK_UP 10
#define EFFECT_DEFENSE_UP 11
#define EFFECT_SPEED_UP 12
#define EFFECT_SPECIAL_ATTACK_UP 13
#define EFFECT_SPECIAL_DEFENSE_UP 14
#define EFFECT_ACCURACY_UP 15
#define EFFECT_EVASION_UP 16
#define EFFECT_SPECIAL_ATTACK_UP_3 17
#define EFFECT_ATTACK_DOWN 18
#define EFFECT_DEFENSE_DOWN 19
#define EFFECT_SPEED_DOWN 20
#define EFFECT_SPECIAL_ATTACK_DOWN 21
#define EFFECT_SPECIAL_DEFENSE_DOWN 22
#define EFFECT_ACCURACY_DOWN 23
#define EFFECT_EVASION_DOWN 24
#define EFFECT_HAZE 25
#define EFFECT_BIDE 26
#define EFFECT_RAMPAGE 27
#define EFFECT_ROAR 28
#define EFFECT_MULTI_HIT 29
#define EFFECT_CONVERSION 30
#define EFFECT_FLINCH_HIT 31
#define EFFECT_RESTORE_HP 32
#define EFFECT_TOXIC 33
#define EFFECT_PAY_DAY 34
#define EFFECT_LIGHT_SCREEN 35
#define EFFECT_TRI_ATTACK 36
#define EFFECT_REST 37
#define EFFECT_OHKO 38
#define EFFECT_FUSION_COMBO 39
#define EFFECT_SUPER_FANG 40
#define EFFECT_DRAGON_RAGE 41
#define EFFECT_TRAP 42
#define EFFECT_HEAL_BLOCK 43
#define EFFECT_RECOIL_IF_MISS 44
#define EFFECT_MIST 45
#define EFFECT_FOCUS_ENERGY 46
#define EFFECT_RECOIL 47
#define EFFECT_CONFUSE 48
#define EFFECT_ATTACK_UP_2 49
#define EFFECT_DEFENSE_UP_2 50
#define EFFECT_SPEED_UP_2 51
#define EFFECT_SPECIAL_ATTACK_UP_2 52
#define EFFECT_SPECIAL_DEFENSE_UP_2 53
#define EFFECT_ACCURACY_UP_2 54
#define EFFECT_EVASION_UP_2 55
#define EFFECT_TRANSFORM 56
#define EFFECT_ATTACK_DOWN_2 57
#define EFFECT_DEFENSE_DOWN_2 58
#define EFFECT_SPEED_DOWN_2 59
#define EFFECT_SPECIAL_ATTACK_DOWN_2 60
#define EFFECT_SPECIAL_DEFENSE_DOWN_2 61
#define EFFECT_ACCURACY_DOWN_2 62
#define EFFECT_EVASION_DOWN_2 63
#define EFFECT_REFLECT 64
#define EFFECT_POISON 65
#define EFFECT_PARALYZE 66
#define EFFECT_ATTACK_DOWN_HIT 67
#define EFFECT_DEFENSE_DOWN_HIT 68
#define EFFECT_SPEED_DOWN_HIT 69
#define EFFECT_SPECIAL_ATTACK_DOWN_HIT 70
#define EFFECT_SPECIAL_DEFENSE_DOWN_HIT 71
#define EFFECT_ACCURACY_DOWN_HIT 72
#define EFFECT_EVASION_DOWN_HIT 73
#define EFFECT_TWO_TURNS_ATTACK 74
#define EFFECT_CONFUSE_HIT 75
#define EFFECT_VITAL_THROW 76
#define EFFECT_SUBSTITUTE 77
#define EFFECT_RECHARGE 78
#define EFFECT_RAGE 79
#define EFFECT_MIMIC 80
#define EFFECT_METRONOME 81
#define EFFECT_LEECH_SEED 82
#define EFFECT_DO_NOTHING 83
#define EFFECT_DISABLE 84
#define EFFECT_LEVEL_DAMAGE 85
#define EFFECT_PSYWAVE 86
#define EFFECT_COUNTER 87
#define EFFECT_ENCORE 88
#define EFFECT_PAIN_SPLIT 89
#define EFFECT_SNORE 90
#define EFFECT_CONVERSION_2 91
#define EFFECT_LOCK_ON 92
#define EFFECT_SKETCH 93
#define EFFECT_HAMMER_ARM 94
#define EFFECT_SLEEP_TALK 95
#define EFFECT_DESTINY_BOND 96
#define EFFECT_FLAIL 97
#define EFFECT_SPITE 98
#define EFFECT_FALSE_SWIPE 99
#define EFFECT_HEAL_BELL 100
#define EFFECT_TRIPLE_KICK 101
#define EFFECT_THIEF 102
#define EFFECT_MEAN_LOOK 103
#define EFFECT_NIGHTMARE 104
#define EFFECT_MINIMIZE 105
#define EFFECT_CURSE 106
#define EFFECT_HEALING_WISH 107
#define EFFECT_PROTECT 108
#define EFFECT_SPIKES 109
#define EFFECT_FORESIGHT 110
#define EFFECT_PERISH_SONG 111
#define EFFECT_SANDSTORM 112
#define EFFECT_ENDURE 113
#define EFFECT_ROLLOUT 114
#define EFFECT_SWAGGER 115
#define EFFECT_FURY_CUTTER 116
#define EFFECT_ATTRACT 117
#define EFFECT_RETURN 118
#define EFFECT_PRESENT 119
#define EFFECT_FRUSTRATION 120
#define EFFECT_SAFEGUARD 121
#define EFFECT_MAGNITUDE 122
#define EFFECT_BATON_PASS 123
#define EFFECT_PURSUIT 124
#define EFFECT_RAPID_SPIN 125
#define EFFECT_SONICBOOM 126
#define EFFECT_CAPTIVATE 127
#define EFFECT_MORNING_SUN 128
#define EFFECT_SYNTHESIS 129
#define EFFECT_MOONLIGHT 130
#define EFFECT_HIDDEN_POWER 131
#define EFFECT_RAIN_DANCE 132
#define EFFECT_SUNNY_DAY 133
#define EFFECT_DEFENSE_UP_HIT 134
#define EFFECT_ATTACK_UP_HIT 135
#define EFFECT_ALL_STATS_UP_HIT 136
#define EFFECT_FELL_STINGER 137
#define EFFECT_BELLY_DRUM 138
#define EFFECT_PSYCH_UP 139
#define EFFECT_MIRROR_COAT 140
#define EFFECT_SKULL_BASH 141
#define EFFECT_EARTHQUAKE 142
#define EFFECT_FUTURE_SIGHT 143
#define EFFECT_GUST 144
#define EFFECT_SOLAR_BEAM 145
#define EFFECT_THUNDER 146
#define EFFECT_TELEPORT 147
#define EFFECT_BEAT_UP 148
#define EFFECT_SEMI_INVULNERABLE 149
#define EFFECT_DEFENSE_CURL 150
#define EFFECT_SOFTBOILED 151
#define EFFECT_FAKE_OUT 152
#define EFFECT_UPROAR 153
#define EFFECT_STOCKPILE 154
#define EFFECT_SPIT_UP 155
#define EFFECT_SWALLOW 156
#define EFFECT_WORRY_SEED 157
#define EFFECT_HAIL 158
#define EFFECT_TORMENT 159
#define EFFECT_FLATTER 160
#define EFFECT_WILL_O_WISP 161
#define EFFECT_MEMENTO 162
#define EFFECT_FACADE 163
#define EFFECT_FOCUS_PUNCH 164
#define EFFECT_SMELLING_SALTS 165
#define EFFECT_FOLLOW_ME 166
#define EFFECT_NATURE_POWER 167
#define EFFECT_CHARGE 168
#define EFFECT_TAUNT 169
#define EFFECT_HELPING_HAND 170
#define EFFECT_TRICK 171
#define EFFECT_ROLE_PLAY 172
#define EFFECT_WISH 173
#define EFFECT_ASSIST 174
#define EFFECT_INGRAIN 175
#define EFFECT_SUPERPOWER 176
#define EFFECT_MAGIC_COAT 177
#define EFFECT_RECYCLE 178
#define EFFECT_REVENGE 179
#define EFFECT_BRICK_BREAK 180
#define EFFECT_YAWN 181
#define EFFECT_KNOCK_OFF 182
#define EFFECT_ENDEAVOR 183
#define EFFECT_ERUPTION 184
#define EFFECT_SKILL_SWAP 185
#define EFFECT_IMPRISON 186
#define EFFECT_REFRESH 187
#define EFFECT_GRUDGE 188
#define EFFECT_SNATCH 189
#define EFFECT_LOW_KICK 190
#define EFFECT_SECRET_POWER 191
#define EFFECT_TEETER_DANCE 192
#define EFFECT_HIT_ESCAPE 193
#define EFFECT_MUD_SPORT 194
#define EFFECT_POISON_FANG 195
#define EFFECT_WEATHER_BALL 196
#define EFFECT_OVERHEAT 197
#define EFFECT_TICKLE 198
#define EFFECT_COSMIC_POWER 199
#define EFFECT_SKY_UPPERCUT 200
#define EFFECT_BULK_UP 201
#define EFFECT_PLACEHOLDER 202
#define EFFECT_WATER_SPORT 203
#define EFFECT_CALM_MIND 204
#define EFFECT_DRAGON_DANCE 205
#define EFFECT_CAMOUFLAGE 206
#define EFFECT_ABSORB 2
#define EFFECT_EXPLOSION 3
#define EFFECT_DREAM_EATER 4
#define EFFECT_MIRROR_MOVE 5
#define EFFECT_ATTACK_UP 6
#define EFFECT_DEFENSE_UP 7
#define EFFECT_SPEED_UP 8
#define EFFECT_SPECIAL_ATTACK_UP 9
#define EFFECT_SPECIAL_DEFENSE_UP 10
#define EFFECT_ACCURACY_UP 11
#define EFFECT_EVASION_UP 12
#define EFFECT_SPECIAL_ATTACK_UP_3 13
#define EFFECT_ATTACK_DOWN 14
#define EFFECT_DEFENSE_DOWN 15
#define EFFECT_SPEED_DOWN 16
#define EFFECT_SPECIAL_ATTACK_DOWN 17
#define EFFECT_SPECIAL_DEFENSE_DOWN 18
#define EFFECT_ACCURACY_DOWN 19
#define EFFECT_EVASION_DOWN 20
#define EFFECT_HAZE 21
#define EFFECT_BIDE 22
#define EFFECT_ROAR 23
#define EFFECT_MULTI_HIT 24
#define EFFECT_CONVERSION 25
#define EFFECT_RESTORE_HP 26
#define EFFECT_TOXIC 27
#define EFFECT_LIGHT_SCREEN 28
#define EFFECT_REST 29
#define EFFECT_OHKO 30
#define EFFECT_FUSION_COMBO 31
#define EFFECT_SUPER_FANG 32
#define EFFECT_FIXED_DAMAGE_ARG 33
#define EFFECT_HEAL_BLOCK 34
#define EFFECT_RECOIL_IF_MISS 35
#define EFFECT_MIST 36
#define EFFECT_FOCUS_ENERGY 37
#define EFFECT_CONFUSE 38
#define EFFECT_ATTACK_UP_2 39
#define EFFECT_DEFENSE_UP_2 40
#define EFFECT_SPEED_UP_2 41
#define EFFECT_SPECIAL_ATTACK_UP_2 42
#define EFFECT_SPECIAL_DEFENSE_UP_2 43
#define EFFECT_ACCURACY_UP_2 44
#define EFFECT_EVASION_UP_2 45
#define EFFECT_TRANSFORM 46
#define EFFECT_ATTACK_DOWN_2 47
#define EFFECT_DEFENSE_DOWN_2 48
#define EFFECT_SPEED_DOWN_2 49
#define EFFECT_SPECIAL_ATTACK_DOWN_2 50
#define EFFECT_SPECIAL_DEFENSE_DOWN_2 51
#define EFFECT_ACCURACY_DOWN_2 52
#define EFFECT_EVASION_DOWN_2 53
#define EFFECT_REFLECT 54
#define EFFECT_POISON 55
#define EFFECT_PARALYZE 56
#define EFFECT_TWO_TURNS_ATTACK 57
#define EFFECT_SUBSTITUTE 58
#define EFFECT_RAGE 59
#define EFFECT_MIMIC 60
#define EFFECT_METRONOME 61
#define EFFECT_LEECH_SEED 62
#define EFFECT_DO_NOTHING 63
#define EFFECT_DISABLE 64
#define EFFECT_LEVEL_DAMAGE 65
#define EFFECT_PSYWAVE 66
#define EFFECT_COUNTER 67
#define EFFECT_ENCORE 68
#define EFFECT_PAIN_SPLIT 69
#define EFFECT_SNORE 70
#define EFFECT_CONVERSION_2 71
#define EFFECT_LOCK_ON 72
#define EFFECT_SKETCH 73
#define EFFECT_SLEEP_TALK 74
#define EFFECT_DESTINY_BOND 75
#define EFFECT_FLAIL 76
#define EFFECT_SPITE 77
#define EFFECT_FALSE_SWIPE 78
#define EFFECT_HEAL_BELL 79
#define EFFECT_TRIPLE_KICK 80
#define EFFECT_MEAN_LOOK 81
#define EFFECT_NIGHTMARE 82
#define EFFECT_MINIMIZE 83
#define EFFECT_CURSE 84
#define EFFECT_HEALING_WISH 85
#define EFFECT_PROTECT 86
#define EFFECT_SPIKES 87
#define EFFECT_FORESIGHT 88
#define EFFECT_PERISH_SONG 89
#define EFFECT_SANDSTORM 90
#define EFFECT_ENDURE 91
#define EFFECT_ROLLOUT 92
#define EFFECT_SWAGGER 93
#define EFFECT_FURY_CUTTER 94
#define EFFECT_ATTRACT 95
#define EFFECT_RETURN 96
#define EFFECT_PRESENT 97
#define EFFECT_FRUSTRATION 98
#define EFFECT_SAFEGUARD 99
#define EFFECT_MAGNITUDE 100
#define EFFECT_BATON_PASS 101
#define EFFECT_PURSUIT 102
#define EFFECT_CAPTIVATE 103
#define EFFECT_MORNING_SUN 104
#define EFFECT_SYNTHESIS 105
#define EFFECT_MOONLIGHT 106
#define EFFECT_HIDDEN_POWER 107
#define EFFECT_RAIN_DANCE 108
#define EFFECT_SUNNY_DAY 109
#define EFFECT_FELL_STINGER 110
#define EFFECT_BELLY_DRUM 111
#define EFFECT_PSYCH_UP 112
#define EFFECT_MIRROR_COAT 113
#define EFFECT_SKULL_BASH 114
#define EFFECT_EARTHQUAKE 115
#define EFFECT_FUTURE_SIGHT 116
#define EFFECT_GUST 117
#define EFFECT_SOLAR_BEAM 118
#define EFFECT_THUNDER 119
#define EFFECT_TELEPORT 120
#define EFFECT_BEAT_UP 121
#define EFFECT_SEMI_INVULNERABLE 122
#define EFFECT_DEFENSE_CURL 123
#define EFFECT_SOFTBOILED 124
#define EFFECT_FAKE_OUT 125
#define EFFECT_UPROAR 126
#define EFFECT_STOCKPILE 127
#define EFFECT_SPIT_UP 128
#define EFFECT_SWALLOW 129
#define EFFECT_WORRY_SEED 130
#define EFFECT_HAIL 131
#define EFFECT_TORMENT 132
#define EFFECT_FLATTER 133
#define EFFECT_WILL_O_WISP 134
#define EFFECT_MEMENTO 135
#define EFFECT_FACADE 136
#define EFFECT_FOCUS_PUNCH 137
#define EFFECT_DOUBLE_POWER_ON_ARG_STATUS 138
#define EFFECT_FOLLOW_ME 139
#define EFFECT_NATURE_POWER 140
#define EFFECT_CHARGE 141
#define EFFECT_TAUNT 142
#define EFFECT_HELPING_HAND 143
#define EFFECT_TRICK 144
#define EFFECT_ROLE_PLAY 145
#define EFFECT_WISH 146
#define EFFECT_ASSIST 147
#define EFFECT_INGRAIN 148
#define EFFECT_MAGIC_COAT 149
#define EFFECT_RECYCLE 150
#define EFFECT_REVENGE 151
#define EFFECT_BRICK_BREAK 152
#define EFFECT_YAWN 153
#define EFFECT_KNOCK_OFF 154
#define EFFECT_ENDEAVOR 155
#define EFFECT_ERUPTION 156
#define EFFECT_SKILL_SWAP 157
#define EFFECT_IMPRISON 158
#define EFFECT_REFRESH 159
#define EFFECT_GRUDGE 160
#define EFFECT_SNATCH 161
#define EFFECT_LOW_KICK 162
#define EFFECT_TEETER_DANCE 163
#define EFFECT_HIT_ESCAPE 164
#define EFFECT_MUD_SPORT 165
#define EFFECT_WEATHER_BALL 166
#define EFFECT_TICKLE 167
#define EFFECT_COSMIC_POWER 168
#define EFFECT_SKY_UPPERCUT 169
#define EFFECT_BULK_UP 170
#define EFFECT_PLACEHOLDER 171
#define EFFECT_WATER_SPORT 172
#define EFFECT_CALM_MIND 173
#define EFFECT_DRAGON_DANCE 174
#define EFFECT_CAMOUFLAGE 175
#define EFFECT_PLEDGE 176
#define EFFECT_FLING 177
#define EFFECT_NATURAL_GIFT 178
#define EFFECT_WRING_OUT 179
#define EFFECT_ASSURANCE 180
#define EFFECT_TRUMP_CARD 181
#define EFFECT_ACROBATICS 182
#define EFFECT_HEAT_CRASH 183
#define EFFECT_PUNISHMENT 184
#define EFFECT_STORED_POWER 185
#define EFFECT_ELECTRO_BALL 186
#define EFFECT_GYRO_BALL 187
#define EFFECT_ECHOED_VOICE 188
#define EFFECT_PAYBACK 189
#define EFFECT_ROUND 190
#define EFFECT_BRINE 191
#define EFFECT_RETALIATE 192
#define EFFECT_BULLDOZE 193
#define EFFECT_FOUL_PLAY 194
#define EFFECT_PSYSHOCK 195
#define EFFECT_ROOST 196
#define EFFECT_GRAVITY 197
#define EFFECT_MIRACLE_EYE 198
#define EFFECT_TAILWIND 199
#define EFFECT_EMBARGO 200
#define EFFECT_AQUA_RING 201
#define EFFECT_TRICK_ROOM 202
#define EFFECT_WONDER_ROOM 203
#define EFFECT_MAGIC_ROOM 204
#define EFFECT_MAGNET_RISE 205
#define EFFECT_TOXIC_SPIKES 206
#define EFFECT_GASTRO_ACID 207
#define EFFECT_STEALTH_ROCK 208
#define EFFECT_TELEKINESIS 209
#define EFFECT_POWER_SWAP 210
#define EFFECT_GUARD_SWAP 211
#define EFFECT_HEART_SWAP 212
#define EFFECT_POWER_SPLIT 213
#define EFFECT_GUARD_SPLIT 214
#define EFFECT_STICKY_WEB 215
#define EFFECT_METAL_BURST 216
#define EFFECT_LUCKY_CHANT 217
#define EFFECT_SUCKER_PUNCH 218
#define EFFECT_SIMPLE_BEAM 219
#define EFFECT_ENTRAINMENT 220
#define EFFECT_HEAL_PULSE 221
#define EFFECT_QUASH 222
#define EFFECT_ION_DELUGE 223
#define EFFECT_FREEZE_DRY 224
#define EFFECT_TOPSY_TURVY 225
#define EFFECT_MISTY_TERRAIN 226
#define EFFECT_GRASSY_TERRAIN 227
#define EFFECT_ELECTRIC_TERRAIN 228
#define EFFECT_PSYCHIC_TERRAIN 229
#define EFFECT_ATTACK_ACCURACY_UP 230
#define EFFECT_ATTACK_SPATK_UP 231
#define EFFECT_HURRICANE 232
#define EFFECT_TWO_TYPED_MOVE 233
#define EFFECT_ME_FIRST 234
#define EFFECT_QUIVER_DANCE 235
#define EFFECT_COIL 236
#define EFFECT_ELECTRIFY 237
#define EFFECT_REFLECT_TYPE 238
#define EFFECT_SOAK 239
#define EFFECT_GROWTH 240
#define EFFECT_LAST_RESORT 241
#define EFFECT_SHELL_SMASH 242
#define EFFECT_SHIFT_GEAR 243
#define EFFECT_DEFENSE_UP_3 244
#define EFFECT_NOBLE_ROAR 245
#define EFFECT_VENOM_DRENCH 246
#define EFFECT_TOXIC_THREAD 247
#define EFFECT_HIT_SWITCH_TARGET 248
#define EFFECT_FINAL_GAMBIT 249
#define EFFECT_CHANGE_TYPE_ON_ITEM 250
#define EFFECT_AUTOTOMIZE 251
#define EFFECT_COPYCAT 252
#define EFFECT_DEFOG 253
#define EFFECT_HIT_ENEMY_HEAL_ALLY 254
#define EFFECT_SYNCHRONOISE 255
#define EFFECT_PSYCHO_SHIFT 256
#define EFFECT_POWER_TRICK 257
#define EFFECT_AFTER_YOU 258
#define EFFECT_BESTOW 259
#define EFFECT_ROTOTILLER 260
#define EFFECT_FLOWER_SHIELD 261
#define EFFECT_SPEED_SWAP 262
#define EFFECT_REVELATION_DANCE 263
#define EFFECT_AURORA_VEIL 264
#define EFFECT_THIRD_TYPE 265
#define EFFECT_ACUPRESSURE 266
#define EFFECT_AROMATIC_MIST 267
#define EFFECT_POWDER 268
#define EFFECT_BELCH 269
#define EFFECT_PARTING_SHOT 270
#define EFFECT_MAT_BLOCK 271
#define EFFECT_STOMPING_TANTRUM 272
#define EFFECT_INSTRUCT 273
#define EFFECT_LASER_FOCUS 274
#define EFFECT_MAGNETIC_FLUX 275
#define EFFECT_GEAR_UP 276
#define EFFECT_STRENGTH_SAP 277
#define EFFECT_MIND_BLOWN 278
#define EFFECT_PURIFY 279
#define EFFECT_FAIL_IF_NOT_ARG_TYPE 280
#define EFFECT_SHORE_UP 281
#define EFFECT_GEOMANCY 282
#define EFFECT_FAIRY_LOCK 283
#define EFFECT_ALLY_SWITCH 284
#define EFFECT_RELIC_SONG 285
#define EFFECT_BODY_PRESS 286
#define EFFECT_EERIE_SPELL 287
#define EFFECT_JUNGLE_HEALING 288
#define EFFECT_COACHING 289
#define EFFECT_LASH_OUT 290
#define EFFECT_GRASSY_GLIDE 291
#define EFFECT_DYNAMAX_DOUBLE_DMG 292
#define EFFECT_DECORATE 293
#define EFFECT_SNIPE_SHOT 294
#define EFFECT_RECOIL_HP_25 295
#define EFFECT_STUFF_CHEEKS 296
#define EFFECT_GRAV_APPLE 297
#define EFFECT_GLITZY_GLOW 298
#define EFFECT_BADDY_BAD 299
#define EFFECT_SAPPY_SEED 300
#define EFFECT_FREEZY_FROST 301
#define EFFECT_SPARKLY_SWIRL 302
#define EFFECT_PLASMA_FISTS 303
#define EFFECT_HYPERSPACE_FURY 304
#define EFFECT_AURA_WHEEL 305
#define EFFECT_PHOTON_GEYSER 306
#define EFFECT_SHELL_SIDE_ARM 307
#define EFFECT_TERRAIN_PULSE 308
#define EFFECT_NO_RETREAT 309
#define EFFECT_TAR_SHOT 310
#define EFFECT_POLTERGEIST 311
#define EFFECT_OCTOLOCK 312
#define EFFECT_CLANGOROUS_SOUL 313
#define EFFECT_BOLT_BEAK 314
#define EFFECT_SKY_DROP 315
#define EFFECT_EXPANDING_FORCE 316
#define EFFECT_METEOR_BEAM 317
#define EFFECT_RISING_VOLTAGE 318
#define EFFECT_BEAK_BLAST 319
#define EFFECT_COURT_CHANGE 320
#define EFFECT_STEEL_BEAM 321
#define EFFECT_EXTREME_EVOBOOST 322
#define EFFECT_HIT_SET_REMOVE_TERRAIN 323
#define EFFECT_DARK_VOID 324
#define EFFECT_VICTORY_DANCE 325
#define EFFECT_TEATIME 326
#define EFFECT_ATTACK_UP_USER_ALLY 327
#define EFFECT_SHELL_TRAP 328
#define EFFECT_PSYBLADE 329
#define EFFECT_HYDRO_STEAM 330
#define EFFECT_REVIVAL_BLESSING 331
#define EFFECT_SNOWSCAPE 332
#define EFFECT_TAKE_HEART 333
#define EFFECT_COLLISION_COURSE 334
#define EFFECT_CORROSIVE_GAS 335
#define EFFECT_POPULATION_BOMB 336
#define EFFECT_SALT_CURE 337
#define EFFECT_CHILLY_RECEPTION 338
#define EFFECT_MAX_MOVE 339
#define EFFECT_GLAIVE_RUSH 340
#define EFFECT_RAGING_BULL 341
#define EFFECT_RAGE_FIST 342
#define EFFECT_DOODLE 343
#define EFFECT_FILLET_AWAY 344
#define EFFECT_IVY_CUDGEL 345
#define EFFECT_FICKLE_BEAM 346
// New move effects
#define EFFECT_PLEDGE 207
#define EFFECT_FLING 208
#define EFFECT_NATURAL_GIFT 209
#define EFFECT_WAKE_UP_SLAP 210
#define EFFECT_WRING_OUT 211
#define EFFECT_HEX 212
#define EFFECT_ASSURANCE 213
#define EFFECT_TRUMP_CARD 214
#define EFFECT_ACROBATICS 215
#define EFFECT_HEAT_CRASH 216
#define EFFECT_PUNISHMENT 217
#define EFFECT_STORED_POWER 218
#define EFFECT_ELECTRO_BALL 219
#define EFFECT_GYRO_BALL 220
#define EFFECT_ECHOED_VOICE 221
#define EFFECT_PAYBACK 222
#define EFFECT_ROUND 223
#define EFFECT_BRINE 224
#define EFFECT_VENOSHOCK 225
#define EFFECT_RETALIATE 226
#define EFFECT_BULLDOZE 227
#define EFFECT_FOUL_PLAY 228
#define EFFECT_PSYSHOCK 229
#define EFFECT_ROOST 230
#define EFFECT_GRAVITY 231
#define EFFECT_MIRACLE_EYE 232
#define EFFECT_TAILWIND 233
#define EFFECT_EMBARGO 234
#define EFFECT_AQUA_RING 235
#define EFFECT_TRICK_ROOM 236
#define EFFECT_WONDER_ROOM 237
#define EFFECT_MAGIC_ROOM 238
#define EFFECT_MAGNET_RISE 239
#define EFFECT_TOXIC_SPIKES 240
#define EFFECT_GASTRO_ACID 241
#define EFFECT_STEALTH_ROCK 242
#define EFFECT_TELEKINESIS 243
#define EFFECT_POWER_SWAP 244
#define EFFECT_GUARD_SWAP 245
#define EFFECT_HEART_SWAP 246
#define EFFECT_POWER_SPLIT 247
#define EFFECT_GUARD_SPLIT 248
#define EFFECT_STICKY_WEB 249
#define EFFECT_METAL_BURST 250
#define EFFECT_LUCKY_CHANT 251
#define EFFECT_SUCKER_PUNCH 252
#define EFFECT_SPECIAL_DEFENSE_DOWN_HIT_2 253
#define EFFECT_SIMPLE_BEAM 254
#define EFFECT_ENTRAINMENT 255
#define EFFECT_HEAL_PULSE 256
#define EFFECT_QUASH 257
#define EFFECT_ION_DELUGE 258
#define EFFECT_FREEZE_DRY 259
#define EFFECT_TOPSY_TURVY 260
#define EFFECT_MISTY_TERRAIN 261
#define EFFECT_GRASSY_TERRAIN 262
#define EFFECT_ELECTRIC_TERRAIN 263
#define EFFECT_PSYCHIC_TERRAIN 264
#define EFFECT_ATTACK_ACCURACY_UP 265
#define EFFECT_ATTACK_SPATK_UP 266
#define EFFECT_HURRICANE 267
#define EFFECT_TWO_TYPED_MOVE 268
#define EFFECT_ME_FIRST 269
#define EFFECT_SPEED_UP_HIT 270
#define EFFECT_QUIVER_DANCE 271
#define EFFECT_COIL 272
#define EFFECT_ELECTRIFY 273
#define EFFECT_REFLECT_TYPE 274
#define EFFECT_SOAK 275
#define EFFECT_GROWTH 276
#define EFFECT_CLOSE_COMBAT 277
#define EFFECT_LAST_RESORT 278
#define EFFECT_FLINCH_STATUS 279
#define EFFECT_SHELL_SMASH 280
#define EFFECT_SHIFT_GEAR 281
#define EFFECT_DEFENSE_UP_3 282
#define EFFECT_NOBLE_ROAR 283
#define EFFECT_VENOM_DRENCH 284
#define EFFECT_TOXIC_THREAD 285
#define EFFECT_CLEAR_SMOG 286
#define EFFECT_HIT_SWITCH_TARGET 287
#define EFFECT_FINAL_GAMBIT 288
#define EFFECT_CHANGE_TYPE_ON_ITEM 289
#define EFFECT_AUTOTOMIZE 290
#define EFFECT_COPYCAT 291
#define EFFECT_DEFOG 292
#define EFFECT_HIT_ENEMY_HEAL_ALLY 293
#define EFFECT_SMACK_DOWN 294
#define EFFECT_SYNCHRONOISE 295
#define EFFECT_PSYCHO_SHIFT 296
#define EFFECT_POWER_TRICK 297
#define EFFECT_FLAME_BURST 298
#define EFFECT_AFTER_YOU 299
#define EFFECT_BESTOW 300
#define EFFECT_ROTOTILLER 301
#define EFFECT_FLOWER_SHIELD 302
#define EFFECT_HIT_PREVENT_ESCAPE 303
#define EFFECT_SPEED_SWAP 304
#define EFFECT_DEFENSE_UP2_HIT 305
#define EFFECT_REVELATION_DANCE 306
#define EFFECT_AURORA_VEIL 307
#define EFFECT_THIRD_TYPE 308
#define EFFECT_FEINT 309
#define EFFECT_SPARKLING_ARIA 310
#define EFFECT_ACUPRESSURE 311
#define EFFECT_AROMATIC_MIST 312
#define EFFECT_POWDER 313
#define EFFECT_SP_ATTACK_UP_HIT 314
#define EFFECT_BELCH 315
#define EFFECT_PARTING_SHOT 316
#define EFFECT_SPECTRAL_THIEF 317
#define EFFECT_V_CREATE 318
#define EFFECT_MAT_BLOCK 319
#define EFFECT_STOMPING_TANTRUM 320
#define EFFECT_CORE_ENFORCER 321
#define EFFECT_INSTRUCT 322
#define EFFECT_THROAT_CHOP 323
#define EFFECT_LASER_FOCUS 324
#define EFFECT_MAGNETIC_FLUX 325
#define EFFECT_GEAR_UP 326
#define EFFECT_INCINERATE 327
#define EFFECT_BUG_BITE 328
#define EFFECT_STRENGTH_SAP 329
#define EFFECT_MIND_BLOWN 330
#define EFFECT_PURIFY 331
#define EFFECT_BURN_UP 332
#define EFFECT_SHORE_UP 333
#define EFFECT_GEOMANCY 334
#define EFFECT_FAIRY_LOCK 335
#define EFFECT_ALLY_SWITCH 336
#define EFFECT_RELIC_SONG 337
#define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 338
#define EFFECT_BODY_PRESS 339
#define EFFECT_EERIE_SPELL 340
#define EFFECT_JUNGLE_HEALING 341
#define EFFECT_COACHING 342
#define EFFECT_LASH_OUT 343
#define EFFECT_GRASSY_GLIDE 344
#define EFFECT_DYNAMAX_DOUBLE_DMG 345
#define EFFECT_DECORATE 346
#define EFFECT_SNIPE_SHOT 347
#define EFFECT_RECOIL_HP_25 348
#define EFFECT_STUFF_CHEEKS 349
#define EFFECT_GRAV_APPLE 350
#define EFFECT_EVASION_UP_HIT 351
#define EFFECT_GLITZY_GLOW 352
#define EFFECT_BADDY_BAD 353
#define EFFECT_SAPPY_SEED 354
#define EFFECT_FREEZY_FROST 355
#define EFFECT_SPARKLY_SWIRL 356
#define EFFECT_PLASMA_FISTS 357
#define EFFECT_HYPERSPACE_FURY 358
#define EFFECT_AURA_WHEEL 359
#define EFFECT_PHOTON_GEYSER 360
#define EFFECT_SHELL_SIDE_ARM 361
#define EFFECT_TERRAIN_PULSE 362
#define EFFECT_JAW_LOCK 363
#define EFFECT_NO_RETREAT 364
#define EFFECT_TAR_SHOT 365
#define EFFECT_POLTERGEIST 366
#define EFFECT_OCTOLOCK 367
#define EFFECT_CLANGOROUS_SOUL 368
#define EFFECT_BOLT_BEAK 369
#define EFFECT_SKY_DROP 370
#define EFFECT_EXPANDING_FORCE 371
#define EFFECT_METEOR_BEAM 372
#define EFFECT_RISING_VOLTAGE 373
#define EFFECT_BEAK_BLAST 374
#define EFFECT_COURT_CHANGE 375
#define EFFECT_STEEL_BEAM 376
#define EFFECT_EXTREME_EVOBOOST 377
#define EFFECT_HIT_SET_REMOVE_TERRAIN 378
#define EFFECT_DARK_VOID 379
#define EFFECT_SLEEP_HIT 380
#define EFFECT_DOUBLE_SHOCK 381
#define EFFECT_SPECIAL_ATTACK_UP_HIT 382
#define EFFECT_VICTORY_DANCE 383
#define EFFECT_TEATIME 384
#define EFFECT_ATTACK_UP_USER_ALLY 385
#define EFFECT_SHELL_TRAP 386
#define EFFECT_PSYBLADE 387
#define EFFECT_HYDRO_STEAM 388
#define EFFECT_HIT_SET_ENTRY_HAZARD 389
#define EFFECT_DIRE_CLAW 390
#define EFFECT_BARB_BARRAGE 391
#define EFFECT_REVIVAL_BLESSING 392
#define EFFECT_FROSTBITE_HIT 393
#define EFFECT_SNOWSCAPE 394
#define EFFECT_TRIPLE_ARROWS 395
#define EFFECT_INFERNAL_PARADE 396
#define EFFECT_TAKE_HEART 397
#define EFFECT_AXE_KICK 398
#define EFFECT_COLLISION_COURSE 399
#define EFFECT_SPIN_OUT 400
#define EFFECT_MAKE_IT_RAIN 401
#define EFFECT_CORROSIVE_GAS 402
#define EFFECT_POPULATION_BOMB 403
#define EFFECT_MORTAL_SPIN 404
#define EFFECT_SALT_CURE 405
#define EFFECT_CHILLY_RECEPTION 406
#define EFFECT_MATCHA_GOTCHA 407
#define EFFECT_SYRUP_BOMB 408
#define EFFECT_MAX_MOVE 409
#define EFFECT_GLAIVE_RUSH 410
#define EFFECT_RAGING_BULL 411
#define EFFECT_RAGE_FIST 412
#define EFFECT_DOODLE 413
#define EFFECT_FILLET_AWAY 414
#define EFFECT_IVY_CUDGEL 415
#define EFFECT_FICKLE_BEAM 416
#define NUM_BATTLE_MOVE_EFFECTS 417
#define NUM_BATTLE_MOVE_EFFECTS 347
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -140,7 +140,7 @@
#define VARIOUS_TRY_SOAK 48
#define VARIOUS_HANDLE_MEGA_EVO 49
#define VARIOUS_TRY_LAST_RESORT 50
#define VARIOUS_ARGUMENT_STATUS_EFFECT 51
#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 51
#define VARIOUS_TRY_HIT_SWITCH_TARGET 52
#define VARIOUS_TRY_AUTOTOMIZE 53
#define VARIOUS_ABILITY_POPUP 54
@ -151,95 +151,94 @@
#define VARIOUS_POWER_TRICK 59
#define VARIOUS_AFTER_YOU 60
#define VARIOUS_BESTOW 61
#define VARIOUS_ARGUMENT_TO_MOVE_EFFECT 62
#define VARIOUS_JUMP_IF_NOT_GROUNDED 63
#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 64
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 65
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 66
#define VARIOUS_SET_AURORA_VEIL 67
#define VARIOUS_TRY_THIRD_TYPE 68
#define VARIOUS_ACUPRESSURE 69
#define VARIOUS_SET_POWDER 70
#define VARIOUS_SPECTRAL_THIEF 71
#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 72
#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 73
#define VARIOUS_JUMP_IF_ROAR_FAILS 74
#define VARIOUS_TRY_INSTRUCT 75
#define VARIOUS_JUMP_IF_NOT_BERRY 76
#define VARIOUS_TRACE_ABILITY 77
#define VARIOUS_UPDATE_NICK 78
#define VARIOUS_TRY_ILLUSION_OFF 79
#define VARIOUS_SET_SPRITEIGNORE0HP 80
#define VARIOUS_HANDLE_FORM_CHANGE 81
#define VARIOUS_GET_STAT_VALUE 82
#define VARIOUS_JUMP_IF_FULL_HP 83
#define VARIOUS_LOSE_TYPE 84
#define VARIOUS_TRY_ACTIVATE_SOULHEART 85
#define VARIOUS_TRY_ACTIVATE_RECEIVER 86
#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 87
#define VARIOUS_TRY_FRISK 88
#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 89
#define VARIOUS_TRY_FAIRY_LOCK 90
#define VARIOUS_JUMP_IF_NO_ALLY 91
#define VARIOUS_POISON_TYPE_IMMUNITY 92
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 93
#define VARIOUS_INFATUATE_WITH_BATTLER 94
#define VARIOUS_SET_LAST_USED_ITEM 95
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 96
#define VARIOUS_JUMP_IF_ABSENT 97
#define VARIOUS_DESTROY_ABILITY_POPUP 98
#define VARIOUS_TOTEM_BOOST 99
#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 100
#define VARIOUS_MOVEEND_ITEM_EFFECTS 101
#define VARIOUS_TERRAIN_SEED 102
#define VARIOUS_MAKE_INVISIBLE 103
#define VARIOUS_ROOM_SERVICE 104
#define VARIOUS_EERIE_SPELL_PP_REDUCE 105
#define VARIOUS_JUMP_IF_TEAM_HEALTHY 106
#define VARIOUS_TRY_HEAL_QUARTER_HP 107
#define VARIOUS_REMOVE_TERRAIN 108
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 109
#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 110
#define VARIOUS_GET_ROTOTILLER_TARGETS 111
#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 112
#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 113
#define VARIOUS_CONSUME_BERRY 114
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 115
#define VARIOUS_JUMP_IF_SPECIES 116
#define VARIOUS_UPDATE_ABILITY_POPUP 117
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 118
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 119
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 120
#define VARIOUS_SHELL_SIDE_ARM_CHECK 121
#define VARIOUS_TRY_NO_RETREAT 122
#define VARIOUS_TRY_TAR_SHOT 123
#define VARIOUS_CAN_TAR_SHOT_WORK 124
#define VARIOUS_CHECK_POLTERGEIST 125
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 126
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 127
#define VARIOUS_JUMP_IF_UNDER_200 128
#define VARIOUS_SET_SKY_DROP 129
#define VARIOUS_CLEAR_SKY_DROP 130
#define VARIOUS_SKY_DROP_YAWN 131
#define VARIOUS_JUMP_IF_HOLD_EFFECT 132
#define VARIOUS_CURE_CERTAIN_STATUSES 133
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 134
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 135
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 136
#define VARIOUS_SAVE_BATTLER_ITEM 137
#define VARIOUS_RESTORE_BATTLER_ITEM 138
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 139
#define VARIOUS_SET_BEAK_BLAST 140
#define VARIOUS_SWAP_SIDE_STATUSES 141
#define VARIOUS_SWAP_STATS 142
#define VARIOUS_TEATIME_INVUL 143
#define VARIOUS_TEATIME_TARGETS 144
#define VARIOUS_TRY_WIND_RIDER_POWER 145
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 146
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 147
#define VARIOUS_STORE_HEALING_WISH 148
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 149
#define VARIOUS_TRY_REVIVAL_BLESSING 150
#define VARIOUS_JUMP_IF_NOT_GROUNDED 62
#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 63
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 64
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 65
#define VARIOUS_SET_AURORA_VEIL 66
#define VARIOUS_TRY_THIRD_TYPE 67
#define VARIOUS_ACUPRESSURE 68
#define VARIOUS_SET_POWDER 69
#define VARIOUS_SPECTRAL_THIEF 70
#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 71
#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 72
#define VARIOUS_JUMP_IF_ROAR_FAILS 73
#define VARIOUS_TRY_INSTRUCT 74
#define VARIOUS_JUMP_IF_NOT_BERRY 75
#define VARIOUS_TRACE_ABILITY 76
#define VARIOUS_UPDATE_NICK 77
#define VARIOUS_TRY_ILLUSION_OFF 78
#define VARIOUS_SET_SPRITEIGNORE0HP 79
#define VARIOUS_HANDLE_FORM_CHANGE 80
#define VARIOUS_GET_STAT_VALUE 81
#define VARIOUS_JUMP_IF_FULL_HP 82
#define VARIOUS_LOSE_TYPE 83
#define VARIOUS_TRY_ACTIVATE_SOULHEART 84
#define VARIOUS_TRY_ACTIVATE_RECEIVER 85
#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 86
#define VARIOUS_TRY_FRISK 87
#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 88
#define VARIOUS_TRY_FAIRY_LOCK 89
#define VARIOUS_JUMP_IF_NO_ALLY 90
#define VARIOUS_POISON_TYPE_IMMUNITY 91
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 92
#define VARIOUS_INFATUATE_WITH_BATTLER 93
#define VARIOUS_SET_LAST_USED_ITEM 94
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 95
#define VARIOUS_JUMP_IF_ABSENT 96
#define VARIOUS_DESTROY_ABILITY_POPUP 97
#define VARIOUS_TOTEM_BOOST 98
#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 99
#define VARIOUS_MOVEEND_ITEM_EFFECTS 100
#define VARIOUS_TERRAIN_SEED 101
#define VARIOUS_MAKE_INVISIBLE 102
#define VARIOUS_ROOM_SERVICE 103
#define VARIOUS_EERIE_SPELL_PP_REDUCE 104
#define VARIOUS_JUMP_IF_TEAM_HEALTHY 105
#define VARIOUS_TRY_HEAL_QUARTER_HP 106
#define VARIOUS_REMOVE_TERRAIN 107
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 108
#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 109
#define VARIOUS_GET_ROTOTILLER_TARGETS 110
#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 111
#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 112
#define VARIOUS_CONSUME_BERRY 113
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 114
#define VARIOUS_JUMP_IF_SPECIES 115
#define VARIOUS_UPDATE_ABILITY_POPUP 116
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 117
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 118
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 119
#define VARIOUS_SHELL_SIDE_ARM_CHECK 120
#define VARIOUS_TRY_NO_RETREAT 121
#define VARIOUS_TRY_TAR_SHOT 122
#define VARIOUS_CAN_TAR_SHOT_WORK 123
#define VARIOUS_CHECK_POLTERGEIST 124
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 125
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 126
#define VARIOUS_JUMP_IF_UNDER_200 127
#define VARIOUS_SET_SKY_DROP 128
#define VARIOUS_CLEAR_SKY_DROP 129
#define VARIOUS_SKY_DROP_YAWN 130
#define VARIOUS_JUMP_IF_HOLD_EFFECT 131
#define VARIOUS_CURE_CERTAIN_STATUSES 132
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 133
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 134
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 135
#define VARIOUS_SAVE_BATTLER_ITEM 136
#define VARIOUS_RESTORE_BATTLER_ITEM 137
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 138
#define VARIOUS_SET_BEAK_BLAST 139
#define VARIOUS_SWAP_SIDE_STATUSES 140
#define VARIOUS_SWAP_STATS 141
#define VARIOUS_TEATIME_INVUL 142
#define VARIOUS_TEATIME_TARGETS 143
#define VARIOUS_TRY_WIND_RIDER_POWER 144
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 145
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 146
#define VARIOUS_STORE_HEALING_WISH 147
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 148
#define VARIOUS_TRY_REVIVAL_BLESSING 149
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -698,8 +698,10 @@
#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 696
#define STRINGID_HOSPITALITYRESTORATION 697
#define STRINGID_ELECTROSHOCKCHARGING 698
#define STRINGID_ITEMWASUSEDUP 699
#define STRINGID_ATTACKERLOSTITSTYPE 700
#define BATTLESTRINGS_COUNT 699
#define BATTLESTRINGS_COUNT 701
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View File

@ -451,8 +451,9 @@ struct BattleMove
u16 accuracy:7;
u16 recoil:7;
u16 criticalHitStage:2;
u8 padding:6; // coming soon...
u8 numAdditionalEffects:2; // limited to 3 - don't want to get too crazy
u8 pp;
u8 secondaryEffectChance;
u16 target;
s8 priority;
@ -508,7 +509,22 @@ struct BattleMove
u32 skyBattleBanned:1;
u32 sketchBanned:1;
u16 argument;
u32 argument; // also coming soon
// primary/secondary effects
const struct AdditionalEffect *additionalEffects;
};
#define EFFECTS_ARR(...) (const struct AdditionalEffect[]) {__VA_ARGS__}
#define ADDITIONAL_EFFECTS(...) EFFECTS_ARR( __VA_ARGS__ ), .numAdditionalEffects = ARRAY_COUNT(EFFECTS_ARR( __VA_ARGS__ ))
struct AdditionalEffect
{
u8 self:1;
u8 onlyIfTargetRaisedStats:1;
u8 onChargeTurnOnly:1;
u8 chance; // 0% = effect certain, primary effect
u16 moveEffect;
};
struct Ability

View File

@ -167,13 +167,13 @@ enum RandomTag
RNG_POISON_POINT,
RNG_RAMPAGE_TURNS,
RNG_SECONDARY_EFFECT,
RNG_SECONDARY_EFFECT_2,
RNG_SECONDARY_EFFECT_3,
RNG_SLEEP_TURNS,
RNG_SPEED_TIE,
RNG_STATIC,
RNG_STENCH,
RNG_TRI_ATTACK,
RNG_TRIPLE_ARROWS_DEFENSE_DOWN,
RNG_TRIPLE_ARROWS_FLINCH,
RNG_QUICK_DRAW,
RNG_QUICK_CLAW,
RNG_TRACE,

View File

@ -52,6 +52,7 @@ static s32 AI_Safari(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
{
[0] = AI_CheckBadMove, // AI_FLAG_CHECK_BAD_MOVE
@ -1051,7 +1052,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
// check move effects
switch (moveEffect)
{
case EFFECT_HIT:
case EFFECT_HIT: // only applies to Vital Throw
if (gBattleMoves[move].priority < 0 && AI_STRIKES_FIRST(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40)
ADJUST_SCORE(-2); // don't want to move last
break;
default:
break; // check move damage
case EFFECT_SLEEP:
@ -1402,14 +1406,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
}
break;
//case EFFECT_BIDE:
//case EFFECT_RECHARGE:
//case EFFECT_COUNTER:
case EFFECT_PRESENT:
case EFFECT_SONICBOOM:
//case EFFECT_MIRROR_COAT:
case EFFECT_FIXED_DAMAGE_ARG:
case EFFECT_FOCUS_PUNCH:
//case EFFECT_ENDEAVOR:
// AI_CBM_HighRiskForDamage
if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
ADJUST_SCORE(-10);
@ -1691,13 +1690,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
break;
case EFFECT_HIT_ESCAPE:
break;
case EFFECT_RAPID_SPIN:
if ((gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED) || (gStatuses3[battlerAtk] & STATUS3_LEECHSEED))
break; // check damage/accuracy
//Spin checks
if (!(gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY))
ADJUST_SCORE(-6);
break;
case EFFECT_BELLY_DRUM:
case EFFECT_FILLET_AWAY:
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
@ -1899,15 +1891,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (aiData->abilities[battlerAtk] != ABILITY_MAGIC_GUARD && AI_DATA->moveAccuracy[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] < 75)
ADJUST_SCORE(-6);
break;
case EFFECT_RECOIL:
if (AI_IsDamagedByRecoil(battlerAtk))
{
u32 recoilDmg = max(1, aiData->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex] * max(1, gBattleMoves[move].recoil) / 100);
if (!ShouldUseRecoilMove(battlerAtk, battlerDef, recoilDmg, AI_THINKING_STRUCT->movesetIndex))
ADJUST_SCORE(-10);
break;
}
break;
case EFFECT_TEETER_DANCE:
if (((gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
|| (!DoesBattlerIgnoreAbilityChecks(aiData->abilities[battlerAtk], move) && aiData->abilities[battlerDef] == ABILITY_OWN_TEMPO)
@ -1979,8 +1962,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (!AnyPartyMemberStatused(battlerAtk, gBattleMoves[move].soundMove) || PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))
ADJUST_SCORE(-10);
break;
case EFFECT_HIT_PREVENT_ESCAPE:
break;
case EFFECT_ENDURE:
if (gBattleMons[battlerAtk].hp == 1 || GetBattlerSecondaryDamage(battlerAtk)) //Don't use Endure if you'll die after using it
ADJUST_SCORE(-10);
@ -2059,12 +2040,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|| DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
ADJUST_SCORE(-9);
break;
case EFFECT_BURN_UP:
if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_FIRE))
ADJUST_SCORE(-10);
break;
case EFFECT_DOUBLE_SHOCK:
if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_ELECTRIC))
case EFFECT_FAIL_IF_NOT_ARG_TYPE:
if (!IS_BATTLER_OF_TYPE(battlerAtk, gBattleMoves[move].argument))
ADJUST_SCORE(-10);
break;
case EFFECT_DEFOG:
@ -2101,7 +2078,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|| ((aiData->abilities[battlerDef] == ABILITY_CONTRARY) && !IS_TARGETING_PARTNER(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner
ADJUST_SCORE(-10);
break;
case EFFECT_PSYCH_UP: // haze stats check
{
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
@ -2116,8 +2092,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
}
}
break;
case EFFECT_SPECTRAL_THIEF:
break;
case EFFECT_SEMI_INVULNERABLE:
if (predictedMove != MOVE_NONE
&& AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER
@ -2206,8 +2180,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|| aiData->holdEffects[battlerAtk] == HOLD_EFFECT_ABILITY_SHIELD)
ADJUST_SCORE(-10);
break;
case EFFECT_CORE_ENFORCER:
break;
case EFFECT_SIMPLE_BEAM:
if (aiData->abilities[battlerDef] == ABILITY_SIMPLE
|| gAbilities[aiData->abilities[battlerDef]].cantBeOverwritten
@ -2442,8 +2414,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
ADJUST_SCORE(-10);
break;
case EFFECT_THROAT_CHOP:
break;
case EFFECT_HEAL_BLOCK:
if (gDisableStructs[battlerDef].healBlockTimer != 0
|| PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove))
@ -2525,7 +2495,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (instructedMove == MOVE_NONE
|| gBattleMoves[instructedMove].instructBanned
|| gBattleMoves[instructedMove].twoTurnMove
|| gBattleMoves[instructedMove].effect == EFFECT_RECHARGE
|| MoveHasMoveEffectSelf(instructedMove, MOVE_EFFECT_RECHARGE)
|| IsZMove(instructedMove)
|| (gLockedMoves[battlerDef] != 0 && gLockedMoves[battlerDef] != 0xFFFF)
|| gBattleMons[battlerDef].status2 & STATUS2_MULTIPLETURNS
@ -2616,10 +2586,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (aiData->hpPercents[battlerDef] < 50)
ADJUST_SCORE(-1);
break;
case EFFECT_VITAL_THROW:
if (AI_STRIKES_FIRST(battlerAtk, battlerDef, move) && aiData->hpPercents[battlerAtk] < 40)
ADJUST_SCORE(-1); // don't want to move last
break;
case EFFECT_FLAIL:
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER // Opponent should go first
|| aiData->hpPercents[battlerAtk] > 50)
@ -2750,7 +2716,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_PERISH_SONG:
if (!(gBattleMons[battlerDef].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED)))
{
if (IsTrappingMoveEffect(effect) || predictedMove == MOVE_INGRAIN)
if (IsTrappingMove(aiData->partnerMove) || predictedMove == MOVE_INGRAIN)
ADJUST_SCORE(1);
}
break;
@ -3238,7 +3204,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
struct AiLogicData *aiData = AI_DATA;
u32 movesetIndex = AI_THINKING_STRUCT->movesetIndex;
u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][movesetIndex];
u32 secondaryEffectChance = AI_CalcSecondaryEffectChance(battlerAtk, gBattleMoves[move].secondaryEffectChance);
s8 atkPriority = GetMovePriority(battlerAtk, move);
u32 predictedMove = aiData->predictedMoves[battlerDef];
u32 predictedMoveSlot = GetMoveSlot(GetMovesArray(battlerDef), predictedMove);
@ -3296,6 +3261,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
switch (moveEffect)
{
case EFFECT_HIT:
// TEMPORARY - should be applied to all moves regardless of effect
score = AI_CheckMoveEffects(battlerAtk, battlerDef, move, score, aiData, predictedMove, isDoubleBattle);
break;
case EFFECT_SLEEP:
case EFFECT_YAWN:
@ -3537,15 +3504,19 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_HAZE:
if (AnyStatIsRaised(BATTLE_PARTNER(battlerAtk))
|| PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove))
{
ADJUST_SCORE(-3);
break;
// fallthrough
}
score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle);
break;
case EFFECT_ROAR:
case EFFECT_CLEAR_SMOG:
if (isDoubleBattle)
score += min(CountPositiveStatStages(battlerDef) + CountPositiveStatStages(BATTLE_PARTNER(battlerDef)), 7);
else
score += min(CountPositiveStatStages(battlerDef), 4);
if ((gBattleMoves[move].soundMove && aiData->abilities[battlerDef] == ABILITY_SOUNDPROOF) || aiData->abilities[battlerDef] == ABILITY_SUCTION_CUPS)
{
ADJUST_SCORE(-3);
break;
}
score += AI_TryToClearStats(battlerAtk, battlerDef, isDoubleBattle);
break;
case EFFECT_MULTI_HIT:
case EFFECT_TRIPLE_KICK:
@ -3558,9 +3529,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
if (!IS_BATTLER_OF_TYPE(battlerAtk, gBattleMoves[gBattleMons[battlerAtk].moves[0]].type))
ADJUST_SCORE(1);
break;
case EFFECT_FLINCH_HIT:
score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move);
break;
case EFFECT_SWALLOW:
if (gDisableStructs[battlerAtk].stockpileCounter == 0)
{
@ -3601,8 +3569,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
break;
case EFFECT_TOXIC:
case EFFECT_POISON:
case EFFECT_BARB_BARRAGE:
case EFFECT_MORTAL_SPIN:
IncreasePoisonScore(battlerAtk, battlerDef, move, &score);
break;
case EFFECT_LIGHT_SCREEN:
@ -3644,14 +3610,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
if (gStatuses3[battlerAtk] & STATUS3_ALWAYS_HITS)
ADJUST_SCORE(5);
break;
case EFFECT_TRAP:
if (HasMoveEffect(battlerDef, EFFECT_RAPID_SPIN))
break;
//fallthrough
case EFFECT_MEAN_LOOK:
if (IsBattlerTrapped(battlerDef, TRUE))
break; // in this case its a bad attacking move
else if (ShouldTrap(battlerAtk, battlerDef, move))
if (!IsBattlerTrapped(battlerDef, TRUE) && ShouldTrap(battlerAtk, battlerDef, move))
ADJUST_SCORE(5);
break;
case EFFECT_MIST:
@ -3672,18 +3632,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_PARALYZE:
IncreaseParalyzeScore(battlerAtk, battlerDef, move, &score);
break;
case EFFECT_SPEED_DOWN_HIT:
if (!ShouldLowerSpeed(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
break;
case EFFECT_ATTACK_DOWN_HIT:
case EFFECT_DEFENSE_DOWN_HIT:
case EFFECT_SPECIAL_ATTACK_DOWN_HIT:
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT:
case EFFECT_ACCURACY_DOWN_HIT:
case EFFECT_EVASION_DOWN_HIT:
if (secondaryEffectChance >= 100 && aiData->abilities[battlerDef] != ABILITY_CONTRARY)
ADJUST_SCORE(2);
break;
case EFFECT_SUBSTITUTE:
if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG)
ADJUST_SCORE(3);
@ -3710,7 +3658,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_LEECH_SEED:
if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS)
|| gStatuses3[battlerDef] & STATUS3_LEECHSEED
|| HasMoveEffect(battlerDef, EFFECT_RAPID_SPIN)
|| HasMoveWithMoveEffect(battlerDef, MOVE_EFFECT_RAPIDSPIN)
|| aiData->abilities[battlerDef] == ABILITY_LIQUID_OOZE
|| aiData->abilities[battlerDef] == ABILITY_MAGIC_GUARD)
break;
@ -3808,10 +3756,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
else if (HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, TRUE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]))
ADJUST_SCORE(1);
break;
case EFFECT_SPEED_UP_HIT:
if (secondaryEffectChance >= 100 && aiData->abilities[battlerDef] != ABILITY_CONTRARY && !AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
ADJUST_SCORE(3);
break;
case EFFECT_DESTINY_BOND:
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && CanTargetFaintAi(battlerDef, battlerAtk))
ADJUST_SCORE(3);
@ -3824,58 +3768,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
if (ShouldUseWishAromatherapy(battlerAtk, battlerDef, move))
ADJUST_SCORE(3);
break;
case EFFECT_THIEF:
{
bool32 canSteal = FALSE;
if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE)
canSteal = TRUE;
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER)
canSteal = TRUE;
if (canSteal && aiData->items[battlerAtk] == ITEM_NONE
&& aiData->items[battlerDef] != ITEM_NONE
&& CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef])
&& CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef])
&& !HasMoveEffect(battlerAtk, EFFECT_ACROBATICS)
&& aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD)
{
switch (aiData->holdEffects[battlerDef])
{
case HOLD_EFFECT_NONE:
break;
case HOLD_EFFECT_CHOICE_BAND:
case HOLD_EFFECT_CHOICE_SCARF:
case HOLD_EFFECT_CHOICE_SPECS:
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_TOXIC_ORB:
if (ShouldPoisonSelf(battlerAtk, aiData->abilities[battlerAtk]))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_FLAME_ORB:
if (ShouldBurnSelf(battlerAtk, aiData->abilities[battlerAtk]))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_BLACK_SLUDGE:
if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_IRON_BALL:
if (HasMoveEffect(battlerAtk, EFFECT_FLING))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_LAGGING_TAIL:
case HOLD_EFFECT_STICKY_BARB:
break;
default:
ADJUST_SCORE(1);
break;
}
}
break;
}
break;
case EFFECT_NIGHTMARE:
if (aiData->abilities[battlerDef] != ABILITY_MAGIC_GUARD
&& !(gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE)
@ -3968,15 +3860,10 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
break;
case EFFECT_SPIKES:
case EFFECT_HIT_SET_ENTRY_HAZARD:
case EFFECT_STEALTH_ROCK:
case EFFECT_STICKY_WEB:
case EFFECT_TOXIC_SPIKES:
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
break;
if (gDisableStructs[battlerAtk].isFirstTurn)
ADJUST_SCORE(2);
//TODO - track entire opponent party data to determine hazard effectiveness
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
break;
case EFFECT_FORESIGHT:
if (aiData->abilities[battlerAtk] == ABILITY_SCRAPPY || aiData->abilities[battlerAtk] == ABILITY_MINDS_EYE)
@ -4067,14 +3954,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
ADJUST_SCORE(1);
}
break;
case EFFECT_ATTACK_UP_HIT:
if (secondaryEffectChance >= 100)
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score);
break;
case EFFECT_SPECIAL_ATTACK_UP_HIT:
if (secondaryEffectChance >= 100)
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPATK, &score);
break;
case EFFECT_FELL_STINGER:
if (gBattleMons[battlerAtk].statStages[STAT_ATK] < MAX_STAT_STAGE
&& aiData->abilities[battlerAtk] != ABILITY_CONTRARY
@ -4091,35 +3970,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
score += (MAX_STAT_STAGE - gBattleMons[battlerAtk].statStages[STAT_ATK]);
break;
case EFFECT_PSYCH_UP:
case EFFECT_SPECTRAL_THIEF:
// Want to copy positive stat changes
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
{
switch (i)
{
case STAT_ATK:
if (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_PHYSICAL))
ADJUST_SCORE(1);
break;
case STAT_SPATK:
if (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_SPECIAL))
ADJUST_SCORE(1);
break;
case STAT_ACC:
case STAT_EVASION:
case STAT_SPEED:
ADJUST_SCORE(1);
break;
case STAT_DEF:
case STAT_SPDEF:
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL)
ADJUST_SCORE(1);
break;
}
}
}
score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef);
break;
case EFFECT_SEMI_INVULNERABLE:
ADJUST_SCORE(1);
@ -4164,7 +4015,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_SWAGGER:
if (HasMoveEffect(battlerAtk, EFFECT_FOUL_PLAY)
|| HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
|| HasMoveWithMoveEffect(battlerAtk, MOVE_EFFECT_SPECTRAL_THIEF))
ADJUST_SCORE(1);
if (aiData->abilities[battlerDef] == ABILITY_CONTRARY)
@ -4174,7 +4025,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
break;
case EFFECT_FLATTER:
if (HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
|| HasMoveWithMoveEffect(battlerAtk, MOVE_EFFECT_SPECTRAL_THIEF))
ADJUST_SCORE(2);
if (aiData->abilities[battlerDef] == ABILITY_CONTRARY)
@ -4211,48 +4062,24 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
else if (IsPredictedToUsePursuitableMove(battlerDef, battlerAtk) && !MoveWouldHitFirst(move, battlerAtk, battlerDef)) //Pursuit against fast U-Turn
ADJUST_SCORE(3);*/
break;
case EFFECT_RAPID_SPIN:
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPEED, &score); // Gen 8 increases speed
//fallthrough
case EFFECT_DEFOG:
if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
|| (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST)))
{
ADJUST_SCORE(3);
break;
}
switch (move)
else if (!(gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SPIKES)) //Don't blow away hazards if you set them up
{
case MOVE_DEFOG:
if (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST))
if (isDoubleBattle)
{
ADJUST_SCORE(3);
if (IsHazardMoveEffect(gBattleMoves[aiData->partnerMove].effect) // Partner is going to set up hazards
&& AI_WhoStrikesFirst(battlerAtk, BATTLE_PARTNER(battlerAtk), move) == AI_IS_SLOWER) // Partner going first
break; // Don't use Defog if partner is going to set up hazards
}
else if (!(gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SPIKES)) //Don't blow away hazards if you set them up
{
if (isDoubleBattle)
{
if (IsHazardMoveEffect(gBattleMoves[aiData->partnerMove].effect) // Partner is going to set up hazards
&& AI_WhoStrikesFirst(battlerAtk, BATTLE_PARTNER(battlerAtk), move) == AI_IS_SLOWER) // Partner going first
break; // Don't use Defog if partner is going to set up hazards
}
// check defog lowering evasion
if (ShouldLowerEvasion(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
{
if (gBattleMons[battlerDef].statStages[STAT_EVASION] > 7
|| HasMoveWithLowAccuracy(battlerAtk, battlerDef, 90, TRUE, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]))
ADJUST_SCORE(2); // encourage lowering evasion if they are evasive or we have a move with low accuracy
else
ADJUST_SCORE(1);
}
}
break;
case MOVE_RAPID_SPIN:
case MOVE_MORTAL_SPIN:
if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED)
ADJUST_SCORE(3);
break;
// check defog lowering evasion
if (ShouldLowerEvasion(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
ADJUST_SCORE(2);
}
break;
case EFFECT_TORMENT:
@ -4390,12 +4217,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
else
ADJUST_SCORE(1);
break;
case EFFECT_SUPERPOWER:
case EFFECT_OVERHEAT:
case EFFECT_MAKE_IT_RAIN:
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
ADJUST_SCORE(3);
break;
case EFFECT_MAGIC_COAT:
if (IS_MOVE_STATUS(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH))
ADJUST_SCORE(3);
@ -4426,24 +4247,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_AURORA_VEIL)
ADJUST_SCORE(1);
break;
case EFFECT_KNOCK_OFF:
if (CanKnockOffItem(battlerDef, aiData->items[battlerDef]))
{
switch (aiData->holdEffects[battlerDef])
{
case HOLD_EFFECT_IRON_BALL:
if (HasMoveEffect(battlerDef, EFFECT_FLING))
ADJUST_SCORE(4);
break;
case HOLD_EFFECT_LAGGING_TAIL:
case HOLD_EFFECT_STICKY_BARB:
break;
default:
ADJUST_SCORE(3);
break;
}
}
break;
case EFFECT_SKILL_SWAP:
if (gAbilities[aiData->abilities[battlerDef]].aiRating > gAbilities[aiData->abilities[battlerAtk]].aiRating)
ADJUST_SCORE(1);
@ -4618,22 +4421,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
ADJUST_SCORE(1);
}
break;
case EFFECT_BUG_BITE: // And pluck
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD)
break;
else if (ItemId_GetPocket(aiData->items[battlerDef]) == POCKET_BERRIES)
ADJUST_SCORE(3);
break;
case EFFECT_INCINERATE:
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD)
break;
else if (ItemId_GetPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS)
ADJUST_SCORE(3);
break;
case EFFECT_SMACK_DOWN:
if (!IsBattlerGrounded(battlerDef))
ADJUST_SCORE(3);
break;
case EFFECT_RELIC_SONG:
if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) // Don't try to change form if it's transformed.
{
@ -4717,10 +4504,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
break;
}*/
break;
case EFFECT_FEINT:
if (gBattleMoves[predictedMove].effect == EFFECT_PROTECT)
ADJUST_SCORE(3);
break;
case EFFECT_EMBARGO:
if (aiData->holdEffects[battlerDef] != HOLD_EFFECT_NONE)
ADJUST_SCORE(1);
@ -4734,12 +4517,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
|| !IsBattlerGrounded(battlerDef))
ADJUST_SCORE(1);
break;
case EFFECT_THROAT_CHOP:
if (predictedMove != MOVE_NONE && gBattleMoves[predictedMove].soundMove && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
ADJUST_SCORE(3); // Ai goes first and predicts the target will use a sound move
else if (HasSoundMove(battlerDef))
ADJUST_SCORE(3);
break;
case EFFECT_HEAL_BLOCK:
if (AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER && predictedMove != MOVE_NONE && IsHealingMove(predictedMove))
ADJUST_SCORE(3); // Try to cancel healing move
@ -4818,16 +4595,6 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
&& !IS_MOVE_STATUS(move) && AI_GetTypeEffectiveness(predictedMove, battlerDef, battlerAtk) != AI_EFFECTIVENESS_x0)
ADJUST_SCORE(1);
break;
case EFFECT_FLAME_BURST:
if (isDoubleBattle)
{
if (IsBattlerAlive(BATTLE_PARTNER(battlerDef))
&& aiData->hpPercents[BATTLE_PARTNER(battlerDef)] < 12
&& aiData->abilities[BATTLE_PARTNER(battlerDef)] != ABILITY_MAGIC_GUARD
&& !IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerDef), TYPE_FIRE))
ADJUST_SCORE(1);
}
break;
case EFFECT_TOXIC_THREAD:
IncreasePoisonScore(battlerAtk, battlerDef, move, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPEED, &score);
@ -4908,6 +4675,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
// Effects that are encouraged on the first turn of battle
static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
u8 i;
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)
|| gBattleResults.battleTurnCounter != 0)
return score;
@ -5006,9 +4774,23 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
case EFFECT_SNOWSCAPE:
case EFFECT_GEOMANCY:
case EFFECT_VICTORY_DANCE:
case EFFECT_HIT_SET_ENTRY_HAZARD:
ADJUST_SCORE(2);
break;
case EFFECT_HIT:
// TEMPORARY - should applied to all moves regardless of EFFECT
// Consider move effects
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_SPIKES:
ADJUST_SCORE(2);
break;
default:
break;
}
}
default:
break;
}
@ -5019,6 +4801,7 @@ static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
// Adds score bonus to 'riskier' move effects and high crit moves
static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
u8 i;
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))
return score;
@ -5039,7 +4822,6 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_SWAGGER:
case EFFECT_ATTRACT:
case EFFECT_PRESENT:
case EFFECT_ALL_STATS_UP_HIT:
case EFFECT_BELLY_DRUM:
case EFFECT_MIRROR_COAT:
case EFFECT_FOCUS_PUNCH:
@ -5049,6 +4831,21 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (Random() & 1)
ADJUST_SCORE(2);
break;
case EFFECT_HIT:
// TEMPORARY - should applied to all moves regardless of EFFECT
// Consider move effects
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_ALL_STATS_UP:
if (Random() & 1)
ADJUST_SCORE(2);
break;
default:
break;
}
}
default:
break;
}

View File

@ -511,11 +511,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
case EFFECT_PSYWAVE:
dmg = gBattleMons[battlerAtk].level * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
case EFFECT_DRAGON_RAGE:
dmg = 40 * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
case EFFECT_SONICBOOM:
dmg = 20 * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
case EFFECT_FIXED_DAMAGE_ARG:
dmg = gBattleMoves[move].argument * (aiData->abilities[battlerAtk] == ABILITY_PARENTAL_BOND ? 2 : 1);
break;
case EFFECT_MULTI_HIT:
dmg *= (aiData->abilities[battlerAtk] == ABILITY_SKILL_LINK
@ -591,110 +588,101 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3
switch (gBattleMoves[move].effect)
{
case EFFECT_HIT:
default:
return FALSE;
case EFFECT_PARALYZE_HIT:
if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE))
return TRUE;
break;
case EFFECT_BURN_HIT:
if (AI_CanBurn(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE))
return TRUE;
break;
case EFFECT_POISON_HIT:
case EFFECT_POISON_FANG:
if (AI_CanPoison(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE))
return TRUE;
break;
case EFFECT_FREEZE_HIT:
if (AI_CanGetFrostbite(battlerDef, abilityDef))
return TRUE;
break;
case EFFECT_CONFUSE_HIT:
if (AI_CanConfuse(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE))
return TRUE;
break;
case EFFECT_FLINCH_STATUS:
switch (gBattleMoves[move].argument)
{
case STATUS1_PARALYSIS:
if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE))
return TRUE;
break;
case STATUS1_BURN:
if (AI_CanBurn(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE))
return TRUE;
break;
case STATUS1_FREEZE:
if (AI_CanGetFrostbite(battlerDef, abilityDef))
return TRUE;
break;
}
// fallthrough
case EFFECT_FLINCH_HIT:
if (ShouldTryToFlinch(battlerAtk, battlerDef, abilityAtk, abilityDef, move))
return TRUE;
break;
case EFFECT_HIT_ESCAPE:
if (CountUsablePartyMons(battlerAtk) != 0 && ShouldPivot(battlerAtk, battlerDef, abilityDef, move, AI_THINKING_STRUCT->movesetIndex))
return TRUE;
break;
case EFFECT_ATTACK_UP_HIT:
case EFFECT_FELL_STINGER:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK))
return TRUE;
break;
case EFFECT_DEFENSE_UP2_HIT:
case EFFECT_DEFENSE_UP_HIT:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF))
return TRUE;
break;
case EFFECT_SPEED_UP_HIT:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPEED))
return TRUE;
break;
case EFFECT_SPECIAL_ATTACK_UP_HIT:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPATK))
return TRUE;
break;
case EFFECT_ATTACK_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ATK) && abilityDef != ABILITY_HYPER_CUTTER && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_DEFENSE_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_DEF) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_BULLDOZE:
case EFFECT_SPEED_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_SPEED) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_SPECIAL_ATTACK_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_SPATK) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT:
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT_2:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_SPDEF) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_ACCURACY_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ACC) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_EVASION_DOWN_HIT:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_EVASION) && noOfHitsToKo != 1)
return TRUE;
break;
case EFFECT_ALL_STATS_UP_HIT:
for (i = STAT_ATK; i <= NUM_STATS; i++)
}
// check ADDITIONAL_EFFECTS
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
// Consider move effects that target self
if (gBattleMoves[move].additionalEffects[i].self)
{
if (BattlerStatCanRise(battlerAtk, abilityAtk, i))
return TRUE;
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_ATK_PLUS_1:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK))
return TRUE;
break;
case MOVE_EFFECT_DEF_PLUS_2:
case MOVE_EFFECT_DEF_PLUS_1:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF))
return TRUE;
break;
case MOVE_EFFECT_SPD_PLUS_1:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPEED))
return TRUE;
break;
case MOVE_EFFECT_SP_ATK_PLUS_1:
if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPATK))
return TRUE;
break;
case MOVE_EFFECT_ALL_STATS_UP:
for (i = STAT_ATK; i <= NUM_STATS; i++)
{
if (BattlerStatCanRise(battlerAtk, abilityAtk, i))
return TRUE;
}
break;
}
}
else // consider move effects that hinder the target
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_POISON:
case MOVE_EFFECT_TOXIC:
if (AI_CanPoison(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE))
return TRUE;
break;
case MOVE_EFFECT_BURN:
if (AI_CanBurn(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE))
return TRUE;
break;
case MOVE_EFFECT_FREEZE_OR_FROSTBITE:
if (AI_CanGetFrostbite(battlerDef, abilityDef))
return TRUE;
break;
case MOVE_EFFECT_PARALYSIS:
if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE))
return TRUE;
break;
case MOVE_EFFECT_CONFUSION:
if (AI_CanConfuse(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE))
return TRUE;
break;
case MOVE_EFFECT_FLINCH:
if (ShouldTryToFlinch(battlerAtk, battlerDef, abilityAtk, abilityDef, move))
return TRUE;
break;
case MOVE_EFFECT_ATK_MINUS_1:
case MOVE_EFFECT_DEF_MINUS_1:
case MOVE_EFFECT_SPD_MINUS_1:
case MOVE_EFFECT_SP_ATK_MINUS_1:
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_ACC_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ATK + (gBattleMoves[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_1)) && noOfHitsToKo != 1)
return TRUE;
break;
case MOVE_EFFECT_ATK_MINUS_2:
case MOVE_EFFECT_DEF_MINUS_2:
case MOVE_EFFECT_SPD_MINUS_2:
case MOVE_EFFECT_SP_ATK_MINUS_2:
case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_ACC_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2:
if (ShouldLowerStat(battlerDef, abilityDef, STAT_ATK + (gBattleMoves[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_MINUS_2)) && noOfHitsToKo != 1)
return TRUE;
break;
}
}
break;
}
return FALSE;
@ -704,29 +692,44 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s
{
u32 abilityAtk = AI_DATA->abilities[battlerAtk];
u32 abilityDef = AI_DATA->abilities[battlerDef];
u8 i;
// recoil
if (gBattleMoves[move].recoil > 0 && AI_IsDamagedByRecoil(battlerAtk))
return TRUE;
switch (gBattleMoves[move].effect)
{
case EFFECT_RECHARGE:
case EFFECT_SUPERPOWER:
case EFFECT_OVERHEAT:
case EFFECT_MAKE_IT_RAIN:
case EFFECT_MIND_BLOWN:
case EFFECT_STEEL_BEAM:
return TRUE;
case EFFECT_RECOIL_IF_MISS:
case EFFECT_RECOIL:
if (AI_IsDamagedByRecoil(battlerAtk))
return TRUE;
break;
case EFFECT_SPEED_DOWN_HIT:
case EFFECT_ATTACK_DOWN_HIT:
case EFFECT_DEFENSE_DOWN_HIT:
case EFFECT_SPECIAL_ATTACK_DOWN_HIT:
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT:
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT_2:
if (noOfHitsToKo != 1 && abilityDef == ABILITY_CONTRARY && !IsMoldBreakerTypeAbility(abilityAtk))
return TRUE;
default:
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_ATK_MINUS_1:
case MOVE_EFFECT_DEF_MINUS_1:
case MOVE_EFFECT_SPD_MINUS_1:
case MOVE_EFFECT_SP_ATK_MINUS_1:
case MOVE_EFFECT_SP_ATK_TWO_DOWN:
case MOVE_EFFECT_V_CREATE:
case MOVE_EFFECT_ATK_DEF_DOWN:
case MOVE_EFFECT_DEF_SPDEF_DOWN:
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_SP_DEF_MINUS_2:
if ((gBattleMoves[move].additionalEffects[i].self && GetBattlerAbility(battlerAtk) != ABILITY_CONTRARY)
|| (noOfHitsToKo != 1 && abilityDef == ABILITY_CONTRARY && !IsMoldBreakerTypeAbility(abilityAtk)))
return TRUE;
break;
case MOVE_EFFECT_RECHARGE:
return gBattleMoves[move].additionalEffects[i].self;
}
}
break;
}
return FALSE;
@ -1234,7 +1237,6 @@ bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move)
// increased accuracy but don't always hit
if ((((weather & B_WEATHER_RAIN) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|| (((weather & (B_WEATHER_HAIL | B_WEATHER_SNOW)) && move == MOVE_BLIZZARD)))
|| (gBattleMoves[move].effect == EFFECT_VITAL_THROW)
|| (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && gBattleMoves[move].minimizeDoubleDamage)
|| (gBattleMoves[move].accuracy == 0))
{
@ -1440,13 +1442,19 @@ bool32 ShouldLowerStat(u32 battler, u32 battlerAbility, u32 stat)
|| battlerAbility == ABILITY_FULL_METAL_BODY)
return FALSE;
// If AI is faster and doesn't have any mons left, lowering speed doesn't give any
if (stat == STAT_SPEED)
switch (stat)
{
if (AI_WhoStrikesFirst(sBattler_AI, battler, AI_THINKING_STRUCT->moveConsidered) == AI_IS_FASTER
&& CountUsablePartyMons(sBattler_AI) == 0
&& !HasMoveEffect(sBattler_AI, EFFECT_ELECTRO_BALL))
return FALSE;
case STAT_ATK:
return !(battlerAbility == ABILITY_HYPER_CUTTER);
case STAT_DEF:
return !(battlerAbility == ABILITY_BIG_PECKS);
case STAT_SPEED:
// If AI is faster and doesn't have any mons left, lowering speed doesn't give any
return !(AI_WhoStrikesFirst(sBattler_AI, battler, AI_THINKING_STRUCT->moveConsidered) == AI_IS_FASTER
&& CountUsablePartyMons(sBattler_AI) == 0
&& !HasMoveEffect(sBattler_AI, EFFECT_ELECTRO_BALL));
case STAT_ACC:
return !(battlerAbility == ABILITY_KEEN_EYE || (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE));
}
return TRUE;
}
@ -1699,14 +1707,62 @@ bool32 HasMoveWithType(u32 battler, u32 type)
return FALSE;
}
bool32 HasMoveEffect(u32 battlerId, u32 moveEffect)
bool32 HasMoveEffect(u32 battlerId, u32 effect)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && gBattleMoves[moves[i]].effect == moveEffect)
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
&& gBattleMoves[moves[i]].effect == effect)
return TRUE;
}
return FALSE;
}
bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
&& gBattleMoves[moves[i]].effect == effect
&& (gBattleMoves[moves[i]].argument & argument))
return TRUE;
}
return FALSE;
}
bool32 HasMoveWithMoveEffect(u32 battlerId, u32 moveEffect)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
&& MoveHasMoveEffect(moves[i], moveEffect))
return TRUE;
}
return FALSE;
}
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception)
{
s32 i;
u16 *moves = GetMovesArray(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE
&& gBattleMoves[moves[i]].effect != exception
&& MoveHasMoveEffect(moves[i], moveEffect))
return TRUE;
}
@ -1793,18 +1849,17 @@ bool32 HasHealingEffect(u32 battlerId)
return FALSE;
}
bool32 IsTrappingMoveEffect(u32 effect)
bool32 IsTrappingMove(u32 move)
{
switch (effect)
switch (gBattleMoves[move].effect)
{
case EFFECT_MEAN_LOOK:
case EFFECT_TRAP:
case EFFECT_HIT_PREVENT_ESCAPE:
case EFFECT_FAIRY_LOCK:
//case EFFECT_NO_RETREAT: // TODO
return TRUE;
default:
return FALSE;
return MoveHasMoveEffect(move, MOVE_EFFECT_PREVENT_ESCAPE)
|| MoveHasMoveEffect(move, MOVE_EFFECT_WRAP);
}
}
@ -1815,7 +1870,7 @@ bool32 HasTrappingMoveEffect(u32 battler)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && IsTrappingMoveEffect(gBattleMoves[moves[i]].effect))
if (moves[i] != MOVE_NONE && moves[i] != MOVE_UNAVAILABLE && IsTrappingMove(moves[i]))
return TRUE;
}
@ -3375,8 +3430,7 @@ void IncreasePoisonScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT))
ADJUST_SCORE_PTR(1); // stall tactic
if (HasMoveEffect(battlerAtk, EFFECT_VENOSHOCK)
|| HasMoveEffect(battlerAtk, EFFECT_HEX)
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PSN_ANY)
|| HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH)
|| AI_DATA->abilities[battlerAtk] == ABILITY_MERCILESS)
ADJUST_SCORE_PTR(2);
@ -3400,7 +3454,8 @@ void IncreaseBurnScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
ADJUST_SCORE_PTR(2); // burning the target to stay alive is cool
}
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX))
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN)
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_BURN))
ADJUST_SCORE_PTR(1);
}
}
@ -3417,8 +3472,8 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
u32 defSpeed = AI_DATA->speedStats[battlerDef];
if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe
|| HasMoveEffect(battlerAtk, EFFECT_HEX)
|| HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT)
|| HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_PARALYSIS)
|| (HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FAKE_OUT)) // filter out Fake Out
|| gBattleMons[battlerDef].status2 & STATUS2_INFATUATION
|| gBattleMons[battlerDef].status2 & STATUS2_CONFUSION)
ADJUST_SCORE_PTR(4);
@ -3442,7 +3497,8 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score)
&& !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK)))
ADJUST_SCORE_PTR(1);
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX))
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP)
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_SLEEP))
ADJUST_SCORE_PTR(1);
}
@ -3458,7 +3514,7 @@ void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score
{
if (gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS
|| gBattleMons[battlerDef].status2 & STATUS2_INFATUATION
|| (AI_DATA->abilities[battlerAtk] == ABILITY_SERENE_GRACE && HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT)))
|| (AI_DATA->abilities[battlerAtk] == ABILITY_SERENE_GRACE && HasMoveWithMoveEffectExcept(battlerAtk, MOVE_EFFECT_FLINCH, EFFECT_FAKE_OUT)))
ADJUST_SCORE_PTR(3);
else
ADJUST_SCORE_PTR(2);
@ -3479,7 +3535,8 @@ void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score
ADJUST_SCORE_PTR(2); // frostbiting the target to stay alive is cool
}
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX))
if (HasMoveEffectANDArg(battlerAtk, EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE)
|| HasMoveEffectANDArg(BATTLE_PARTNER(battlerAtk), EFFECT_DOUBLE_POWER_ON_ARG_STATUS, STATUS1_FROSTBITE))
ADJUST_SCORE_PTR(1);
}
}
@ -3530,10 +3587,276 @@ bool32 AI_IsBattlerAsleepOrComatose(u32 battlerId)
return (gBattleMons[battlerId].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerId] == ABILITY_COMATOSE;
}
u32 AI_CalcSecondaryEffectChance(u32 battler, u32 secondaryEffectChance)
s32 AI_CheckMoveEffects(u32 battlerAtk, u32 battlerDef, u32 move, s32 score, struct AiLogicData *aiData, u32 predictedMove, bool32 isDoubleBattle)
{
if (AI_DATA->abilities[battler] == ABILITY_SERENE_GRACE)
secondaryEffectChance *= 2;
u8 i;
// check move additional effects that are likely to happen
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
// Only consider effects with a guaranteed chance to happen
if (!MoveEffectIsGuaranteed(battlerAtk, aiData->abilities[battlerAtk], &gBattleMoves[move].additionalEffects[i]))
continue;
return secondaryEffectChance;
// Consider move effects that target self
if (gBattleMoves[move].additionalEffects[i].self)
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_SPD_PLUS_2:
case MOVE_EFFECT_SPD_PLUS_1:
if (aiData->abilities[battlerAtk] != ABILITY_CONTRARY && !AI_STRIKES_FIRST(battlerAtk, battlerDef, move))
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_ATK_PLUS_1:
case MOVE_EFFECT_DEF_PLUS_1:
case MOVE_EFFECT_SP_ATK_PLUS_1:
case MOVE_EFFECT_SP_DEF_PLUS_1:
case MOVE_EFFECT_ACC_PLUS_1:
case MOVE_EFFECT_EVS_PLUS_1:
IncreaseStatUpScore(
battlerAtk,
battlerDef,
STAT_ATK + gBattleMoves[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_1,
&score
);
break;
case MOVE_EFFECT_ATK_PLUS_2:
case MOVE_EFFECT_DEF_PLUS_2:
case MOVE_EFFECT_SP_ATK_PLUS_2:
case MOVE_EFFECT_SP_DEF_PLUS_2:
case MOVE_EFFECT_ACC_PLUS_2:
case MOVE_EFFECT_EVS_PLUS_2:
IncreaseStatUpScore(
battlerAtk,
battlerDef,
STAT_ATK + gBattleMoves[move].additionalEffects[i].moveEffect - MOVE_EFFECT_ATK_PLUS_2,
&score
);
break;
// Effects that lower stat(s) - only need to consider Contrary
case MOVE_EFFECT_ATK_MINUS_1:
case MOVE_EFFECT_DEF_MINUS_1:
case MOVE_EFFECT_SPD_MINUS_1:
case MOVE_EFFECT_SP_ATK_MINUS_1:
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_V_CREATE:
case MOVE_EFFECT_DEF_SPDEF_DOWN:
case MOVE_EFFECT_ATK_DEF_DOWN:
case MOVE_EFFECT_SP_ATK_TWO_DOWN:
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_RAPIDSPIN:
if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0)
|| (gStatuses3[battlerAtk] & STATUS3_LEECHSEED || gBattleMons[battlerAtk].status2 & STATUS2_WRAPPED))
{
ADJUST_SCORE(3);
break;
}
//Spin checks
if (!(gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY))
ADJUST_SCORE(-6);
break;
}
}
else // consider move effects that hinder the target
{
switch (gBattleMoves[move].additionalEffects[i].moveEffect)
{
case MOVE_EFFECT_FLINCH:
score += ShouldTryToFlinch(battlerAtk, battlerDef, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], move);
break;
case MOVE_EFFECT_SPD_MINUS_1:
case MOVE_EFFECT_SPD_MINUS_2:
if (!ShouldLowerSpeed(battlerAtk, battlerDef, aiData->abilities[battlerDef]))
break;
case MOVE_EFFECT_ATK_MINUS_1:
case MOVE_EFFECT_DEF_MINUS_1:
case MOVE_EFFECT_SP_ATK_MINUS_1:
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_ACC_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1:
if (aiData->abilities[battlerDef] != ABILITY_CONTRARY)
ADJUST_SCORE(2);
break;
case MOVE_EFFECT_ATK_MINUS_2:
case MOVE_EFFECT_DEF_MINUS_2:
case MOVE_EFFECT_SP_ATK_MINUS_2:
case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_ACC_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2:
if (aiData->abilities[battlerDef] != ABILITY_CONTRARY)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_POISON:
IncreasePoisonScore(battlerAtk, battlerDef, move, &score);
break;
case MOVE_EFFECT_CLEAR_SMOG:
score += AI_TryToClearStats(battlerAtk, battlerDef, FALSE);
break;
case MOVE_EFFECT_SPECTRAL_THIEF:
score += AI_ShouldCopyStatChanges(battlerAtk, battlerDef);
break;
case MOVE_EFFECT_BUG_BITE: // And pluck
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD)
break;
else if (ItemId_GetPocket(aiData->items[battlerDef]) == POCKET_BERRIES)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_INCINERATE:
if (gBattleMons[battlerDef].status2 & STATUS2_SUBSTITUTE || aiData->abilities[battlerDef] == ABILITY_STICKY_HOLD)
break;
else if (ItemId_GetPocket(aiData->items[battlerDef]) == POCKET_BERRIES || aiData->holdEffects[battlerDef] == HOLD_EFFECT_GEMS)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_SMACK_DOWN:
if (!IsBattlerGrounded(battlerDef) && HasDamagingMoveOfType(battlerAtk, TYPE_GROUND))
ADJUST_SCORE(1);
break;
case MOVE_EFFECT_KNOCK_OFF:
if (CanKnockOffItem(battlerDef, aiData->items[battlerDef]))
{
switch (aiData->holdEffects[battlerDef])
{
case HOLD_EFFECT_IRON_BALL:
if (HasMoveEffect(battlerDef, EFFECT_FLING))
ADJUST_SCORE(4);
break;
case HOLD_EFFECT_LAGGING_TAIL:
case HOLD_EFFECT_STICKY_BARB:
break;
default:
ADJUST_SCORE(3);
break;
}
}
break;
case MOVE_EFFECT_STEAL_ITEM:
{
bool32 canSteal = FALSE;
if (B_TRAINERS_KNOCK_OFF_ITEMS == TRUE)
canSteal = TRUE;
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER)
canSteal = TRUE;
if (canSteal && aiData->items[battlerAtk] == ITEM_NONE
&& aiData->items[battlerDef] != ITEM_NONE
&& CanBattlerGetOrLoseItem(battlerDef, aiData->items[battlerDef])
&& CanBattlerGetOrLoseItem(battlerAtk, aiData->items[battlerDef])
&& !HasMoveEffect(battlerAtk, EFFECT_ACROBATICS)
&& aiData->abilities[battlerDef] != ABILITY_STICKY_HOLD)
{
switch (aiData->holdEffects[battlerDef])
{
case HOLD_EFFECT_NONE:
break;
case HOLD_EFFECT_CHOICE_BAND:
case HOLD_EFFECT_CHOICE_SCARF:
case HOLD_EFFECT_CHOICE_SPECS:
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_TOXIC_ORB:
if (ShouldPoisonSelf(battlerAtk, aiData->abilities[battlerAtk]))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_FLAME_ORB:
if (ShouldBurnSelf(battlerAtk, aiData->abilities[battlerAtk]))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_BLACK_SLUDGE:
if (IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_IRON_BALL:
if (HasMoveEffect(battlerAtk, EFFECT_FLING))
ADJUST_SCORE(2);
break;
case HOLD_EFFECT_LAGGING_TAIL:
case HOLD_EFFECT_STICKY_BARB:
break;
default:
ADJUST_SCORE(1);
break;
}
}
break;
}
break;
case MOVE_EFFECT_STEALTH_ROCK:
case MOVE_EFFECT_SPIKES:
score += AI_ShouldSetUpHazards(battlerAtk, battlerDef, aiData);
break;
case MOVE_EFFECT_FEINT:
if (gBattleMoves[predictedMove].effect == EFFECT_PROTECT)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_THROAT_CHOP:
if (HasSoundMove(battlerDef) && gBattleMoves[predictedMove].soundMove && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_FASTER)
ADJUST_SCORE(3);
break;
case MOVE_EFFECT_FLAME_BURST:
if (isDoubleBattle)
{
if (IsBattlerAlive(BATTLE_PARTNER(battlerDef))
&& aiData->hpPercents[BATTLE_PARTNER(battlerDef)] < 12
&& aiData->abilities[BATTLE_PARTNER(battlerDef)] != ABILITY_MAGIC_GUARD
&& !IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerDef), TYPE_FIRE))
ADJUST_SCORE(1);
}
break;
case MOVE_EFFECT_WRAP:
if (!HasMoveWithMoveEffect(battlerDef, MOVE_EFFECT_RAPIDSPIN) && !IsBattlerTrapped(battlerDef, TRUE) && ShouldTrap(battlerAtk, battlerDef, move))
ADJUST_SCORE(5);
break;
}
}
}
return score;
}
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle)
{
if (isDoubleBattle)
return min(CountPositiveStatStages(battlerDef) + CountPositiveStatStages(BATTLE_PARTNER(battlerDef)), 7);
else
return min(CountPositiveStatStages(battlerDef), 4);
}
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef)
{
u8 i;
// Want to copy positive stat changes
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
{
switch (i)
{
case STAT_ATK:
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_PHYSICAL));
case STAT_SPATK:
return (HasMoveWithCategory(battlerAtk, BATTLE_CATEGORY_SPECIAL));
case STAT_ACC:
case STAT_EVASION:
case STAT_SPEED:
return TRUE;
case STAT_DEF:
case STAT_SPDEF:
return (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_STALL);
}
}
}
return FALSE;
}
//TODO - track entire opponent party data to determine hazard effectiveness
s32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData *aiData)
{
if (aiData->abilities[battlerDef] == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
return 0;
return 2 * gDisableStructs[battlerAtk].isFirstTurn;
}

View File

@ -4041,11 +4041,10 @@ static bool32 IsDomePopularMove(u32 move)
}
}
static bool32 IsDomeStatusMoveEffect(u32 effect)
static bool32 IsDomeStatusMoveEffect(u32 move)
{
switch(effect)
switch(gBattleMoves[move].effect)
{
case EFFECT_TRAP:
case EFFECT_SLEEP:
case EFFECT_CONFUSE:
case EFFECT_DISABLE:
@ -4063,7 +4062,7 @@ static bool32 IsDomeStatusMoveEffect(u32 effect)
case EFFECT_CURSE:
return TRUE;
default:
return FALSE;
return MoveHasMoveEffect(move, MOVE_EFFECT_WRAP);
}
}
@ -4366,7 +4365,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId)
allocatedArray[k] = IsDomeRiskyMoveEffect(gBattleMoves[move].effect) ? 1 : 0;
break;
case MOVE_POINTS_STATUS:
allocatedArray[k] = IsDomeStatusMoveEffect(gBattleMoves[move].effect) ? 1 : 0;
allocatedArray[k] = IsDomeStatusMoveEffect(move);
break;
case MOVE_POINTS_DMG:
allocatedArray[k] = (gBattleMoves[move].power != 0) ? 1 : 0;
@ -4393,7 +4392,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId)
allocatedArray[k] = (gBattleMoves[move].pp <= 5) ? 1 : 0;
break;
case MOVE_POINTS_EFFECT:
allocatedArray[k] = (gBattleMoves[move].secondaryEffectChance > 0) ? 1 : 0;
allocatedArray[k] = gBattleMoves[move].sheerForceBoost;
break;
}
}

View File

@ -436,11 +436,10 @@ static u8 GetMaxPowerTier(u16 move)
case EFFECT_TERRAIN_PULSE:
case EFFECT_PUNISHMENT:
case EFFECT_TRUMP_CARD:
case EFFECT_SONICBOOM:
case EFFECT_FIXED_DAMAGE_ARG:
case EFFECT_SPIT_UP:
case EFFECT_NATURAL_GIFT:
case EFFECT_MIRROR_COAT:
case EFFECT_DRAGON_RAGE:
case EFFECT_FINAL_GAMBIT:
//case EFFECT_DRAGON_DARTS:
return MAX_POWER_TIER_2;

View File

@ -835,6 +835,8 @@ static const u8 sText_SwampEnvelopedSide[] = _("A swamp enveloped\n{B_DEF_TEAM2}
static const u8 sText_TheSwampDisappeared[] = _("The swamp around {B_ATK_TEAM2}\nteam disappeared!");
static const u8 sText_HospitalityRestoration[] = _("The {B_ATK_PARTNER_NAME} drank down all\nthe matcha that Sinistcha made!");
static const u8 sText_ElectroShockCharging[] = _("{B_ATK_NAME_WITH_PREFIX} absorbed\nelectricity!");
static const u8 sText_ItemWasUsedUp[] = _("The {B_LAST_ITEM}\nwas used up...");
static const u8 sText_AttackerLostItsType[] = _("{B_ATK_NAME_WITH_PREFIX} lost\nits {B_BUFF1} type!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
@ -1525,6 +1527,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_ULTRABURSTCOMPLETED - BATTLESTRINGS_TABLE_START] = sText_UltraBurstCompleted,
[STRINGID_TEAMGAINEDEXP - BATTLESTRINGS_TABLE_START] = sText_TeamGainedEXP,
[STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP - BATTLESTRINGS_TABLE_START] = sText_TargetCoveredInStickyCandySyrup,
[STRINGID_ITEMWASUSEDUP - BATTLESTRINGS_TABLE_START] = sText_ItemWasUsedUp,
[STRINGID_ATTACKERLOSTITSTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostItsType,
};
const u16 gTrainerUsedItemStringIds[] =

View File

@ -355,6 +355,8 @@ static bool32 ChangeOrderTargetAfterAttacker(void);
void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler);
static void RemoveAllTerrains(void);
static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate);
static bool8 CanBurnHitThaw(u16 move);
static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent);
static void Cmd_attackcanceler(void);
static void Cmd_accuracycheck(void);
@ -377,7 +379,7 @@ static void Cmd_printselectionstring(void);
static void Cmd_waitmessage(void);
static void Cmd_printfromtable(void);
static void Cmd_printselectionstringfromtable(void);
static void Cmd_seteffectwithchance(void);
static void Cmd_setadditionaleffects(void);
static void Cmd_seteffectprimary(void);
static void Cmd_seteffectsecondary(void);
static void Cmd_clearstatusfromeffect(void);
@ -496,7 +498,7 @@ static void Cmd_setdrainedhp(void);
static void Cmd_statbuffchange(void);
static void Cmd_normalisebuffs(void);
static void Cmd_setbide(void);
static void Cmd_confuseifrepeatingattackends(void);
static void Cmd_unused0x8C(void);
static void Cmd_setmultihitcounter(void);
static void Cmd_initmultihitstring(void);
static void Cmd_forcerandomswitch(void);
@ -584,7 +586,7 @@ static void Cmd_trysetsnatch(void);
static void Cmd_unused2(void);
static void Cmd_switchoutabilities(void);
static void Cmd_jumpifhasnohp(void);
static void Cmd_getsecretpowereffect(void);
static void Cmd_jumpifnotcurrentmoveargtype(void);
static void Cmd_pickup(void);
static void Cmd_unused3(void);
static void Cmd_unused4(void);
@ -636,7 +638,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_waitmessage, //0x12
Cmd_printfromtable, //0x13
Cmd_printselectionstringfromtable, //0x14
Cmd_seteffectwithchance, //0x15
Cmd_setadditionaleffects, //0x15
Cmd_seteffectprimary, //0x16
Cmd_seteffectsecondary, //0x17
Cmd_clearstatusfromeffect, //0x18
@ -747,7 +749,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_trysetrest, //0x81
Cmd_jumpifnotfirstturn, //0x82
Cmd_setmiracleeye, //0x83
Cmd_jumpifuproarwakes, //0x84
Cmd_jumpifuproarwakes, //0x84
Cmd_stockpile, //0x85
Cmd_stockpiletobasedamage, //0x86
Cmd_stockpiletohpheal, //0x87
@ -755,7 +757,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_statbuffchange, //0x89
Cmd_normalisebuffs, //0x8A
Cmd_setbide, //0x8B
Cmd_confuseifrepeatingattackends, //0x8C
Cmd_unused0x8C, //0x8C
Cmd_setmultihitcounter, //0x8D
Cmd_initmultihitstring, //0x8E
Cmd_forcerandomswitch, //0x8F
@ -843,7 +845,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_unused2, //0xE1
Cmd_switchoutabilities, //0xE2
Cmd_jumpifhasnohp, //0xE3
Cmd_getsecretpowereffect, //0xE4
Cmd_jumpifnotcurrentmoveargtype, //0xE4
Cmd_pickup, //0xE5
Cmd_unused3, //0xE6
Cmd_unused4, //0xE7
@ -971,20 +973,14 @@ static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX /
static const u16 sFinalStrikeOnlyEffects[] =
{
EFFECT_RELIC_SONG,
EFFECT_BUG_BITE,
EFFECT_THIEF,
EFFECT_BURN_UP,
EFFECT_DOUBLE_SHOCK,
EFFECT_SECRET_POWER,
EFFECT_SMACK_DOWN,
EFFECT_SPARKLING_ARIA,
EFFECT_SMELLING_SALTS,
EFFECT_WAKE_UP_SLAP,
EFFECT_HIT_ESCAPE,
EFFECT_RECOIL_HP_25,
EFFECT_HIT_PREVENT_ESCAPE,
EFFECT_HIT_SWITCH_TARGET,
MOVE_EFFECT_BUG_BITE,
MOVE_EFFECT_STEAL_ITEM,
MOVE_EFFECT_REMOVE_ARG_TYPE,
MOVE_EFFECT_SMACK_DOWN,
MOVE_EFFECT_REMOVE_STATUS,
MOVE_EFFECT_RECOIL_HP_25,
MOVE_EFFECT_PREVENT_ESCAPE,
MOVE_EFFECT_WRAP,
};
static const u16 sNaturePowerMoves[BATTLE_TERRAIN_COUNT] =
@ -1604,12 +1600,6 @@ static bool32 AccuracyCalcHelper(u16 move)
}
}
if (gBattleMoves[move].effect == EFFECT_VITAL_THROW)
{
JumpIfMoveFailed(7, move);
return TRUE;
}
if (B_MINIMIZE_DMG_ACC >= GEN_6
&& (gStatuses3[gBattlerTarget] & STATUS3_MINIMIZED)
&& gBattleMoves[move].minimizeDoubleDamage)
@ -1843,6 +1833,9 @@ static void Cmd_ppreduce(void)
if (gBattleControllerExecFlags)
return;
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
if (moveTarget == MOVE_TARGET_BOTH
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY
|| moveTarget == MOVE_TARGET_ALL_BATTLERS
@ -2760,7 +2753,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem)
return; \
}
void SetMoveEffect(bool32 primary, u32 certain)
void SetMoveEffect(bool32 primary, bool32 certain)
{
s32 i, affectsUser = 0;
bool32 statusChanged = FALSE;
@ -2771,7 +2764,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT
&& gBattleMons[gBattlerTarget].hp != 0
&& IsFinalStrikeEffect(gCurrentMove))
&& IsFinalStrikeEffect(gBattleScripting.moveEffect))
{
gBattlescriptCurrInstr++;
return;
@ -2830,7 +2823,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
&& !primary && gBattleScripting.moveEffect <= MOVE_EFFECT_CONFUSION)
INCREMENT_RESET_RETURN
if (TestSheerForceFlag(gBattlerAttacker, gCurrentMove) && gBattleScripting.moveEffect != MOVE_EFFECT_CHARGING)
if (TestSheerForceFlag(gBattlerAttacker, gCurrentMove) && !primary && gBattleScripting.moveEffect != MOVE_EFFECT_CHARGING)
INCREMENT_RESET_RETURN
if (gBattleMons[gEffectBattler].hp == 0 && !activateAfterFaint)
@ -2868,7 +2861,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
case STATUS1_POISON:
if ((battlerAbility == ABILITY_IMMUNITY || battlerAbility == ABILITY_PASTEL_VEIL)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
gLastUsedAbility = battlerAbility;
RecordAbilityBattle(gEffectBattler, battlerAbility);
@ -2889,7 +2882,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (!CanPoisonType(gBattleScripting.battler, gEffectBattler)
&& (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
@ -2903,11 +2896,8 @@ void SetMoveEffect(bool32 primary, u32 certain)
statusChanged = TRUE;
break;
case STATUS1_BURN:
if (gCurrentMove == MOVE_BURNING_JEALOUSY && !gProtectStructs[gEffectBattler].statRaised)
break;
if ((battlerAbility == ABILITY_WATER_VEIL || battlerAbility == ABILITY_WATER_BUBBLE)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
gLastUsedAbility = battlerAbility;
RecordAbilityBattle(gEffectBattler, battlerAbility);
@ -2927,7 +2917,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE)
&& (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_BRNPrevention;
@ -2940,7 +2930,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
u8 moveType = 0;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (primary == FALSE && certain != MOVE_EFFECT_CERTAIN && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
break;
}
@ -2954,7 +2944,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
u8 moveType = 0;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (primary == FALSE && certain != MOVE_EFFECT_CERTAIN && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
break;
}
if (!CanBeFrozen(gEffectBattler))
@ -2968,7 +2958,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
case STATUS1_PARALYSIS:
if (battlerAbility == ABILITY_LIMBER)
{
if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
if (primary == TRUE || certain == TRUE)
{
gLastUsedAbility = ABILITY_LIMBER;
RecordAbilityBattle(gEffectBattler, ABILITY_LIMBER);
@ -2994,12 +2984,12 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
u8 moveType = 0;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (primary == FALSE && certain != MOVE_EFFECT_CERTAIN && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
break;
}
if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler)
&& (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PRLZPrevention;
@ -3016,7 +3006,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
case STATUS1_TOXIC_POISON:
if ((battlerAbility == ABILITY_IMMUNITY || battlerAbility == ABILITY_PASTEL_VEIL)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
gLastUsedAbility = battlerAbility;
RecordAbilityBattle(gEffectBattler, battlerAbility);
@ -3037,7 +3027,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (!CanPoisonType(gBattleScripting.battler, gEffectBattler)
&& (gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
&& (primary == TRUE || certain == TRUE))
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_PSNPrevention;
@ -3065,7 +3055,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
u8 moveType = 0;
GET_MOVE_TYPE(gCurrentMove, moveType);
if (primary == FALSE && certain != MOVE_EFFECT_CERTAIN && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
if (primary == FALSE && certain == FALSE && IS_BATTLER_OF_TYPE(gEffectBattler, moveType))
break;
}
if (!CanGetFrostbite(gEffectBattler))
@ -3137,9 +3127,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
switch (gBattleScripting.moveEffect)
{
case MOVE_EFFECT_CONFUSION:
if (gCurrentMove == MOVE_ALLURING_VOICE && !gProtectStructs[gEffectBattler].statRaised)
break;
if (!CanBeConfused(gEffectBattler))
{
gBattlescriptCurrInstr++;
@ -3166,7 +3153,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
case MOVE_EFFECT_FLINCH:
if (battlerAbility == ABILITY_INNER_FOCUS)
{
if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
// Inner Focus ALWAYS prevents flinching but only activates
// on a move that's supposed to flinch, like Fake Out
if (primary == TRUE || certain == TRUE)
{
gLastUsedAbility = ABILITY_INNER_FOCUS;
gBattlerAbility = gEffectBattler;
@ -3208,8 +3197,15 @@ void SetMoveEffect(bool32 primary, u32 certain)
if (payday > gPaydayMoney)
gPaydayMoney = 0xFFFF;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectPayDay;
// For a move that hits multiple targets (i.e. Make it Rain)
// we only want to print the message on the final hit
if (GetNextTarget(gBattleMoves[gCurrentMove].target, TRUE) == MAX_BATTLERS_COUNT)
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectPayDay;
}
else
gBattlescriptCurrInstr++;
}
else
{
@ -3234,11 +3230,11 @@ void SetMoveEffect(bool32 primary, u32 certain)
static const u8 sTriAttackEffects[] =
{
MOVE_EFFECT_BURN,
B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE,
MOVE_EFFECT_FREEZE_OR_FROSTBITE,
MOVE_EFFECT_PARALYSIS
};
gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects);
SetMoveEffect(FALSE, 0);
SetMoveEffect(primary, certain);
}
break;
case MOVE_EFFECT_CHARGING:
@ -3477,7 +3473,8 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
break;
case MOVE_EFFECT_THRASH:
if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE)
// Petal Dance doesn't lock mons that copy the move with Dancer
if (gSpecialStatuses[gEffectBattler].dancerUsedMove)
{
gBattlescriptCurrInstr++;
}
@ -3650,15 +3647,22 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
gBattleMons[gBattlerAttacker].status2 |= STATUS2_ESCAPE_PREVENTION;
break;
case MOVE_EFFECT_BURN_UP:
case MOVE_EFFECT_REMOVE_ARG_TYPE:
// This seems unnecessary but is done to make it work properly with Parental Bond
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_BurnUpRemoveType;
break;
case MOVE_EFFECT_DOUBLE_SHOCK:
// This seems unnecessary but is done to make it work properly with Parental Bond
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_DoubleShockRemoveType;
switch (gBattleMoves[gCurrentMove].argument)
{
case TYPE_FIRE: // Burn Up
gBattlescriptCurrInstr = BattleScript_RemoveFireType;
break;
case TYPE_ELECTRIC: // Double Shot
gBattlescriptCurrInstr = BattleScript_RemoveElectricType;
break;
default:
gBattlescriptCurrInstr = BattleScript_RemoveGenericType;
break;
}
RemoveBattlerType(gEffectBattler, gBattleMoves[gCurrentMove].argument);
break;
case MOVE_EFFECT_ROUND:
TryUpdateRoundTurnOrder(); // If another Pokémon uses Round before the user this turn, the user will use Round directly after it
@ -3669,7 +3673,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP };
gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects);
SetMoveEffect(TRUE, 0);
SetMoveEffect(primary, certain);
}
break;
case MOVE_EFFECT_STEALTH_ROCK:
@ -3691,26 +3695,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
else
gBattlescriptCurrInstr = BattleScript_SpikesActivates;
}
break;
case MOVE_EFFECT_TRIPLE_ARROWS:
{
u8 randomLowerDefenseChance = RandomPercentage(RNG_TRIPLE_ARROWS_DEFENSE_DOWN, CalcSecondaryEffectChance(gBattlerAttacker, 50, EFFECT_DEFENSE_DOWN_HIT));
u8 randomFlinchChance = RandomPercentage(RNG_TRIPLE_ARROWS_FLINCH, CalcSecondaryEffectChance(gBattlerAttacker, 30, EFFECT_FLINCH_HIT));
if (randomFlinchChance && battlerAbility != ABILITY_INNER_FOCUS && GetBattlerTurnOrderNum(gEffectBattler) > gCurrentTurnActionNumber)
gBattleMons[gEffectBattler].status2 |= sStatusFlagsForMoveEffects[MOVE_EFFECT_FLINCH];
if (randomLowerDefenseChance)
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_DefDown;
}
else
{
gBattlescriptCurrInstr++;
}
}
break;
case MOVE_EFFECT_SYRUP_BOMB:
if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB))
@ -3724,6 +3708,89 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattlescriptCurrInstr = BattleScript_SyrupBombActivates;
}
break;
case MOVE_EFFECT_SECRET_POWER:
if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
{
switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
{
case STATUS_FIELD_MISTY_TERRAIN:
gBattleScripting.moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP;
break;
case STATUS_FIELD_ELECTRIC_TERRAIN:
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1;
break;
default:
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
break;
}
}
else
{
switch (gBattleTerrain)
{
case BATTLE_TERRAIN_GRASS:
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON);
break;
case BATTLE_TERRAIN_UNDERWATER:
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1);
break;
case BATTLE_TERRAIN_POND:
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1);
break;
case BATTLE_TERRAIN_MOUNTAIN:
if (B_SECRET_POWER_EFFECT >= GEN_5)
gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1;
else if (B_SECRET_POWER_EFFECT >= GEN_4)
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
else
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION;
break;
case BATTLE_TERRAIN_PUDDLE:
gBattleScripting.moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1);
break;
case BATTLE_TERRAIN_LONG_GRASS:
gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP;
break;
case BATTLE_TERRAIN_SAND:
gBattleScripting.moveEffect = MOVE_EFFECT_ACC_MINUS_1;
break;
case BATTLE_TERRAIN_WATER:
gBattleScripting.moveEffect = MOVE_EFFECT_ATK_MINUS_1;
break;
case BATTLE_TERRAIN_CAVE:
case BATTLE_TERRAIN_BURIAL_GROUND:
case BATTLE_TERRAIN_SPACE:
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
break;
case BATTLE_TERRAIN_SOARING:
case BATTLE_TERRAIN_SKY_PILLAR:
case BATTLE_TERRAIN_MARSH:
case BATTLE_TERRAIN_SWAMP:
gBattleScripting.moveEffect = MOVE_EFFECT_SPD_MINUS_1;
break;
case BATTLE_TERRAIN_SNOW:
case BATTLE_TERRAIN_ICE:
gBattleScripting.moveEffect = MOVE_EFFECT_FREEZE_OR_FROSTBITE;
break;
case BATTLE_TERRAIN_VOLCANO:
gBattleScripting.moveEffect = MOVE_EFFECT_BURN;
break;
case BATTLE_TERRAIN_ULTRA_SPACE:
gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_1;
break;
default:
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
break;
}
}
SetMoveEffect(primary, certain);
break;
}
}
}
@ -3731,36 +3798,63 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattleScripting.moveEffect = 0;
}
static void Cmd_seteffectwithchance(void)
static void Cmd_setadditionaleffects(void)
{
CMD_ARGS();
u32 percentChance = CalcSecondaryEffectChance(gBattlerAttacker, gBattleMoves[gCurrentMove].secondaryEffectChance, gBattleMoves[gCurrentMove].effect);
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleScripting.moveEffect)
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
{
if (gBattleScripting.moveEffect & MOVE_EFFECT_CERTAIN
|| percentChance >= 100)
if (gBattleMoves[gCurrentMove].numAdditionalEffects > gBattleStruct->additionalEffectsCounter)
{
gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN;
SetMoveEffect(FALSE, MOVE_EFFECT_CERTAIN);
}
else if (RandomPercentage(RNG_SECONDARY_EFFECT, percentChance))
{
SetMoveEffect(FALSE, 0);
u32 percentChance;
const u8 *currentPtr = gBattlescriptCurrInstr;
const struct AdditionalEffect *additionalEffect = &gBattleMoves[gCurrentMove].additionalEffects[gBattleStruct->additionalEffectsCounter];
// Check additional effect flags
// self-targeting move effects cannot occur multiple times per turn
// only occur on the last setmoveeffect when there are multiple targets
if (!(gBattleMoves[gCurrentMove].additionalEffects[gBattleStruct->additionalEffectsCounter].self
&& GetNextTarget(gBattleMoves[gCurrentMove].target, TRUE) != MAX_BATTLERS_COUNT)
&& !(additionalEffect->onlyIfTargetRaisedStats && !gProtectStructs[gBattlerTarget].statRaised)
&& additionalEffect->onChargeTurnOnly == gProtectStructs[gBattlerAttacker].chargingTurn)
{
percentChance = CalcSecondaryEffectChance(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), additionalEffect);
// Activate effect if it's primary (chance == 0) or if RNGesus says so
if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance))
{
gBattleScripting.moveEffect = additionalEffect->moveEffect | (MOVE_EFFECT_AFFECTS_USER * (additionalEffect->self));
SetMoveEffect(
percentChance == 0, // a primary effect
percentChance >= 100 // certain to happen
);
}
}
// Move script along if we haven't jumped elsewhere
if (gBattlescriptCurrInstr == currentPtr)
gBattlescriptCurrInstr = cmd->nextInstr;
// Call setadditionaleffects again in the case of a move with multiple effects
gBattleStruct->additionalEffectsCounter++;
if (gBattleMoves[gCurrentMove].numAdditionalEffects > gBattleStruct->additionalEffectsCounter)
gBattleScripting.moveEffect = MOVE_EFFECT_CONTINUE;
else
gBattleScripting.moveEffect = gBattleStruct->additionalEffectsCounter = 0;
}
else
{
gBattleScripting.moveEffect = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
else
{
gBattleScripting.moveEffect = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
}
gBattleScripting.moveEffect = 0;
gBattleScripting.multihitMoveEffect = 0;
}
@ -3768,14 +3862,14 @@ static void Cmd_seteffectprimary(void)
{
CMD_ARGS();
SetMoveEffect(TRUE, 0);
SetMoveEffect(TRUE, FALSE);
}
static void Cmd_seteffectsecondary(void)
{
CMD_ARGS();
SetMoveEffect(FALSE, 0);
SetMoveEffect(FALSE, FALSE);
}
static void Cmd_clearstatusfromeffect(void)
@ -3787,7 +3881,11 @@ static void Cmd_clearstatusfromeffect(void)
if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT)
gBattleMons[battler].status1 &= (~sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]);
else
{
gBattleMons[battler].status2 &= (~sStatusFlagsForMoveEffects[gBattleScripting.moveEffect]);
if (gBattleScripting.moveEffect == MOVE_EFFECT_CHARGING)
gProtectStructs[battler].chargingTurn = FALSE;
}
gBattleScripting.moveEffect = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
@ -5229,12 +5327,13 @@ static bool32 TryKnockOffBattleScript(u32 battlerDef)
&& gBattleMons[battler].hp != 0 \
&& gBattleMons[ally].hp != 0
static u32 GetNextTarget(u32 moveTarget)
static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent)
{
u32 i;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (i != gBattlerAttacker
&& !(excludeCurrent && i == gBattlerTarget)
&& IsBattlerAlive(i)
&& !(gBattleStruct->targetsDone[gBattlerAttacker] & gBitTable[i])
&& (GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY))
@ -5380,8 +5479,7 @@ static void Cmd_moveend(void)
if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE
&& gBattleMons[gBattlerTarget].hp != 0
&& gBattlerAttacker != gBattlerTarget
&& (moveType == TYPE_FIRE
|| (B_BURN_HIT_THAW >= GEN_6 && gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT))
&& (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove))
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
{
gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE;
@ -5412,17 +5510,12 @@ static void Cmd_moveend(void)
&& IsBattlerAlive(gBattlerAttacker)
&& gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one
{
switch (gBattleMoves[gCurrentMove].effect)
if (gBattleMoves[gCurrentMove].recoil > 0)
{
case EFFECT_RECOIL:
gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gBattleMoves[gCurrentMove].recoil) / 100);
BattleScriptPushCursor();
if (gBattleMoves[gCurrentMove].argument) // Flare Blitz - can burn, Volt Tackle - can paralyze
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus;
else
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
effect = TRUE;
break;
}
}
gBattleScripting.moveendState++;
@ -5783,7 +5876,7 @@ static void Cmd_moveend(void)
|| moveTarget == MOVE_TARGET_FOES_AND_ALLY)
&& !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
{
u32 nextTarget = GetNextTarget(moveTarget);
u32 nextTarget = GetNextTarget(moveTarget, FALSE);
gHitMarker |= HITMARKER_NO_PPDEDUCT;
if (nextTarget != MAX_BATTLERS_COUNT)
@ -5804,7 +5897,7 @@ static void Cmd_moveend(void)
gBattleStruct->targetsDone[gBattlerAttacker] |= gBitTable[originalBounceTarget];
gBattleStruct->targetsDone[originalBounceTarget] = 0;
nextTarget = GetNextTarget(moveTarget);
nextTarget = GetNextTarget(moveTarget, FALSE);
if (nextTarget != MAX_BATTLERS_COUNT)
{
// We found another target for the original move user.
@ -6114,7 +6207,7 @@ static void Cmd_moveend(void)
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
if (B_RAMPAGE_CANCELLING >= GEN_5
&& gBattleMoves[gCurrentMove].effect == EFFECT_RAMPAGE // If we're rampaging
&& MoveHasMoveEffectSelf(gCurrentMove, MOVE_EFFECT_THRASH) // If we're rampaging
&& (gMoveResultFlags & MOVE_RESULT_NO_EFFECT) // And it is unusable
&& (gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE) != STATUS2_LOCK_CONFUSE_TURN(1)) // And won't end this turn
CancelMultiTurnMoves(gBattlerAttacker); // Cancel it
@ -6138,6 +6231,7 @@ static void Cmd_moveend(void)
gBattleStruct->isAtkCancelerForCalledMove = FALSE;
gBattleStruct->swapDamageCategory = FALSE;
gBattleStruct->enduredDamage = 0;
gBattleStruct->additionalEffectsCounter = 0;
gBattleScripting.moveendState++;
break;
case MOVEEND_COUNT:
@ -9496,42 +9590,10 @@ static void Cmd_various(void)
gBattlescriptCurrInstr = cmd->failInstr;
return;
}
case VARIOUS_ARGUMENT_STATUS_EFFECT:
case VARIOUS_SET_ARG_TO_BATTLE_DAMAGE:
{
VARIOUS_ARGS();
switch (gBattleMoves[gCurrentMove].argument)
{
case STATUS1_SLEEP:
gBattleScripting.moveEffect = MOVE_EFFECT_SLEEP;
break;
case STATUS1_BURN:
gBattleScripting.moveEffect = MOVE_EFFECT_BURN;
break;
case STATUS1_FREEZE:
gBattleScripting.moveEffect = MOVE_EFFECT_FREEZE;
break;
case STATUS1_PARALYSIS:
gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS;
break;
case STATUS1_POISON:
gBattleScripting.moveEffect = MOVE_EFFECT_POISON;
break;
case STATUS1_TOXIC_POISON:
gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC;
break;
case STATUS1_FROSTBITE:
gBattleScripting.moveEffect = MOVE_EFFECT_FROSTBITE;
break;
default:
gBattleScripting.moveEffect = 0;
break;
}
if (gBattleScripting.moveEffect != 0)
{
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_EffectWithChance;
return;
}
gBattleMoveDamage = gBattleMoves[gCurrentMove].argument;
break;
}
case VARIOUS_TRY_HIT_SWITCH_TARGET:
@ -9570,7 +9632,7 @@ static void Cmd_various(void)
{
VARIOUS_ARGS(const u8 *failInstr);
u16 move = gLastPrintedMoves[gBattlerTarget];
if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || gBattleMoves[move].effect == EFFECT_RECHARGE
if (move == MOVE_NONE || move == MOVE_UNAVAILABLE || MoveHasMoveEffectSelf(move, MOVE_EFFECT_RECHARGE)
|| gBattleMoves[move].instructBanned || gBattleMoves[move].twoTurnMove || IsDynamaxed(gBattlerTarget))
{
gBattlescriptCurrInstr = cmd->failInstr;
@ -9634,11 +9696,7 @@ static void Cmd_various(void)
case VARIOUS_LOSE_TYPE:
{
VARIOUS_ARGS(u8 type);
for (i = 0; i < 3; i++)
{
if (*(u8 *)(&gBattleMons[battler].type1 + i) == cmd->type)
*(u8 *)(&gBattleMons[battler].type1 + i) = TYPE_MYSTERY;
}
RemoveBattlerType(battler, cmd->type);
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
@ -9717,12 +9775,6 @@ static void Cmd_various(void)
}
return;
}
case VARIOUS_ARGUMENT_TO_MOVE_EFFECT:
{
VARIOUS_ARGS();
gBattleScripting.moveEffect = gBattleMoves[gCurrentMove].argument;
break;
}
case VARIOUS_JUMP_IF_NOT_GROUNDED:
{
VARIOUS_ARGS(const u8 *jumpInstr);
@ -11626,14 +11678,8 @@ static void Cmd_setbide(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_confuseifrepeatingattackends(void)
static void Cmd_unused0x8C(void)
{
CMD_ARGS();
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_LOCK_CONFUSE) && !gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
gBattleScripting.moveEffect = (MOVE_EFFECT_THRASH | MOVE_EFFECT_AFFECTS_USER);
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_setmultihitcounter(void)
@ -14368,99 +14414,17 @@ static void Cmd_jumpifhasnohp(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_getsecretpowereffect(void)
static void Cmd_jumpifnotcurrentmoveargtype(void)
{
CMD_ARGS();
CMD_ARGS(u8 battler, const u8 *failInstr);
gBattleScripting.moveEffect = GetSecretPowerMoveEffect();
gBattlescriptCurrInstr = cmd->nextInstr;
}
u8 battler = GetBattlerForBattleScript(cmd->battler);
const u8 *failInstr = cmd->failInstr;
u16 GetSecretPowerMoveEffect(void)
{
u16 moveEffect;
u32 fieldTerrain = gFieldStatuses & STATUS_FIELD_TERRAIN_ANY;
if (fieldTerrain)
{
switch (fieldTerrain)
{
case STATUS_FIELD_MISTY_TERRAIN:
moveEffect = MOVE_EFFECT_SP_ATK_MINUS_1;
break;
case STATUS_FIELD_GRASSY_TERRAIN:
moveEffect = MOVE_EFFECT_SLEEP;
break;
case STATUS_FIELD_ELECTRIC_TERRAIN:
moveEffect = MOVE_EFFECT_PARALYSIS;
break;
case STATUS_FIELD_PSYCHIC_TERRAIN:
moveEffect = MOVE_EFFECT_SPD_MINUS_1;
break;
default:
moveEffect = MOVE_EFFECT_PARALYSIS;
break;
}
}
if (!IS_BATTLER_OF_TYPE(battler, gBattleMoves[gCurrentMove].argument))
gBattlescriptCurrInstr = failInstr;
else
{
switch (gBattleTerrain)
{
case BATTLE_TERRAIN_GRASS:
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_SLEEP : MOVE_EFFECT_POISON);
break;
case BATTLE_TERRAIN_UNDERWATER:
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_6 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_DEF_MINUS_1);
break;
case BATTLE_TERRAIN_POND:
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_4 ? MOVE_EFFECT_ATK_MINUS_1 : MOVE_EFFECT_SPD_MINUS_1);
break;
case BATTLE_TERRAIN_MOUNTAIN:
if (B_SECRET_POWER_EFFECT >= GEN_5)
moveEffect = MOVE_EFFECT_ACC_MINUS_1;
else if (B_SECRET_POWER_EFFECT >= GEN_4)
moveEffect = MOVE_EFFECT_FLINCH;
else
moveEffect = MOVE_EFFECT_CONFUSION;
break;
case BATTLE_TERRAIN_PUDDLE:
moveEffect = (B_SECRET_POWER_EFFECT >= GEN_5 ? MOVE_EFFECT_SPD_MINUS_1 : MOVE_EFFECT_ACC_MINUS_1);
break;
case BATTLE_TERRAIN_LONG_GRASS:
moveEffect = MOVE_EFFECT_SLEEP;
break;
case BATTLE_TERRAIN_SAND:
moveEffect = MOVE_EFFECT_ACC_MINUS_1;
break;
case BATTLE_TERRAIN_WATER:
moveEffect = MOVE_EFFECT_ATK_MINUS_1;
break;
case BATTLE_TERRAIN_CAVE:
case BATTLE_TERRAIN_BURIAL_GROUND:
case BATTLE_TERRAIN_SPACE:
moveEffect = MOVE_EFFECT_FLINCH;
break;
case BATTLE_TERRAIN_SOARING:
case BATTLE_TERRAIN_SKY_PILLAR:
case BATTLE_TERRAIN_MARSH:
case BATTLE_TERRAIN_SWAMP:
moveEffect = MOVE_EFFECT_SPD_MINUS_1;
break;
case BATTLE_TERRAIN_SNOW:
case BATTLE_TERRAIN_ICE:
moveEffect = (B_USE_FROSTBITE == TRUE ? MOVE_EFFECT_FROSTBITE : MOVE_EFFECT_FREEZE);
break;
case BATTLE_TERRAIN_VOLCANO:
moveEffect = MOVE_EFFECT_BURN;
break;
case BATTLE_TERRAIN_ULTRA_SPACE:
moveEffect = MOVE_EFFECT_DEF_MINUS_1;
break;
default:
moveEffect = MOVE_EFFECT_PARALYSIS;
break;
}
}
return moveEffect;
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void Cmd_pickup(void)
@ -15713,6 +15677,21 @@ static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 byIntimidate)
return FALSE;
}
static bool8 CanBurnHitThaw(u16 move)
{
u8 i;
if (B_BURN_HIT_THAW >= GEN_6)
{
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
if (gBattleMoves[move].additionalEffects[i].moveEffect == MOVE_EFFECT_BURN)
return TRUE;
}
}
return FALSE;
}
void BS_CheckParentalBondCounter(void)
{
NATIVE_ARGS(u8 counter, const u8 *jumpInstr);

View File

@ -88,11 +88,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
{
[EFFECT_HIT] = 1,
[EFFECT_SLEEP] = 1,
[EFFECT_POISON_HIT] = 1,
[EFFECT_ABSORB] = 4,
[EFFECT_BURN_HIT] = 1,
[EFFECT_FREEZE_HIT] = 1,
[EFFECT_PARALYZE_HIT] = 1,
[EFFECT_EXPLOSION] = 0,
[EFFECT_DREAM_EATER] = 5,
[EFFECT_MIRROR_MOVE] = 1,
@ -113,28 +109,21 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_EVASION_DOWN] = 1,
[EFFECT_HAZE] = 5,
[EFFECT_BIDE] = 5,
[EFFECT_RAMPAGE] = 4,
[EFFECT_ROAR] = 5,
[EFFECT_MULTI_HIT] = 1,
[EFFECT_CONVERSION] = 3,
[EFFECT_FLINCH_HIT] = 1,
[EFFECT_RESTORE_HP] = 3,
[EFFECT_TOXIC] = 5,
[EFFECT_PAY_DAY] = 1,
[EFFECT_LIGHT_SCREEN] = 7,
[EFFECT_TRI_ATTACK] = 1,
[EFFECT_REST] = 7,
[EFFECT_OHKO] = 7,
// [EFFECT_RAZOR_WIND] = 1,
[EFFECT_SUPER_FANG] = 5,
[EFFECT_DRAGON_RAGE] = 2,
[EFFECT_TRAP] = 4,
// [EFFECT_HIGH_CRITICAL] = 1,
// [EFFECT_DOUBLE_HIT] = 1,
[EFFECT_RECOIL_IF_MISS] = 1,
[EFFECT_MIST] = 5,
[EFFECT_FOCUS_ENERGY] = 1,
[EFFECT_RECOIL] = 2,
[EFFECT_CONFUSE] = 4,
[EFFECT_ATTACK_UP_2] = 1,
[EFFECT_DEFENSE_UP_2] = 1,
@ -154,19 +143,9 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_REFLECT] = 7,
[EFFECT_POISON] = 4,
[EFFECT_PARALYZE] = 4,
[EFFECT_ATTACK_DOWN_HIT] = 1,
[EFFECT_DEFENSE_DOWN_HIT] = 1,
[EFFECT_SPEED_DOWN_HIT] = 1,
[EFFECT_SPECIAL_ATTACK_DOWN_HIT] = 1,
[EFFECT_SPECIAL_DEFENSE_DOWN_HIT] = 1,
[EFFECT_ACCURACY_DOWN_HIT] = 1,
[EFFECT_EVASION_DOWN_HIT] = 1,
// [EFFECT_SKY_ATTACK] = 4,
[EFFECT_CONFUSE_HIT] = 1,
// [EFFECT_TWINEEDLE] = 1,
[EFFECT_VITAL_THROW] = 1,
[EFFECT_SUBSTITUTE] = 4,
[EFFECT_RECHARGE] = 5,
[EFFECT_RAGE] = 2,
[EFFECT_MIMIC] = 4,
[EFFECT_METRONOME] = 1,
@ -190,7 +169,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_HEAL_BELL] = 5,
// [EFFECT_QUICK_ATTACK] = 1,
[EFFECT_TRIPLE_KICK] = 1,
[EFFECT_THIEF] = 4,
[EFFECT_MEAN_LOOK] = 5,
[EFFECT_NIGHTMARE] = 3,
[EFFECT_MINIMIZE] = 1,
@ -209,21 +187,16 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_PRESENT] = 1,
[EFFECT_FRUSTRATION] = 1,
[EFFECT_SAFEGUARD] = 5,
// [EFFECT_THAW_HIT] = 1, Now unused
[EFFECT_MAGNITUDE] = 1,
[EFFECT_BATON_PASS] = 7,
[EFFECT_PURSUIT] = 2,
[EFFECT_RAPID_SPIN] = 2,
[EFFECT_SONICBOOM] = 1,
[EFFECT_FIXED_DAMAGE_ARG] = 1,
[EFFECT_MORNING_SUN] = 4,
[EFFECT_SYNTHESIS] = 4,
[EFFECT_MOONLIGHT] = 4,
[EFFECT_HIDDEN_POWER] = 1,
[EFFECT_RAIN_DANCE] = 4,
[EFFECT_SUNNY_DAY] = 4,
[EFFECT_DEFENSE_UP_HIT] = 1,
[EFFECT_ATTACK_UP_HIT] = 1,
[EFFECT_ALL_STATS_UP_HIT] = 1,
[EFFECT_BELLY_DRUM] = 7,
[EFFECT_PSYCH_UP] = 7,
[EFFECT_MIRROR_COAT] = 6,
@ -253,7 +226,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_MEMENTO] = 7,
[EFFECT_FACADE] = 1,
[EFFECT_FOCUS_PUNCH] = 7,
[EFFECT_SMELLING_SALTS] = 1,
[EFFECT_DOUBLE_POWER_ON_ARG_STATUS] = 1,
[EFFECT_FOLLOW_ME] = 5,
[EFFECT_NATURE_POWER] = 0,
[EFFECT_CHARGE] = 4,
@ -264,7 +237,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_WISH] = 2,
[EFFECT_ASSIST] = 2,
[EFFECT_INGRAIN] = 6,
[EFFECT_SUPERPOWER] = 3,
[EFFECT_MAGIC_COAT] = 6,
[EFFECT_RECYCLE] = 4,
[EFFECT_REVENGE] = 4,
@ -279,13 +251,10 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_GRUDGE] = 1,
[EFFECT_SNATCH] = 1,
[EFFECT_LOW_KICK] = 1,
[EFFECT_SECRET_POWER] = 1,
[EFFECT_TEETER_DANCE] = 6,
// [EFFECT_BLAZE_KICK] = 1,
[EFFECT_MUD_SPORT] = 4,
[EFFECT_POISON_FANG] = 1,
[EFFECT_WEATHER_BALL] = 1,
[EFFECT_OVERHEAT] = 3,
[EFFECT_TICKLE] = 1,
[EFFECT_COSMIC_POWER] = 1,
[EFFECT_SKY_UPPERCUT] = 1,
@ -298,9 +267,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_PLEDGE] = 0, // TODO: Assign points
[EFFECT_FLING] = 0, // TODO: Assign points
[EFFECT_NATURAL_GIFT] = 0, // TODO: Assign points
[EFFECT_WAKE_UP_SLAP] = 0, // TODO: Assign points
[EFFECT_WRING_OUT] = 0, // TODO: Assign points
[EFFECT_HEX] = 0, // TODO: Assign points
[EFFECT_ASSURANCE] = 0, // TODO: Assign points
[EFFECT_TRUMP_CARD] = 0, // TODO: Assign points
[EFFECT_ACROBATICS] = 0, // TODO: Assign points
@ -313,7 +280,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_PAYBACK] = 0, // TODO: Assign points
[EFFECT_ROUND] = 0, // TODO: Assign points
[EFFECT_BRINE] = 0, // TODO: Assign points
[EFFECT_VENOSHOCK] = 0, // TODO: Assign points
[EFFECT_RETALIATE] = 0, // TODO: Assign points
[EFFECT_BULLDOZE] = 0, // TODO: Assign points
[EFFECT_FOUL_PLAY] = 0, // TODO: Assign points
@ -341,7 +307,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_METAL_BURST] = 0, // TODO: Assign points
[EFFECT_LUCKY_CHANT] = 0, // TODO: Assign points
[EFFECT_SUCKER_PUNCH] = 0, // TODO: Assign points
[EFFECT_SPECIAL_DEFENSE_DOWN_HIT_2] = 0, // TODO: Assign points
[EFFECT_SIMPLE_BEAM] = 0, // TODO: Assign points
[EFFECT_ENTRAINMENT] = 0, // TODO: Assign points
[EFFECT_HEAL_PULSE] = 0, // TODO: Assign points
@ -358,23 +323,19 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_HURRICANE] = 0, // TODO: Assign points
[EFFECT_TWO_TYPED_MOVE] = 0, // TODO: Assign points
[EFFECT_ME_FIRST] = 0, // TODO: Assign points
[EFFECT_SPEED_UP_HIT] = 0, // TODO: Assign points
[EFFECT_QUIVER_DANCE] = 0, // TODO: Assign points
[EFFECT_COIL] = 0, // TODO: Assign points
[EFFECT_ELECTRIFY] = 0, // TODO: Assign points
[EFFECT_REFLECT_TYPE] = 0, // TODO: Assign points
[EFFECT_SOAK] = 0, // TODO: Assign points
[EFFECT_GROWTH] = 0, // TODO: Assign points
[EFFECT_CLOSE_COMBAT] = 0, // TODO: Assign points
[EFFECT_LAST_RESORT] = 0, // TODO: Assign points
[EFFECT_FLINCH_STATUS] = 0, // TODO: Assign points
[EFFECT_SHELL_SMASH] = 0, // TODO: Assign points
[EFFECT_SHIFT_GEAR] = 0, // TODO: Assign points
[EFFECT_DEFENSE_UP_3] = 0, // TODO: Assign points
[EFFECT_NOBLE_ROAR] = 0, // TODO: Assign points
[EFFECT_VENOM_DRENCH] = 0, // TODO: Assign points
[EFFECT_TOXIC_THREAD] = 0, // TODO: Assign points
[EFFECT_CLEAR_SMOG] = 0, // TODO: Assign points
[EFFECT_HIT_SWITCH_TARGET] = 0, // TODO: Assign points
[EFFECT_FINAL_GAMBIT] = 0, // TODO: Assign points
[EFFECT_CHANGE_TYPE_ON_ITEM] = 0, // TODO: Assign points
@ -382,51 +343,36 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_COPYCAT] = 0, // TODO: Assign points
[EFFECT_DEFOG] = 0, // TODO: Assign points
[EFFECT_HIT_ENEMY_HEAL_ALLY] = 0, // TODO: Assign points
[EFFECT_SMACK_DOWN] = 0, // TODO: Assign points
[EFFECT_SYNCHRONOISE] = 0, // TODO: Assign points
[EFFECT_PSYCHO_SHIFT] = 0, // TODO: Assign points
[EFFECT_POWER_TRICK] = 0, // TODO: Assign points
[EFFECT_FLAME_BURST] = 0, // TODO: Assign points
[EFFECT_AFTER_YOU] = 0, // TODO: Assign points
[EFFECT_BESTOW] = 0, // TODO: Assign points
[EFFECT_ROTOTILLER] = 0, // TODO: Assign points
[EFFECT_FLOWER_SHIELD] = 0, // TODO: Assign points
[EFFECT_HIT_PREVENT_ESCAPE] = 0, // TODO: Assign points
[EFFECT_SPEED_SWAP] = 0, // TODO: Assign points
[EFFECT_DEFENSE_UP2_HIT] = 0, // TODO: Assign points
[EFFECT_REVELATION_DANCE] = 0, // TODO: Assign points
[EFFECT_AURORA_VEIL] = 0, // TODO: Assign points
[EFFECT_THIRD_TYPE] = 0, // TODO: Assign points
[EFFECT_FEINT] = 0, // TODO: Assign points
[EFFECT_SPARKLING_ARIA] = 0, // TODO: Assign points
[EFFECT_ACUPRESSURE] = 0, // TODO: Assign points
[EFFECT_AROMATIC_MIST] = 0, // TODO: Assign points
[EFFECT_POWDER] = 0, // TODO: Assign points
[EFFECT_SP_ATTACK_UP_HIT] = 0, // TODO: Assign points
[EFFECT_BELCH] = 0, // TODO: Assign points
[EFFECT_PARTING_SHOT] = 0, // TODO: Assign points
[EFFECT_SPECTRAL_THIEF] = 0, // TODO: Assign points
[EFFECT_V_CREATE] = 0, // TODO: Assign points
[EFFECT_MAT_BLOCK] = 0, // TODO: Assign points
[EFFECT_STOMPING_TANTRUM] = 0, // TODO: Assign points
[EFFECT_CORE_ENFORCER] = 0, // TODO: Assign points
[EFFECT_INSTRUCT] = 0, // TODO: Assign points
[EFFECT_THROAT_CHOP] = 0, // TODO: Assign points
[EFFECT_LASER_FOCUS] = 0, // TODO: Assign points
[EFFECT_MAGNETIC_FLUX] = 0, // TODO: Assign points
[EFFECT_GEAR_UP] = 0, // TODO: Assign points
[EFFECT_INCINERATE] = 0, // TODO: Assign points
[EFFECT_BUG_BITE] = 0, // TODO: Assign points
[EFFECT_STRENGTH_SAP] = 0, // TODO: Assign points
[EFFECT_MIND_BLOWN] = 0, // TODO: Assign points
[EFFECT_PURIFY] = 0, // TODO: Assign points
[EFFECT_BURN_UP] = 0, // TODO: Assign points
[EFFECT_SHORE_UP] = 0, // TODO: Assign points
[EFFECT_GEOMANCY] = 0, // TODO: Assign points
[EFFECT_FAIRY_LOCK] = 0, // TODO: Assign points
[EFFECT_ALLY_SWITCH] = 0, // TODO: Assign points
[EFFECT_RELIC_SONG] = 0, // TODO: Assign points
[EFFECT_ATTACKER_DEFENSE_DOWN_HIT] = 0, // TODO: Assign points
[EFFECT_BODY_PRESS] = 0, // TODO: Assign points
[EFFECT_EERIE_SPELL] = 0, // TODO: Assign points
[EFFECT_JUNGLE_HEALING] = 0, // TODO: Assign points
@ -439,7 +385,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_RECOIL_HP_25] = 0, // TODO: Assign points
[EFFECT_STUFF_CHEEKS] = 0, // TODO: Assign points
[EFFECT_GRAV_APPLE] = 0, // TODO: Assign points
[EFFECT_EVASION_UP_HIT] = 0, // TODO: Assign points
[EFFECT_GLITZY_GLOW] = 0, // TODO: Assign points
[EFFECT_BADDY_BAD] = 0, // TODO: Assign points
[EFFECT_SAPPY_SEED] = 0, // TODO: Assign points
@ -451,7 +396,6 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_PHOTON_GEYSER] = 0, // TODO: Assign points
[EFFECT_SHELL_SIDE_ARM] = 0, // TODO: Assign points
[EFFECT_TERRAIN_PULSE] = 0, // TODO: Assign points
[EFFECT_JAW_LOCK] = 0, // TODO: Assign points
[EFFECT_NO_RETREAT] = 0, // TODO: Assign points
[EFFECT_TAR_SHOT] = 0, // TODO: Assign points
[EFFECT_POLTERGEIST] = 0, // TODO: Assign points
@ -468,11 +412,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_EXTREME_EVOBOOST] = 0, // TODO: Assign points
[EFFECT_HIT_SET_REMOVE_TERRAIN] = 0, // TODO: Assign points
[EFFECT_DARK_VOID] = 0, // TODO: Assign points
[EFFECT_SLEEP_HIT] = 1,
[EFFECT_DOUBLE_SHOCK] = 0, // TODO: Assign points
[EFFECT_SPECIAL_ATTACK_UP_HIT] = 1,
[EFFECT_VICTORY_DANCE] = 0, // TODO: Assign points
[EFFECT_FROSTBITE_HIT] = 1,
};
static const u16 sPoints_Effectiveness[] =
@ -1165,7 +1105,7 @@ void BattleTv_SetDataBasedOnMove(u16 move, u16 weatherFlags, struct DisableStruc
tvPtr->pos[defSide][GetBattlerPosition(gBattlerAttacker) / 2].attackedByMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1;
tvPtr->pos[defSide][GetBattlerPosition(gBattlerAttacker) / 2].attackedByMoveSlot = moveSlot;
tvPtr->side[atkSide].usedMoveSlot = moveSlot;
AddMovePoints(PTS_MOVE_EFFECT, moveSlot, gBattleMoves[move].effect, 0);
AddMovePoints(PTS_MOVE_EFFECT, moveSlot, move, 0);
AddPointsBasedOnWeather(weatherFlags, move, moveSlot);
if (disableStructPtr->chargeTimer != 0)
AddMovePoints(PTS_ELECTRIC, move, moveSlot, 0);
@ -1327,7 +1267,27 @@ static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3)
switch (caseId)
{
case PTS_MOVE_EFFECT:
case PTS_MOVE_EFFECT: // arg1 -> move slot, arg2 -> move
{
u8 baseFromEffect = sPointsArray[caseId][gBattleMoves[arg2].effect];
// Various cases to add/remove points
if (gBattleMoves[arg2].recoil > 0)
baseFromEffect++; // Recoil moves
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_RAPIDSPIN))
baseFromEffect++;
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_SP_ATK_TWO_DOWN) || MoveHasMoveEffect(arg2, MOVE_EFFECT_ATK_DEF_DOWN))
baseFromEffect += 2; // Overheat, Superpower, etc.
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_STEAL_ITEM))
baseFromEffect += 3;
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_WRAP) || MoveHasMoveEffectSelf(arg2, MOVE_EFFECT_THRASH))
baseFromEffect += 3;
if (MoveHasMoveEffect(arg2, MOVE_EFFECT_RECHARGE))
baseFromEffect += 4;
movePoints->points[atkSide][gBattlerPartyIndexes[gBattlerAttacker] * 4 + arg1] += baseFromEffect;
break;
}
case PTS_EFFECTIVENESS:
case PTS_CRITICAL_HIT:
case PTS_STAT_INCREASE_1:

View File

@ -2679,7 +2679,7 @@ u8 DoBattlerEndTurnEffects(void)
if (!(gBattleMons[battler].status2 & STATUS2_CONFUSION))
{
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER;
SetMoveEffect(TRUE, 0);
SetMoveEffect(TRUE, FALSE);
if (gBattleMons[battler].status2 & STATUS2_CONFUSION)
BattleScriptExecute(BattleScript_ThrashConfuses);
effect++;
@ -3462,7 +3462,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
case CANCELLER_THAW: // move thawing
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE)
{
if (!(gBattleMoves[gCurrentMove].effect == EFFECT_BURN_UP && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)))
if (!(MoveHasMoveEffectSelfArg(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)))
{
gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FREEZE;
BattleScriptPushCursor();
@ -3473,7 +3473,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
}
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && gBattleMoves[gCurrentMove].thawsUser)
{
if (!(gBattleMoves[gCurrentMove].effect == EFFECT_BURN_UP && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)))
if (!(MoveHasMoveEffectSelfArg(gCurrentMove, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)))
{
gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE;
BattleScriptPushCursor();
@ -5580,13 +5580,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& RandomWeighted(RNG_STENCH, 9, 1)
&& !IS_MOVE_STATUS(move)
&& gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_HIT
&& gBattleMoves[gCurrentMove].effect != EFFECT_FLINCH_STATUS
&& gBattleMoves[gCurrentMove].effect != EFFECT_TRIPLE_ARROWS)
&& !MoveHasMoveEffect(gCurrentMove, MOVE_EFFECT_FLINCH))
{
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
BattleScriptPushCursor();
SetMoveEffect(FALSE, 0);
SetMoveEffect(FALSE, FALSE);
BattleScriptPop();
effect++;
}
@ -7488,7 +7486,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
{
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
BattleScriptPushCursor();
SetMoveEffect(FALSE, 0);
SetMoveEffect(FALSE, FALSE);
BattleScriptPop();
}
}
@ -8459,22 +8457,14 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3
case EFFECT_NATURAL_GIFT:
basePower = gNaturalGiftTable[ITEM_TO_BERRY(gBattleMons[battlerAtk].item)].power;
break;
case EFFECT_WAKE_UP_SLAP:
if (gBattleMons[battlerDef].status1 & STATUS1_SLEEP || abilityDef == ABILITY_COMATOSE)
basePower *= 2;
break;
case EFFECT_SMELLING_SALTS:
if (gBattleMons[battlerDef].status1 & STATUS1_PARALYSIS)
case EFFECT_DOUBLE_POWER_ON_ARG_STATUS:
// Comatose targets treated as if asleep
if ((gBattleMons[battlerDef].status1 | (STATUS1_SLEEP * (abilityDef == ABILITY_COMATOSE))) & gBattleMoves[move].argument)
basePower *= 2;
break;
case EFFECT_WRING_OUT:
basePower = 120 * gBattleMons[battlerDef].hp / gBattleMons[battlerDef].maxHP;
break;
case EFFECT_HEX:
case EFFECT_INFERNAL_PARADE:
if (gBattleMons[battlerDef].status1 & STATUS1_ANY || abilityDef == ABILITY_COMATOSE)
basePower *= 2;
break;
case EFFECT_ASSURANCE:
if (gProtectStructs[battlerDef].physicalDmg != 0 || gProtectStructs[battlerDef].specialDmg != 0 || gProtectStructs[battlerDef].confusionSelfDmg)
basePower *= 2;
@ -8665,11 +8655,6 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
if (gBattleMons[battlerDef].hp <= (gBattleMons[battlerDef].maxHP / 2))
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
break;
case EFFECT_BARB_BARRAGE:
case EFFECT_VENOSHOCK:
if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
break;
case EFFECT_RETALIATE:
if (gSideTimers[atkSide].retaliateTimer == 1)
modifier = uq4_12_multiply(modifier, UQ_4_12(2.0));
@ -10939,22 +10924,28 @@ bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2)
return (gender1 != MON_GENDERLESS && gender2 != MON_GENDERLESS && gender1 == gender2);
}
u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance, u16 moveEffect)
u32 CalcSecondaryEffectChance(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect)
{
bool8 hasSereneGrace = (GetBattlerAbility(battler) == ABILITY_SERENE_GRACE);
bool8 hasSereneGrace = (battlerAbility == ABILITY_SERENE_GRACE);
bool8 hasRainbow = (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_RAINBOW) != 0;
u16 secondaryEffectChance = additionalEffect->chance;
if (hasRainbow && hasSereneGrace && moveEffect == EFFECT_FLINCH_HIT)
return secondaryEffectChance *= 2;
if (hasRainbow && hasSereneGrace && additionalEffect->moveEffect == MOVE_EFFECT_FLINCH)
return secondaryEffectChance * 2;
if (hasSereneGrace)
secondaryEffectChance *= 2;
if (hasRainbow && moveEffect != EFFECT_SECRET_POWER)
if (hasRainbow && additionalEffect->moveEffect != MOVE_EFFECT_SECRET_POWER)
secondaryEffectChance *= 2;
return secondaryEffectChance;
}
bool32 MoveEffectIsGuaranteed(u32 battler, u32 battlerAbility, const struct AdditionalEffect *additionalEffect)
{
return additionalEffect->chance == 0 || CalcSecondaryEffectChance(battler, battlerAbility, additionalEffect) >= 100;
}
bool32 IsAlly(u32 battlerAtk, u32 battlerDef)
{
return (GetBattlerSide(battlerAtk) == GetBattlerSide(battlerDef));
@ -10969,6 +10960,47 @@ bool32 IsGen6ExpShareEnabled(void)
#endif
}
bool32 MoveHasMoveEffect(u32 move, u32 moveEffect)
{
u32 i;
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
if (gBattleMoves[move].additionalEffects[i].moveEffect == moveEffect
&& gBattleMoves[move].additionalEffects[i].self == FALSE)
return TRUE;
}
return FALSE;
}
bool32 MoveHasMoveEffectWithChance(u32 move, u32 moveEffect, u32 chance)
{
u32 i;
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
if (gBattleMoves[move].additionalEffects[i].moveEffect == moveEffect
&& gBattleMoves[move].additionalEffects[i].chance == chance)
return TRUE;
}
return FALSE;
}
bool32 MoveHasMoveEffectSelf(u32 move, u32 moveEffect)
{
u32 i;
for (i = 0; i < gBattleMoves[move].numAdditionalEffects; i++)
{
if (gBattleMoves[move].additionalEffects[i].moveEffect == moveEffect
&& gBattleMoves[move].additionalEffects[i].self == TRUE)
return TRUE;
}
return FALSE;
}
bool32 MoveHasMoveEffectSelfArg(u32 move, u32 moveEffect, u32 argument)
{
return (gBattleMoves[move].argument == argument) && MoveHasMoveEffectSelf(move, moveEffect);
}
bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon)
{
u16 species = GetMonData(mon, MON_DATA_SPECIES);
@ -11041,3 +11073,13 @@ u8 GetBattlerType(u32 battler, u8 typeIndex)
return types[typeIndex];
}
void RemoveBattlerType(u32 battler, u8 type)
{
u32 i;
for (i = 0; i < 3; i++)
{
if (*(u8 *)(&gBattleMons[battler].type1 + i) == type)
*(u8 *)(&gBattleMons[battler].type1 + i) = TYPE_MYSTERY;
}
}

View File

@ -13,7 +13,7 @@ struct BattlePyramidRequirement {
u8 nEvoItems;
};
// EFFECT_PARALYZE, EFFECT_PARALYZE_HIT (30% or more)
// EFFECT_PARALYZE, MOVE_EFFECT_PARALYZE (30% or more)
static const u16 sParalyzingMoves[] = {
//MOVE_THUNDER_PUNCH,
MOVE_BODY_SLAM,
@ -35,7 +35,7 @@ static const u16 sParalyzingMoves[] = {
MOVE_COMBAT_TORQUE,
};
// EFFECT_POISON_HIT (30% or more), EFFECT_POISON, EFFECT_POISON_FANG, EFFECT_TOXIC, EFFECT_TOXIC_THREAD
// MOVE_EFFECT_POISON (30% or more), EFFECT_POISON, MOVE_EFFECT_TOXIC, EFFECT_TOXIC, EFFECT_TOXIC_THREAD
static const u16 sPoisoningMoves[] = {
MOVE_POISON_STING,
//MOVE_TWINEEDLE,
@ -57,7 +57,7 @@ static const u16 sPoisoningMoves[] = {
MOVE_TOXIC_THREAD,
};
// EFFECT_BURN_HIT, EFFECT_WILL_O_WISP
// MOVE_EFFECT_BURN, EFFECT_WILL_O_WISP
static const u16 sBurningMoves[] = {
MOVE_WILL_O_WISP,
//MOVE_EMBER,
@ -79,7 +79,7 @@ static const u16 sBurningMoves[] = {
MOVE_BLAZING_TORQUE,
};
// EFFECT_FREEZE, EFFECT_FREEZE_HIT
// EFFECT_FREEZE, MOVE_EFFECT_FREEZE_OR_FROSTBITE
static const u16 sFrostbiteMoves[] = {
MOVE_ICE_PUNCH,
MOVE_ICE_BEAM,
@ -110,7 +110,7 @@ static const u16 sWeatherChangingMoves[] = {
MOVE_SUNNY_DAY,
};
// EFFECT_RECHARGE, EFFECT_RECOIL
// MOVE_EFFECT_RECHARGE, recoil
static const u16 sPowerfulNormalMoves[] = {
MOVE_HYPER_BEAM,
MOVE_GIGA_IMPACT,
@ -169,7 +169,7 @@ static const struct BattlePyramidRequirement sBattlePyramidRequirementsByRound[]
{
.type = TYPE_ICE,
},
[7] = /* pokemon with explosion effects */
{
.type = TYPE_MYSTERY,

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
ASSUME(gBattleMoves[MOVE_OVERHEAT].effect == EFFECT_OVERHEAT);
ASSUME(MoveHasMoveEffectSelf(MOVE_OVERHEAT, MOVE_EFFECT_SP_ATK_TWO_DOWN) == TRUE);
ASSUME(gBattleMoves[MOVE_OVERHEAT].category == BATTLE_CATEGORY_SPECIAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SPINDA) { Ability(ability); }

View File

@ -79,7 +79,7 @@ SINGLE_BATTLE_TEST("Hyper Cutter is ignored by Mold Breaker")
SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Attack stage reduction from moves used by the user")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SUPERPOWER].effect == EFFECT_SUPERPOWER);
ASSUME(MoveHasMoveEffectSelf(MOVE_SUPERPOWER, MOVE_EFFECT_ATK_DEF_DOWN) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); }
} WHEN {
@ -117,7 +117,7 @@ SINGLE_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting p
{
GIVEN {
ASSUME(gBattleMoves[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2);
ASSUME(gBattleMoves[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF);
ASSUME(MoveHasMoveEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); }
} WHEN {

View File

@ -4,7 +4,7 @@
SINGLE_BATTLE_TEST("Immunity prevents Poison Sting poison")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POISON_STING, MOVE_EFFECT_POISON) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SNORLAX) { Ability(ABILITY_IMMUNITY); }
} WHEN {

View File

@ -174,7 +174,7 @@ SINGLE_BATTLE_TEST("Keen Eye & Gen9+ Illuminate don't prevent Spectral Thief fro
GIVEN {
ASSUME(gBattleMoves[MOVE_HONE_CLAWS].effect == EFFECT_ATTACK_ACCURACY_UP);
ASSUME(gBattleMoves[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF);
ASSUME(MoveHasMoveEffect(MOVE_SPECTRAL_THIEF, MOVE_EFFECT_SPECTRAL_THIEF) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(species) { Ability(ability); }
} WHEN {

View File

@ -9,29 +9,21 @@ SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun")
PARAMETRIZE { move = MOVE_HYPNOSIS; status = STATUS1_SLEEP; }
PARAMETRIZE { move = MOVE_THUNDER_WAVE; status = STATUS1_PARALYSIS; }
PARAMETRIZE { move = MOVE_TOXIC; status = STATUS1_TOXIC_POISON; }
PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; }
// PARAMETRIZE { move = MOVE_POWDER_SNOW; status = STATUS1_FREEZE; } // Pointless since you can't freeze in sunlight anyway
GIVEN {
ASSUME(gBattleMoves[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP);
ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP);
ASSUME(gBattleMoves[MOVE_THUNDER_WAVE].effect == EFFECT_PARALYZE);
ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC);
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT);
PLAYER(SPECIES_LEAFEON) { Ability(ABILITY_LEAF_GUARD); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); }
} SCENE {
if (move != MOVE_POWDER_SNOW) {
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…");
NOT STATUS_ICON(player, status);
} else {
NONE_OF {
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
STATUS_ICON(player, status);
}
}
NOT ANIMATION(ANIM_TYPE_MOVE, move, opponent);
ABILITY_POPUP(player, ABILITY_LEAF_GUARD);
MESSAGE("It doesn't affect Leafeon…");
NOT STATUS_ICON(player, status);
}
}

View File

@ -44,7 +44,7 @@ SINGLE_BATTLE_TEST("Own Tempo prevents confusion from moves by the opponent")
SINGLE_BATTLE_TEST("Own Tempo prevents confusion from moves by the user")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_PETAL_DANCE].effect == EFFECT_RAMPAGE);
ASSUME(MoveHasMoveEffectSelf(MOVE_PETAL_DANCE, MOVE_EFFECT_THRASH));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); };
} WHEN {

View File

@ -4,7 +4,7 @@
SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POISON_STING, MOVE_EFFECT_POISON) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_PONYTA_GALARIAN) { Ability(ABILITY_PASTEL_VEIL); }
} WHEN {
@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison")
DOUBLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison on partner")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POISON_STING, MOVE_EFFECT_POISON) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_PONYTA_GALARIAN) { Ability(ABILITY_PASTEL_VEIL); }

View File

@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Purifying Salt grants immunity to status effects")
ASSUME(gBattleMoves[MOVE_HYPNOSIS].effect == EFFECT_SLEEP);
ASSUME(gBattleMoves[MOVE_THUNDER_WAVE].effect == EFFECT_PARALYZE);
ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC);
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POWDER_SNOW, MOVE_EFFECT_FREEZE_OR_FROSTBITE) == TRUE);
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_PURIFYING_SALT); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {

View File

@ -8,7 +8,10 @@ SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of m
for (j = 1; j < MOVES_COUNT; j++)
{
if (gBattleMoves[j].sheerForceBoost && j != MOVE_ORDER_UP)
if (gBattleMoves[j].sheerForceBoost
//&& gBattleMoves[j].effect != EFFECT_ORDER_UP
&& gBattleMoves[j].effect != EFFECT_AURA_WHEEL
&& gBattleMoves[j].effect != EFFECT_PLACEHOLDER)
{
PARAMETRIZE { ability = ABILITY_ANGER_POINT; move = j; }
PARAMETRIZE { ability = ABILITY_SHEER_FORCE; move = j; }
@ -19,8 +22,12 @@ SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of m
PLAYER(SPECIES_TAUROS) { Ability(ability); Status1(move == MOVE_SNORE ? STATUS1_SLEEP : STATUS1_NONE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
if (gBattleMoves[move].effect == EFFECT_TWO_TURNS_ATTACK || gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE) {
if (move == MOVE_ALLURING_VOICE || move == MOVE_BURNING_JEALOUSY) // Alluring Voice requires the target to boost stats to have an effect
TURN { MOVE(opponent, MOVE_AGILITY); MOVE(player, move); }
else
TURN { MOVE(player, move); }
if (gBattleMoves[move].effect == EFFECT_TWO_TURNS_ATTACK || gBattleMoves[move].effect == EFFECT_SEMI_INVULNERABLE
|| gBattleMoves[move].effect == EFFECT_METEOR_BEAM) {
TURN { SKIP_TURN(player); }
TURN { ; }
}
@ -40,7 +47,7 @@ SINGLE_BATTLE_TEST("Sheer Force boosts power, but removes secondary effects of m
MESSAGE("Wobbuffet flinched!");
}
// Volt Tackle/Flare Blitz edge case: recoil happens, but target isn't statused
if (gBattleMoves[move].effect == EFFECT_RECOIL)
if (gBattleMoves[move].recoil > 0)
{
HP_BAR(player);
MESSAGE("Tauros is hit with recoil!");

View File

@ -4,7 +4,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_BODY_SLAM].effect == EFFECT_PARALYZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_BODY_SLAM, MOVE_EFFECT_PARALYSIS) == TRUE);
}
AI_SINGLE_BATTLE_TEST("AI sees increased base power of Facade")
@ -36,7 +36,8 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Smelling Salt")
GIVEN {
ASSUME(B_UPDATED_MOVE_DATA >= GEN_6);
ASSUME(gBattleMoves[MOVE_SMELLING_SALTS].effect == EFFECT_SMELLING_SALTS);
ASSUME(gBattleMoves[MOVE_SMELLING_SALTS].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_SMELLING_SALTS].argument == STATUS1_PARALYSIS);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { HP(60); Status1(status1); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_BODY_SLAM, MOVE_SMELLING_SALTS); }
@ -57,7 +58,8 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Wake Up Slap")
GIVEN {
ASSUME(B_UPDATED_MOVE_DATA >= GEN_6);
ASSUME(gBattleMoves[MOVE_WAKE_UP_SLAP].effect == EFFECT_WAKE_UP_SLAP);
ASSUME(gBattleMoves[MOVE_WAKE_UP_SLAP].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_WAKE_UP_SLAP].argument == STATUS1_SLEEP);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_MEGANIUM) { HP(35); Status1(status1); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_BODY_SLAM, MOVE_WAKE_UP_SLAP); }
@ -74,17 +76,18 @@ AI_SINGLE_BATTLE_TEST("AI sees increased base power of Grav Apple")
u32 movePlayer;
u16 expectedMove;
PARAMETRIZE { movePlayer = MOVE_CELEBRATE; expectedMove = MOVE_TROP_KICK; }
PARAMETRIZE { movePlayer = MOVE_CELEBRATE; expectedMove = MOVE_DRUM_BEATING; }
PARAMETRIZE { movePlayer = MOVE_GRAVITY; expectedMove = MOVE_GRAV_APPLE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_GRAV_APPLE].effect == EFFECT_GRAV_APPLE);
ASSUME(gBattleMoves[MOVE_TROP_KICK].effect == EFFECT_ATTACK_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_GRAV_APPLE].power == gBattleMoves[MOVE_DRUM_BEATING].power);
ASSUME(MoveHasMoveEffect(MOVE_DRUM_BEATING, MOVE_EFFECT_SPD_MINUS_1) == TRUE);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_WOBBUFFET) { HP(81); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); Moves(MOVE_TROP_KICK, MOVE_GRAV_APPLE); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); Moves(MOVE_DRUM_BEATING, MOVE_GRAV_APPLE); }
} WHEN {
TURN { MOVE(player, movePlayer); EXPECT_MOVE(opponent, MOVE_TROP_KICK); }
TURN { MOVE(player, movePlayer); EXPECT_MOVE(opponent, MOVE_DRUM_BEATING); }
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, expectedMove); }
} SCENE {
if (expectedMove == MOVE_GRAV_APPLE)
@ -175,10 +178,8 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% c
GIVEN {
AI_LOG;
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].secondaryEffectChance == 20);
ASSUME(gBattleMoves[MOVE_OCTAZOOKA].effect == EFFECT_ACCURACY_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_OCTAZOOKA].secondaryEffectChance == 50);
ASSUME(MoveHasMoveEffectWithChance(MOVE_SHADOW_BALL, MOVE_EFFECT_SP_DEF_MINUS_1, 20));
ASSUME(MoveHasMoveEffectWithChance(MOVE_OCTAZOOKA, MOVE_EFFECT_ACC_MINUS_1, 50));
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_REGICE);
OPPONENT(SPECIES_REGIROCK) { Ability(ability); Moves(MOVE_SHADOW_BALL, MOVE_OCTAZOOKA); }

View File

@ -3,7 +3,7 @@
SINGLE_BATTLE_TEST("Shaymin-Sky reverts to Shaymin-Land when frozen or frostbitten")
{
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == ((B_USE_FROSTBITE == TRUE) ? EFFECT_FROSTBITE_HIT : EFFECT_FREEZE_HIT));
ASSUME(MoveHasMoveEffect(MOVE_POWDER_SNOW, MOVE_EFFECT_FREEZE_OR_FROSTBITE));
GIVEN {
PLAYER(SPECIES_SHAYMIN_SKY);
OPPONENT(SPECIES_WOBBUFFET);

View File

@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Air Balloon pops before it can be stolen with Thief or Covet
PARAMETRIZE { move = MOVE_THIEF; }
PARAMETRIZE { move = MOVE_COVET; }
GIVEN {
ASSUME(gBattleMoves[move].effect == EFFECT_THIEF);
ASSUME(MoveHasMoveEffect(move, MOVE_EFFECT_STEAL_ITEM) == TRUE);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_AIR_BALLOON); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_LIECHI_BERRY].holdEffect == HOLD_EFFECT_ATTACK_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Liechi Berry raises the holder's Attack by one stage when HP drops to 1/4 or below")

View File

@ -72,12 +72,12 @@ SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats")
PARAMETRIZE { move = MOVE_MUD_SLAP; }
GIVEN {
ASSUME(gBattleMoves[MOVE_AURORA_BEAM].effect == EFFECT_ATTACK_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_ROCK_SMASH].effect == EFFECT_DEFENSE_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_SNARL].effect == EFFECT_SPECIAL_ATTACK_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_PSYCHIC].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_BUBBLE_BEAM].effect == EFFECT_SPEED_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_MUD_SLAP].effect == EFFECT_ACCURACY_DOWN_HIT);
ASSUME(MoveHasMoveEffect(MOVE_AURORA_BEAM, MOVE_EFFECT_ATK_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_ROCK_SMASH, MOVE_EFFECT_DEF_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_BUBBLE_BEAM, MOVE_EFFECT_SPD_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_SNARL, MOVE_EFFECT_SP_ATK_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_PSYCHIC, MOVE_EFFECT_SP_DEF_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_MUD_SLAP, MOVE_EFFECT_ACC_MINUS_1) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); };
} WHEN {

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_LANSAT_BERRY].holdEffect == HOLD_EFFECT_CRITICAL_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Lansat Berry raises the holder's critical-hit-ratio by two stages when HP drops to 1/4 or below")

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_GANLON_BERRY].holdEffect == HOLD_EFFECT_DEFENSE_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Ganlon Berry raises the holder's Defense by one stage when HP drops to 1/4 or below")

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_MICLE_BERRY].holdEffect == HOLD_EFFECT_MICLE_BERRY);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Micle Berry raises the holder's accuracy by 1.2 when HP drops to 1/4 or below")

View File

@ -170,7 +170,7 @@ SINGLE_BATTLE_TEST("Red Card does not activate if stolen by a move")
bool32 activate;
PARAMETRIZE { item = ITEM_NONE; activate = FALSE; }
PARAMETRIZE { item = ITEM_POTION; activate = TRUE; }
ASSUME(gBattleMoves[MOVE_THIEF].effect == EFFECT_THIEF);
ASSUME(MoveHasMoveEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_PETAYA_BERRY].holdEffect == HOLD_EFFECT_SP_ATTACK_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Petaya Berry raises the holder's Sp. Atk by one stage when HP drops to 1/4 or below")

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_APICOT_BERRY].holdEffect == HOLD_EFFECT_SP_DEFENSE_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Apicot Berry raises the holder's Sp. Def by one stage when HP drops to 1/4 or below")

View File

@ -4,7 +4,8 @@
ASSUMPTIONS
{
ASSUME(gItems[ITEM_SALAC_BERRY].holdEffect == HOLD_EFFECT_SPEED_UP);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_DRAGON_RAGE);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].effect == EFFECT_FIXED_DAMAGE_ARG);
ASSUME(gBattleMoves[MOVE_DRAGON_RAGE].argument == 40);
}
SINGLE_BATTLE_TEST("Salac Berry raises the holder's Speed by one stage when HP drops to 1/4 or below")

View File

@ -135,7 +135,7 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if it is knocked off o
KNOWN_FAILING; // Knock off fails, Thief is fine
GIVEN {
ASSUME(gBattleMoves[MOVE_THIEF].effect == EFFECT_THIEF);
ASSUME(MoveHasMoveEffect(MOVE_THIEF, MOVE_EFFECT_STEAL_ITEM) == TRUE);
ASSUME(gBattleMoves[MOVE_KNOCK_OFF].effect == EFFECT_KNOCK_OFF);
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); }
OPPONENT(SPECIES_WOBBUFFET);
@ -190,7 +190,7 @@ SINGLE_BATTLE_TEST("White Herb wont have time to activate if Pickpocket steals i
{
KNOWN_FAILING; // White Herb is activated
GIVEN {
ASSUME(gBattleMoves[MOVE_LEAF_STORM].effect == EFFECT_OVERHEAT);
ASSUME(MoveHasMoveEffectSelf(MOVE_LEAF_STORM, MOVE_EFFECT_SP_ATK_TWO_DOWN));
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); Item(ITEM_WHITE_HERB); }
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
} WHEN {

View File

@ -21,15 +21,15 @@ SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses")
}
}
SINGLE_BATTLE_TEST("Secondary Effect Chance controls the proportion of secondary effects")
SINGLE_BATTLE_TEST("AdditionalEffect.chance controls the proportion of secondary effects")
{
u32 move;
PARAMETRIZE { move = MOVE_THUNDER_SHOCK; }
PARAMETRIZE { move = MOVE_DISCHARGE; }
PARAMETRIZE { move = MOVE_NUZZLE; }
ASSUME(gBattleMoves[move].effect == EFFECT_PARALYZE_HIT);
ASSUME(0 < gBattleMoves[move].secondaryEffectChance && gBattleMoves[move].secondaryEffectChance <= 100);
PASSES_RANDOMLY(gBattleMoves[move].secondaryEffectChance, 100, RNG_SECONDARY_EFFECT);
ASSUME(MoveHasMoveEffect(move, MOVE_EFFECT_PARALYSIS) == TRUE);
ASSUME(0 < gBattleMoves[move].additionalEffects[0].chance && gBattleMoves[move].additionalEffects[0].chance <= 100);
PASSES_RANDOMLY(gBattleMoves[move].additionalEffects[0].chance, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);

View File

@ -41,3 +41,30 @@ SINGLE_BATTLE_TEST("Absorb fails if Heal Block applies")
}
}
}
DOUBLE_BATTLE_TEST("Matcha Gatcha recovers 50% of the damage dealt from both targets")
{
s16 damageLeft;
s16 damageRight;
s16 healedLeft;
s16 healedRight;
GIVEN {
ASSUME(gBattleMoves[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft, captureDamage: &damageLeft);
HP_BAR(playerLeft, captureDamage: &healedLeft);
HP_BAR(opponentRight, captureDamage: &damageRight);
HP_BAR(playerLeft, captureDamage: &healedRight);
} THEN {
EXPECT_MUL_EQ(damageLeft, Q_4_12(-0.5), healedLeft);
EXPECT_MUL_EQ(damageRight, Q_4_12(-0.5), healedRight);
}
}

View File

@ -0,0 +1,51 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasMoveEffectSelf(MOVE_AURA_WHEEL, MOVE_EFFECT_SPD_PLUS_1) == TRUE);
ASSUME(gBattleMoves[MOVE_AURA_WHEEL].effect == EFFECT_AURA_WHEEL);
}
SINGLE_BATTLE_TEST("Aura Wheel raises Speed; fails if the user is not Morpeko")
{
u16 species;
PARAMETRIZE{ species = SPECIES_WOBBUFFET; }
PARAMETRIZE{ species = SPECIES_MORPEKO; }
GIVEN {
PLAYER(species);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_AURA_WHEEL); }
} SCENE {
if (species != SPECIES_MORPEKO)
{
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player);
MESSAGE("But Wobbuffet can't use the move!");
}
else {
ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Morpeko's Speed rose!");
}
}
}
SINGLE_BATTLE_TEST("Aura Wheel changes type depending on Morpeko's form")
{
GIVEN {
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_AURA_WHEEL); }
TURN { MOVE(player, MOVE_AURA_WHEEL); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player);
HP_BAR(opponent);
NOT MESSAGE("It's super effective!");
// Turn 2 (Hangry)
ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player);
HP_BAR(opponent);
MESSAGE("It's super effective!");
}
}

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_AXE_KICK].effect == EFFECT_AXE_KICK);
ASSUME(gBattleMoves[MOVE_AXE_KICK].effect == EFFECT_RECOIL_IF_MISS);
ASSUME(MoveHasMoveEffect(MOVE_AXE_KICK, MOVE_EFFECT_CONFUSION) == TRUE);
}
SINGLE_BATTLE_TEST("Axe Kick confuses the target")

View File

@ -3,7 +3,9 @@
ASSUMPTIONS
{
//ASSUME(gBattleMoves[MOVE_BARB_BARRAGE].effect == EFFECT_BARB_BARRAGE);
ASSUME(gBattleMoves[MOVE_BARB_BARRAGE].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_BARB_BARRAGE].argument == STATUS1_PSN_ANY);
ASSUME(MoveHasMoveEffect(MOVE_BARB_BARRAGE, MOVE_EFFECT_POISON) == TRUE);
}
SINGLE_BATTLE_TEST("Barb Barrage inflicts poison")

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_BUG_BITE].effect == EFFECT_BUG_BITE);
ASSUME(MoveHasMoveEffect(MOVE_BUG_BITE, MOVE_EFFECT_BUG_BITE));
ASSUME(gBattleMoves[MOVE_BUG_BITE].pp == 20);
}

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_EMBER].effect == EFFECT_BURN_HIT);
ASSUME(MoveHasMoveEffect(MOVE_EMBER, MOVE_EFFECT_BURN) == TRUE);
}
SINGLE_BATTLE_TEST("Ember inflicts burn")
@ -39,6 +39,69 @@ SINGLE_BATTLE_TEST("Ember cannot burn a Fire-type Pokémon")
}
}
DOUBLE_BATTLE_TEST("Lava Plume inflicts burn to all adjacent battlers")
{
GIVEN {
ASSUME(MoveHasMoveEffect(MOVE_LAVA_PLUME, MOVE_EFFECT_BURN) == TRUE);
ASSUME(gBattleMoves[MOVE_LAVA_PLUME].target == MOVE_TARGET_FOES_AND_ALLY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_LAVA_PLUME); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_LAVA_PLUME, playerLeft);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentLeft);
STATUS_ICON(opponentLeft, burn: TRUE);
HP_BAR(playerRight);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, playerRight);
STATUS_ICON(playerRight, burn: TRUE);
HP_BAR(opponentRight);
STATUS_ICON(opponentRight, burn: TRUE);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentRight);
}
}
SINGLE_BATTLE_TEST("Matcha Gotcha inflicts burn 20% of the time")
{
PASSES_RANDOMLY(20, 100, RNG_SECONDARY_EFFECT);
GIVEN {
ASSUME(MoveHasMoveEffect(MOVE_MATCHA_GOTCHA, MOVE_EFFECT_BURN) == TRUE);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent);
STATUS_ICON(opponent, burn: TRUE);
}
}
DOUBLE_BATTLE_TEST("Matcha Gatcha can burn both targets")
{
GIVEN {
ASSUME(MoveHasMoveEffect(MOVE_MATCHA_GOTCHA, MOVE_EFFECT_BURN) == TRUE);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentLeft);
STATUS_ICON(opponentLeft, burn: TRUE);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentRight);
STATUS_ICON(opponentRight, burn: TRUE);
}
}
#if B_STATUS_TYPE_IMMUNITY > GEN_1
SINGLE_BATTLE_TEST("Scald should burn a Water-type Pokémon")
#else
@ -47,7 +110,7 @@ SINGLE_BATTLE_TEST("Scald shouldn't burn a Water-type Pokémon")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[0] == TYPE_WATER);
ASSUME(gBattleMoves[MOVE_SCALD].effect == EFFECT_BURN_HIT);
ASSUME(MoveHasMoveEffect(MOVE_SCALD, MOVE_EFFECT_BURN) == TRUE);
ASSUME(gBattleMoves[MOVE_SCALD].type == TYPE_WATER);
PLAYER(SPECIES_SQUIRTLE);
OPPONENT(SPECIES_SQUIRTLE);

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_BURN_UP].effect == EFFECT_BURN_UP);
ASSUME(gBattleMoves[MOVE_BURN_UP].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE);
ASSUME(MoveHasMoveEffectSelfArg(MOVE_BURN_UP, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_FIRE) == TRUE);
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_FIRE || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_FIRE);
ASSUME(gSpeciesInfo[SPECIES_CYNDAQUIL].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_CYNDAQUIL].types[1] == TYPE_FIRE);
}

View File

@ -9,7 +9,7 @@ SINGLE_BATTLE_TEST("Alluring Voice confuses the target if the target raised a st
PARAMETRIZE { move = MOVE_SWORDS_DANCE; }
GIVEN {
ASSUME(gBattleMoves[MOVE_ALLURING_VOICE].effect == EFFECT_CONFUSE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_ALLURING_VOICE, MOVE_EFFECT_CONFUSION));
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Alluring Voice confuses the target if the target raised a st
SINGLE_BATTLE_TEST("Alluring Voice confuse effect is removed if it is Sheer Force boosted")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_ALLURING_VOICE].effect == EFFECT_CONFUSE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_ALLURING_VOICE, MOVE_EFFECT_CONFUSION));
PLAYER(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_DIRE_CLAW].effect == EFFECT_DIRE_CLAW);
ASSUME(MoveHasMoveEffect(MOVE_DIRE_CLAW, MOVE_EFFECT_DIRE_CLAW) == TRUE);
}
SINGLE_BATTLE_TEST("Dire Claw can inflict poison, paralysis or sleep")

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_DOUBLE_SHOCK].effect == EFFECT_DOUBLE_SHOCK);
ASSUME(gBattleMoves[MOVE_DOUBLE_SHOCK].effect == EFFECT_FAIL_IF_NOT_ARG_TYPE);
ASSUME(MoveHasMoveEffectSelfArg(MOVE_DOUBLE_SHOCK, MOVE_EFFECT_REMOVE_ARG_TYPE, TYPE_ELECTRIC) == TRUE);
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ELECTRIC || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ELECTRIC);
ASSUME(gSpeciesInfo[SPECIES_PIKACHU].types[0] == TYPE_ELECTRIC || gSpeciesInfo[SPECIES_PIKACHU].types[1] == TYPE_ELECTRIC);
}

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HEADBUTT].effect == EFFECT_FLINCH_HIT);
ASSUME(MoveHasMoveEffect(MOVE_HEADBUTT, MOVE_EFFECT_FLINCH) == TRUE);
}
SINGLE_BATTLE_TEST("Headbutt flinches the target if attacker is faster")

View File

@ -3,12 +3,12 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_THUNDER_FANG].effect == EFFECT_FLINCH_STATUS);
ASSUME(gBattleMoves[MOVE_THUNDER_FANG].argument == STATUS1_PARALYSIS);
ASSUME(gBattleMoves[MOVE_ICE_FANG].effect == EFFECT_FLINCH_STATUS);
ASSUME(gBattleMoves[MOVE_ICE_FANG].argument == STATUS1_FREEZE);
ASSUME(gBattleMoves[MOVE_FIRE_FANG].effect == EFFECT_FLINCH_STATUS);
ASSUME(gBattleMoves[MOVE_FIRE_FANG].argument == STATUS1_BURN);
ASSUME(MoveHasMoveEffect(MOVE_THUNDER_FANG, MOVE_EFFECT_PARALYSIS) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_THUNDER_FANG, MOVE_EFFECT_FLINCH) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_ICE_FANG, MOVE_EFFECT_FREEZE) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_ICE_FANG, MOVE_EFFECT_FLINCH) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_FIRE_FANG, MOVE_EFFECT_BURN) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_FIRE_FANG, MOVE_EFFECT_FLINCH) == TRUE);
}
SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang inflict status 10% of the time")
@ -49,7 +49,7 @@ SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang cause the opponent to flinch 10%
PARAMETRIZE { move = MOVE_ICE_FANG; }
PARAMETRIZE { move = MOVE_FIRE_FANG; }
PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT);
PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT_2);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(100); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }

View File

@ -203,14 +203,14 @@ SINGLE_BATTLE_TEST("Fling doesn't consume the item if pokemon is asleep/frozen/p
SINGLE_BATTLE_TEST("Fling applies special effects when throwing specific Items")
{
u16 item, effect;
u16 item;
PARAMETRIZE {item = ITEM_FLAME_ORB; effect = EFFECT_WILL_O_WISP; }
PARAMETRIZE {item = ITEM_TOXIC_ORB; effect = EFFECT_TOXIC; }
PARAMETRIZE {item = ITEM_POISON_BARB; effect = EFFECT_POISON; }
PARAMETRIZE {item = ITEM_LIGHT_BALL; effect = EFFECT_PARALYZE; }
PARAMETRIZE {item = ITEM_RAZOR_FANG; effect = EFFECT_FLINCH_HIT; }
PARAMETRIZE {item = ITEM_KINGS_ROCK; effect = EFFECT_FLINCH_HIT; }
PARAMETRIZE {item = ITEM_FLAME_ORB; }
PARAMETRIZE {item = ITEM_LIGHT_BALL; }
PARAMETRIZE {item = ITEM_POISON_BARB; }
PARAMETRIZE {item = ITEM_TOXIC_ORB; }
PARAMETRIZE {item = ITEM_RAZOR_FANG; }
PARAMETRIZE {item = ITEM_KINGS_ROCK; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
@ -221,26 +221,116 @@ SINGLE_BATTLE_TEST("Fling applies special effects when throwing specific Items")
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
switch (effect)
switch (item)
{
case EFFECT_WILL_O_WISP:
MESSAGE("Foe Wobbuffet was burned!");
STATUS_ICON(opponent, STATUS1_BURN);
case ITEM_FLAME_ORB:
{
MESSAGE("Foe Wobbuffet was burned!");
STATUS_ICON(opponent, STATUS1_BURN);
}
break;
case EFFECT_PARALYZE:
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
STATUS_ICON(opponent, STATUS1_PARALYSIS);
case ITEM_LIGHT_BALL:
{
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
STATUS_ICON(opponent, STATUS1_PARALYSIS);
}
break;
case EFFECT_POISON:
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, STATUS1_POISON);
case ITEM_POISON_BARB:
{
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, STATUS1_POISON);
}
break;
case EFFECT_TOXIC:
MESSAGE("Foe Wobbuffet is badly poisoned!");
STATUS_ICON(opponent, STATUS1_TOXIC_POISON);
case ITEM_TOXIC_ORB:
{
MESSAGE("Foe Wobbuffet is badly poisoned!");
STATUS_ICON(opponent, STATUS1_TOXIC_POISON);
}
break;
case EFFECT_FLINCH_HIT:
MESSAGE("Foe Wobbuffet flinched!");
case ITEM_RAZOR_FANG:
case ITEM_KINGS_ROCK:
{
MESSAGE("Foe Wobbuffet flinched!");
}
break;
}
}
}
SINGLE_BATTLE_TEST("Fling's secondary effects are blocked by Shield Dust")
{
u16 item;
PARAMETRIZE {item = ITEM_FLAME_ORB; }
PARAMETRIZE {item = ITEM_LIGHT_BALL; }
PARAMETRIZE {item = ITEM_POISON_BARB; }
PARAMETRIZE {item = ITEM_TOXIC_ORB; }
PARAMETRIZE {item = ITEM_RAZOR_FANG; }
PARAMETRIZE {item = ITEM_KINGS_ROCK; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(item); }
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SHIELD_DUST); }
} WHEN {
TURN { MOVE(player, MOVE_FLING); }
} SCENE {
MESSAGE("Wobbuffet used Fling!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
HP_BAR(opponent);
switch (item)
{
case ITEM_FLAME_ORB:
{
NONE_OF {
MESSAGE("Foe Wobbuffet was burned!");
STATUS_ICON(opponent, STATUS1_BURN);
}
MESSAGE("The Flame Orb was used up...");
}
break;
case ITEM_LIGHT_BALL:
{
NONE_OF {
MESSAGE("Foe Wobbuffet is paralyzed! It may be unable to move!");
STATUS_ICON(opponent, STATUS1_PARALYSIS);
}
MESSAGE("The Light Ball was used up...");
}
break;
case ITEM_POISON_BARB:
{
NONE_OF {
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, STATUS1_POISON);
}
MESSAGE("The Poison Barb was used up...");
}
break;
case ITEM_TOXIC_ORB:
{
NONE_OF {
MESSAGE("Foe Wobbuffet is badly poisoned!");
STATUS_ICON(opponent, STATUS1_TOXIC_POISON);
}
MESSAGE("The Toxic Orb was used up...");
}
break;
case ITEM_RAZOR_FANG:
case ITEM_KINGS_ROCK:
{
NONE_OF {
MESSAGE("Foe Wobbuffet flinched!");
}
switch (item)
{
case ITEM_RAZOR_FANG:
MESSAGE("The Razor Fang was used up...");
break;
case ITEM_KINGS_ROCK:
MESSAGE("The King's Rock was used up...");
break;
}
}
break;
}
}

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_POWDER_SNOW].effect == EFFECT_FREEZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POWDER_SNOW, MOVE_EFFECT_FREEZE_OR_FROSTBITE) == TRUE);
ASSUME(gBattleMoves[MOVE_BLIZZARD].accuracy == 70);
}
@ -75,7 +75,7 @@ SINGLE_BATTLE_TEST("Freezing Glare shouldn't freeze Psychic-types")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_ARTICUNO_GALARIAN].types[0] == TYPE_PSYCHIC);
ASSUME(gBattleMoves[MOVE_FREEZING_GLARE].effect == EFFECT_FREEZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_FREEZING_GLARE, MOVE_EFFECT_FREEZE_OR_FROSTBITE) == TRUE);
ASSUME(gBattleMoves[MOVE_FREEZING_GLARE].type == TYPE_PSYCHIC);
PLAYER(SPECIES_ARTICUNO_GALARIAN);
OPPONENT(SPECIES_ARTICUNO_GALARIAN);

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_HEX].effect == EFFECT_HEX);
ASSUME(gBattleMoves[MOVE_HEX].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_HEX].argument == STATUS1_ANY);
}
SINGLE_BATTLE_TEST("Hex deals double damage to foes with a status", s16 damage)

View File

@ -3,8 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_STONE_AXE].effect == EFFECT_HIT_SET_ENTRY_HAZARD);
ASSUME(gBattleMoves[MOVE_CEASELESS_EDGE].effect == EFFECT_HIT_SET_ENTRY_HAZARD);
ASSUME(MoveHasMoveEffect(MOVE_STONE_AXE, MOVE_EFFECT_STEALTH_ROCK) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_CEASELESS_EDGE, MOVE_EFFECT_SPIKES) == TRUE);
}
SINGLE_BATTLE_TEST("Stone Axe / Ceaseless Edge set up hazards after hitting the target")

View File

@ -3,10 +3,11 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_INFERNAL_PARADE].effect == EFFECT_INFERNAL_PARADE);
ASSUME(gBattleMoves[MOVE_INFERNAL_PARADE].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_INFERNAL_PARADE].argument == STATUS1_ANY);
}
SINGLE_BATTLE_TEST("Infernal Parade inflicts poison")
SINGLE_BATTLE_TEST("Infernal Parade inflicts burn")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);

View File

@ -0,0 +1,23 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasMoveEffect(MOVE_JAW_LOCK, MOVE_EFFECT_TRAP_BOTH) == TRUE);
}
SINGLE_BATTLE_TEST("Jaw Lock traps both opponents")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_JAW_LOCK); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_JAW_LOCK, player);
MESSAGE("Neither Pokémon can run away!");
} THEN { // Can't find good way to test trapping
EXPECT(opponent->status2 & STATUS2_ESCAPE_PREVENTION);
EXPECT(player->status2 & STATUS2_ESCAPE_PREVENTION);
}
}

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_MAKE_IT_RAIN].effect == EFFECT_MAKE_IT_RAIN);
ASSUME(MoveHasMoveEffect(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_PAYDAY));
ASSUME(MoveHasMoveEffectSelf(MOVE_MAKE_IT_RAIN, MOVE_EFFECT_SP_ATK_MINUS_1));
}
SINGLE_BATTLE_TEST("Make It Rain lowers special attack by one stage")

View File

@ -1,66 +0,0 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_MATCHA_GOTCHA].effect == EFFECT_MATCHA_GOTCHA);
}
SINGLE_BATTLE_TEST("Matcha Gotcha inflicts burn 20% of the time")
{
PASSES_RANDOMLY(20, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent);
STATUS_ICON(opponent, burn: TRUE);
}
}
DOUBLE_BATTLE_TEST("Matcha Gatcha can burn both targets")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentLeft);
STATUS_ICON(opponentLeft, burn: TRUE);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponentRight);
STATUS_ICON(opponentRight, burn: TRUE);
}
}
DOUBLE_BATTLE_TEST("Matcha Gatcha recovers 50% of the damage dealt from both targets")
{
s16 damageLeft;
s16 damageRight;
s16 healedLeft;
s16 healedRight;
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft, captureDamage: &damageLeft);
HP_BAR(playerLeft, captureDamage: &healedLeft);
HP_BAR(opponentRight, captureDamage: &damageRight);
HP_BAR(playerLeft, captureDamage: &healedRight);
}
}

View File

@ -1,24 +0,0 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_MORTAL_SPIN].effect == EFFECT_MORTAL_SPIN);
}
SINGLE_BATTLE_TEST("Mortal Spin blows away hazards and poisons foe")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); MOVE(player, MOVE_MORTAL_SPIN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MORTAL_SPIN, player);
MESSAGE("Wobbuffet blew away Stealth Rock!");
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, poison: TRUE);
}
}

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_THUNDER_SHOCK].effect == EFFECT_PARALYZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_THUNDER_SHOCK, MOVE_EFFECT_PARALYSIS) == TRUE);
}
SINGLE_BATTLE_TEST("Thunder Shock inflicts paralysis")
@ -48,7 +48,7 @@ SINGLE_BATTLE_TEST("Body Slam shouldn't paralyze Normal-types")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_TAUROS].types[0] == TYPE_NORMAL);
ASSUME(gBattleMoves[MOVE_BODY_SLAM].effect == EFFECT_PARALYZE_HIT);
ASSUME(MoveHasMoveEffect(MOVE_BODY_SLAM, MOVE_EFFECT_PARALYSIS) == TRUE);
ASSUME(gBattleMoves[MOVE_BODY_SLAM].type == TYPE_NORMAL);
PLAYER(SPECIES_TAUROS);
OPPONENT(SPECIES_TAUROS);

View File

@ -38,7 +38,7 @@ DOUBLE_BATTLE_TEST("Rainbow doubles the chance of secondary move effects")
{
PASSES_RANDOMLY(20, 100, RNG_SECONDARY_EFFECT);
GIVEN {
ASSUME(gBattleMoves[MOVE_EMBER].effect == EFFECT_BURN_HIT);
ASSUME(MoveHasMoveEffect(MOVE_EMBER, MOVE_EFFECT_BURN) == TRUE);
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
PLAYER(SPECIES_WYNAUT) { Speed(3); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(8); }
@ -59,7 +59,7 @@ DOUBLE_BATTLE_TEST("Rainbow flinch chance does not stack with Serene Grace")
{
PASSES_RANDOMLY(60, 100, RNG_SECONDARY_EFFECT);
GIVEN {
ASSUME(gBattleMoves[MOVE_BITE].effect == EFFECT_FLINCH_HIT);
ASSUME(MoveHasMoveEffect(MOVE_BITE, MOVE_EFFECT_FLINCH) == TRUE);
PLAYER(SPECIES_TOGEPI) { Speed(8); Ability(ABILITY_SERENE_GRACE); }
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(4); }
@ -76,27 +76,6 @@ DOUBLE_BATTLE_TEST("Rainbow flinch chance does not stack with Serene Grace")
}
}
DOUBLE_BATTLE_TEST("Rainbow flinch chance does not stack with Serene Grace if mvoe Triple Arrows is used")
{
PASSES_RANDOMLY(60, 100, RNG_TRIPLE_ARROWS_FLINCH);
GIVEN {
ASSUME(gBattleMoves[MOVE_TRIPLE_ARROWS].effect == EFFECT_TRIPLE_ARROWS);
PLAYER(SPECIES_TOGEPI) { Speed(8); Ability(ABILITY_SERENE_GRACE); }
PLAYER(SPECIES_WOBBUFFET) { Speed(5); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(4); }
OPPONENT(SPECIES_WYNAUT) { Speed(3); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_WATER_PLEDGE, target: opponentLeft);
MOVE(playerRight, MOVE_FIRE_PLEDGE, target: opponentRight);
}
TURN { MOVE(playerLeft, MOVE_TRIPLE_ARROWS, target: opponentRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_PLEDGE, playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRIPLE_ARROWS, playerLeft);
MESSAGE("Foe Wynaut flinched!");
}
}
DOUBLE_BATTLE_TEST("Fire and Grass Pledge summons Sea Of Fire for four turns that damages the opponent")
{
GIVEN {

View File

@ -3,8 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(gBattleMoves[MOVE_TWINEEDLE].effect == EFFECT_POISON_HIT);
ASSUME(MoveHasMoveEffect(MOVE_POISON_STING, MOVE_EFFECT_POISON) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_TWINEEDLE, MOVE_EFFECT_POISON) == TRUE);
}
SINGLE_BATTLE_TEST("Poison Sting inflicts poison")

View File

@ -240,10 +240,10 @@ SINGLE_BATTLE_TEST("Recoil damage is not applied if target was protected")
GIVEN {
ASSUME(gBattleMoves[MOVE_VOLT_TACKLE].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_HEAD_SMASH].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_TAKE_DOWN].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_DOUBLE_EDGE].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_VOLT_TACKLE].recoil > 0);
ASSUME(gBattleMoves[MOVE_HEAD_SMASH].recoil > 0);
ASSUME(gBattleMoves[MOVE_TAKE_DOWN].recoil > 0);
ASSUME(gBattleMoves[MOVE_DOUBLE_EDGE].recoil > 0);
PLAYER(SPECIES_RAPIDASH);
OPPONENT(SPECIES_BEAUTIFLY);
} WHEN {

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_THRASH].effect == EFFECT_RAMPAGE);
ASSUME(MoveHasMoveEffectSelf(MOVE_THRASH, MOVE_EFFECT_THRASH) == TRUE);
}
SINGLE_BATTLE_TEST("Thrash lasts for 2 or 3 turns")
@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Thrash lasts for 2 or 3 turns")
SINGLE_BATTLE_TEST("Thrash confuses the user after it finishes")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET) { MovesWithPP({MOVE_THRASH, 10}); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_THRASH); }
@ -37,6 +37,9 @@ SINGLE_BATTLE_TEST("Thrash confuses the user after it finishes")
ANIMATION(ANIM_TYPE_MOVE, MOVE_THRASH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THRASH, player);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
} THEN {
// Check that PP has been consumed correctly
EXPECT_EQ(player->pp[0], 9);
}
}
@ -85,3 +88,19 @@ SINGLE_BATTLE_TEST("Thrash confuses the user if it is canceled on turn 3 of 3")
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
}
}
SINGLE_BATTLE_TEST("Petal Dance does not lock mons that copy the move with Dancer")
{
GIVEN {
PLAYER(SPECIES_VILEPLUME);
OPPONENT(SPECIES_ORICORIO);
} WHEN {
TURN { MOVE(player, MOVE_PETAL_DANCE); }
TURN { SKIP_TURN(player); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent);
// How do you actually test locking?
EXPECT(!(opponent->status2 & STATUS2_MULTIPLETURNS));
}
}

View File

@ -0,0 +1,51 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
ASSUME(MoveHasMoveEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_SPD_PLUS_1) == TRUE);
#endif
ASSUME(MoveHasMoveEffectSelf(MOVE_MORTAL_SPIN, MOVE_EFFECT_RAPIDSPIN) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_MORTAL_SPIN, MOVE_EFFECT_POISON) == TRUE);
}
SINGLE_BATTLE_TEST("Rapin Spin blows away Wrap, hazards and raises Speed (Gen 8+)")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_WRAP); }
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); MOVE(player, MOVE_RAPID_SPIN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAPID_SPIN, player);
MESSAGE("Wobbuffet got free of Foe Wobbuffet's Wrap!");
MESSAGE("Wobbuffet blew away Stealth Rock!");
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's Speed rose!");
#endif
}
}
SINGLE_BATTLE_TEST("Mortal Spin blows away Wrap, hazards and poisons foe")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_WRAP); }
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); MOVE(player, MOVE_MORTAL_SPIN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MORTAL_SPIN, player);
MESSAGE("Wobbuffet got free of Foe Wobbuffet's Wrap!");
MESSAGE("Wobbuffet blew away Stealth Rock!");
MESSAGE("Foe Wobbuffet was poisoned!");
STATUS_ICON(opponent, poison: TRUE);
}
}

View File

@ -7,7 +7,6 @@ SINGLE_BATTLE_TEST("Take Down deals 25% of recoil damage to the user")
s16 recoilDamage;
GIVEN {
ASSUME(gBattleMoves[MOVE_TAKE_DOWN].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_TAKE_DOWN].recoil == 25);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -28,7 +27,6 @@ SINGLE_BATTLE_TEST("Double Edge deals 33% of recoil damage to the user")
s16 recoilDamage;
GIVEN {
ASSUME(gBattleMoves[MOVE_DOUBLE_EDGE].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_DOUBLE_EDGE].recoil == 33);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -49,7 +47,6 @@ SINGLE_BATTLE_TEST("Head Smash deals 50% of recoil damage to the user")
s16 recoilDamage;
GIVEN {
ASSUME(gBattleMoves[MOVE_HEAD_SMASH].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_HEAD_SMASH].recoil == 50);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -70,7 +67,6 @@ SINGLE_BATTLE_TEST("Flare Blitz deals 33% of recoil damage to the user and can b
s16 recoilDamage;
GIVEN {
ASSUME(gBattleMoves[MOVE_FLARE_BLITZ].effect == EFFECT_RECOIL);
ASSUME(gBattleMoves[MOVE_FLARE_BLITZ].recoil == 33);
ASSUME(gBattleMoves[MOVE_FLARE_BLITZ].argument == STATUS1_BURN);
PLAYER(SPECIES_WOBBUFFET);

View File

@ -4,6 +4,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_RELIC_SONG].effect == EFFECT_RELIC_SONG);
ASSUME(MoveHasMoveEffect(MOVE_RELIC_SONG, MOVE_EFFECT_SLEEP) == TRUE);
}
SINGLE_BATTLE_TEST("Relic Song has a 10% chance to put the target to sleep")

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_SPIN_OUT].effect == EFFECT_SPIN_OUT);
ASSUME(MoveHasMoveEffectSelf(MOVE_SPIN_OUT, MOVE_EFFECT_SPD_MINUS_2) == TRUE);
}
SINGLE_BATTLE_TEST("Spin Out lowers speed by 2 stages")

View File

@ -0,0 +1,45 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(MoveHasMoveEffect(MOVE_THROAT_CHOP, MOVE_EFFECT_THROAT_CHOP) == TRUE);
}
SINGLE_BATTLE_TEST("Throat Chop prevents the usage of sound moves")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(100); };
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); };
} WHEN {
TURN { MOVE(player, MOVE_THROAT_CHOP); MOVE(opponent, MOVE_HYPER_VOICE); }
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THROAT_CHOP, player);
HP_BAR(opponent);
MESSAGE("Foe Wobbuffet can't use Hyper Voice due to Throat Chop!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, opponent);
}
}
}
SINGLE_BATTLE_TEST("Throat Chop won't work through a substitute")
{
GIVEN {
PLAYER(SPECIES_INCINEROAR) { Speed(100); };
OPPONENT(SPECIES_WOBBUFFET) { Speed(50); };
} WHEN {
TURN { MOVE(opponent, MOVE_SUBSTITUTE); }
TURN { MOVE(player, MOVE_THROAT_CHOP); MOVE(opponent, MOVE_HYPER_VOICE); }
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_THROAT_CHOP, player);
NONE_OF {
MESSAGE("Foe Wobbuffet can't use Hyper Voice due to Throat Chop!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, opponent);
}
}

View File

@ -3,7 +3,7 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_TRI_ATTACK].effect == EFFECT_TRI_ATTACK);
ASSUME(MoveHasMoveEffect(MOVE_TRI_ATTACK, MOVE_EFFECT_TRI_ATTACK) == TRUE);
}
SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze")

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_TRIPLE_ARROWS].effect == EFFECT_TRIPLE_ARROWS);
ASSUME(MoveHasMoveEffect(MOVE_TRIPLE_ARROWS, MOVE_EFFECT_DEF_MINUS_1) == TRUE);
ASSUME(MoveHasMoveEffect(MOVE_TRIPLE_ARROWS, MOVE_EFFECT_FLINCH) == TRUE);
}
SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage")
@ -12,7 +13,7 @@ SINGLE_BATTLE_TEST("Triple Arrows may lower Defense by one stage")
u32 chance;
PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 50; }
PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 100; }
PASSES_RANDOMLY(chance, 100, RNG_TRIPLE_ARROWS_DEFENSE_DOWN);
PASSES_RANDOMLY(chance, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_TOGEPI) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
@ -31,7 +32,7 @@ SINGLE_BATTLE_TEST("Triple Arrows makes the foe flinch 30% of the time")
u32 chance;
PARAMETRIZE { ability = ABILITY_HUSTLE; chance = 30; }
PARAMETRIZE { ability = ABILITY_SERENE_GRACE; chance = 60; }
PASSES_RANDOMLY(chance, 100, RNG_TRIPLE_ARROWS_FLINCH);
PASSES_RANDOMLY(chance, 100, RNG_SECONDARY_EFFECT_2);
GIVEN {
PLAYER(SPECIES_TOGEPI) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);

View File

@ -3,7 +3,8 @@
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_VENOSHOCK].effect == EFFECT_VENOSHOCK);
ASSUME(gBattleMoves[MOVE_VENOSHOCK].effect == EFFECT_DOUBLE_POWER_ON_ARG_STATUS);
ASSUME(gBattleMoves[MOVE_VENOSHOCK].argument == STATUS1_PSN_ANY);
}
SINGLE_BATTLE_TEST("Venoshock's power doubles if the target is poisoned/badly poisoned", s16 damage)