Adds Glaive Rush, fixes for Plasma Fists and Relic Song (#3476)

* Adds Glaive Rush

* Fixes: Glaive Rush status is removed until users next turn

* Glaive Rush no affect

* simplify glaive rush script

* simlify script further

* leftover

* Fix Plasma Fists and Relic Song + tests

* Callnative for Plasma Fists

* Use Status Field Ion Deludge for Plasma Fists

* add assumes for flinch_status

---------

Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
Alex 2023-11-18 15:19:38 +01:00 committed by GitHub
parent efe4929ce2
commit 5fa1bffa8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 602 additions and 125 deletions

View File

@ -1372,6 +1372,14 @@
.4byte \failInstr
.endm
.macro setglaiverush
callnative BS_SetGlaiveRush
.endm
.macro tryrelicsong
callnative BS_TryRelicSong
.endm
.macro setzeffect
callnative BS_SetZEffect
.endm
@ -1500,7 +1508,7 @@
callnative BS_TryRecycleBerry
.4byte \ptr
.endm
.macro updatedynamax
callnative BS_UpdateDynamax
.endm
@ -2053,10 +2061,6 @@
.4byte \jumpInstr
.endm
.macro applyplasmafists
various BS_ATTACKER, VARIOUS_APPLY_PLASMA_FISTS
.endm
.macro jumpifweatheraffected battler:req, flags:req, jumpInstr:req
various \battler, VARIOUS_JUMP_IF_WEATHER_AFFECTED
.4byte \flags

View File

@ -440,11 +440,17 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectSyrupBomb @ EFFECT_SYRUP_BOMB
.4byte BattleScript_EffectHit @ EFFECT_IVY_CUDGEL
.4byte BattleScript_EffectMaxMove @ EFFECT_MAX_MOVE
.4byte BattleScript_EffectGlaiveRush @ EFFECT_GLAIVE_RUSH
BattleScript_EffectGlaiveRush::
call BattleScript_EffectHit_Ret
jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_TryFaintMon
setglaiverush
goto BattleScript_TryFaintMon
BattleScript_EffectSyrupBomb::
setmoveeffect MOVE_EFFECT_SYRUP_BOMB
call BattleScript_EffectHit_Ret
seteffectwithchance
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
@ -529,7 +535,6 @@ BattleScript_EffectMakeItRain:
BattleScript_MakeItRainContinuous:
setmoveeffect MOVE_EFFECT_PAYDAY
call BattleScript_EffectHit_Ret
seteffectwithchance
tryfaintmon BS_TARGET
setmoveeffect MOVE_EFFECT_SP_ATK_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
seteffectprimary
@ -1167,9 +1172,8 @@ BattleScript_HyperspaceFuryRemoveProtect::
BattleScript_EffectPlasmaFists:
call BattleScript_EffectHit_Ret
seteffectwithchance
tryfaintmon BS_TARGET
applyplasmafists
orword gFieldStatuses, STATUS_FIELD_ION_DELUGE
printstring STRINGID_IONDELUGEON
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
@ -1345,12 +1349,12 @@ BattleScript_NoMoveEffect:
goto BattleScript_EffectHit
BattleScript_EffectRelicSong:
setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
setmoveeffect MOVE_EFFECT_SLEEP
call BattleScript_EffectHit_Ret
seteffectwithchance
argumentstatuseffect
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
moveendall
tryrelicsong
end
BattleScript_EffectAllySwitch:
attackcanceler
@ -3135,6 +3139,7 @@ BattleScript_HitFromAtkAnimation::
resultmessage
waitmessage B_WAIT_TIME_LONG
seteffectwithchance
BattleScript_TryFaintMon::
tryfaintmon BS_TARGET
BattleScript_MoveEnd::
moveendall
@ -3159,6 +3164,7 @@ BattleScript_EffectHit_Ret::
waitmessage B_WAIT_TIME_LONG
resultmessage
waitmessage B_WAIT_TIME_LONG
seteffectwithchance
return
BattleScript_EffectNaturalGift:
@ -3353,7 +3359,6 @@ BattleScript_EffectPoisonHit:
BattleScript_EffectAbsorb::
call BattleScript_EffectHit_Ret
seteffectwithchance
jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_AbsorbHealBlock
setdrainedhp
manipulatedamage DMG_BIG_ROOT
@ -3788,7 +3793,6 @@ BattleScript_EffectFlinchHit::
BattleScript_EffectFlinchStatus:
setmoveeffect MOVE_EFFECT_FLINCH
call BattleScript_EffectHit_Ret
seteffectwithchance
argumentstatuseffect
tryfaintmon BS_TARGET
goto BattleScript_MoveEnd
@ -7827,7 +7831,7 @@ BattleScript_AttackerFormChangeMoveEffect::
printstring STRINGID_PKMNTRANSFORMED
waitmessage B_WAIT_TIME_LONG
handleformchange BS_ATTACKER, 2
end3
return
BattleScript_BallFetch::
call BattleScript_AbilityPopUp

View File

@ -157,7 +157,7 @@ bool32 CanBattlerEscape(u32 battler); // no ability check
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn);
void ClearFuryCutterDestinyBondGrudge(u32 battler);
void ClearVariousBattlerFlags(u32 battler);
void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler);
u32 GetMoveTarget(u16 move, u8 setTarget);

View File

@ -183,12 +183,12 @@
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE)
#define STATUS4_ELECTRIFIED (1 << 0)
#define STATUS4_PLASMA_FISTS (1 << 1)
#define STATUS4_MUD_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene
#define STATUS4_SALT_CURE (1 << 5)
#define STATUS4_SYRUP_BOMB (1 << 6)
#define STATUS4_MUD_SPORT (1 << 1) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_WATER_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_INFINITE_CONFUSION (1 << 3) // Used for Berserk Gene
#define STATUS4_SALT_CURE (1 << 4)
#define STATUS4_SYRUP_BOMB (1 << 5)
#define STATUS4_GLAIVE_RUSH (1 << 6)
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.
#define HITMARKER_SKIP_DMG_TRACK (1 << 5)
@ -378,18 +378,17 @@
#define MOVE_EFFECT_INCINERATE 67
#define MOVE_EFFECT_BUG_BITE 68
#define MOVE_EFFECT_RECOIL_HP_25 69
#define MOVE_EFFECT_RELIC_SONG 70
#define MOVE_EFFECT_TRAP_BOTH 71
#define MOVE_EFFECT_DOUBLE_SHOCK 72
#define MOVE_EFFECT_ROUND 73
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 74
#define MOVE_EFFECT_DIRE_CLAW 75
#define MOVE_EFFECT_STEALTH_ROCK 76
#define MOVE_EFFECT_SPIKES 77
#define MOVE_EFFECT_TRIPLE_ARROWS 78
#define MOVE_EFFECT_SYRUP_BOMB 79
#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 NUM_MOVE_EFFECTS 80
#define NUM_MOVE_EFFECTS 79
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000

View File

@ -417,7 +417,8 @@
#define EFFECT_SYRUP_BOMB 411
#define EFFECT_IVY_CUDGEL 412
#define EFFECT_MAX_MOVE 413
#define EFFECT_GLAIVE_RUSH 414
#define NUM_BATTLE_MOVE_EFFECTS 414
#define NUM_BATTLE_MOVE_EFFECTS 415
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -209,45 +209,44 @@
#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 116
#define VARIOUS_CONSUME_BERRY 117
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 118
#define VARIOUS_APPLY_PLASMA_FISTS 119
#define VARIOUS_JUMP_IF_SPECIES 120
#define VARIOUS_UPDATE_ABILITY_POPUP 121
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 122
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 123
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 124
#define VARIOUS_PHOTON_GEYSER_CHECK 125
#define VARIOUS_SHELL_SIDE_ARM_CHECK 126
#define VARIOUS_TRY_NO_RETREAT 127
#define VARIOUS_TRY_TAR_SHOT 128
#define VARIOUS_CAN_TAR_SHOT_WORK 129
#define VARIOUS_CHECK_POLTERGEIST 130
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 131
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 132
#define VARIOUS_JUMP_IF_UNDER_200 133
#define VARIOUS_SET_SKY_DROP 134
#define VARIOUS_CLEAR_SKY_DROP 135
#define VARIOUS_SKY_DROP_YAWN 136
#define VARIOUS_JUMP_IF_HOLD_EFFECT 137
#define VARIOUS_CURE_CERTAIN_STATUSES 138
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 139
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 140
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 141
#define VARIOUS_SAVE_BATTLER_ITEM 142
#define VARIOUS_RESTORE_BATTLER_ITEM 143
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 144
#define VARIOUS_SET_BEAK_BLAST 145
#define VARIOUS_SWAP_SIDE_STATUSES 146
#define VARIOUS_SWAP_STATS 147
#define VARIOUS_TEATIME_INVUL 148
#define VARIOUS_TEATIME_TARGETS 149
#define VARIOUS_TRY_WIND_RIDER_POWER 150
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 151
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 152
#define VARIOUS_STORE_HEALING_WISH 153
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 154
#define VARIOUS_TRY_REVIVAL_BLESSING 155
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 156
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 157
#define VARIOUS_JUMP_IF_SPECIES 119
#define VARIOUS_UPDATE_ABILITY_POPUP 120
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 121
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 122
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 123
#define VARIOUS_PHOTON_GEYSER_CHECK 124
#define VARIOUS_SHELL_SIDE_ARM_CHECK 125
#define VARIOUS_TRY_NO_RETREAT 126
#define VARIOUS_TRY_TAR_SHOT 127
#define VARIOUS_CAN_TAR_SHOT_WORK 128
#define VARIOUS_CHECK_POLTERGEIST 129
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 130
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 131
#define VARIOUS_JUMP_IF_UNDER_200 132
#define VARIOUS_SET_SKY_DROP 133
#define VARIOUS_CLEAR_SKY_DROP 134
#define VARIOUS_SKY_DROP_YAWN 135
#define VARIOUS_JUMP_IF_HOLD_EFFECT 136
#define VARIOUS_CURE_CERTAIN_STATUSES 137
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 138
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 139
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 140
#define VARIOUS_SAVE_BATTLER_ITEM 141
#define VARIOUS_RESTORE_BATTLER_ITEM 142
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 143
#define VARIOUS_SET_BEAK_BLAST 144
#define VARIOUS_SWAP_SIDE_STATUSES 145
#define VARIOUS_SWAP_STATS 146
#define VARIOUS_TEATIME_INVUL 147
#define VARIOUS_TEATIME_TARGETS 148
#define VARIOUS_TRY_WIND_RIDER_POWER 149
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 150
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 151
#define VARIOUS_STORE_HEALING_WISH 152
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 153
#define VARIOUS_TRY_REVIVAL_BLESSING 154
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 155
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 156
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -5671,13 +5671,8 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk)
}
attackerAbility = GetBattlerAbility(battlerAtk);
GET_MOVE_TYPE(move, moveType);
if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL)
|| gStatuses4[battlerAtk] & STATUS4_ELECTRIFIED)
{
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_2;
}
else if (gBattleMoves[move].type == TYPE_NORMAL
if (gBattleMoves[move].type == TYPE_NORMAL
&& gBattleMoves[move].effect != EFFECT_HIDDEN_POWER
&& gBattleMoves[move].effect != EFFECT_WEATHER_BALL
&& gBattleMoves[move].effect != EFFECT_CHANGE_TYPE_ON_ITEM
@ -5706,15 +5701,16 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk)
{
gBattleStruct->dynamicMoveType = TYPE_WATER | F_DYNAMIC_TYPE_2;
}
else if (gStatuses4[battlerAtk] & STATUS4_PLASMA_FISTS && moveType == TYPE_NORMAL)
{
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_2;
}
else if (move == MOVE_AURA_WHEEL && gBattleMons[battlerAtk].species == SPECIES_MORPEKO_HANGRY)
{
gBattleStruct->dynamicMoveType = TYPE_DARK | F_DYNAMIC_TYPE_2;
}
GET_MOVE_TYPE(move, moveType);
if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL)
|| gStatuses4[battlerAtk] & STATUS4_ELECTRIFIED)
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_2;
// Check if a gem should activate.
GET_MOVE_TYPE(move, moveType);
if (holdEffect == HOLD_EFFECT_GEMS

View File

@ -1531,12 +1531,9 @@ static bool8 JumpIfMoveAffectedByProtect(u16 move)
static bool32 AccuracyCalcHelper(u16 move)
{
if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
{
JumpIfMoveFailed(7, move);
return TRUE;
}
else if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON))
if ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
|| (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON))
|| gStatuses4[gBattlerTarget] & STATUS4_GLAIVE_RUSH)
{
JumpIfMoveFailed(7, move);
return TRUE;
@ -3546,21 +3543,6 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite;
}
break;
case MOVE_EFFECT_RELIC_SONG:
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SHEER_FORCE && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED))
{
if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_ARIA)
{
gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE;
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect);
}
else if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_PIROUETTE)
{
gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_ARIA;
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeMoveEffect);
}
}
break;
case MOVE_EFFECT_TRAP_BOTH:
if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_ESCAPE_PREVENTION))
{
@ -10238,13 +10220,6 @@ static void Cmd_various(void)
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_APPLY_PLASMA_FISTS:
{
VARIOUS_ARGS();
for (i = 0; i < gBattlersCount; i++)
gStatuses4[i] |= STATUS4_PLASMA_FISTS;
break;
}
case VARIOUS_JUMP_IF_SPECIES:
{
VARIOUS_ARGS(u16 species, const u8 *jumpInstr);
@ -16281,3 +16256,30 @@ void BS_TrySetOctolock(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
void BS_SetGlaiveRush(void)
{
NATIVE_ARGS();
gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH;
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_TryRelicSong(void)
{
NATIVE_ARGS();
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SHEER_FORCE && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED))
{
if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_ARIA)
gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_PIROUETTE;
else if (gBattleMons[gBattlerAttacker].species == SPECIES_MELOETTA_PIROUETTE)
gBattleMons[gBattlerAttacker].species = SPECIES_MELOETTA_ARIA;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_AttackerFormChangeMoveEffect;
}
else
gBattlescriptCurrInstr = cmd->nextInstr;
}

View File

@ -329,7 +329,6 @@ void HandleAction_UseMove(void)
gCurrentMove = gBattleStruct->zmove.toBeUsed[gBattlerAttacker];
}
if (gBattleMons[gBattlerAttacker].hp != 0)
{
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
@ -564,7 +563,7 @@ void HandleAction_UseItem(void)
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
ClearVariousBattlerFlags(gBattlerAttacker);
gLastUsedItem = gBattleResources->bufferB[gBattlerAttacker][1] | (gBattleResources->bufferB[gBattlerAttacker][2] << 8);
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[ItemId_GetBattleUsage(gLastUsedItem) - 1];
@ -688,7 +687,7 @@ void HandleAction_Run(void)
{
if (!TryRunFromBattle(gBattlerAttacker)) // failed to run away
{
ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
ClearVariousBattlerFlags(gBattlerAttacker);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CANT_ESCAPE_2;
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
@ -1342,6 +1341,7 @@ const u8* CancelMultiTurnMoves(u32 battler)
gDisableStructs[battler].rolloutTimer = 0;
gDisableStructs[battler].furyCutterCounter = 0;
return result;
}
@ -2476,7 +2476,6 @@ enum
ENDTURN_POWDER,
ENDTURN_THROAT_CHOP,
ENDTURN_SLOW_START,
ENDTURN_PLASMA_FISTS,
ENDTURN_CUD_CHEW,
ENDTURN_TORMENT, // supposedly this goes after Taunt, before Encore, but Encore is first right now?
ENDTURN_SALT_CURE,
@ -3013,10 +3012,6 @@ u8 DoBattlerEndTurnEffects(void)
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_PLASMA_FISTS:
gStatuses4[battler] &= ~STATUS4_PLASMA_FISTS;
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_CUD_CHEW:
if (GetBattlerAbility(battler) == ABILITY_CUD_CHEW && !gDisableStructs[battler].cudChew && ItemId_GetPocket(GetUsedHeldItem(battler)) == POCKET_BERRIES)
gDisableStructs[battler].cudChew = TRUE;
@ -3322,6 +3317,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
case CANCELLER_FLAGS: // flags clear
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND;
gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE;
gStatuses4[gBattlerAttacker] &= ~ STATUS4_GLAIVE_RUSH;
gBattleScripting.tripleKickPower = 0;
gBattleStruct->atkCancellerTracker++;
break;
@ -7897,11 +7893,12 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
return effect;
}
void ClearFuryCutterDestinyBondGrudge(u32 battler)
void ClearVariousBattlerFlags(u32 battler)
{
gDisableStructs[battler].furyCutterCounter = 0;
gBattleMons[battler].status2 &= ~STATUS2_DESTINY_BOND;
gStatuses3[battler] &= ~STATUS3_GRUDGE;
gStatuses4[battler] &= ~ STATUS4_GLAIVE_RUSH;
}
void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands
@ -9551,6 +9548,13 @@ static inline uq4_12_t GetCriticalModifier(bool32 isCrit)
return UQ_4_12(1.0);
}
static inline uq4_12_t GetGlaiveRushModifier(u32 battlerDef)
{
if (gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH)
return UQ_4_12(2.0);
return UQ_4_12(1.0);
}
static inline uq4_12_t GetZMaxMoveAgainstProtectionModifier(u32 battlerDef, u32 move)
{
if ((gBattleStruct->zmove.active || IsMaxMove(move)) && IS_BATTLER_PROTECTED(battlerDef))
@ -9786,7 +9790,8 @@ static inline s32 DoMoveDamageCalcVars(u32 move, u32 battlerAtk, u32 battlerDef,
DAMAGE_APPLY_MODIFIER(GetParentalBondModifier(battlerAtk));
DAMAGE_APPLY_MODIFIER(GetWeatherDamageModifier(battlerAtk, move, moveType, holdEffectAtk, holdEffectDef, weather));
DAMAGE_APPLY_MODIFIER(GetCriticalModifier(isCrit));
// TODO: Glaive Rush (Gen IX effect)
DAMAGE_APPLY_MODIFIER(GetGlaiveRushModifier(battlerDef));
if (randomFactor)
{
dmg *= 100 - RandomUniform(RNG_DAMAGE_MODIFIER, 0, 15);

View File

@ -9557,7 +9557,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.priority = 0,
.split = SPLIT_SPECIAL,
.zMoveEffect = Z_EFFECT_NONE,
.argument = STATUS1_SLEEP,
.sheerForceBoost = TRUE,
.ignoresSubstitute = B_UPDATED_MOVE_FLAGS >= GEN_6,
.soundMove = TRUE,
@ -13683,7 +13682,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
[MOVE_GLAIVE_RUSH] =
{
.effect = EFFECT_PLACEHOLDER, // EFFECT_GLAIVE_RUSH
.effect = EFFECT_GLAIVE_RUSH,
.power = 120,
.type = TYPE_DRAGON,
.accuracy = 100,

View File

@ -0,0 +1,64 @@
#include "global.h"
#include "test/battle.h"
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);
}
SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang inflict status 10% of the time")
{
u16 move;
PARAMETRIZE { move = MOVE_THUNDER_FANG; }
PARAMETRIZE { move = MOVE_ICE_FANG; }
PARAMETRIZE { move = MOVE_FIRE_FANG; }
PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
if (move == MOVE_THUNDER_FANG) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponent);
STATUS_ICON(opponent, paralysis: TRUE);
} if (move == MOVE_ICE_FANG) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
STATUS_ICON(opponent, freeze: TRUE);
} if (move == MOVE_FIRE_FANG) {
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent);
STATUS_ICON(opponent, burn: TRUE);
}
}
}
SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang cause the opponent to flinch 10% of the time")
{
u16 move;
PARAMETRIZE { move = MOVE_THUNDER_FANG; }
PARAMETRIZE { move = MOVE_ICE_FANG; }
PARAMETRIZE { move = MOVE_FIRE_FANG; }
PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(100); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, move, player);
HP_BAR(opponent);
MESSAGE("Foe Wobbuffet flinched!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent);
}
}

View File

@ -0,0 +1,143 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_GLAIVE_RUSH].effect == EFFECT_GLAIVE_RUSH);
}
SINGLE_BATTLE_TEST("If Glaive Rush is successful moves targeted at the user do not check accuracy")
{
PASSES_RANDOMLY(100, 100, RNG_ACCURACY);
GIVEN {
ASSUME(gBattleMoves[MOVE_MEGA_PUNCH].accuracy == 85);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_GLAIVE_RUSH); MOVE(opponent, MOVE_MEGA_PUNCH); }
} SCENE {
MESSAGE("Wobbuffet used Glaive Rush!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEGA_PUNCH, opponent);
}
}
SINGLE_BATTLE_TEST("If Glaive Rush is successful, moves targeted at the user deal double damage")
{
s16 glaiveRushEffectedDmg;
s16 normalDmg;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_GLAIVE_RUSH); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &glaiveRushEffectedDmg);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &normalDmg);
} THEN {
EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), glaiveRushEffectedDmg);
}
}
SINGLE_BATTLE_TEST("If Glaive Rush is successful, moves targeted at the user deal double damage until the user moves again")
{
s16 glaiveRushEffectedDmg;
s16 normalDmg;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_GLAIVE_RUSH); }
TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &normalDmg);
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &glaiveRushEffectedDmg);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
} THEN {
EXPECT_MUL_EQ(normalDmg, Q_4_12(2.0), glaiveRushEffectedDmg);
}
}
SINGLE_BATTLE_TEST("If Glaive Rush isn't successful moves targeted at the user don't deal double damage", s16 damage)
{
bool32 missesGlaiveRush;
PARAMETRIZE { missesGlaiveRush = FALSE; }
PARAMETRIZE { missesGlaiveRush = TRUE; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); }
} WHEN {
TURN { MOVE(player, MOVE_GLAIVE_RUSH, hit: missesGlaiveRush); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (!missesGlaiveRush)
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Glaive Rush doesn't affect the user if the effect is blocked", s16 damage)
{
u32 species;
PARAMETRIZE { species = SPECIES_CLEFAIRY; }
PARAMETRIZE { species = SPECIES_WOBBUFFET; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(species) { Attack(50); }
} WHEN {
TURN { MOVE(player, MOVE_GLAIVE_RUSH); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (species == SPECIES_CLEFAIRY)
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
else
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Glaive Rush status last until the the user's next turn")
{
s16 normalDmgFristHit;
s16 normalDmgSecondHit;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_GLAIVE_RUSH); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GLAIVE_RUSH, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &normalDmgFristHit);
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &normalDmgSecondHit);
} THEN {
EXPECT_EQ(normalDmgFristHit, normalDmgSecondHit);
}
}

View File

@ -0,0 +1,99 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_PLASMA_FISTS].effect == EFFECT_PLASMA_FISTS);
}
SINGLE_BATTLE_TEST("Ion Duldge turns normal moves into electric for the remainder of the current turn")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_ION_DELUGE].effect == EFFECT_ION_DELUGE);
PLAYER(SPECIES_KRABBY);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_ION_DELUGE); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Krabby used Ion Deluge!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ION_DELUGE, player);
MESSAGE("A deluge of ions showers the battlefield!");
MESSAGE("Foe Wobbuffet used Tackle!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
MESSAGE("It's super effective!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
NOT MESSAGE("It's super effective!");
}
}
SINGLE_BATTLE_TEST("Plasma Fists turns normal moves into electric for the remainder of the current turn")
{
GIVEN {
PLAYER(SPECIES_KRABBY);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_PLASMA_FISTS); MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Krabby used Plasma Fists!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_PLASMA_FISTS, player);
MESSAGE("A deluge of ions showers the battlefield!");
MESSAGE("Foe Wobbuffet used Tackle!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
MESSAGE("It's super effective!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
NOT MESSAGE("It's super effective!");
}
}
SINGLE_BATTLE_TEST("Plasma Fists type-changing effect is applied after Pixilate")
{
GIVEN {
PLAYER(SPECIES_KRABBY) { Speed(300); };
OPPONENT(SPECIES_ALTARIA) { Speed(1); Item(ITEM_ALTARIANITE); }
} WHEN {
TURN { MOVE(player, MOVE_PLASMA_FISTS); MOVE(opponent, MOVE_EMBER, megaEvolve: TRUE); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent);
MESSAGE("Krabby used Plasma Fists!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_PLASMA_FISTS, player);
MESSAGE("A deluge of ions showers the battlefield!");
MESSAGE("Foe Altaria used Ember!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
NOT MESSAGE("It's super effective!");
}
}
SINGLE_BATTLE_TEST("Plasma Fists type-changing effect is applied after Normalize")
{
GIVEN {
PLAYER(SPECIES_KRABBY);
OPPONENT(SPECIES_SKITTY) { Ability(ABILITY_NORMALIZE); }
} WHEN {
TURN { MOVE(player, MOVE_PLASMA_FISTS); MOVE(opponent, MOVE_EMBER); }
} SCENE {
MESSAGE("Krabby used Plasma Fists!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_PLASMA_FISTS, player);
MESSAGE("A deluge of ions showers the battlefield!");
MESSAGE("Foe Skitty used Ember!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
MESSAGE("It's super effective!");
}
}
SINGLE_BATTLE_TEST("Plasma Fists turns normal type dynamax-moves into electric type moves")
{
GIVEN {
PLAYER(SPECIES_KRABBY) { Speed(100); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
} WHEN {
TURN { MOVE(player, MOVE_PLASMA_FISTS); MOVE(opponent, MOVE_TACKLE, dynamax: TRUE); }
} SCENE {
MESSAGE("Krabby used Plasma Fists!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_PLASMA_FISTS, player);
MESSAGE("A deluge of ions showers the battlefield!");
MESSAGE("Foe Wobbuffet used Max Lightning!");
MESSAGE("It's super effective!");
}
}

View File

@ -0,0 +1,162 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_RELIC_SONG].effect == EFFECT_RELIC_SONG);
ASSUME(P_GEN_5_POKEMON == TRUE);
}
SINGLE_BATTLE_TEST("Relic Song has a 10% chance to put the target to sleep")
{
PASSES_RANDOMLY(10, 100, RNG_SECONDARY_EFFECT);
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, opponent);
STATUS_ICON(opponent, sleep: TRUE);
}
}
SINGLE_BATTLE_TEST("Relic Song is prevented by Soundproof")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_VOLTORB) { Ability(ABILITY_SOUNDPROOF); }
} WHEN {
TURN { MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_SOUNDPROOF);
MESSAGE("Foe Voltorb's Soundproof blocks Relic Song!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
}
}
}
SINGLE_BATTLE_TEST("Relic Song will become a Water-type move when used by a Pokémon with the Ability Liquid Voice")
{
GIVEN {
ASSUME(P_GEN_7_POKEMON == TRUE);
PLAYER(SPECIES_VULPIX);
OPPONENT(SPECIES_POPPLIO) { Ability(ABILITY_LIQUID_VOICE); }
} WHEN {
TURN { MOVE(opponent, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, opponent);
HP_BAR(player);
MESSAGE("It's super effective!");
}
}
SINGLE_BATTLE_TEST("Relic Song is blocked by Throat Chop")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_THROAT_CHOP); MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_THROAT_CHOP, opponent);
HP_BAR(player);
MESSAGE("Wobbuffet can't use Relic Song due to Throat Chop!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
}
}
SINGLE_BATTLE_TEST("Relic Song transforms Meloetta if used successfully")
{
GIVEN {
PLAYER(SPECIES_MELOETTA_ARIA);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
MESSAGE("Meloetta transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MELOETTA_PIROUETTE);
}
}
SINGLE_BATTLE_TEST("Relic Song transforms Meloetta twice if used successfully")
{
GIVEN {
PLAYER(SPECIES_MELOETTA_ARIA);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_RELIC_SONG); }
TURN { MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
MESSAGE("Meloetta transformed!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
MESSAGE("Meloetta transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MELOETTA_ARIA);
}
}
SINGLE_BATTLE_TEST("Relic Song transformation is the last thing that happens after it hits")
{
GIVEN {
PLAYER(SPECIES_MELOETTA_ARIA);
OPPONENT(SPECIES_GOSSIFLEUR) { HP(1); Ability(ABILITY_COTTON_DOWN); }
} WHEN {
TURN { MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
MESSAGE("Foe Gossifleur fainted!");
ABILITY_POPUP(opponent, ABILITY_COTTON_DOWN);
MESSAGE("Meloetta's Speed fell!");
MESSAGE("Meloetta transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MELOETTA_PIROUETTE);
}
}
DOUBLE_BATTLE_TEST("Relic Song transforms once Meloetta in a double battle")
{
GIVEN {
PLAYER(SPECIES_MELOETTA_ARIA);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
MESSAGE("Meloetta transformed!");
} THEN {
EXPECT_EQ(playerLeft->species, SPECIES_MELOETTA_PIROUETTE);
}
}
SINGLE_BATTLE_TEST("Relic Song loses the form-changing effect with Sheer Force")
{
GIVEN {
PLAYER(SPECIES_MELOETTA_ARIA);
OPPONENT(SPECIES_NIDOKING) { Ability(ABILITY_SHEER_FORCE); }
} WHEN {
TURN { MOVE(opponent, MOVE_SKILL_SWAP); MOVE(player, MOVE_RELIC_SONG); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_RELIC_SONG, player);
HP_BAR(opponent);
NOT MESSAGE("Meloetta transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_MELOETTA_ARIA);
}
}